Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

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:

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:

  1. 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.
  2. 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.
share|improve this question
2  
I would grab an evaluation of MsSQL and fiddle with it - I am not sure what MySQL provides in terms of replication but MsSQL 2008 R2 gives you a LOAD of replication (5-6) techniques to choose from. Just a thought, not hating on MySQL or anything, but Microsoft is really good at clustering. –  Jonathan Dickinson Oct 5 '11 at 15:41
1  
@Jonathan Dickinson: There is MySQL Cluster :P –  Coyote Oct 5 '11 at 16:49
1  
Also look at PostgreSQL -- version 9 has replication technology, PostgreSQL has an excellent long-standing reputation for handling heavy loads really well, many of the developers seem to be optimization nuts, and best of all it's open source and completely free for all uses (including commercial). –  Randolf Richardson Oct 5 '11 at 18:07
    
the thing is that we cannot use same database at client and server side. I think most suitable DB for client would be SQLite so that it does not consume a lot of resources as app would be running on mobile devices. While the person working on server part only knows MySQL so that's why we have opted for it. Also I have heard that most MMO games use MySQL database. –  umair Oct 5 '11 at 18:39
1  
@umair: Client side can be SQLite (on the iPhone for instance it's already available). But you can chose to simply store just the relevant data you need in a file (What SQLite does anyway) and not bother with the client side DB at all kind of like you would do with a Javascript app. –  Coyote Oct 5 '11 at 19:38
show 1 more comment

2 Answers

up vote 13 down vote accepted

If it's not a "real time" game in the sense that players don't need to see the immediate result of another player's actions on a game scene then you should be fine with HTTP requests. But Keep in mind the overhead of HTTP.

That said using HTTP will not save you from designing your communication protocol with care. But if you are in charge of both the server and the client side you are lucky as you can adjust the protocol when you need it.

To synchronize between the Master DB and the Client DB you can use whatever transport protocol you have access to, HTTP or others. The important part is the logics behind the sync. For a straightforward approach, simply pool from the server all the latest changes needed by the client since the last timestamp in the client DB. Apply It to the client DB and go with that. If you have more changes on client side upload it if it's still relevant, otherwise discard.

Some games don't even use a local DB, they simply keep track of the status by pooling the relevant info from the server when needed.

If loosing local events is not acceptable then yes, you should have local storage and save to that storage as often as possible. You can try doing that before each network send.

To check for active users we used to ping with HTTP every 20 seconds on a successful game... This value went up immediately as the servers have been overloaded :( The server team did not think about success. So I would tell you to add a message or some sort of special header in your communication protocol which will let you reconfigure your clients (for ping frequency load balancing and other communication related values).

Client side validations are enough if you don't mind cheaters, hackers and other automated scripts attacking your game. The server can simply refuse your action and send an error message with some details. You handle that error message by either rolling back the local changes or by not applying them to your local storage if you can wait until the server responds to actually save the changes.

We used the command pattern in our game to allow for simple and efficient rollback of failed or invalid user actions. Commands were played locally sent to the peers or translated to the server message and then applied on the peers or checked on the server, in case of a problem the commands were unplayed and the game scene went back to the initial state with a notification.

Using HTTP is not a bad idea as, later, it will allow you to integrate very easily with Flash or HTML5 clients, it's flexible, you can use any type of server scripting language and with basic load balancing techniques add more servers later without much effort to scale your backend.

You have a lot to do but it's a fun job... So enjoy!

share|improve this answer
3  
+1 for 'HTML probably being good enough' because it probably is :). –  Jonathan Dickinson Oct 5 '11 at 15:36
1  
@Coyote: thanks for taking out time and providing such a detailed answer. Really like your HTTP idea for providing support to other clients. –  umair Oct 5 '11 at 18:27
1  
May the force be with you :) –  Coyote Oct 5 '11 at 19:34
add comment

What would be the best way of synchronizing server and client databases?

The easiest way is to implement the database as a single file you can transfer. If you get into trying to compare differences between databases then that's a world of pain, and I speak from experience.

Note that your server must not trust decisions that the client makes based on that local database, because the client can change it. It must exist purely for presentational detail.

Should an event get saved to local DB before updating it to server?

No. What if the server decides the event never happened? The client shouldn't be making decisions about events anyway, because the client can't be trusted.

I notice you are also talking about the local DB in two ways: one, for "things that do not change frequently" and two, for events. These should not really be in the same database, for the reasons above - you don't want to start trying to merge or diff individual data rows in databases. For example, referential integrity becomes a problem when a client has a reference to an item which you decide to remove from the server. Or if the client changes a row and the server changes a row, which change takes precedence, and why?

Will simple HTTP requests serve the purpose of synchronization?

Yes, providing they're fairly infrequent or small. HTTP is not bandwidth-efficient so bear that in mind.

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).

If you use a transient protocol like HTTP, then that is a reasonable idea. When the server receives a message from a client, you can update the 'last seen' time for that client.

Are client side validations enough? If not, how to revert an action if server does not validate something?

No, not at all. The client is in the hands of the enemy. How to revert an action depends entirely on what you consider an action to be and what effects it might have. The easiest route is to not implement the action at all until the server responds to allow it. A slightly trickier route is to ensure every action has a rollback capability to undo the action, and cache all unacknowledged actions on the client. When the server acknowledges them, delete them from the cache. If an action is refused, rollback each action in reverse order up to and including the refused one.

share|improve this answer
    
You nailed it. You are right about syncing DBs +1 The client should never change the DB on its own... Just call functions that run on the server and update the DB using the game's logics, then retrieve the results. –  Coyote Oct 6 '11 at 13:08
    
@Kylotan: thanks for pointing out flows in my model –  umair Oct 6 '11 at 13:53
    
@Kylotan:"The easiest way is to implement the database as a single file you can transfer. If you get into trying to compare differences between databases then that's a world of pain, and I speak from experience." this means that all data is downloaded each time application is launched. There are things that wont be changing very frequently and so it might not be acceptable to download them each time. This will also increase launch time of app considerably. Any thoughts? –  umair Oct 6 '11 at 17:21
    
If the data is small, then the problem goes away. I'd be surprised if your centralised database of static data was very large. But anyway, if you split the static data up into smaller parts, then you only need to send the ones that have changed since last time. Sure, you -can- do this on a per-row basis, if you're willing to keep a modification time in each row. Generally I prefer to have static data outside of the relational DB, to allow me to overwrite it easily. –  Kylotan Oct 6 '11 at 18:37
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.