What is the best way to save Players state in game Server?

what is the best way to save players state in a game server and access to the state from different nodes ?
if best way is database,which database is the solution ?
can do that with elixir phoenix ?

It depends entirely on the kind of game.

If it is a real-time multiplayer game, you probably only want to store the state in an ephereral way. In that case, I’d suggest using a GenServer to store the state. This is an approach I’ve used multiple times in the past, including our Global Game Jam game of one year ago, when we were using Elixir/Phoenix to synchronize the game state between a computer running the visuals of the game on a big Unity-powered screen and any number of phones that were used as controllers.

If instead you were to make the new lichess then you’d probably want to store your game states and the changes to succeeding states in some kind of persistent database. Which one is best here again depends very much on the kind of game and in what way players are expected to interact with each other.

EDIT: I suggest watching the second half of Chris McCord’s talk at ElixirConf.EU 2018 (starting at 19:11), which talks about when to use a database and when not, especially when talking about games.

6 Likes

thank you for help, I need to study more
i will ask you again some questions

what about ETS or Agent ? can i use them or GenServer is better >

An Agent is a GenServer that only stores state and nothing else. Unlike a database, an Agent will store state in memory and the state will be lost when the agent dies.

An ETS table is also an in-memory storage mechanism that stores information in a Tuple and allows you to look up that information based on one of the terms in the tuple. It has particularly high performance when looking up items based on the key term. An ETS table is owned by a process and the entire table of information will go away when the process that owns the table dies.

Either could be used to store information about a player in a game. Both would be in-memory storage and ephemeral (the information would go away when the process or node they are running on ends).

2 Likes

However, if you also want to update the game logic, using a plain GenServer is probably the way to go.

so what is the best way ? save the states in data base or … ?

is there any way to save states when the node crash ?

You can save data in a flat file. You can save data in a Database. You could send data over the internet into an object storage system. There are innumerable ways you could save the data that you are asking about.

You have asked a bad question. There is no single “Best” way to save data for a game.

It all depends on what kind of data you need to save, how persistent that data needs to be, when the data must be reloaded.

Here’s my best suggestion. Start by saving the data into an Agent. Or, if you want to combine the data with logic, in a custom GenServer. When you have a lot of different options and can’t make a good choice between them, then choose the option that is easiest to change. Putting the data in some form of GenServer and keeping it in memory would be easy to change later.

Then, when you have a better handle on how you will use the data, when you know that it must be saved, then you can look at options on how to save that data and will be able to ask better questions about how to do so.

1 Like

A quite common approach that I have used with simple games is to let the GenServer write its state after each update to a file, using :erlang.term_to_binary, while, if an update comes in for a game whose GenServer is not currently running, we check if the file is available and, if so, start a GenServer using :erlang.binary_to_term.

If you want to do this across multiple nodes, then you’ll need some kind of data store. Depending on how you want to handle failures and how likely they are, choose either a CP (consistent under partitioning, but therefore potentially temporarily unavailable) database (Sharded Postgres, CockroachDB, most other SQL-like DBs), or an AP (available under partitioning, but therefore potentially inconsistent) database (Riak, Cassandra, CouchDB).

But honestly, I agree with @easco : Keep it simple. Build a working basic game with ephemeral state. Then, if it works, extend it so it becomes persistent. Then, if that works, try to share the state between nodes. Only then decide whether it makes sense to look into distributed databases.

The main thing you are looking for, a ‘persistent actor’, is something which unfortunately still is a bit of a myth right now, because there are a couple of very difficult edge cases to consider (such as: how do you prevent an actor being started twice when the network is partitioned?): There is some research being done by @michalmuskala and a couple of other people in the Firenest and Lasp projects, but this is still in a very preliminary stage, so if you want to handle state in a way that works across failing nodes, your best option currently is to build something yourself.

1 Like

@Qqwy @easco thank you
if i have any question ,i will ask you again :smile:

1 Like