Game integration API
Overview
Game integrations communicate with the web instance using HTTP endpoints under /api/game
controlled by App\Controllers\GameIntegrationController
, hereinafter referred to as the web API.
Integrations communicate by
- periodically sending connecting and connected players' identifiers and polling for incoming actions from the POST
/api/game/poll
route. - responding to game events (e.g. bans and group changes) by sending requests to the web API.
Authentication
Game integrations authenticate every request using a server token in the Authorization header (Authorization: Bearer: <token>
).
Initialization
Settings are be obtained with the GET /api/game/meta?actions[]=settings
request (under the actions
key of the JSON response).
Polling
Further actions (possibly including changes to settings) are received by calling the /api/game/poll
endpoint at intervals specified by its X-RateLimit-Reset
response header.
Endpoints
Method | Route | Parameters | Note |
---|---|---|---|
GET | /api/game/meta | actions | Returns actions |
POST | /api/game/poll | players | Returns actions |
PATCH | /api/game/actions/executions/{execution_id}/finish | error | |
POST | /api/game/players/{source_id}/{account_id}/bans | admin_{source_id}_account_id , duration_minutes , reason , scope | |
DELETE | /api/game/players/{source_id}/{account_id}/bans | ||
POST | /api/game/players/{source_id}/{account_id}/roles | name | Multi-role games |
DELETE | /api/game/players/{source_id}/{account_id}/roles/{role_ingame_equivalent} | Multi-role games | |
GET | /api/game/players/{source_id}/{account_id}/primaryrole | Single-role games | |
POST | /api/game/players/{source_id}/{account_id}/primaryrole | name | Single-role games |
POST | /api/game/players/{source_id}/{account_id}/link | token | Auth providerless games |
Placeholder definitions
{source_id}
: abbreviated fromexternal_account_source_id
; refers to an external account source (which may correspond to an OAuth provider).{account_id}
: abbreviated fromexternal_account_id
; refers to the player's external account identifier from the given source.
Example requests
- URL:
/api/game/poll
- Body:
players[steam][connecting][ids]=76561198131926932
- Body:
- URL:
/api/game/players/steam/76561198131926932/roles
- Body:
name=admin
- Body:
- URL:
/api/game/players/steam/76561198131926932/bans
- Body:
admin_steam_account_id=76561198131926932&scope=global
- Body:
Action types
Below is a partial overview of the actions types available.
Code action
Code to be compiled and executed, specified by payload
.
Command action
A console command to be executed, specified by payload
.
Roles action
Actions of type roles
concern a single player identified by payload.player_{source_id}_account_id
.
Exhaustive
- Dispatched only when role sync is configured to send roles to the game server.
- Dispatched only when the player is connecting.
payload.exhaustive
is set totrue
.payload.grant
andpayload.revoke
contain all of the associated user's roles and (prior) revoked roles, respectively.
Partial
- Dispatched from store package actions and role sync.
- May be dispatched even when the player is not present.
payload.exhaustive
is set tofalse
.payload.grant
andpayload.revoke
contain some or all of the associated user's roles and (prior) revoked roles, respectively.
Settings action
Settings for the integration (configured from the server manager in the web UI).
E.g. payload.role_sync
specifies if and how roles should be synchronized.
Implementation
Adding a game to the backend
- Implement a game class (see the abstract class
App\Models\Games\Game
for available member variables and methods). - In a module service provider's
boot
method, call theApp\Models\Server::setGame
method supplying a key and a game class.
Example game
GarrysMod.php
Class namespace Modules\Example\Games;
use App\Models\User;
class GarrysMod extends SteamGame
{
protected static string $name = 'Garry\'s Mod';
protected static int $steamAppId = 4000;
protected static bool $integration = true;
public static function getConsoleCommands(): array
{
return [
'kick' => static fn (User $user, string $reason) => "kickid {$user->steamid2} \"{$reason}\"",
];
}
}
Registration
Server::setGame('gmod', GarrysMod::class);
Writing an integration
Refer to the game's (or a modding framework's) documentation and implement the web API as a plugin.
Implementation notes
Actions
- The PATCH
/api/game/actions/executions/{execution_id}/finish
endpoint should be called for actions which specifypayload.execution_id
(with the body containing anerror
string on failure). - Applicability is game-specific, thus actions may be ignored.
- Unrecognized action types must be handled gracefully.
Roles
WARNING
Games which only support a single role per player
The GET/POST primary role endpoint at /api/game/players/{source_id}/{account_id}/primaryrole
must be used when handling roles
actions.
Setting the user's primary role implicitly revokes roles lower in hierarchy.
Desired behavior depends on the role sync configuration of the server.
role_sync.receive
set to true
)
Receive from web API (For exhaustive actions it's safe to grant payload.grant[0]
(as the order is hierarchial). If grants are empty, the player's current role (if any) must be revoked if it corresponds to a role in payload.revoke
. If it does not and role_sync.send
is set to true
, the player's current role should be sent to the web API (to handle initial synchronization).
If a partial revoke contains the player's current role, the GET primary role endpoint must be used to determine whether the corresponding user retains another role (which, if any, should be granted to the player).
role_sync.send
set to true
)
Send to web API (If role_sync.receive
is set to
true
, when handling partial actions avoid inadvertently revoking roles (implicitly) by GETting the player's primary role.false
, exhaustive actions are to be handled by POSTing the player's current role if it is not already present inpayload.grant
.