IOGrid — A framework for building scalable IO Games

Jonathan Gros-Dubois
HackerNoon.com
4 min readJan 6, 2017

--

Soon after publishing a basic demo which showed how to build multi-player IO games using SocketCluster and Phaser, I was approached by the Percepts and Concepts Laboratory at Indiana University to turn that demo into a more complete game engine/framework which they could use as part of their research.

They agreed to sponsor this work and to have it released publicly under an open source license (MIT). The result is IOGrid.

Currently, CPU usage is an important factor to consider when building desktop-based games. Most high-end games employ multi-threading strategies to make use of all available CPU cores on a machine — A typical threading strategy might involve doing AI/NPC logic in one thread, player logic in another, audio in another, etc… Separating parallel tasks into different threads like this is a good way to make use of multiple cores on a CPU.

Unlike desktop games however, multiplayer ‘IO games’ have both a client-side and a server-side component — So when it comes to making use of multiple CPU cores, the back end has its own set of challenges.

To overcome these challenges, I investigated a number of possible solutions; one of these was to try to make the server-side stateless by offloading some of the processing tasks to front end clients. One obstacle with this approach is that, when it comes to multi-player games (particularly web-based games), you cannot trust clients to provide accurate information about themselves or to accurately report their interactions with other players (particularly when those interactions result in a negative outcome for the reporting player) — There are many ways to cheat such a system; especially in the browser where any player can easily open-up the developer console and start sending fake data to the server.

One way to circumvent this issue it to sign all outgoing states with a timestamp and checksum. That way, if a client claims that a particular interaction/outcome took place, the server (without any prior knowledge about the game state) can verify the claims by looking at the checksums and timestamps of the relevant states. With this approach, a stateless server process can validate the location of various objects within the game just by verifying signatures and evaluating whether or not the claims are valid.

This approach of signing everything with a checksum might work for some types of state within a game but it adds a lot of complexity on both the client and the server-side. Furthermore, the server side claim-verification step might vary considerably depending on which type of item/claim needs to be verified — This means that it is difficult to generalize this type of logic into a simple game engine.

Another drawback with this approach is the added overhead of having checksums on every single state inside every packet sent to and from clients — In a real-time multi-player game, this typically happens many times per second.

In the end, the approach which I chose for IOGrid was to make the server fully authoritative and to shard the game across multiple CPU cores based on the location of each player within a grid of cells. The idea is that, if you have a grid with 2 columns and 2 rows, then you would end up using 4 CPU cores — One for each cell in the game. This type of logic is easy to generalize into a simple framework. To achieve this, I introduced the concept of a ‘Cell Controller’; it’s basically just an entry point to your code which gets called once-per-frame and which allows you to perform processing on the content a single arbitrary cell within your world grid— The secret sauce behind this approach is that the same logic which can be applied to one cell can be reused in a generic way and applied to every cell within a game grid.

The main difficulty with the grid/cell approach is that users have to be able to seamlessly move between cells within the game world. With SocketCluster pub/sub channels, you can easily allow cells to share game states with each other. To make the transition seamless, each cell has transition zones near its edges (with configurable length); when a player state moves into such a zone, the closest neighbouring cell(s) will be able to see them (but these states will be marked with an ‘external’ flag and are read-only within non-owner cells).

In general, sharing state between processes is bad for scalability, but in this case, because we are only sharing transitioning states and only doing so among a fixed/limited number of neighbouring cells, the cost is just a constant.

Based on simple initial tests (using bots), it appears that IOGrid is able to scale linearly across CPU cores.

If you would like to try it out for yourself. Check out the instructions on the GitHub repo here: https://github.com/SocketCluster/iogrid

Feel free to mess with the values inside config.js for some interesting results :)

Hacker Noon is how hackers start their afternoons. We’re a part of the @AMIfamily. We are now accepting submissions and happy to discuss advertising &sponsorship opportunities.

To learn more, read our about page, like/message us on Facebook, or simply, tweet/DM @HackerNoon.

If you enjoyed this story, we recommend reading our latest tech stories and trending tech stories. Until next time, don’t take the realities of the world for granted!

--

--