[Dev Blog] Server Tick Rates

In a previous post I wrote about the naive authoritative server solution I implemented for my fledgling multiplayer game. I have the server set up so that all incoming commands (requests, really) from the client are processed and responded to in real-time. While this method works for the small number of simultaneously connected clients I can test at any given time, it doesn’t scale well for larger numbers of clients. For instance, during player movement the client sends commands repeatedly while the arrow keys are held down. With a handful of connected clients the server can easily respond to every client as their commands are accepted, but as the number of clients increases, the amount of data being sent back and forth can completely saturate the connection. The solution is to limit the rate at which the server responds to commands.

Most servers of multiplayer games have what is called a tick rate – the rate at which a server sends updates to a connected client. The faster the tick rate, the more updates a client receives and as a result the client’s representation of the game state is closer to the state on the server. The type of game you’re making generally dictates the tick rate. Fast-paced action games that require fast reflexes and precision like first person shooters will require a higher tick rate so the client can react faster to changes in state. Slower-paced games like role playing games can get away with a lower tick rate, especially if combat is turn-based. For my game, since I’m using Node.js, I can implement the tick rate using the setInterval method. It will likely look something like:

In addition to updating clients, the server will have a separate rate for simulating the game world. Generally the game world will be simulated and updated at a faster rate than client updates. If I’m trying to target a frame rate of 60fps, the server has to complete its processing per update call in roughly 16 milliseconds (16 milliseconds per frame means 16 * 60 = 960 milliseconds to process 60 frames). For the simulation update I’ll have a similar set up as above but with an interval of 16.

[Dev Blog] Client Authoritative Vs. Server Authoritative

It turns out that writing a server that can handle multiple clients and keep them all synchronized is, well, extremely difficult. But I knew this going in. The number one piece of advice given to novices who want to get into game development is

DON’T MAKE AN RPG

and the second piece of advice is

MAKE A SINGLE PLAYER GAME

So what am I trying to do? Make a multiplayer RPG of course!

After finishing the Let’s Build An MMO series I’ve been left wanting to do more. Currently the game is client authoritative. This means that the client (the game running on a player’s machine) has the final say in all game interactions. If the player presses the left arrow key the client figures out where the player should be (likely 1 unit to the left) and sends this value over to the server. The server accepts this value, updates the database with the player’s new location, and the game continues. The upside to this is that clients experience very little lag. With all game logic handled by the client, players instantly see a response to their actions. The downside to this is that clients are notoriously easy to hack. By intercepting the communication between client and server a hacker could easily spoof messages and send data that the game logic would otherwise reject. A hack3r could teleport themselves to areas of the maps not meant to be accessed by players, wreaking havoc on my insignificant game.

A naive fix, and the one that I’ve currently implemented, is to make the server authoritative. This means that the server has the final say in where the client should be and what the client is allowed to do. When the player presses the left arrow, the client now sends a request to move to the left. The server receives the request, figures out if the client can indeed move to the left (or if there’s something in the way) and sends the client back the new position. This extends for all interactions a player may have with their environment. The client essentially turns into a “dumb terminal”, simply sending requests to the server and awaiting a response. The upside to this approach is that our enterprising h4ck3r can no longer mess with my game (yay!). The downside is that clients have to wait for a full round-trip before updating the game state. With latency always being an issue in online games, players are left with the uncomfortable experience of feeling a slight delay between indicating intent and receiving a response.

A proper solution involves a mix of the two. The server still has the final say in terms of game state, but the client can assume the player is good and can update the game state before receiving a response. In the case that the player is not good (or there was an issue during transmission), the client can synchronize its current state with the server’s. This is a slightly more complicated solution and requires more research before I can implement it into my game.