Use the SDK to set up the server - Dedicated servers with AccelByte Multiplayer Servers (AMS) - (Unity module)
Understand the AMS dedicated server flow
Take some time to look at the flow of how a game server is managed by AccelByte Multiplayer Servers (AMS). For more information, read about the AMS dedicated server states in the Integrate dedicated servers with AMS using AGS SDK guide.
Unwrap the wrapper
You are now ready to use AMS functions provided by the AccelByte Gaming Services (AGS) Game SDK.
The Byte Wars project uses a wrapper class named MultiplayerDSAMSWrapper
that act as the wrapper to cache and handle AMS-related functionalities when using the AGS Game SDK.
The MultiplayerDSAMSWrapper
class uses the ServerApiClient
, ServerAMS
, and ServerDSHub
classes provided by the AccelByte Game SDK. They interact with AGS to provide the ability to register and unregister your server, receive notifications from DS Hub and AMS, and handle multiplayer features.
What's in the Starter Pack
The class MultiplayerDSAMSWrapper_Starter
has been provided for you to act as a starter version of MultiplayerDSAMSWrapper
so you can follow the tutorial from scratch. You can find the file in the Resources section and it consists of the following file:
- MultiplayerDSAMSWrapper_Starter file:
/Assets/Resources/Modules/MultiplayerDSEssentials/Scripts/MultiplayerDSAMSWrapper_Starter.cs
It already contains some functionalities:
Namespaces declaration for using the
ServerAMS
andServerDSHub
classes in the AGS Game SDKusing AccelByte.Core;
using AccelByte.Models;
using AccelByte.Server;Some Action events to give AMS notifications regarding connection and status changes.
public event Action OnAMSConnectionOpened = delegate {};
public event Action OnAMSConnectionClosed = delegate {};
public event Action OnAMSDrainSignalReceived = delegate {};
Server login
Open the
MultiplayerDSAMSWrapper_Starter
C# script. Then, declare several global variables to store the AGS Game SDK interfaces for the dedicated server, AMS, and DS Hub. Then, initialize those variables in theStart()
function.void Start()
{
ds = AccelByteSDK.GetServerRegistry().GetApi().GetDedicatedServer();
if (ds == null)
{
BytewarsLogger.LogWarning("AccelByte Dedicated Server interface is null");
return;
}
ams = AccelByteSDK.GetServerRegistry().GetAMS();
if (ams == null)
{
BytewarsLogger.LogWarning("AccelByte AMS interface is null");
return;
}
dsHub = AccelByteSDK.GetServerRegistry().GetApi().GetDsHub();
if (dsHub == null)
{
BytewarsLogger.LogWarning("AccelByte DSHub interface is null");
return;
}
}Next, create a callback function to handle the on-server login complete event.
private void OnLoginWithClientCredentialsCompleted(Result result, ResultCallback callback = null)
{
if (!result.IsError)
{
BytewarsLogger.Log("DS login success.");
}
else
{
BytewarsLogger.Log($"DS login failed. Error code: {result.Error.Code}, message: {result.Error.Message}");
}
callback?.Invoke(result);
}Create a function to perform the server login. When it is called, the server will log in using the credentials stored in the
AccelByteServerSDKOAuthConfig.json
file.public void LoginWithClientCredentials(ResultCallback resultCallback = null)
{
BytewarsLogger.Log("Logging in DS to AccelByte.");
ds?.LoginWithClientCredentials(
result => OnLoginWithClientCredentialsCompleted(result, resultCallback)
);
}Compile your project and make sure there are no errors.
Register server
After your dedicated server logs in, you need to register it to AMS and DS Hub so it can listen to AMS and DS Hub events. In this section, you will create several functions to register your dedicated server to AMS and DS Hub.
Open the
MultiplayerDSAMSWrapper_Starter
C# script. Then, prepare a getter function to get the dedicated server ID. This ID will be important for connecting to DS Hub later. Its value is retrieved from the provided config values inAccelByteSDK
.public string DedicatedServerId
{
get
{
return AccelByteSDK.GetServerConfig().DsId;
}
}Create a function to be called when the dedicated server is connected to AMS. This function invokes the
OnAMSConnectionOpened
event, which you can use later.private void OnAMSConnected()
{
BytewarsLogger.Log("DS is connected to AMS.");
OnAMSConnectionOpened?.Invoke();
ams.OnOpen -= OnAMSConnected;
}Next, create the function as shown below to bind the function you just created to listen to the AMS on-connected, on-disconnected, and on-drain events. You may notice some binding functions are missing. You will create them later.
public void SubscribeAMSEvents()
{
#if UNITY_STANDALONE_WIN || UNITY_STANDALONE_LINUX
OnAMSConnected();
#else
if(ams.IsConnected)
{
OnAMSConnected();
}
else
{
ams.OnOpen += OnAMSConnected;
}
#endif
ams.OnDrainReceived += OnAMSDrainReceived;
ams.Disconnected += OnAMSDisconnected;
}Create a function to send a ready message to AMS, which indicates that the dedicated server is ready to be managed by AMS.
public void SendReadyMessageToAMS()
{
BytewarsLogger.Log("Sending DS ready to AMS.");
ams?.SendReadyMessage();
}Create a function to connect the dedicated server to DS Hub.
public void ConnectToDSHub(string serverId)
{
BytewarsLogger.Log($"Connecting DS to DSHub by dsid {serverId}");
dsHub?.Connect(serverId);
}Create a function to be called when the dedicated server is connected to AMS. This function prints a log to inform that the dedicated has successfully connected to DS Hub.
private void OnDSHubConnected()
{
BytewarsLogger.Log($"DS connected to DSHub");
}Next, create the function as shown below to be called when DS Hub successfully claims your dedicated server. This function is used by Byte Wars to store the server session ID. The server session ID will not be used in this module, but it will be used later in matchmaking integration.
private void OnServerClaimed(Result<ServerClaimedNotification> result)
{
if (result.IsError)
{
BytewarsLogger.LogWarning($"Failed to claim DS. Error: {result.Error.Message}");
}
else
{
BytewarsLogger.Log($"Success to claim DS: {result.Value}");
GameData.ServerSessionID = result.Value.sessionId;
}
}Create the function as shown below to bind the function you just created to listen to the DS Hub on-connected, on-disconnected, and on-matchmaking server claimed events. You may notice some binding functions are missing. You will create them later.
public void SubscribeDSHubEvents()
{
dsHub.OnConnected += OnDSHubConnected;
dsHub.OnDisconnected += OnDSHubDisconnected;
dsHub.MatchmakingV2ServerClaimed += OnServerClaimed;
}Compile your project and make sure there are no errors.
Deregister server
Before your dedicated server shuts down, you need to deregister it from AMS and DS Hub. In this section, you will create several functions to deregister your dedicated server from AMS and DS Hub.
Open the
MultiplayerDSAMSWrapper_Starter
C# script. Then, create a function to be called when the dedicated server is disconnected from AMS. If the disconnection from AMS was intentional, this function will disconnect the dedicated server from DS Hub. Remember that you've already bound this function to the corresponding AMS event in theSubscribeAMSEvents()
function.private void OnAMSDisconnected(WsCloseCode wsCloseCode)
{
BytewarsLogger.Log($"DS disconnected from AMS. Disconnect code: {wsCloseCode}");
// If disconnected intentionally, continue to disconnect DS from DSHub.
if (wsCloseCode.Equals(WsCloseCode.Normal))
{
BytewarsLogger.Log("Disconnecting DS from DSHub.");
ams.Disconnected -= OnAMSDisconnected;
dsHub.Disconnect();
}
}Next, create a function to be called when the dedicated server is disconnected from DS Hub. This function, if the disconnection was intentional, will call the
OnAMSConnectionClosed
event, which determines if the dedicated server has successfully disconnected from AMS and DS Hub. If the disconnection was not intentional, it will try to reconnect to DS Hub. Remember that you've already bound this function to the corresponding DS Hub event in theSubscribeDSHubEvents()
function.private void OnDSHubDisconnected(WsCloseCode wsCloseCode)
{
BytewarsLogger.Log($"DS disconnected from DSHub. Disconnect code: {wsCloseCode}");
switch (wsCloseCode)
{
case WsCloseCode.Normal:
// DS disconnected from DSHub intentionally. Signal that the DS connection is closed.
OnAMSConnectionClosed?.Invoke();
break;
case WsCloseCode.Undefined or WsCloseCode.Abnormal or WsCloseCode.NoStatus:
if (!string.IsNullOrEmpty(DedicatedServerId) && dsHub != null)
{
BytewarsLogger.Log("DS disconnected from DSHub unexpectedly. Trying to reconnect.");
ConnectToDSHub(DedicatedServerId);
}
else
{
BytewarsLogger.LogWarning("DS disconnected from DSHub unexpectedly and unable to reconnect because of the dsid is empty.");
}
break;
}
}Finally, create a function to disconnect the dedicated server from AMS.
public void DisconnectFromAMS()
{
BytewarsLogger.Log($"Disconnecting DS from AMS.");
ams?.Disconnect();
}Compile your project and make sure there are no errors.
Handle drain state
In this section, you will create simple functions to handle the AMS drain signal.
Create a function to be called when the dedicated server receives a drain signal from AMS. This function invokes the
OnAMSDrainSignalReceived
event, which you can use later. Remember that you've already bound this function to the corresponding AMS event in theSubscribeAMSEvents()
function.private void OnAMSDrainReceived()
{
BytewarsLogger.Log($"DS received drain signal from AMS.");
OnAMSDrainSignalReceived?.Invoke();
}Compile your project and make sure there are no errors.
Resources
- GitHub Link to the files in the ByteWars repository: