Comments welcome.
Multiplayer is something that has always interested me.
For those of you who understand at least a little about multiplayer, you will understand the advantages and limitations of a client - side game state. It is this which my networking components / addon utilises. It allows for anyone to create a mutliplayer game but it is limited in the sense that it can require complicated logic in order to allow a dynamic game environment, such as that of a First Person Shooter. For this reason, the multiplayer system in Blender that I have created is nearing completion. This is, in the sense that to give it more features would be defunct because by that point you ought to code your own game dynamic.
So here shall lie my development log for an optimised server-side multiplayer system, for use in both Necrosis, (various other projects whom i am helping) and Matter.
Authoritative Server Game Loop
An authoritative server - client game loop has to consider two factors.
- Firstly, the server must only receive events from each client. Events describes keyboard and mouse inputs - the user’s interaction with the game. By utilising events, and not game-dependant data, the server can ensure an unmodified game state (within limitations), because it modifies the game state itself.
- The client depends upon the server for the game state. However, if the connection latency is 100ms, it will take 200 m/s + calculation time for the client to receive the newest game state after sending user events. This means that the client will naturally appear to lag. To circumvent this there are a variety of lag compensation techniques.
You can see in this chart that the server will process the game state every frame. It is likely in my case that parts of the game state, such as physics can simply be simulated within blender, for otherwise it just incurs processing time using Python, which is less than likely to be efficient. As the server updates the game state, it will first check for user input. If this is the case, it will update the events stored on the user’s game state.
The second game-state update will affect the entire game. This update would run every frame, and update the game including the changes incurred through user input. This would process event driven updates as well as server-side AI.
Authoritative Server Responsibility Model
Within an authoritative server - client model, there are certain elements to the game that belong purely to the server (they are only calculated on the server), whilst some are only calculated on the client.
- Server Side Data
Typically server-side calculation involves critical data, which must not differ between clients, and the server wishes to prevent from cheating by spoofing. - Client Side Data
Client side data can involve trivial or insignificant details, such as particles, bullet trails, which are not required to be exact for the game to continue - they don’t modify the game dynamic.
Lag Compensation Techniques
Due to the inherent nature of the authoritative server architecture, the client must be able to predict or continue the previous game state for a limited period into the future. This is due to the time difference (or latency) of the connection between Client -> Server -> Client.
Here is a visualisation of this delay:
-
Client-side Extrapolation
As aforementioned, Client Side Prediction is key to creating the illusion of a low latency connection.
It allows the client to predict a future game state based upon previous game states - using extrapolation.
Client Side Extrapolation is useful as it hides the update period between a client sending data, and receiving data for the game state. It can only be used in a limited scope, because as inputs are unreliable from the clients, predictions are rarely accurate.
Due to this inaccuracy of prediction, the game state on the server and on the client will likely differ. Therefore, to avoid jerk-like transitions between predicted and server game state, the client will determine how close the server game state is to the client prediction, and use it within an error margin - but it will interpolate the client’s prediction towards the server’s game state, to avoid the two states becoming completely desynchronized.
This is used for entities that aren’t controlled by the client - such as NPCs, and other players. This extrapolation often uses linear interpolation - taking the change in a value, dividing by the time taken for the change to occur, which returns a delta, and then extrapolating that delta multiplying it by the elapsed time since the last packet, and adding to the data of the last packet:
-
Input Prediciton
As mentioned in Valve’s Article, Input prediction allows the client to simulate (predict) the effects of its inputs before the server confirms their legitimacy. The design of this model means that if a client were to press a key, for example a movement key, they wouldn’t see a response on screen until the server received the input, processed it and replied. This could take a few hundred milliseconds, which to the player is unnerving and causes issues with playing. So, predicting the output of a key before it is confirmed, we can reduce the apparent lack of response.
Because we want to make sure that little damage to the game state is done if a client is cheating, we limit the input prediction to that of the local player’s attributes - movement and potentially shooting.
To predict a gamestate is relatively easy, though it requires moving away from a totally dumb client, and therefore moves away from a centralised logic-based approach. After informing the server of the client’s input events, the client will predict the outcome of the input based upon the client’s current GameState. Typically, this should be acceptable if the client’s game state is relatively new. For example, a doorway is unlikely to move during the course of a game, so a client will most likely be able to move through it, however an enemy with a weapon could shoot the client before it is aware of it, and thus the input events are likely to be rendered ‘invalid’.
When the client receives a game state, it will already be old due to the latency between the server and client. The input events would also be old relative to the server, but the server is able to calculate the inputs based upon the gamestate at the time of transmission - looking back into previous gamestates at the same time stamp as the input packet (assuming the server and client times are synchronised).
In order to determine whether a prediction should be corrected, the client will compare the outcome of the prediction with the server game state update. In this event, one can use time stamps, or input ids - stamp the events sent to the server with an id, which the server appends to the new game state packet. The client checks to see whether the predicted outcome for input X is equal to the server state for input X. This technique would allow for stacking of input predictions - where by two different inputs are sent to the server, and the client predicts upon each valid one, e.g:
This is used for the local player.
- Rewind Time
This method I believe is used by Valve’s Source engine. Essentially it moves players and other objects subject to hit-detection back to the point where they were at the time the player issued the command (such as shoot) according to the server game state). Because the Client and Server Game States should be very similar, the server will position the players at the positions that they were at the time of the event for the client, and they should match similar states to that of what the client saw them to be.
However using this method for the same example; shooting, client and server hit-boxes won’t exactly match because of small precision errors in time measurement. Even a small difference of a few milliseconds can cause an error of several inches (in game) for fast-moving objects.
But it reduces the effect of latency; as a client’s packet is on its way through the network, the server continues to simulate the world, and the target might have moved to a different position, which may not register a hit which the client saw on its screen.
Here is a video that documents the advantages and disadvantages