Game Server Tasks #

Tasks related to game servers include:

Allocate a dedicated game server #

Allocate a game server to host the game instance

Allocate a dedicated server

If you are using the Pragma Fleet service for game server management, see Pragma Fleet Service.

Game server allocation is initiated by the Game Instance interface allocateGameServer() method.

interface GameInstance {
    fun allocateGameServer(ext: ExtAllocateGameServer)
}

GameInstance.allocateGameServer() can be called from any Game Instance Plugin method. When allocateGameServer() is called, your Game Server Provider Plugin implementation’s startAllocationForGameInstance() method is invoked.

suspend fun startAllocationForGameInstance(
    gameInstanceId: GameInstanceId,
    ext: ExtAllocateGameServer,
    clientTokenFunction: () -> PartnerClientTokens,
    gameServerVersion: GameServerVersion,
    gameServerZone: GameServerZone
)

The plugin implementation and method functionality is determined by your fleet management solution.

Allocate using third-party solution #

If you are using a third-party fleet management solution (such as GameLift, Hathora, or Multiplay), implement the startAllocationForGameInstance method as follows:

  • Send the game instance ID to the game server so the game server can link back to the correct game instance
  • Send data from the ExtAllocateGameServer payload to the game server. This should be information that the game server needs to allocate the correct server. For example, data may include preferred region or version, or data the game server needs on start, such as a map or game mode.
  • Send partner session tokens to the game server using the clientTokenFunction parameter, as shown in the following example. Each game server requires a set of partner session tokens, regardless of how many game instances that game server can run at once.

For example:

suspend fun startAllocationForGameInstance(
    gameInstanceId: GameInstanceId,
    ext: ExtAllocateGameServer,
    clientTokenFunction: () -> PartnerClientTokens
) {
    val tokens = clientTokenFunction()
    val dispatchRequest = mapOf(
        META to mapOf(
            PARTNER_GAME_AUTH_TOKEN to tokens.gameToken,
            PARTNER_SOCIAL_AUTH_TOKEN to tokens.socialToken,
        )
    )
}

When you initiate the game server allocation process, Pragma generates a unique set of partner session tokens and passes them to the Game Server Provider plugin’s startAllocationForGameInstance() method.

Allocate for local development #

If you are running both Pragma Engine and a game server on a local machine, use the LocalProcessGameServerProviderPlugin, which is an implementation that will run a game server executable on the local machine. To do so, edit the GameInstanceService.gameServerProviderPlugin block of your local-dev.yml file. Include a path to your locally build game server.

game:
  pluginConfigs:
    GameInstanceService.gameServerProviderPlugin:
      class: "pragma.gameinstance.LocalProcessGameServerProviderPlugin"
      config:
        serverExecutablePath: "C:/path/to/game/server/executable.exe"
        serverLogDirectory: "."

Related events:

Related errors:

Establish connection to Pragma backend #

To communicate with the Pragma backend, a game server must provide the SDK with the partner tokens, and establish a connection using the WebSocket protocol.

Provide SDK with partner tokens and address #

To use the Pragma SDK, the game server has to provide it with the partner tokens and partner backend address. There are several ways to accomplish this:

Setting programmatically:

auto Runtime = Subsystem->Runtime();
Runtime->Config().PartnerBackendAddress = "http://HOSTNAME:PORT";
Runtime->Config().PartnerSessionSocialAuthToken = "PARTNER_SOCIAL_TOKEN";
Runtime->Config().PartnerSessionGameAuthToken = "PARTNER_GAME_TOKEN";
PragmaSessionManager.SetConfig(new SdkConfig.Data
{
    partnerBackendAddress = "http://HOSTNAME:PORT",
    partnerSessionSocialAuthToken = "PARTNER_SOCIAL_TOKEN",    
    partnerSessionGameAuthToken = "PARTNER_GAME_TOKEN"
});

Adding command-line arguments to your game server executable:

C:/path/to/server.exe -PragmaPartnerBackendAddress=<http://HOSTNAME:PORT> -PragmaPartnerSessionSocialAuthToken=<PARTNER_SOCIAL_TOKEN> -PragmaPartnerSessionGameAuthToken=<PARTNER_GAME_TOKEN>

Using config files:

Put the following in the appropriate configuration file (e.g., DefaultGame.ini for Unreal or Pragma.json for Unity):

[/Script/PragmaSdk.PragmaSdkConfig]
PartnerBackendAddress = "http://HOSTNAME:PORT";
PartnerSessionSocialAuthToken = "PARTNER_SOCIAL_TOKEN";
PartnerSessionGameAuthToken = "PARTNER_GAME_TOKEN";
{
  "partnerBackendAddress": "http://HOSTNAME:PORT",
  "partnerSessionSocialAuthToken": "PARTNER_SOCIAL_TOKEN",
  "partnerSessionGameAuthToken": "PARTNER_GAME_TOKEN"
}

Establish WebSockets #

To establish a connection using the WebSocket protocol, get the Pragma server object and then call Connect().

const auto* Subsystem = GetWorld()->GetGameInstance()->GetSubsystem<UPragmaGameServerSubsystem>();
auto Runtime = Subsystem->Runtime();

// Optionally, set configurations on the Runtime
Runtime->Config().BackendAddress = "http://127.0.0.1:10000";

auto Server = Runtime->Server();
Server->Connect(FServer::FConnectedDelegate::CreateLambda([this]
{
    ...
}));
var runtime = Runtime.Get();

// Optionally, set configurations on the Runtime
runtime.Config.ConfigData.partnerBackendAddress = "http://127.0.0.1:10000";

