Moderation
Keep a room pleasant with mutes, kicks, bans, passwords and join verification.
Mute
setPlayerMuted() silences a player's room chat, direct messages and typing indicator until you unmute them or they leave.
Kick and ban
kickPlayer(id, reason, ban) removes a player and shows them the reason. With ban: true, the service also refuses them for the rest of the room's life. A room holds up to 256 bans; lift them with clearBan() or clearBans().
const offensive = /\b(idiot|loser)\b/i;
const strikes = new Map();
room.onPlayerChat = (player, text) => {
if (!offensive.test(text)) return;
const count = (strikes.get(player.id) ?? 0) + 1;
strikes.set(player.id, count);
if (count >= 3)
void room.kickPlayer(player.id, 'Repeated abuse', true);
return false;
};Bans are applied by the Ball2D service. If it cannot confirm a ban, the command rejects and the player stays, so handle the rejection.
Private rooms
A password keeps a room to people you invite. Set one at creation or later with setPassword(); pass null to open the room again. Leave public off to keep the room out of the list; it stays reachable by link.
Join verification
setRequireVerification(true) asks each joining player to pass a human verification challenge first. It slows automated joins without affecting players already in the room.
Watch for trouble
Handle onPlayerKicked to log what admins do from the game, and onPlayerActivity to find idle players:
const lastSeen = new Map();
room.onPlayerActivity = (p) => lastSeen.set(p.id, Date.now());
room.onPlayerJoin = (p) => lastSeen.set(p.id, Date.now());
// Move players idle for a minute to the spectators.
const timer = setInterval(() => {
for (const player of room.getPlayerList()) {
if (
player.team !== 0 &&
Date.now() - (lastSeen.get(player.id) ?? 0) > 60_000
)
void room.setPlayerTeam(player.id, 0);
}
}, 10_000);
room.signal.addEventListener('abort', () =>
clearInterval(timer),
);