Network Game Programming - Issue 07 - I bent my Wookie...
by Dan Royer (25 August 1999)



Return to The Archives
Introduction


Right, this week's topics include synchronization between client(s) and server; optimizations, tips and pitfalls to avoid; links to sites that can provide you with some more information on network and network game programming.


Synchronization


Synchronization is extremely important because it makes sure that what you are seeing on your screen is the same thing as everybody else which means that if you shoot someone with a missile they're actually there to get hit. At first this problem seems really easy to solve: make the server keep a copy of everything going on in the game and have the server update players as necessary. This also prevents players from most forms of cheating, depending on how you design your messages (more on that later).

As I said, at first the problem seems pretty straightforward. Here is where lag becomes your mortal enemy. Consider this picture:



At time t1 the local client (you) start to move forward. The message is sent through the network and a little latter (at time t2) it arrives at the server. At this point the server copy starts moving forward. Unfortunately it is already behind the actual position because it was late getting the message and always will be. Now the server broadcasts to all clients that you have started moving forward. Every client, including you, receives the message. Effect: all clients are now behind the SERVER. Worse still, your ship tried to compensate for the difference between the server message and your current state by "jumping" your ship to where the server said it should be. So what happens is you see everyone else's ships at a slightly old position, plus your player's movements are jerky and confusing. The solution comes in two parts.


Prediction


We know where the ship is at t0. We know that any message we send to the server won't arrive until t1. So what if we take the data from t0 and predict where eevrything will be at t1 and draw that to the screen? Now the user sees almost exactly what will be happening on the server when the next client messages get there, instead of always responding a little too late.

The second part of the solution is to figure out how long the t1-t0 delay really is. You could set up a ping system to hit the server every snapshot or two but I have a better idea. When the player successfully logs in the server should send it the current snapshot ID number. When the client sends out data to the server it should be earmarked "intended for snapshot S(n+i)" and when the server sends out snapshots it should send "This is snapshot n, the last data I got from you was intended for snapshot x". i here is equal to (int)( ( t1 - t0 ) / ( milliseconds / snapshot ) ) (So if you were sending out 20 snapshots a second you would have (int)( ( t1 - t0 ) / 50 ). x is some previous n+i. Now given that we know when we sent message intended for n+i and we know what time we got an acknowledgement from server that gives us the ping value! Average that over a could of snapshots and things should run pretty smoothly.

(I guarantee you that a TCP/IP system will have greater t1-t0 delays than a UDP system.)


Extrapolation


Now we're only sending out snapshots every couple of milliseconds, so in order to keep things moving slowly the client and server also have to make a guess at what goes on between messages. Given that you know what everybody is doing at a particular instant in time and what they are doing to cause change at that instant you can extrapolate where they will be in the next little while. This is close to but not quite the same as prediction because can go beyond time t1 and sometimes has to in order to keep the game running smoothly. If you watch Quake III's lag-o-meter there are blue and yellow lines being updated every frame. the blue lines mean extrapolation is occuring at less than t1 (which is fairly safe) and the yellow lines mean extrapolation is going beyond t1 (which becomes less and less acurate).


TCP vs. UDP (continued)


TCP is a simple and effective way of transmitting data. For making sure that your client and server can talk to each other it is very good. However, it carries with it a lot of overhead and extra network lag so once you feel you are ready you should make the jump to UDP. The big problems you will face with UDP include:
  • You won't have an individual socket for each client. In fact FD_ACCEPT will never be called. There won't be any clear notice that the client now sending you data wants to join the game unless you make the client say as much.
  • Given that clients don't need to open a unique socket in order to transmit data there is the very real possibility that a client who is not logged into the game will start sending all kinds of garbage to your server in some kind of attack. It becomes much more difficult to stop them at this point.
  • Likewise, you won't have a clear disconnect/leave game message unless you write one yourself.
  • Some data may not reach the other machine, so you may have to send important stuff many times.
  • Some data may arrive in the wrong order. Imagine that you got snapshot 5 before snapshot 4. Snapshot 4 would have to be suppressed (rejected).
  • While switching to UDP will get you a signifigant speed boost, there are a few more tricks you can try.


    Optimizations / Tips


  • Reduce the number of messages. Reduce the ammount of data in those messsages. Smaller messages = less data transmitted = more players per server and/or smoother gameplay.
  • Players could send a special extra tiny message that simply means "I have made no changes to what I am doing so keep going," often refered to as a keep alive.
  • Try giving messages a priority flag. If lag starts to grow, don't send some of the lower priority messages. Since this is UDP you can also dictate that some messages should take effect in order and some should not. For example, chat messages should appear in the dialog in order. Two or more simultaneous death/collision messages do not.
  • Weapons' fire: Do NOT spawn a missile/laser/etc on the client machine until the server replies with an acknowledgement. Those of you who HPBs that can't use the Quake rail-gun now know why.
  • Player motion: Players don't need to keep sending updates of how they're moving, just the changes they make to how they're moving. Also, they should only send very abstract info such as "I am moving forward" but do not say how FAST they are moving forward or else someone will probably find a way to superboost their speed. If you want the player to have limited control over velocity then have the client send "I want to increase my speed" and have the server reply "your speed is now x".
  • It's much harder to predict when things are moving on curved paths then when they move in a straight line. The same is true for objects that don't have a fixed velocity.


  • Things not covered by this article


  • Slot servers - manages the login process for the game server
  • Master servers - maintains a list of all games servers in the world
  • UDP communications in detail


  • Links to other resources


    http://www.parsec.org/netdocs/index.html
    www.parsec.org has put together an excellent little paper on how they designed their network API. It even covers slot servers and master servers, so if you don't find what you're looking for in this article, it'll definitely be there.

    http://www.sockets.com
    Lots of helpful material on windows sockets programming


    Source Code


    Yes, as promised, there is source code. You may have seen the game displayed as a screenshot of the day. However, I'm not releasing it until I've cleaned it up and add more comments/error catching routines. Any differences between what I said here and what I do in the code will be clearly spelled out in the accompanying readme.txt

    Download network.zip (163k)

    This is the end
    my only friends, the end...


    Article Series:
  • Network Game Programming - Issue 01 - Things that make you go "hmm..."
  • Network Game Programming - Issue 02 - cComm one, cComm all
  • Network Game Programming - Issue 03 - cClient. cClient run
  • Network Game Programming - Issue 04 - cServer? I barely know her!
  • Network Game Programming - Issue 05 - Watch your Language
  • Network Game Programming - Issue 06 - Talk about things you like to do...
  • Network Game Programming - Issue 07 - I bent my Wookie...
  •  

    Copyright 1999-2008 (C) FLIPCODE.COM and/or the original content author(s). All rights reserved.
    Please read our Terms, Conditions, and Privacy information.