var server = runtime.Server();
var connectPromise = new Promise();
server.Connect(connectPromise.Complete);
yield return connectPromise.Future;
...

Link the game server with the game instance.

When the game server is allocated and communication with the Pragma backend is established, the game server needs to link to the appropriate game instance. To do so, the game server needs to call MatchApi.RequestStartGame(). On success, this call triggers the OnGameStart event, which provides a GameStart object that includes a list of players and custom data.

Server->MatchApi().OnGameStart.AddUObject(
	this, &AMyPlayerController::HandleOnGameStart);

Server->MatchApi()->RequestStartGame(GameInstanceId);
Server.MatchApi.OnGameStart += HandleOnGameStart;

Server.MatchApi.RequestStartGame(GameInstanceId);

Connect players #

Connect players to the game server.

After establishing a connection with the Pragma backend, the game server can call MatchApi.ConnectPlayers() to indicate that it’s ready for players to connect to the game server.

Verify player

Players receive a OnHostConnectionDetailsReceived notification, which includes host connection details such as host name, port, game instance ID, the ExtPlayerConnectionDetails payload (which can be used to define custom game server host information), and a unique set of partner session tokens.

Server->MatchApi()->ConnectPlayers(
  const FString& GameInstanceId,
  const TArray<FPragma_GameInstance_PlayerConnectionDetails>& PlayerConnectionDetails,
  const FString& Hostname,
  const int Port,
  const FOnCompleteDelegate& OnComplete
);
Server.MatchApi.ConnectPlayers(
  PragmaId gameInstanceId,
  IEnumerable<PlayerConnectionDetails> playerConnectionDetails, 
  string hostname, 
  int port,
  CompleteDelegate onComplete
);

Verify player connection tokens #

Using player connection tokens, Pragma Engine can determine whether a specific player can connect to a specific game server. The player verification process is optional, but recommended for competitive games.

When a game server links to a game instance, each player in the game instance receives a unique connection token along with host connection details. The player sends the connection token to the game server, at which point the game server forwards the token to the engine via MatchApi.VerifyPlayer(). If the engine determines the token is valid, players can connect to the game server.

Server->MatchApi()->VerifyPlayer(
  const FString& GameInstanceId,
	const FString& PlayerId,
	const FString& ConnectionToken,
	const FVerifyPlayerDelegate& OnComplete
);
Server.MatchApi.VerifyPlayer(
  PragmaId gameInstanceId, 
  PragmaId playerId, 
  string connectionToken,
  VerifyPlayerDelegate onComplete
);

A player who disconnects and reconnects to the same game instance can fetch the same player connection token with GetGameInstanceCache().

Related events:

Related errors:

Configure keep-alive values #

When the keep-alive service is enabled (default), game servers are required to send heartbeats at specified intervals to Pragma Engine. This allows Pragma Engine to confirm that the game instance and game server are still operational.

Game servers using the Pragma SDKs automatically send keep-alive signals to Pragma Engine when this feature is enabled.

To customize keep-alive features, edit the following values in the GameInstanceServiceConfig block of your config file:

  • enableKeepAlive: When true, enables the keepalive feature (default: true)
  • keepAliveIntervalMillis: Interval, in milliseconds, to wait between keepalive requests (default: 30000 milliseconds)
  • keepAliveMissesLimit: Number of keepalive requests that can be missed before releasing the game instance from the service (default: 3)

For example:

  serviceConfigs: 
    GameInstanceServiceConfig:
      enableKeepAlive: true
      keepAliveIntervalMillis: 30000
      keepAliveMissesLimit: 3

As a best practice, we recommend against disabling the keep alive feature, as it’s critical for game flow health.

Manage game server compatibility #

Define compatibility maps for game servers

Game servers and clients must be updated in parallel as updates are added to live service games. Pragma Engine checks for server/client compatibility whenever a party changes (players added/removed, party enters matchmaking, etc.).

Pragma specifies a defaultGameServerVersion in the dev-defaults.yml config as a fallback configuration for all game client versions.

You can define a list of game server versions and corresponding compatible game client versions in the gameServerVersionCompatibility block of your config file. Unique compatibility keys (positive integers) define the priority of the server/client version mappings. Each mapping includes:

  • server version
  • one or more corresponding client versions. Note that this value can contain a wildcard character (*).
  • unique compatibility keys (positive integers) that define the priority of the client version. Higher numbers indicate higher priority.

The following is an example PartyConfig configuration block:

game:
  core:
  serviceConfigs:
    PartyConfig:
        gameServerVersionCompatibility:
          1:
            serverVersion: "server0"
            clientVersions:
              1: "client0-*"
              2: "client1-*"
              3: "client2-pc"
          2:
            serverVersion: "server1"
            clientVersions:
              1: "client1-*"
              2: "client2-ps4"
              3: "client2-xbox"
              4: "client3-*"

If any player client in the party is incompatible with the server version, the player client(s) with incompatible client versions will receive the OnGameClientVersionUpdateRequired notification. Every player in the party will receive the OnPartyClientVersionMismatch notification. If all player clients are supported but cannot match to the same game server, all players will receive the OnPartyClientVersionMismatch notification.

The only action Pragma Engine prevents as a result of server/client version mismatch is entering matchmaking. If a party with mismatched server/client versions attempts to enter matchmaking, Pragma Engine throws an error and does not allow add the party to the matchmaking queue.

If you want to override the game server version mapping, configure your party plugin to set the party’s overrideGameServerVersion value to true and manually set thegameServerVersion value.

Related events:

Related errors: