AOS REVIVALMenuJoin Discord
Server guide 09

Admin and moderation

Most moderation on BattleSpades is automatic — grief and AFK kicks, team balance, look-alike name protection, protocol checks. This guide shows how those systems work, how to tune them, and how to step in yourself.

Checked BattleSpades 0.1.0-beta.113 minute read

Becoming admin

  1. Set a password

    [admin] password must be at least 12 characters and not changeme; otherwise /admin login is disabled and startup logs a warning. Containers use BATTLESPADES_ADMIN_PASSWORD.

  2. Log in

    In game chat type /admin <password> (or /login). The session lasts until you disconnect.

  3. Check

    /help now also lists the admin commands.

  • Passwords are compared in constant time and never written to the log (the command log shows <redacted>).
  • After [anticheat] admin_login_attempts (3) wrong guesses from one address within 10 minutes, the player is kicked and the address is banned for 10 minutes.
  • Everyone who knows the password is a full admin; there are no separate moderator levels in the game server. Share it carefully and change it (then restart) when someone leaves your team.
  • Players (not admins) are rate-limited to a burst of 5 commands, then one per second.

Everyday actions

GoalCommand
Remove someone now/kick Name reason
Keep someone out for a while/ban Name 2h reason — durations 90 (s), 30m, 2h, 1d, 1w
Keep someone out for good/ban Name perma reason (or no duration)
Stop chat spam/mute Name / /unmute Name (ends when they reconnect)
Watch a suspect/tp Name to move to them, /acreport Name, /acstats Name
Talk to everyone/say Server restarts in 5 minutes
Fix uneven teams/balance
Stop a broken round/restart or /endround

Commands find players by a case-insensitive name prefix and act on the first match, so type enough of the name to be unique. /acreport and /acstats also accept #id. Everything is in the commands reference.

Bans and unbanning

Bans are stored by IP address in bans.json (or [admin] bans_path) and survive restarts; timed bans remove themselves when they expire. There is no unban command. Stop the server, delete the entry, and start it again (the running server rewrites the file on every ban, so edits made while it runs can be lost).

bans.jsonTXT
{
  "203.0.113.55": {
    "name": "Griefer",
    "reason": "team killing",
    "until": 0
  }
}

until is a Unix timestamp; 0 means permanent. Banned players are refused at connect with the retail “banned” or “temporarily banned” message.

Player kick votes

Players can start the retail kick vote from the game UI. The server enforces the retail limits and sends the stock refusal message (spectator, self-kick, kicking the host, vote in progress, too soon, not enough players).

SettingDefaultMeaning
[lobby] votekick_cooldown_seconds300Wait before the same address can start another vote
[lobby] votekick_cancelled_cooldown_seconds45Shorter wait after cancelling your own vote
[lobby] votekick_min_team_players3Players (bots included) needed on the starter's team; 0 disables
[game_rules] RULE_VOTES_REQUIRED_FOR_KICK50%Share of votes needed: 25%, 50% or 75%

Anti-cheat

The server is authoritative: it simulates movement itself and validates shots, tools and builds. On top of that come two layers.

1. Enforcement switches

SwitchDefaultWhat it enforces
kick_on_protocol_violationtrueImmediate kick for packets the stock client never sends (NaN values, forged tools)
enforce_shot_originfalse (log-only)Shots/builds must start near the server's eye position (shot_origin_tolerance blocks)
enforce_aim_directionfalse (log-only)Shot direction must match that frame's aim (aim_direction_tolerance_deg)
enforce_input_starvationfalse (log-only)Airborne players fall and silent clients time out when input stops
enforce_input_backlogfalse (log-only)Players with a long input queue (fake lag) are caught up
enforce_block_intervalfalse (log-only)Retail minimum of 0.1 s between one player's block builds

2. Suspicion report

