Server-side technology to handle time-based games

Started by
4 comments, last by alnite 10 years, 7 months ago

I am thinking of writing a server-side app to support social gaming. You can identify one common feature in many social games and that is they utilize real-life time as part of the gameplay. For example, in FarmVille, you plant and water crops and after 8 real-life hours, you can harvest them. Some of these timing can be as long as 24 hours, some others are as short as 1 minute.

I want to try making a server that can handle this feature, and I have two options:

  1. Lazy Server / Active Client. You store the time when a task (i.e harvesting a crop) should be completed by in the database server. When a client loads up, it will get that time, and display the countdown timer from the client-side. When this timer elapses, client does a POST to the server indicating that this particular crop should progress to the next state. This moves all the processing power to the client side, and so server becomes dumb and only stores the time. This has some issues:
    1. Cheaters and Hacking. If someone figures out what data to send to the server, anyone will be able to cheat. This is very easy to do with wireshark and netstat.
    2. Activities are disabled when players are offline. There are games where that allow a player to interact with another player even when both players are offline. For example, in a game like Travian, a player can attack another player. Based on the distance of their villages and the unit types, the server calculates how long till the attack actually happens. Even when both players are offline, the attack is still happening. The accuracy of this game is down to seconds. This is not possible with this option.
  2. Server to continually keeps tabs of all the activities across all players, and update the timing accordingly. This seems to be the right thing to do. It prevents malformed requests from messing with the game, and it also allows certain activities to be executed even when players are offline. I don't have much experience dealing with server-side technologies, would cron do the job for this? Is cron effective in handling timing jobs from millions of players? If not, what would the be ideal program to handle this? Should I make my own app that continually update the database?
Advertisement

You can do all simulation on the server, yet not have to do processing unless a client is logged on.

Most FarmVille type games can be simulated in almost zero time.

Thus, you can remember when the server last saw the player.

When next a player asks for a status update, read the last state you saw, compare the current time to the time that was saved, and fast-forward the state to the new point.

In fact, you can build all of FarmVille as simple web requests.

The client would send any commands being performed as POSTs to the game state.

The client would ask for a status update (using GET) every so often, which would make the server calculate a new state.
The client can simulate time on its own, too, and only ask for an update when it knows something is supposed to have changed.
This is totally cheat proof, because if you ask for an update too often, the server will just notice that nothing has changed since the last time, and return the appropriate game state.
enum Bool { True, False, FileNotFound };

Thanks for the great response, hplus0603. I didn't think about fast-forwarding mechanism. That would make it easier for testing, too.

Just thinking out loud here: smile.png

What about in games like Travian? Consider the following the scenario. There are three players (P1, P2, P3). P1 is on vacation and is logged off all the time. P2 comes online, looks at P1's village, and decided to attack. It takes 4 hours for P2's army to arrive. P2 clicked on the attack button, thus initiating the attack, and logged off and went to sleep. P3 then came along, looked at P1's village, and also decided to attack. It takes 2 hours for P3's army to arrive. P3 also initiated the attack, and logged off.

So, the sequence looks like this

t0 - P2 decides to attack. Army will arrive at t4

t1 - P3 decides to attack. Army will arrive at t3

t2 - Nothing happens

t3 - P3 army arrived, damage is calculated.

t4 - P2 army arrived, damage is calculated (but this should already take the P3's attack into account).

It seems that this too can also be simulated.

So you would have the storage that represents the current state of the player, along with all the list of actions of what's going to happen in the future. And, whenever any player is interested in the state of that player, server will then process all the actions in the list according to their time, and apply the result as the current state of the player.

Would this cause synchronization issue since each player has its own timing frame? Imagine an inactive player that's never been checked. His time would be so behind of everyone else's.

If a tree falls in the forest and no one is around to hear it, does it make a noise?

If all the people interested in the combat is offline, you don't need to calculate the result of that combat until one of the involved players is online. In other words, you should avoid calculations until a player requests the result of the combat and you should use the fast-forward mechanism not only when the player is online, but also when another player who interacts with the player is online:

t0 - P2 decides to attack P1, army will arrive at t5.
t1 - P3 decides to attack P1, army will arrive at t4.
t2 - P4 decides to attack P1, army will arrive at t6.
t3 - Nothing happens
t4 - P3 army should arrive and attack, but since P1 and P3 are offline, we don't need to calculate damage at this moment.
t5 - P2 army should arrive and attack, but since P1 and P2 are offline, we don't need to calculate damage at this moment.
t6 - P4 army should arrive and attack, but since P1 and P4 are offline, we don't need to calculate damage at this moment.

... Much Later ...

P2 connects and the server realizes he attacked P1 at t5, so the server must resolve (using the fast-forward mechanism) not only that combat, but also all the prior actions which involve one of those players before calculating the result of that combat:

- The server calculates the results of the combat between P3 and P1 at t4.
- The server calculates the results of the combat between P2 and P1 at t5.
- The server doesn't need to calculate the results of the combat between P4 and P1 because both of them are offline and this combat happened after the combat between P2 and P1.

Would this cause synchronization issue since each player has its own timing frame?


In this model, you should always use the time stamps at the server when the command is received. This will avoid cheating, and also make it so that there is no timing skew.

You can build this system internally as a "update-on-demand" system. When some other component asks for "the current state of object X" then that object will simulate forward to the current time. If that object has dependencies on other objects, it will ask those objects for their state, which may cause them to simulate forward as well.

Implementing this in a way that reduces the object-to-object dependencies (this may require careful game design choices) as well as optimizes the "slurpy" object updating process requires some careful planning. It's not something you can reasonably whip up in an afternoon and expect to stand the test of time. (That being said, you can probably whip something up in an afternoon to get started with :-)
enum Bool { True, False, FileNotFound };

Ok. Very cool :D. Thanks for the help, guys!

This topic is closed to new replies.

Advertisement