I made some pretty good progress today. I was able to get in about two hours between other activities to work on the server reconciliation code.
Thank goodness for source control! I keep all the game’s source code hosted at GitHub. Today I was able to go back and look at code I had written almost a year ago to help me today.
It was networking code that I had put in to improve network performance but had actually made the performance worse so I removed it. But it was very valuable to go back again and see what I had done at the time.
In order to get server reconciliation working the server has to tell each client the sequence number of the last command it processed. But I couldn’t remember off the top of my head how to identify the clients.
It turns out that Meteor exposes an onConnection method that you can pass a callback to. This callback gets invoked whenever the running Meteor server application accepts a new connection from a client. FYI, Meteor uses the SockJS library for Web Sockets.
So whenever a new client connection is created I add a new player object to a players array. This player object just stores the connection ID and last command sequence number for that player.
Every time the server receives a command from a player, it reads the sequence number for the command and updates the player’s object in the players array. Then when the game updates are broadcast to all the clients this player array is inserted into the game state.
Each client can then find their player object to reference the last command the server received from them. The client can then locally replay all the commands beyond what the server knows about. This ensures that commands don’t get erased on the client, which results in very jerky animation.
I need to finish the very last part of this where the client resubmits the commands that the server does not know about yet and then prune the old commands that the server already took into account.
I’m hoping to have a report out tomorrow of this being completed and resulting in a noticeable improvement in the playing experience.