Integrate your dedicated server to AMS using the AGS SDK
Overview
This article walks you through the lifecycle of a dedicated server (DS) in AccelByte Multiplayer Servers (AMS) and how to integrate a dedicated server with the AccelByte Gaming Services (AGS) Game SDK.
The SDK used to develop both the Server-side and the game client-side is the same SDK.
Prerequisites
Before you begin this guide, you must have:
Set up an IAM client for dedicated servers, preferably a confidential client. No additional permissions are required. To learn how, see Create an IAM client.
Prepared a dedicated server executable, built using the Linux architecture.
noteAMS only supports dedicated servers that are built for the Linux architecture.
Installed and configured the AGS Game SDK for your project. The AGS Game SDK is available on both Unreal Engine and Unity. See the SDK setup guides to learn how to install the SDKs.
The lifecycle of a dedicated server under AMS
The local watchdog uses states to keep track of the lifecycle of a dedicated server. The states are:
- Creating: the dedicated server has been launched by the watchdog, and is loading any necessary resources to serve a game session.
- Ready: the server is ready to serve a game session.
- In Session: the server is serving a game session.
- Unresponsive: the server has failed one or more health checks.
- Draining: the server has been sent the drain command and will soon be terminated.
The change of states are best described by the following diagram:
The dedicated server is required to notify the watchdog when it is ready to handle a game session by using the SendReadyMessage()
API. This is because the dedicated server sometimes requires loading its own assets (such as meshes for a game level) in order to serve a game session. The time required to load such assets vary significantly from game to game. The SendReadyMessage()
API is used so that the dedicated server has time to do this, and can then notify the watchdog, and in turn the fleet command that it is ready to serve a game session. The watchdog will then change the dedicated server state from Creating to Ready.
The APIs we created are only applicable when your dedicated server is running in AMS (or during local testing with AMS Simulator).
We took extra care to ensure that the SDK you integrate will not block your dedicated server from running on its own, even if it fails to connect to a local watchdog or an AMS simulator. This is to ensure that you can continue working on your dedicated server locally without having to worry about the AMS requirements.
When you are ready to start testing your integration with AMS, you can do so locally by using the AMS Simulator. This will be a much faster way to test your AMS integration code than uploading your dedicated server to AMS. Learn more in the Run the AMS Simulator section.
Listening to the correct ports
AMS runs multiple of your dedicated servers on each VM. In order to avoid port conflicts, your dedicated server will be assigned arbitrary port numbers determined by the local watchdog.
When your dedicated server starts, it will be passed these port numbers in the form of command line arguments. The exact flags used to specify the port numbers are specified by you in your command line template that is part of the fleet configuration.
To learn more about configuring your command line argument, see Construct your dedicated server command.
Integrate a dedicated server to AMS
To integrate a dedicated server to AMS, follow these steps, in this order:
Set up your server configuration
- Unreal OSS
- Unity
Add the following configuration into your DefaultEngine.ini
file.
[OnlineSubsystemAccelByte]
bManualRegisterServer=True
[/Script/AccelByteUe4Sdk.AccelByteSettings]
bServerUseAMS=True
Mixing AB Unreal SDK and AB Unreal OSS usage is not fully supported and, in most cases, will not function. We recommend to integrate using only the AB OSS as it is more streamlined as opposed to only using the AB SDK.
To register your dedicated server, the SDK requires a dedicated server ID on Unity startup. A dedicated register ID is registered using Unity command-line arguments:
- Editor
- Linux Server
Set the arguments of your project from Unity Hub before starting the project.
-ABDsId "Dedicated Server ID Value"
Set the dedicated server ID as a command-line argument before executing the server binary.
[YourBinaryName].x86_64 -ABDsId "Dedicated Server ID Value"
To direct the game client to connect to AMS dedicated server, open the SDK editor on the menu toolbar AccelByte > Edit Client Settings. Enable the checkbox on Service Url Configs > Use AMS QoS Server Url and click Save.
Register your dedicated server
When your dedicated server is created by a local watchdog, it will transition into the "Creating" state. During the "Creating" state, the server will start to initialize and load all the necessary assets that it requires to serve a game session. During this time, the server is subjected to the creation timeout, which will automatically remove the server if the timeout is exceeded.
Once your server has finished loading, and is ready to serve a game session, your server should notify AMS by calling the respective API:
- Unreal
- Unreal OSS
- Unity
FRegistry::ServerAMS.SendReadyMessage();
const FOnRegisterServerComplete OnServerReady = FOnRegisterServerComplete::CreateUObject(this, &YourClass::OnServerReady);
SessionInterface->SendServerReady(TEXT(""), OnServerReady);
// The `sessionName` parameter, which is the first argument of SendServerReady(), is not utilized in AMS. You can simply pass TEXT("") as its value.
- Editor
- Linux Server
In the Unity Editor, the game needs to wait for the SDK to be connected with AMS.
var ams = AccelByteSDK.GetServerRegistry().GetAMS();
ams.OnOpen += OnAmsConnected;
void OnAmsConnected()
{
ams.OnOpen -= OnAmsConnected;
ams.SendReadyMessage();
}
AccelByteSDK.GetServerRegistry().GetAMS().SendReadyMessage();
Make sure your DS has done everything it needs to do to be ready to serve a game session before calling SendReadyMessage()
. This should include finishing server login as the DS will not be ready to interact with AGS until login is complete.
Listening to the drain signal
The drain signal tells a dedicated server that the VM it is running on is slated to be removed. Unless the the dedicated server is serving a game session, it will be set to the Draining state and be subject to the drain timeout; upon reaching the drain timeout the watchdog will automatically terminate the dedicated server. Dedicated servers in the In Session state will remain subject to the session timeout after being sent a drain signal; upon reaching the session timeout the watchdog will automatically terminate the dedicated server. When your DS receives the drain signal, it should finish any essential work (which may include finishing an active game session) and then exit. Note that unless your game has unique reasons for behaving differently, the usual expected behavior for a DS that receives the drain signal is:
- if the DS is serving an active game session, finish the session as usual and then exit
- if the DS is not serving a session (e.g., is in the "Ready" state), exit cleanly
There are several reasons why your dedicated servers might receive a drain signal:
- The fleet is deactivated.
- The is fleet scaling in as demand for dedicated servers decreases.
- The nodes hosting the dedicated servers need to be taken down for maintenance.
To register a handler to listen to the drain signal, use this:
- Unreal
- Unreal OSS
- Unity
AccelByte::GameServerApi::ServerAMS::FOnAMSDrainReceived OnAMSDrainReceivedDelegate = AccelByte::GameServerApi::ServerAMS::FOnAMSDrainReceived::CreateThreadSafeSP(SharedThis(this), &ClassName::OnAMSDrain);
FRegistry::ServerAMS.SetOnAMSDrainReceivedDelegate(OnAMSDrainReceivedDelegate);
FOnAMSDrainReceivedDelegate OnAMSDrainReceivedDelegate = FOnAMSDrainReceivedDelegate::CreateUObject(this, &ClassName::OnAMSDrain);
OnAMSDrainReceivedHandle = SessionInterface->AddOnAMSDrainReceivedDelegate_Handle(OnAMSDrainReceivedDelegate);
AccelByteSDK.GetServerRegistry().GetAMS().OnDrainReceived += () =>
{
// Drain callback
};
For a full code example, see Complete code example.
Now that you have completed your dedicated server integration code and configuration, you are ready to test it out using the AMS Simulator.
Run the AMS Simulator
The AMS Simulator emulates how the watchdog interacts with the dedicated server. It is a great tool to verify your dedicated server interactions with the watchdog so that you can be confident that your dedicated server will work on the AMS environment before uploading a dedicated server build. You can download the AMS Simulator on the Download Resource page on the Admin Portal. For more information, see Download AMS CLI tools from the Admin Portal.
To run the AMS Simulator, use this command:
> amssim run
Generate a config.json file
The first time when you call the run command, a config.json
file will be automatically generated for you. config.json
is located in the directory from which you run the amssim
executable and it contains settings that are essential to run your dedicated servers. Feel free to change any of these values to match how you would want your dedicated server to run.
Here's an example of a config.json
file:
{
"WatchdogPort": 5555,
"AGSEnvironmentURL": "",
"AGSNamespace": "",
"IAM": {
"ClientID": "",
"ClientSecret": ""
},
"LocalDSHost": "",
"LocalDSPort": 0,
"ClaimKeys": [],
"ServerName": "my-computer-name"
}
Alternatively, you can use the following command to generate or replace your config.json
with default values.
> amssim generate-config
Generate a session
Every time you start the amssim
, a unique session will be created. You can review your session information by using the info command:
amssim> info
AMS simulator url ws://0.0.0.0:5555/watchdog
AMS simulator session id: 01hcnefg15exp386j9rx901saa.
AMS simulator session log path: session\01hcnefg15exp386j9rx901saa.log
no connected dedicated server
Launch a dedicated server
When you have integrated your dedicated server with the AccelByte SDK, you can launch your dedicated server directly from your IDE. If you have not changed the WatchdogPort
in the config.json
file, the AccelByte SDK will automatically connect to the AMS SIM instance at ws://localhost:5555/watchdog
. Otherwise, make sure that the dedicated server is connecting to the correct AMS Simulator by using the -watchdog_url
command line argument for Unreal or -watchdogUrl
for Unity.
If the connection is successful, you will see that the ds
state is Creating or Ready, depending on whether your dedicated server has called the Ready API.
When running in AMS, a server in the Creating state will be subjected to the creation timeout and will be terminated if it does not signal that it is ready within that timeout. Unlike the watchdog, amssim
does not enforce timeouts.
At any point if you want to check your dedicated server state, use this status command:
amssim> ds status
Set dedicated servers to the Ready state without calling the Ready API
The Ready command allows you to set your dedicated server state from Creating (or claimed) to Ready, without making your dedicated server call itself.
To set your dedicated server to the Ready state, use this command:
amssim> ds ready
Send drain signal to the server
The drain signal tells a dedicated server it should exit as soon as it can safely do so. When running in AMS, any server that is not In Session and has received the drain signal is subjected to the drain timeout.
When the drain signal is sent to the dedicated server, the signal will trigger the OnDrainReceived()
handler. Your dedicated server can then override the handler to execute a code path to handle the drain signal.
Your dedicated server should respond to the drain signal by exiting cleanly as soon as it has completed whatever work it needs to do.
To send a drain signal to your dedicated server, use this command:
amssim> ds drain
Complete code example
- Unity
using AccelByte.Core;
using AccelByte.Models;
using AccelByte.Server;
using System.Collections;
using UnityEngine;
public class AmsDsConnection : MonoBehaviour
{
bool isAmsReady = false;
DedicatedServer ds;
ServerDSHub dsHub;
ServerAMS ams;
IEnumerator Start()
{
#if !UNITY_EDITOR && !(UNITY_STANDALONE_LINUX && UNITY_SERVER)
// This feature only available for Linux Server and Unity Editor.
yield break;
#endif
// Ensure the dedicated server is logged in and ready.
ds = AccelByteSDK.GetServerRegistry().GetApi().GetDedicatedServer();
Result loginResult = null;
ds.LoginWithClientCredentials(result =>
{
if (result.IsError)
{
// Do something if LoginWithClientCredentials fails.
Debug.Log($"Error LoginWithClientCredentials, Error Code: {result.Error.Code} Error Message: {result.Error.Message}");
return;
}
loginResult = result;
// Your additional logic when the dedicated server successfully logs in.
});
yield return new WaitUntil(() => loginResult != null);
// Connect AMS (when not on server build) and set AMS as ready.
ams = AccelByteSDK.GetServerRegistry().GetAMS();
if (ams == null)
{
Debug.LogError("Failed to connect to AMS, please see SDK warning log");
yield break;
}
#if UNITY_STANDALONE_LINUX && UNITY_SERVER
ams.SendReadyMessage();
isAmsReady = true;
#else
// This code is intentionally for editor only.
ams.OnOpen += OnAmsConnected;
#endif
yield return new WaitUntil(() => isAmsReady);
string myServerId = AccelByteSDK.GetServerRegistry().Config.DsId;
// Connect DS Hub and your logic to its events.
DS Hub = AccelByteSDK.GetServerRegistry().GetApi().GetDsHub();
dsHub.Connect(myServerId);
dsHub.OnConnected += OnDsHubConnected;
dsHub.OnDisconnected += OnDsHubDisconnected;
dsHub.MatchmakingV2ServerClaimed += OnDsHubServerClaimed;
// DS Hub has many more events that you can listen to for your custom game logic.
}
void OnAmsConnected()
{
Debug.Log("AMS connected");
ams.SendReadyMessage();
isAmsReady = true;
ams.OnOpen -= OnAmsConnected;
}
void OnDsHubConnected()
{
Debug.Log("Ds Hub connected");
// Your logic when DS Hub successfully connects.
}
void OnDsHubDisconnected(WsCloseCode closeCode)
{
Debug.Log("Ds Hub disconnected");
// Your logic when DS Hub has disconnected.
}
void OnDsHubServerClaimed(Result<ServerClaimedNotification> claimedNotificationResult)
{
ServerClaimedNotification claimedNotification = claimedNotificationResult.Value;
// Your logic when this instance is claimed for a game session
}
}
What's next
Now that you have your dedicated server integrated and verified using AMS Simulator, you are ready to upload a dedicated server build using the AMS CLI.
You can also register a local dedicated server with AMS to test your integration and claim flow before you upload your dedicated server build and deploy dedicated servers with an AMS fleet.