Client-Server Game Logic Distribution

Started by
6 comments, last by hplus0603 12 years ago
In a First Person Shooter one can get away with doing all decision making on the server, and simply updating objects on the client. But take a game like Diablo 2(not an MMO) where there is a great variety of attacks, damage, spells etc, what all does the server do in this case? Is the client a dumb terminal that is updating objects and running animations, or is it the other way around where the client is doing all the processing(hit detection, damage to enemies etc.) and sending only 'necessary' updates to the server? Taking this game as an example, could you tell me how you'd set it up for a hack and slash game?

I have no experience in this, but I'm trying to set up a client-server architecture where, preferably the game runs mostly on the client. I know this question is quite abstract, but if you could just point me in the right direction, that'd be great!
Advertisement
The problem with simulating stuff on the client is that the client now has a role in determining the outcome. The client also has an incentive to influence this outcome in it's favour, i.e. to cheat. So far, no-one has been able to solve the problem of preventing modified clients (or proxies) from interacting with their servers, so you'll have to do some cutting edge research or accept that potentially malicious (or even just buggy) clients can be used.

Almost every game allows some scope for cheating. Generally, in order to simulate the game without excessive latency, the game client is almost always aware of "additional information" that the player shouldn't have. A simple example is that in FPS games, the client must be aware of the rough position of combatants, even if they are out of sight, in order to play sounds for them. A modified game client could render this combatant, making it considerably easier for the player to locate and kill them (a wall hack, for example).

Given that almost no game can perfectly prevent all possible types of cheating, the question becomes: how much cheating are you prepared to allow? When I say "allow", I just mean that the game itself cannot prevent the cheating. You can provide additional tools to allow other players deal with suspicious activity, such as a vote kick system.

I assume you want to minimise cheating. The simplest solution is to do all decisions on the server.

Let us go back to the start. I infer from your post that you believe such a game will be complex enough* that you must have the clients do some of the work. I think that this is an untested assertion. I think your first step should be to outline the processing, bandwidth and latency requirements of a purely authoritative server. If this exceeds some reasonable limit, only then should you think about how to offload decisions to the client.

By understanding the nature of the server's workload and bandwidth/latency, you can identify the areas that you can offload that will have the biggest impact on performance while minimising the scope for cheating.

You could take other approaches too. A lockstep simulation might be possible. This would more or less prevent cheating, because the cheater's simulation will get out sync. The bandwidth and latency requirements are quite different here.

You could have a peer to peer game that isn't in lockstep. The problems that arise here, cheating aside, is determining which client is authorised to determine the outcome of an action, or whether you can merge two slightly inconsistent views on the game somehow.

[size=2]* I haven't much Diablo, and I have never played it online
If NetHack could run on a DOS machine with 1 MB of RAM, I think you could run the game rules for Diablo on a server without too much sweat.


do some cutting edge research
[/quote]

rip-off is being too subtle here. The problem of trusted client computing is something that the best researchers in the world are looking into, and so far, it looks a lot like you need special hardware support to do it. The end result of any game programmer thinking he/she an out-smart the hackers, is either that the game is too boring so nobody will want to hack it, or a game programmer who ends up learning humility, or quit in frustration.

The best anti-hack solutions are purely social or gameplay-based, unless you can control the hardware platform.
enum Bool { True, False, FileNotFound };
What you're saying is true, one should start by throwing everything to the server and then bringing stuff back to the client if required (bandwidth etc.). Hacking of course is a big issue when we're doing a multiplayer game, but the problem I'm having here is a little different.

Let's say during the process of siphoning off work to the client, I decided to give control to clients, of objects that can be affected by both parties. The behavior of those objects (for eg. enemies) is a function of the characters of both the players. Synchronization is possible but only if these objects were governed by the server, or only one of the clients. Their behavior is deterministic, but we still can't be too sure that both the clients will kill the enemy at the same time, if at all. I took Diablo as an example because it closely resembles the kind of game I'm trying to set up here, but I have absolutely no idea whatsoever as to how its being done. When there is so much a character can do, where do objects reside, where do the characters' stats live, are two separate copies of the same data handled on both the server and the client, is the client only sending the damage done to each enemy, are effects of a spell transmitted to the server after they affect an enemy, or is hit detection done on the server and then broadcasted to all the clients etc. etc.?

