07.Jun.2011 Multiplayer server with node.js
I have been interested in Node.js for a while, and wanting to try it out for a real project. Preferably using WebSockets on the client/browser side.
Recently I have begun to implement a multiplayer server for Orbium. The initial goal is to make it possible for 2 players to play cooperatively over the Internet. To accomplish this I had to start with the basics…
Multiplayer game servers
An excellent text to read about multiplayer FPS games and how they work is Unreal Networking Architecture by Tim Sweeney of Epic Games. The article is over 10 years old but still relevant, still describes the basics about how multiplayer FPS games work. I encourage you to read it if you are interested in this and are a beginner in this (like I am). It opened my eyes a bit about concepts that before I read it seemed magical to me.
The article talk a lot about relevant set in FPS games (the things each player can see). For a game as simple as Orbium, the relevant set is always all actors in the simulation, so that part is not so relevant for this discussion (but very interesting).
Also there are a lot about scripting that is also not applicable to a game as simple as this.
What is relevant in a Orbium multiplayer server is how to run the game simulation on the server, inform clients of the correct game state, all the while the game simulation is run on the clients aswell to get an acceptable experience for the players. Orbs cant jump around due to network lag for example, the animation must still be as smooth in the same way as in a singleplayer game.
So basically both the server and all clients run the same game simulation and server is always authorative about the game state. All random events (like deciding what the color of the next orb is) must happen on the server and be distributed to the clients. The clients must report player actions like launching an orb for example, and that action must cause the orb to be launched in the server simulation aswell as being distributed to all other clients.
A bit about WebSockets
WebSockets is starting to become viable as Chrome, Safari (Including Mobile Safari and UIWebView on iOS) supports it out of the box now. I felt that for my first project I wanted to learn how WebSockets really work instead of using Socket.IO library. Although I must say Socket.IO looks awesome, both shielding you from difficult WebSocket handshake details and providing fallbacks for browsers without WebSocket support. So please use it if you dont have the same goal as I have starting out (learning).
Using WebSockets client side (in the browser) is very easy, look at this code for a quick start: client.js
The development experience is very nice with it, there are no “compilation steps” and “redeploys”. In a lot of ways it mirrors the ease of use you get in the browser, but on the server side. Instead of hitting F5 to see the changes, you do a ctrl-c and rerun “node server.js”. It is very fast.
Like on the client its probably best to use Socket.IO in node aswell, to be shielded from WebSocket protocol details. WebSockets are not raw sockets (for good reasons) so there are some things you have to do like, doing the initial handshake and pad the data you are sending with a pre and postfix.
Details for doing it from scratch can be seen in server.js. The WebSocket protocol is not 100% final so there might be changes in details about how this work so it might break in the future. Another argument for using Socket.IO and let them worry about it (If you are not a masochist like I am ).
Using the same code on the client and server
When doing this you need to architect the code (or refactor it) so it can run on the server in node, that means no window object, no DOM tree, no canvas element. There is also the issue with the module system in node, that is not really compatible with how things are normally done in the browser.
I solved this by just doing a “require(./tile.js)” for example so all code is just put in the “orbium” object that is attached to the global object, esentially in the same way as it works in the browser. I doubt that this is a “best practice”, but it works and I dont really se any major downsides with it.
Deploying this to actual players/customers
At this stage I am not sure how to actually deploy this in the real world. It works to play over the internet now, for example one player on iPhone and another using Chrome on a laptop. To test it out, for the time being, you have to clone the repo from github and change the hardcoded ip address to match your server.
There is a lot of work remaining in how to match up players, user interface for that, etc etc. There is also the question about hosting. If you are reading this and have some experience with node.js hosting providers I would be glad to get any tips in that area.