Every summary_interval_seconds (60) the server scores each human on statistical signals — headshot ratios, per-weapon accuracy against the population, aim snaps onto heads, reaction times, shotgun pellet-seed skew and repeated log-only violations — and appends flagged players to logs/anticheat.jsonl. It never kicks; it tells you whom to watch. Review in game with /acreport (top 5) and /acreport Name (reasons), and /acstats Name for raw counters. All thresholds are in the [[anticheat] reference](/guides/server/configuration#config-anticheat).

Griefing, AFK and names

Team griefing

Players earn grief points for hurting their own team: grief_team_damage_points (1) per 100 HP of teammate damage and grief_team_kill_points (3) per team kill — including a teammate killed by a landmine you set off. One point decays every grief_decay_seconds (60). Everything within grief_incident_seconds (3) is one incident capped at grief_incident_max_points (6), so a single accidental grenade cannot kick. At 5 points the player gets a private warning; at 10 they are kicked with the retail griefing reason. With the defaults, roughly three team kills within a few minutes lead to a kick. Destroying teammates' builds is not scored — digging and rebuilding is normal play.

Stricter or gentlerTXT
[conduct]
grief_kick_enabled = true     # false: warn only
grief_kick_points = 8.0       # kick sooner
grief_warn_points = 4.0
grief_exempt_admins = true

AFK

Only real input resets the idle clock (movement keys, fire, aim or a visible turn); the clock pauses while loading, dead, or between rounds. A warning comes at afk_warn_seconds (9 min), the kick at afk_kick_seconds (10 min; 0 disables). Spectators get afk_spectator_kick_seconds (30 min; 0 exempts them). Admins are exempt by default. These times are BattleSpades choices; retail only had the kick reason.

Names

Always on: names are normalised, invisible characters removed, and uniqueness is checked on a look-alike skeleton (case, accents, Cyrillic/Greek look-alikes, 0/O, 1/l/I, rn/m, vv/w). A joiner imitating an online player gets a ~N suffix; imitating a logged-in admin becomes Player~N; staff-like names (Server, Admin, Console, System, Moderator, BattleSpades, [Admin] tags…) and anything in [conduct] reserved_names become Player.

Reserve your community's namesTXT
[conduct]
reserved_names = ["MyClan", "ServerOwner"]
announce_kicks = true

Team balance

  • [teams] auto_balance places joiners on the smaller team when their pick is already balance_threshold (2) players larger, and refuses team switches that would unbalance. /team and the team menu follow the same rules, plus a 5-second change cooldown.
  • balance_mid_match repairs drift during a match: after an imbalance lasts balance_grace_seconds (5), a dead bot switches sides; after balance_bot_wait_seconds (10) a bot is retired and replaced; last, the most recently joined dead human moves — never a live player, carrier, VIP or last survivor, and nobody twice within balance_player_cooldown (600 s).
  • Zombie, the Tutorial and Map Creator sessions are never balanced; /balance forces a pass now with the same safety rules.

Other server-wide switches

  • Music: [audio] mode_start_music = true plays an in-round music bed from round start. Retail rounds were silent (map ambience only) until the final minute; set false for that.
  • Spectators: RULE_ENABLE_SPECTATORS in [game_rules].
  • Friendly fire / block damage: [game] friendly_fire, build_damage.
  • Welcome message: [server] join_greeting and motd.
  • Plugins: trusted Python files in plugins/; copy plugins/_example_plugin.py to a name without the leading underscore to enable it. Plugins are not sandboxed — only install code you trust.

Common questions

How do I unban someone?

Stop the server, remove their IP entry from bans.json, and start it again. Timed bans expire by themselves.

Can I have moderators with fewer rights?

Not in the game server: anyone with the [admin] password has every admin command. The AoSPlay website has its own staff roles for the public listing, which are separate from in-game admin.

Will anti-cheat kick legitimate players?

Only kick_on_protocol_violation kicks by default, and only for packets the stock client never produces. The other checks are log-only until you enable them, and the suspicion report never kicks.