Multiplayer Game Server, Client Database Structure - database

I had a general question regarding how game data is stored for multiplayer games. Items and characters have base stats and then there is the stats gained while playing the game through upgrades etc.
I would want to store the stats gained in the server-side database but I wasn't so sure for the base value. Specifically for a mobile game, I was thinking the amount of data passed back and forth should be reduced as much as possible.
Would storing these base values for items/characters client side, making use of prefab/scriptable object(I am using Unity) be a bad idea? The battle will take place client-side and the server handles mostly read/write to database of player game data. The main interaction between players will not be a real-time battle between players but something similar to that of clash of clans.

In my opinion, there are two ways to do this properly:
Store the base items client side only. If you want to update them later, you will have to publish a new build of your project, but you don't need to make web requests.
Store the base items server side. You can maintain them in your Database and let the client fetch them, i.e. when the game gets started. This way, every connected player will always have the current base stats.
Another possibility, depending on the scope of your project, is to have two databases. One on the server and one client side. Then, every time the game gets started, you check on your server for updates (you could use some kind of checksum or version number to make that easy).

What I would do is provision a decentralized or distributed database, have a source of truth where the base items are always available there, on a globally replicated basis (assuming this matters), and then have the client also implement a local cache of its own (like React does) where needed data is stored in a local DB that is synced with the remote DB. The game client now only ever talks to the local DB, and the smarts of synchronizing, etc, are left to the DB layer, making your application code much simpler.

Related

How to cache batches of IDs "locally" in a serverless environment?

Traditionally, in a non-serverless environment, I would have the following system. Say I have a custom ID generation protocol for all my models. Say I also have 20 servers scattered around. I give each server a slice of IDs to work with off the whole stack of IDs. When they are done or the server goes down, it returns the IDs back to the system so they don't get wasted. The reason for sending each server a batch of IDs is so that every time a new record is created you don't need to fetch from a central ID server to get the next ID. Instead they have a local set they can work with freely.
How would you do this sort of thing in a serverless system? I am deploying to Vercel and wondering what the appropriate architecture might be for such an ID batching system. There are other use cases for needed a persistent copy of data in a local server, so if you don't like the ID example just imagine another sort of system. How do you solve this optimization problem in a serverless environment?
Serverless is an approach. Like all such things (solutions), it should be matched to the problem - not the other way around. Is this simply a case where serverless is a good solution choice for dealing with 80% of your problem, and that all you need to do is choose something appropriate to deal to the other 20%?
Assuming you have the freedom to do this, can't you just have the serverless parts of the solution consume non-serverless services - e.g. an ID Service?
Separately to this, caching comes to mind - just the general idea of having some data close by which might be mastered somewhere else. Caching patterns like Write Behind would allow you to work with local copies (i.e. immediate consumption) whilst farming out the cache-master communication.

How to share state between users in ReactJS

