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.