I suppose my question is too broad, sorry.
If you want a predictable outcome, there are two models that work:
1) server-authoritative -- either a hosted server, or electing one of the clients to also be the server
2) lock-step -- everyone sends commands to everyone else for each simulation tick, and the simulation is only ticked once the command list from each other player is received ("i have no commands for this tick" is a frequently occurring command list)

1) is tricky, because if you send state dumps from the server, you will use too much bandwidth, so you have to come up with some way of reducing that, using dead reckoning, or baselining with input deltas, or something similar
2) is tricky, because you have to control for all possible sources of variation -- floating point rounding modes, order of command execution, random number generators, etc.

There's also the question of whether you're OK with actually having a delay between command given, and command executed, or whether you need to (speculatively) show things right away on the local client, and if so, how you correct when the local client "guesses" wrong because it has delayed information.
enum Bool { True, False, FileNotFound };
Hypothetical situation, let's say that hacking is not that big an issue (No pub servers, coop only, closed platform). The game is more like a shooter rather than an MMO, the collision detection and damage to enemies is quite a physical affair (speed,acceleration etc.) rather than a pre-calculated (lock-on target) attack mechanism. Would you still suggest a server-knows-all set up?

Its really bugging me here because its really tempting to have the clients do all the work because they're the ones that have to have all the information at all times no matter what. If I try to go for a server authoritative approach, I always end up having two copies of all the data being managed, sometimes even generated (item infos/effects/powers) on both the client and the server! Isn't this supposed to be bad design? Or is this the way to go?
That's a pretty interesting thread here.

I have a school project, where we need to create a basic server-client game. My project is a bit more complex than it should be - I'm making a multi-player space shooter.
In this case it is easier to solve the problem of hacking because the space ships do not collide with almost nothing, expect maybe against other ships but I will try to solve this later. Current logic consists of a simple movement formula, that will calculate the new position every time the getPosXY method is called or when the thrust or speed of the ship will change. This logic applies to both - the client and the server. Only the server is the god, the player(slave) cannot change any parameters without the permission of the server. When the player clicks any movement buttons, it will request the server to update his player parameter values and send a message back with the new parameters. The player will send a message only if the key has just been pressed and when it will be released. It will take time to react to these events because of the connection speed between the client and the server.
Currently I got 3 different login frames and 8 different game frames. The average bandwidth used by this game(client) is less than 1 K bit/s even when I click the movement buttons like a madman.
Maybe I will release my source code after 3-5 weeks and post on these forums as an example about how to handle networking. I will add a lot of candy to it.
I forgot to say what I am using - Java with lwjgl, slick-utils and netty libraries. I love that asynchronous netty nio library :). Yes, it will run on all popular OS-s.

About the problem that the client has all the data and you end up having 2 copies - on the server and the clients. Yes that's a big problem that I try to avoid in my project - I will make my client software as much slave as possible. I don't care what data the client has, I just send the data, that the server has and the client must have the same data. So there is only 1 copy - only one original and others(that the clients have) are aged piles of corrupted data. The client only has the right to ask what it wants the server to do and the server decides.
I remember that WoW had some issues with players speed hacking. So you can make a conclusion about that - the high skilled WoW programmers even didn't figure out a proper way to solve this problem. Some other games had these problems also, including Counter Strike. One more thing about Counter Strike: when you shoot, you cannot see your bullet, it will just calculate the end spot of the bullet. So they avoided the concurrency and real-time logic problems of simulating bullets.

they're the ones that have to have all the information at all times no matter what


Each client has different information at different times. You may have up-to-date information about your own actions, but you have way out-of-date information about my actions, and vice versa. The server is the only one that has "equal time" information from all participants.


two copies of all the data being managed ... Isn't this supposed to be bad design?
[/quote]

You need that information everywhere, because you present it everywhere. When it comes to "bad design," I imagine one of two cases of bad design:

1) The same information kept in more than one place within the same process. This is bad, because you have to keep them both in sync, and it's cheaper to just keep the data in one place most of the time.
2) More than one process thinks that they are the "authority" for the same piece of data. This is bad, because there is latency between processes, and you will end up with different authorities making conflicting decisions.

Replicating the same data between authority and viewers is not bad design in itself, because there are many processes that all need the data.
enum Bool { True, False, FileNotFound };

This topic is closed to new replies.

Advertisement