I have been working on a client-server architecture to enable LAN play for my open source game, Aigilas. In its current state, players stay synced in all running instances of the game but enemies and particle animations are out of sync.
What I cannot understand is how players are the only entities staying synced. I run the clients in lockstep, requiring the latest input states from each client to be announced before taking a turn in the game world. When the game world is built, I seed the random number generator (RNG) with a seed determined by the server. This seed appears to affect the RNG as expected; each client has the same procedurally generated game world and players start in all clients at the appropriate locations.
Particle animations and AI are chosen based on player positions and the RNG. How is it possible for them to become out of sync when the players are always in sync? To the best of my observations of both the game screen and the logs, players never go out of sync with respect to their positions. That leads me to believe that the RNG in C# is not acting deterministically across all clients.
The basic workflow for the game's client<->server communications are as follows:
- Server starts
- Client starts and gets RNG seed from server
- Client tells server when keys are pressed/depressed by a user
- Once a game has started, server tells all clients the current state of each player's keyboards
- Once an update has been received from the server, one turn of the game is simulated
- Repeat step 4
If there are any specific questions targeting a specific portion of the code, then I am happy link to the appropriate page on GitHub.