Serverside Code for Multiplayer Service
This section describes how to implement the serverside code for a multiplayer game, how to respond to the various events that can occur, and how to set up timers to run code at other points in time.
You can also learn how to make your own multiplayer games by following our step-by-step tutorial:
When you are developing your multiplayer game your serverside code is running in your local development server. To make your game use the live Game Server clusters, you need to upload your code through the Control Panel of your game.
All the classes, methods, and properties described here can also be viewed in the reference documentation:
Rooms and Players
Serverside code for an entire game is divided into one or more Room Types, and one or more Player classes. When a player creates a room of a specific type, an instance of that Room Type is created on a game server and starts running.
Whenever a player then joins that room, his client will connect to that game server, and an instance of the corresponding Player object is created. Consequently, when a player leaves a room his Player object is destroyed, and when everyone has left a room, that Room Type object is destroyed. This means that no serverside code can run if there are no players connected, and that you have to take care to persist any player or game state beforehand.
The distributed nature of the system means that players in the same room will always be connected to the same game server, but different rooms of the same room type might run on different servers in different physical locations. This means that no data can be shared between different rooms of the same game.
In a nutshell, the serverside code is largely event-based and should be built to respond to various events such as players connecting, disconnecting, and sending in messages to the server.
Here's a bare-bones example of serverside code that allows all players to join, and every time a player sends a message to the server, it will be broadcast to all connected players:
Inheriting from BasePlayer
The first thing you must do in your serverside code is to make a player class that inherits from BasePlayer.
Since you are inheriting from another class, there will already be some existing properties and methods, but you are otherwise free to add whatever you need that is specific to your game. For each player that connects to your game, an instance of this class will be created, and each game room will contain a list of these.
What you typically want to add to your player class is the state of each player, for example their position in the world, their inventory, their hand of cards, their weapons, their score, etc.
For example, the player class of Fridge Magnets looks like this:
Inheriting from Game<P>
The second thing you must do in your serverside code is to make a game class that inherits from Game<P>.
Just like the base player class, the base game class also has some existing properties and methods, and you need to override some methods to be able to respond to the various events.
You are also free to add any other properties and methods that you need for your game, and what you typically add to your game class is everything that is shared between the players in a room. If the player class holds the state of each player, the game class holds the state of their world. For example, this is where you would store the position of all monsters in the world, the deck of cards in a card game, whos turn it is to go next, a log of chat messages, etc.
To continue the above example, this is how the game class for Fridge Magnets begins. It defines a roomtype, references the player class, and defines a collection of Letters for the game:
Game Started and Game Closed
The first two events that you need to handle is when a game starts and when a game ends. This happens when the first player connects to a room, and when the last player leaves a room.
You can handle these events by overriding the GameStarted and GameClosed methods.
Typically, you want to do all the housekeeping tasks in these methods such as creating a fresh new game world or saving the scores of a completed game.
In Fridge Magnets, all the letters are created in the GameStarted method, but we don't need to do anything when a game closes:
User Joined and User Left
The next events are when a player joins the room and when a player leaves the room.
You can handle these events by overriding the UserJoined and UserLeft methods.
These events should be used first to inform a new player of the state of the world so they are synchronized with everyone else, and to inform the existing players whenever someone joins or leaves.
In Fridge Magnets, each player that joins gets the positions of all existing letters, and whenever someone leaves, all other players are informed of this:
Allow User Join
By overriding the AllowUserJoin method you can control whether or not a player can join a room. If this method returns false, the player is not allowed to join, and consequently, the UserJoined method isn't called for this player either.
You only need to override this method if you need to control who can join a room or not, for example if you want to limit the amount of players, or if a player doesn't meet some other requirement for joining.
Here's an example that checks a value from roomdata to see if the current player should be allowed in or not:
The most important event in your serverside code happens whenever a client sends a message to the server. This is handled by overriding the GotMessage method.
You always need to override this method, and you should add code that handles all the different message types that your client sends in. This is where the bulk of your game logic will be, this is where you react to actions by each client, and where you will send the results of those actions back out to the affected players.
If you look at the Fridge Magnets example below, there are only three message types that the client sends in: When a player moves a letter, when a player moves his mouse, and when a player activates a letter.
Broadcast and Send
Very often you will want to send a message back to players as a reaction to a game event. By calling the Broadcast method, you can send a message to all players that are connected to the room.
If instead you only want to send a message to a specific player, you have to use the Send method which is on your player object. This means that you first have to get the correct player object, and then call the Send method.
The below example shows how to make the serverside code for a simple chat that allows public and private messages:
Sometimes you want your serverside code to take an action that isn't immediately triggered by an incoming event. To accomplish this you can set up different timers.
To set up a one-time timer, you can use the ScheduleCallback method, and to set up a recurring timer, you can use the AddTimer method.
You can use timers for everything periodic in your game such as broadcasting the state of the world, NPC behaviour, random events and much more.
In Fridge Magnets, we set up a timer when each room is created to broadcast the positions of other players every 100 milliseconds like this:
Finally, you can access all of the Backend Services from your serverside code.
You can use BigDB for storing persistent data about your players or your game such as highscores, rankings, inventories, achievements etc.
PayVault is fully accessible from serverside code. Although you can allow player's vaults to be manipulated from clientside code, we recommend that you do all such things from serverside code since it is a secure environment.
Note that before you can use the PlayerObject or PayVault property of your Player class, these have to be loaded with the asynchronous methods GetPlayerObject and Refresh.
To make this process easier you can set up your room so that the player object and vault are automatically preloaded before each player joins, by setting the PreloadPlayerObjects and PreloadPayVaults properties on the room to true:
To make debugging of your game easier you can use the ErrorLog service.
If you need to get any form of resources into your serverside code, you can either embed the resource in the game DLL that you upload and then use EmbeddedResource to retrieve it, or you can host the resource on an external server and use the Web class to retrieve it.