Appearance
Appearance
Metaplay supports banning players by simply manipulating 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 PlayerSetIsBanned
action and can also be mutated manually with the LiveOps Dashboard:
⚠️ Banning limitations
Banning affects only the player account, and in particular 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 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))
{
// Acknowlegdge 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 is shown a visual banned label to communicate the status. If player was banned before starting the game, they remain in the loading screen forever. If they are banned during ongoing session, the label is just shown above the active game. To make this more consistent, game could always throw the player to the loading screen by switching back to loading scene in the Delegate.OnSessionLost
(or Status is SessionForceTerminated && reason == Banned
) control flow path.
On server-side, banning does not require custom integration and is handled automatically. Upon setting player IsBanned
flag with a PlayerSetIsBanned
action, such as in the case of using the LiveOps Dashboard, the server automatically immediately kicks out the player and prevents it from reconnecting.
Notably, this builtin behavior only sets the player as banned and does no 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 as 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 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 the player is banned:
// PlayerActor.cs
protected override async Task OnPlayerBanStateChanged(bool isBanned)
{
if (isBanned)
{
if (Model.GuildState.GuildId != EntityId.None)
{
_ = await LeaveGuildAsync();
}
}
}