Authoritative Multiplayer
In addition to relayed multiplayer, MetaFi also supports the server-authoritative multiplayer model, giving you the freedom and flexibility to decide which approach is best for your game.
In server-authoritative multiplayer, all exchanges of gameplay data are validated and broadcast by the server. In this model you write custom server runtime code for the gameplay rules to be enforced by MetaFi (i.e. how many players can join, whether matches can be joined in progress, etc.).
There are no strong determinative factors that necessitate the relayed or authoritative approach over the other, it is a design decision based on the desired gameplay. Authoritative multiplayer is more suitable for gameplay which depends on central state managed by the game server, gameplay with higher player counts per match, and where you don’t want to trust game clients and instead want stricter control over gameplay rules to minimize cheating, etc.
To support multiplayer game designs which require data messages to change state maintained on the server, the authoritative multiplayer engine enables you to run custom match logic with a fixed tick rate. Messages can be validated and state changes broadcast to connected peers. This enables you to build:
Asynchronous real-time authoritative multiplayer: Fast paced real-time multiplayer. Messages are sent to the server, server calculates changes to the environment and players, and data is broadcasted to relevant peers. This typically requires a high tick-rate for the gameplay to feel responsive.
Active turn-based multiplayer: Some examples are Stormbound or Clash Royale, games where two or more players are connected and are playing a quick turn-based match. Players are expected to respond to turns immediately. The server receives input, validates them and broadcast to players. The expected tick-rate is quite low as rate of message sent and received is low.
Passive turn-based multiplayer: A great example is Words With Friends on mobile where the gameplay can span several hours to weeks. The server receives input, validates them, stores them in the database and broadcast changes to any connected peers before shutting down the server loop until next gameplay sequence.
Session-based multiplayer: For complex gameplay where you want the physics running server-side (e.g. Unity headless instances). MetaFi can manage these headless instances, via an orchestration layer, and can be used for matchmaking, moving players on match completion, and reporting the match results.
It is important to note that there are no out-of-the-box or generic scenarios when building your server-authoritative multiplayer game. You must define the gameplay - how many players per match, whether joining in progress is allowed, how the match ends, etc. - by writing custom runtime code.
There are several concepts to familiarize yourself with when deciding to implement the Authoritative Multiplayer feature.
Match handler
Match handlers represent all server-side functions grouped together to handle game inputs and operate on them. Think of it as a “blueprint” from which a match is instantiated. Your match handler establishes the gameplay rules for the match and, because a game may have multiple modes of play (e.g. Capture the Flag, Deathmatch, Free for All, etc.), you may need multiple match handlers - one for each game mode.
There are 7 functions required in any match handler. These functions are called only by MetaFi, they cannot be called directly by clients or other runtime code.
Match Init
Match Join Attempt
Match Join
Match Leave
Match Loop
Match Terminate
Match Signal
See the Match Handler and Match Runtime function reference for details.
These functions define the state and lifecycle of a given match, with any single MetaFi node capable of running thousands of matches depending on hardware and player count. The match handler and state of a given match is stored on a particular MetaFi instance, with that instance becoming the host for that match.
A single node is responsible for this to ensure the highest level of consistency accessing and updating the state and to avoid potential delays reconciling distributed state.
Every running match is self-contained, it cannot communicate with or affect any other matches. Communication with matches is done only via clients sending match data. MetaFi internally manages the CPU scheduling and Memory allocation to each match ensuring fair and balance distribution of load on a single instance or all instances in the cluster.
The match signal function can be used to accomplish this in a limited manner: reserve a place in a match for a given player or handoff players/data to another match. This should only be used as rare exception and not standard practice.
Match handlers run even if there are no presences connected or active. You must account for the handling of idle or empty matches in your match runtime logic.
Matches cannot be stopped from the outside and end only when one of the lifecycle functions returns a nil
state.
In order to make the match handler available it must be registered.
Tick rate
While most match handler functions are called due to user behavior or internal server processes, the server will periodically call the match loop function even when there is no input waiting to be processed. The logic is able to advance the game state as needed, and can also validate incoming input and kick inactive players.
Your tick rate represents the desired frequency (per second) at which the server calls the match loop function - i.e. how often the match should update. For example a rate of 10
represents 10 ticks to the match loop per second.
The server always tries to maintain even start point spacing. Using the tick rate of 10
example, each loop will start 100ms
after the last one started. Best practice is to leave as much time as possible between loops, allowing for the irregularly called non-loop functions to execute in the gaps between loops.
It is important that your game loop logic and configured tick rate do not cause the server to fall behind - i.e. each loop must be able to finish before the next is scheduled (less than 100ms
in our example). If the match loops do fall behind, the server will first try to “catch up” by starting the next loop as soon as possible. If too many loops fall behind - typically the result of poor loop logic design - the server will end the match.
Tick rate is configurable and typical frequencies range from once per second for turn-based games to dozens of times per second for fast-paced gameplay. Some considerations to keep in mind when choosing your tick rate:
Select the lowest possible tick rate that provides an acceptable player experience (no lag, etc.)
Higher tick rates mean less gaps between match loops, and more responsive “feel” for players
Always start with a low rate and increase in small increments (1-2) until the desired experience is achieved
The lower your tick rate then more matches than can be run concurrently per CPU core
Each match handler can have a different tick rate, such as for different game modes
Match state
MetaFi exposes an in-memory region for authoritative matches to use for the duration of the match to store their state. This can include any information needed to keep track of game data and client behavior during the course of the match.
Each match maintains its own individual, isolated state. This of this state as the result of continuous transformations applied to an initial state based on the loop of user input after validation. Note that these changes in state are not automatically send to connected clients. You must do this manually within your match handler logic by broadcasting the appropriate op codes and data.
Send data messages
Unlike sending messages in relayed multiplayer, in authoritative matches received messages are not automatically rebroadcast to all other connected clients. Your match logic must explicitly call the broadcast
function to send a message.
Each message contains an Op code as well as the payload.
Last updated