I'm building a multiplayer card game mainly in ReactJS and want to share some state between users (players). I need each user to be able to know when it's their turn to play and see some things about other users like score and current number of cards in hand, etc. For example, when one player's turn ends, I need the next player's app to recognize it's their turn and provide the applicable options.
It seems WebSockets or something based on it would be a good option. I'm still learning React and other pieces so I'm trying to keep the number of technologies down for now. I'm considering setting up rapid polling (every 200 ms, perhaps), either to an API or maybe checking against a file on the server or database entries.
Are there especially concerning performance issues or better options to get it working? I'm also learning about AWS and Docker and intend to host on AWS, if possible.
I recommend you use firebase which is a database to send and receive data online because the states of react js are not interlaced between devices
instead of sharing state between players you should explore the possibility of players sharing an instance of game object on the server.
for example :
game={
status:'running',
players:2,
p1:{state:'waiting'},
p2:{state:'active'}
}
time complexity for common state on server will be [n]
expected time complexity for state exchange or polling is [n^2] or more.
If you want to try serverless approach, you can look at AWS Lambda and Dynamo DB.
WebSockets won't work for you as you need one fixed party in WebSocket connection.
You could share the state peer-to-peer style with a WebRTC connection and using the DataChannel in that connection, but that's not an easy task.
(see for example: https://www.html5rocks.com/en/tutorials/webrtc/basics/#toc-rtcdatachannel)
The much more common option is to use a central data storage and either sync your state with that or just store it there in the first place.
You could use Firebase (see answer by David) or any other kind of database.
Firebase is particularly easy to set up, though.
If you have/need/want to use an API-backend anyways, you can use pretty much any kind of database layer in that and just talk REST or GraphQL with the API to share your state between players.

Does it make sense database on client side with service-oriented design?

Suppose a server (or server cluster) launching a web extractor each time a web client calls a specific API.
This web extractor aims to collect some legal data in order to be displayed by web client.
Should be there a single well-designed and secured database on server side and force client to call API each time it wants to display some concerned data?
In this case, suppose client wants to link these retrieved data to its own data present in its own database.
Does it make sense for client to link them with retrieved data IDs/tokens? So that, no needs for it to modelize specific database tables for these remote data but involves more requests in order to find remote data targeted by these IDs/tokens.
Or should there be a specific database on client side in order to avoid huge networks calls caused by all these API Client => Server flows?
Still wonder this question by supposing scenario changed and these data become strictly confidential and no client webs are allowed to store it...
Or both? Even if there are redundancies between both database.
Your question refers rather to caching problem. Database is not the only solution for storing the cached data. I'd choose database only if this data has long effective period and is supposed for querying for different representations on the client side. If the data has short time to live probably some in-place caching solutions are preferable where data is represented effectively in serialized manner. To have this cache on client or server side depends on the security requirements and the way the architecture you are keeping in mind should move towards.

Database performance concern

So, I've got a game server with an accompanying database that works just like any game database, and does it well too. The thing is I'm now thinking of adding a webpage with some stats to go with the game; for example some way to see your character from outside the game; see your stats, standing etc.
My concern is if having this webpage connect to the same database, would it noticably slow down the game server? Or, since it's a different connection, can they work efficiently at the same time? The webpage will just be for displaying information, so it will simply use SELECTs on the data created by the game server.
Is this, performance wise, an acceptable way of doing it, or should I look into stuff such as keeping a seperate database for the webpage that only on low-population hours fetches data from the game server's database, and thusly is kept slightly out of synch, but with less strain on the server latency?
P.S. I'm using MySql 5.5
You won't know until you try it. My advice would be to have your game server and stats page connect to the same database and see what happens. Databases like MySQL are designed to handle lots of connections at once (that is why it is popular with websites - many incoming requests at once), but if you then find that it is adversely affecting your game server you can consider a more optimal solution.
In general, don't over-optimize. Go with a solution that works first, then see if it is worth improving.

Is this the right architecture for our MMORPG mobile game?

These days I am trying to design architecture of a new MMORPG mobile game for my company. This game is similar to Mafia Wars, iMobsters, or RISK. Basic idea is to prepare an army to battle your opponents (online users).
Although I have previously worked on multiple mobile apps but this is something new to me. After a lot of struggle, I have come up with an architecture which is illustrated with the help of a high-level flow diagram:
We have decided to go with client-server model. There will be a centralized database on server. Each client will have its own local database which will remain in sync with server. This database acts as a cache for storing things that do not change frequently e.g. maps, products, inventory etc.
With this model in place, I am not sure how to tackle following issues:
What would be the best way of synchronizing server and client databases?
Should an event get saved to local DB before updating it to server? What if app terminates for some reason before saving changes to centralized DB?
Will simple HTTP requests serve the purpose of synchronization?
How to know which users are currently logged in? (One way could be to have client keep on sending a request to server after every x minutes to notify that it is active. Otherwise consider a client inactive).
Are client side validations enough? If not, how to revert an action if server does not validate something?
I am not sure if this is an efficient solution and how it will scale. I would really appreciate if people who have already worked on such apps can share their experiences which might help me to come up with something better. Thanks in advance.
Additional Info:
Client-side is implemented in C++ game engine called marmalade. This is a cross platform game engine which means you can run your app on all major mobile OS. We certainly can achieve threading and which is also illustrated in my flow diagram. I am planning to use MySQL for server and SQLite for client.
This is not a turn based game so there is not much interaction with other players. Server will provide a list of online players and you can battle them by clicking battle button and after some animation, result will be announced.
For database synchronization I have two solutions in mind:
Store timestamp for each record. Also keep track of when local DB
was last updated. When synchronizing, only select those rows that
have a greater timestamp and send to local DB. Keep a isDeleted flag
for deleted rows so every deletion simply behaves as an update. But
I have serious doubts about performance as for every sync request we
would have to scan the complete DB and look for updated rows.
Another technique might be to keep a log of each insertion or update
that takes place against a user. When the client app asks for sync,
go to this table and find out which rows of which table have been
updated or inserted. Once these rows are successfully transferred to
client remove this log. But then I think of what happens if a user
uses another device. According to logs table all updates have been
transferred for that user but actually that was done on another
device. So we might have to keep track of device also. Implementing
this technique is more time consuming but not sure if it out
performs the first one.
I've actually worked on some of the titles you mentioned.
I do not recommend using mysql, it doesn't scale up correctly, even if you shard. If you do you are loosing any benefits you might have in using a relational database.
You are probably better off using a no-sql database. Its is faster to develop, easy to scale and it is simple to change the document structure which is a given for a game.
If your game data is simple you might want to try couchDB, if you need advanced querying you are probably better of with MongoDB.
Take care of security at the start. They will try to hack the game for sure and if you have a number of clients released it is hard to make security changes backward compatible. SSL won't do much as the end user is the problem not an eavesdropper. Signing or encrypting your data will make it harder for a user to add items and gold to their accounts.
You should also define your architecture to support multiple clients without having a bunch of ifs and case statements. Read the client version and dispatch that client to the appropriate codebase.
Have a maintenance mode with flags for upgrading, maintenance, etc. It will cut you some slack if you need to re-shard your DB or any other change that might require downtime.
Client side validations are not enough, specially if using in app purchases. I agree with the above post. Server should control game logic.
As for DB sync, its best to memcache read only data. Typical examples are buyable items, maps, news, etc. User data is harder as you might not be able to afford loosing any modified data. The easiest setup is to cache user data for a couple of hours and write directly to the DB every time. If you are using no-sql it will probably withstand a high load without the need of using a persistence queue.
I see two potential problem hidden in the fact that you store all the state on the client, and then update the state on the server using a background thread.
How can the server validate the data being posted? If someone hacked your application, they could modify the code so whenever they swing their sword (or whatever they do in your game), it is always a hit. Doing that in a single player game is not that big a deal, but doing that in an MMORPG can ruin the experience for everyone else. So the server should validate every update of data - or even better, the server should be in charge of every business rule. So when you swing your sword against an opponent, that should be a server call, and the server returns whether or not it is a hit, and how many hit points the opponent lost.
What about interaction with other players (since you say it is an MMORP, there will be interaction with other players)? Since you say that you update the server, and get updates in a background thread, interaction will be sluggish. When you communicate with another character you have first wait for you background thread to sync data, but you also have to wait on the background thread of the other player to sync data.
Looks nice. But what is the client-side made of ? Web ? Can you use threading to synchronize both DB ? I should make the game in that way that it interacts immediately with the local DB, and let some background mechanism do the sync (something like a snapshot). This leads me to think about mysql replication. I think it is worth to be tried, but I never did. It also brings you answers to other questions. But what about the charge (how many customers are connected together) ?
http://dev.mysql.com/doc/refman/5.0/en/replication.html
Make your client issue commands to the server ("hit player"), and server send (relevant) events to client ("player was killed"). I wouldn't advice going with data synchronization. Server should be responsible for all important game decisions.

Resources