Appearance
Appearance
Metaplay supports banning players by simply manipulating the IsBanned
flag in the PlayerModel
. If the flag is set, player connections are refused, and the banned players are unable to start a game session. This flag is controlled programmatically with the PlayerSetIsBanned
action and can also be mutated manually with the LiveOps Dashboard:
⚠️ Banning limitations
Banning affects only the player account and does not track any Hardware or Social Platform Id. A banned player can avoid the ban by cleanly reinstalling the game and losing their progress.
ℹ️ Implementation limitations
Built-in Banning does not support timed bans, delivering custom data, such as the ban reason, to the user, or many other advanced features. Please contact us if there is a need for such extensions.
To support banning, the client needs to detect when it is banned and then inform the user. If the player is banned, the connection will fail with a TerminalError.PlayerIsBanned
error. This happens both for new connection attempts and any existing connection if the player was online when banned.
For example, we could handle it as follows:
// Alternative 1: Detect error with IMetaplayLifecycleDelegate
void IMetaplayLifecycleDelegate.OnSessionLost(ConnectionLostEvent connectionLost)
{
...
if (connectionLost.Reason == ConnectionLostReason.PlayerIsBanned)
SwitchGameState(GameState.Banned);
}
void IMetaplayLifecycleDelegate.OnFailedToStartSession(ConnectionLostEvent connectionLost)
{
...
if (connectionLost.Reason == ConnectionLostReason.PlayerIsBanned)
SwitchGameState(GameState.Banned);
}
// Alternative 2: Detect error case by monitoring Connection status
ConnectionState connectionState = MetaplaySDK.Connection.State;
if (connectionState is ConnectionStates.TerminalError.PlayerIsBanned
|| (connectionState is ConnectionStates.TransientError.SessionForceTerminated terminatedDueToBan && terminatedDueToBan.Reason is SessionForceTerminateReason.PlayerBanned))
{
// Acknowledge the error (Connection.State becomes NotConnected)
MetaplayClient.Connection.Close(flushEnqueuedMessages: false);
SwitchGameState(GameState.Banned);
}
// Show error message.
void SwitchGameState(Game state)
{
switch (state)
{
...
case GameState.Banned:
// Show "You are banned" UI.
_bannedUI.SetActive(true);
break;
}
}
In this example, banned players are shown a visual banned label to communicate the status. If a player was banned before starting the game, they remain on the loading screen forever. If they are banned during an ongoing session, the label is just shown above the active game. To make this more consistent, the game could always throw the player to the loading screen by switching back to the loading scene in the Delegate.OnSessionLost
(or Status is SessionForceTerminated && reason == Banned
) control flow path.
On the server side, banning does not require custom integration and is handled automatically. Upon setting the player IsBanned
flag with a PlayerSetIsBanned
action, such as in the case of using the LiveOps Dashboard, the server automatically kicks out the player and prevents them from reconnecting.
Notably, this built-in behavior only sets the player as banned and does not make any other changes to the player. As an example, if the player is a member of a Guild before being banned, the player will still remain a member of the Guild after being banned by default. As this might not be desirable, or there may be other systems that need to react to the player ban state changing, the PlayerActor
may override OnPlayerBanStateChanged
to implement any custom banning behavior.
For example, to force a player out of a guild when the player is banned:
// PlayerActor.cs
protected override async Task OnPlayerBanStateChanged(bool isBanned)
{
if (isBanned)
{
if (Model.GuildState.GuildId != EntityId.None)
{
_ = await LeaveGuildAsync();
}
}
}