Hi User137, I've been developing a game for a year now after many previous years of learning about game engine design and experimentation in a multitude of areas.

Trying to keep all your gamestates identical across all clients according to the lowest ping is a bad move for anything other than the slowest paced turn based games. Pings could fluctuate, bandwidth limitations could mean that a given client has not updated before the next 'turn' etc.

At any point in time, the server and all the clients should be allowed to have a different state that's kept as close as possible to the server state. Tie breaker situations (who shot who first for example) are decided upon by the server according to it's internal gamestate.

The network library I designed for my game, the associated message manager and net-synchronized classes are now complete (add me on msn (phibermon att hotmail c o m) if you want to discuss anything in detail).

The setup allows for clients to connect to a running game at any point by keeping all the information that needs to be shared between clients and server (entity positions, any deformed level geometry etc) in a container that assigns each peice of data an ID.

when a client connects, the server communicates the gamestate by pushing all relevant ID's onto a queue which begins sending the data to the client. For each ID, the server gets the size of the data, sends it over along with the ID and a timestamp and then sends the data itself.

This allows for the gamestate to be reconstructed on the client side using the same ID's.

As the game is progressing for the other clients, messages are fired back and forth between the server as normal.

Any message that makes a change to the server gamestate is added onto the message queues for all other clients (if relevant), including the one that's currently connecting.

The queues are priority queues so critical things such as position can be bumped up and less critical things such as say, money in the bank can be sent when there's time.

Message invalidation comes into play at this stage, any ID that's already on the queue can be removed as it's not already sent, this helps out laggy clients struggling to keep up. I've optimized this process using a hash table so the entire queue doesn't need to be scanned each time a message is pushed.

Essentially everyones pumping messages around on queues, just the connecting player has to play catchup with it's queue until it's in sync, it's determined to be in sync when a predefined offset between the current messages being pumped becomes small enough to be concidered realtime. For my game FPS grade performance is not required so I concider the client in sync if the messages it's handling are less than 400ms old.

If the offset steadily increases, the client can assume that the transfer rate is not enough to sustain a realtime connection to that gamestate and disconnect with a message to that effect.

As stated, message invalidation and synchronization problems (that arise from different packet turn-around times of the various clients) are all sorted out on the server end (Except for some basic invalidation on the client when appropriate), the server is god, it's gamestate gets the final word. However this part of game net-code is challanging, dealing with temporal offsets between clients can be done in a multitude of ways, the quake 3 source code was released ages ago and I highly reccomend reading thru that.

Remember : The server is god. No two players have exactly the same gamestate at any moment in time, only an approximation based upon the last peice of information recieved. The tie breaker problems you've attempted to avoid must be handled for a game that works well over the internet with many clients.

I'm not sure if this is the best approach but it works well for me.

Sorry if this isn't too clear, I got no sleep last night due to the apparently newly wedded couple next door.