AOS REVIVALMenuJoin Discord
Soldiers fighting across a block-built Ace of Spades battlefield
Changelog // field reports

What's newin the revival

Everything that changed in the BattleSpades server and client, in plain words. Open “Technical details” on any entry for the evidence and the exact numbers.

Updated Maintained from the BattleSpades server and client docs

How to read this

Live, ready or in testing

We only call something ready once it has passed its tests and been checked in a live match. Work that still waits for a play-test or a deployment is marked in testing, with what is left listed under each entry. For the full picture see the implementation status and the beta status pages.

  • Live

    Released and running on the official servers or in the published build.

  • Ready

    Built, tested and checked in a live match. Ships with the next update.

  • In testing

    Built and passing its tests, but a live play-test or deployment is still owed.

Retail parity update

Next update

A week spent making BattleSpades play, sound and look like the original 1.x retail game. Every change was checked against the stock Steam game, its code or a live capture. It is in development builds now and reaches the official servers and the client downloads with the next update.

Every game mode reworked to retail rules

Capture the Flag now plays to 5 captures, Zombie runs three rounds per map, VIP has real sudden death, and Territory Control, Multi-Hill, Occupation, Demolition and Diamond Mine all got their retail announcements, awards and rules.

  • CTF: intel sits on the real base point, carriers appear on the minimap after 30 seconds, match-winning captures end the round cleanly.
  • Zombie: 3 rounds per map, 0.5 s spawn protection for patient zero, teams and classes lock during the outbreak.
  • VIP: after the VIP dies the team stops respawning and slowly loses health, and the HUD says “No respawns!”.
  • Territory Control: capture bars fill properly, owned points resupply you, and a crash when joining TC maps is fixed.
  • Diamond Mine: diamonds show their remaining lifetime, and the map vote opens at 12 of 15 diamonds.
  • Map rotations only offer maps that retail allowed for each mode, shuffled once per server start.
Still open
  • Zombie head-count display type, VIP round counting and the exact TC capture rates still want a retail capture to confirm.
Technical details
  • Mode lifecycle contracts: leave hook before PlayerLeft, dead-on-join when respawn is forbidden, alias canonicalisation, failed-transition recovery.
  • TerritoryBaseState(106) uses the 3-byte short form for actions 3/4/6/7; capture_amount is the retail 0..100 attacker percentage.
  • Score fallbacks: ctf 5, dia 15, oc 30, tc = base count, zom 3, dem 1. Crate respawn 25 s, radar station 45 s.
  • GreatWall left the Demolition rotation and BranCastle the Occupation rotation (retail marks both invalid).

Announcements and the end-of-round screen

Mode events use the original translated strings, the round clock calls out 5 minutes, 2 minutes, one minute and the final ten seconds, and every round now ends with the scoreboard, then the stats screen with “X WINS!” and the award rows.

  • “Player has disconnected” and team-change refusals (team full, team locked) now appear like they did in retail.
  • End-screen awards pick from all 30 retail stat types — distance ran, time on fire, biggest collapse, longest kill and more — instead of always showing Kills and Headshots.
  • A forced win (admin end) names the right team instead of the score leader.
Technical details
  • LocalisedMessage(50) with retail string ids, team-relative where retail was.
  • Rollover order: ForceShowScores(72)=1 → 5 s → flush, 72=0, ShowGameStats(53), ShowTextMessage(73) → 12 s → flush, MapEnded(52).
  • Verified live on the new client (2026-09-27): ONE MINUTE LEFT banner, F1–F3 map vote, results strip, win/lose music, next map loads.

Kill banners and stingers

Double kills, dominations and revenge now show their banners and play their stingers, for the killer and the victim.

  • “YOU ARE DOMINATING …”, “… GOT REVENGE ON YOU”, multikill banners and the match-start stinger.
  • Burning now shows the burn indicator instead of a hit arrow.
  • Revenge and payback kills earn their retail bonus points.
Technical details
  • KillAction kill_count = kills chained within MULTIKILLMAXTIMEGAP 6.0 s; domination on the 4th unanswered kill (retail value not recoverable, 4 is the convention).
  • Late-joiner replay zeroes banner fields; burn damage uses SetHP type 3.

Anti-cheat and fair play

Packets the real game can never send now get you kicked. Suspicious shooting, aim and movement are recorded for admins to review, but do not kick anyone yet.

  • Grief points for team damage and team kills, with a warning before a kick.
  • AFK warning at 9 minutes and kick at 10 (30 minutes for spectators).
  • Look-alike names (for example imitating an admin) are renamed, and chat can no longer be forged as a system message.
  • Admin login is disabled while the password is weak and locks out after three failures.
Still open
  • Enforcement stays off until the log-only checks are reviewed against real players on lossy connections.
Technical details
  • server/anticheat.py accounting layer; protocol_violation() kicks with ERROR_KICK_HACKING.
  • Shot origin, melee reach, occluded builds, input starvation/backlog and block spacing are log-only until their [anticheat] enforce_* switch is set.
  • Statistical report (headshot share, accuracy percentile, aim snap, reaction time, pellet-seed skew) → logs/anticheat.jsonl, reviewed with /acreport; never kicks, never analyses bots.

Fairer spawns

Spawns avoid enemies who can see them, move away from a camped base, use the retail indoor spawn areas, and you can always spawn even when the base has been dug down to the water.

  • 3 seconds of spawn protection that ends as soon as you attack or pick up an objective.
  • Players hiding out of bounds, under the map or sealed in blocks show up on the minimap.
  • Objectives buried or sealed away return home after 5 seconds.
Technical details
  • Spawn scoring by enemy distance and line of sight, recent teammate deaths, stacking and squad support; choose_team_spawn p99 3.6 ms in the soak.
  • Retail spawn boxes are volumes (MayanJungle temple, SpookyMansion floors, zombies rising from the sea ring).
  • Respawn time stays at 5 s by choice; retail used 10 s.

Weapons use the original Steam values

Damage, fire rates, reloads, ranges and explosion radii now come from the original Steam game instead of the modded numbers in an old decompile. Limb hits no longer do torso damage.

  • Pistol 0.4 s between shots with a 0.6 s reload; pickaxe 40 damage; spade swings every 0.8 s.
  • Explosions follow the retail damage curve and check line of sight; your own blasts hurt you half as much.
  • Molotovs leave burning blocks; chemical bombs leave green goo that dissolves blocks and burns players.
  • Miners carry one dynamite; RPG2 has 6 rockets per life; ammo crates top up grenades and launchers instead of resetting them.
Still open
  • Range falloff and block penetration were never recovered, so they are not applied.
Technical details
  • Values read by executing the stock aos.pkg weapon classes under Py2.7; damage tuple (TORSO, HEAD, ARMS, LEGS, LEGS); head and class multipliers apply to the victim.
  • ExplosionDamageManager D·(R²−d²)/R² with rays weighted 0.5/0.3/0.2; stock radii dynamite 8, landmine 6, RPG 6.
  • The native client's weapon catalog was regenerated from the same values so the server no longer rejects extra shots and swings.

Blocks, damage and prefabs match between players

Every block has the same health on every screen, craters look identical for everyone (including players who join later), damaged blocks darken like retail, and other players' prefabs no longer create invisible walls.

  • Map blocks break in one spade hit, built blocks need two — one in Classic CTF, like retail.
  • Prefabs appear whole in a single frame for everyone.
  • Digging credits your block wallet.
Technical details
  • One block-health model: map voxels 5, user and prefab blocks 9, packet-33 cells 3, scaled by RULE_BLOCK_HEALTH.
  • Exact Damage(37) footprints for all 44 damage types from a live capture; BlockManagerState(38) carries health and shading to joiners.
  • Live check 2026-09-27: a late joiner's view of a grenade crater differed from the original by 0.04/255 mean pixel difference.

Parachute and jetpacks

Press SPACE in the air to open a parachute, as in retail. Jetpacks burn to empty and drop you without snapping you back, and other players now visibly wear their jetpacks.

  • The chute opens while falling with at least 6 blocks of room, once per fall.
  • Fall damage can no longer be erased by opening the canopy on the last frame.
  • Rocketeer and Engineer bots use their jetpacks to climb ledges.
Still open
  • A small forward nudge (~0.26 blocks) remains once per jetpack burn.
  • Bots never open a parachute.
Technical details
  • Canopy owner handoff at max(S+3, N+2) + RTT·60; jetpack_activation_defer_frames 2, jetpack_exhaustion_tail_frames 3.
  • Live pass 2026-09-27: SPACE from z 140 opened the canopy with a smooth descent; jetpack 66 burnt to empty with 0 position corrections.

Crate airdrops and class gear

Supply crates parachute in from the sky with their fly-by and landing sounds, radar stations last 45 seconds, and the Engineer offers the seven stock constructs.

  • You can grab a crate while it is still falling.
  • Scouts see enemies near their radar station on the minimap.
  • TDM and Zombie survivors get the six stock classes in retail order.
Technical details
  • Server mirrors the crate fall (30 blocks/s², 0.75 slowdown between 10 and 2 blocks above support); drop altitude and fly-by variant are inferred.
  • Radar detection is client-side within 250 blocks; TeamMapVisibility(83) is no longer sent.

Sounds, music and reverb

Retail-style reverb that changes with where you stand, rebalanced gunshots, footsteps and explosions, ambience that follows the map, and music that fades like the original. Music that sometimes never started after joining is fixed.

  • New server cues for intel, bombs, diamonds, captures and airstrikes; last-survivor and survivor-win music.
  • A freeze on the team screen after a map change (a stock client audio bug) is fixed.
  • Up to 128 sounds at once, like retail.
Still open
  • The round-4 audio changes have not been play-tested live yet.
Technical details
  • Server sends a silent PlaySound flush before every music switch, ambience registration, packet 53 and packet 52; join audio goes out before the terrain catch-up.
  • Client: GameScene.update_audio_effects port (dynamic reverb), weapon report gain 0.5, rolloff 0.15, reference distance 1.0, occlusion resolver removed, StopMusic fades over 6.5 s.
  • The in-round music bed is kept on purpose; servers can switch it off with [audio] mode_start_music = false for retail silence.

HUD, menus, vote kick, class select and key bindings

The HUD and menus now follow the retail layout and wording: chat colours, the big-text queue, localised labels, a working vote-kick screen, a class menu driven by the server's class data, and key names that follow your own bindings.

  • Press K to start a vote kick: pick a player, then a reason.
  • The ‘,’ and ‘.’ keys open the class and team menus from the game.
  • Disconnect reasons are shown in plain words (server full, banned, out of date…).
  • The server browser no longer wipes your selection every 10 seconds and remembers your region.
  • Volume and sensitivity controls, the in-game Favourite button and chat up to 200 characters all work properly.
Still open
  • Machine-gun deploy HUD, 3D labels for turret ammo and radar lifetime, and the English “JOIN” prefix on the team button.
Technical details
  • Chat lanes and colours from process_packet_chat_message / localised_message; HUD.add_big_message queue semantics (1.5 s minimum dwell, newest first, 5-row cap).
  • ForceShowScores(72) now stops movement and input; TeamLockScore(81) enforced; TeamMapVisibility index fixed.
  • Live pass 2026-09-27: TDM HUD, class scrollbar, Engineer constructs, vote-kick screen, Settings key names, CTF/Diamond carry and TC bars compared with retail.

Graphics: a RETAIL look by default

New installs start on the RETAIL graphics tier, which uses the original lighting, fog and ambient occlusion. The enhanced tiers stay one click away and now light player models and weapons from the map.

  • Server fog is respected in every graphics tier.
  • Jetpacks, classic corpses and carried intel are drawn on other players; team colours use the retail half-intensity tint.
  • Diamonds, dropped intel and armed bombs show their countdown labels.
Still open
  • Flare blocks do not cast their light pools in the RETAIL tier yet.
Technical details
  • Compatibility tier shown as RETAIL (decision D1); local horizon fog no longer overrides server fog (D2).
  • Enhanced tiers: map light on KV6 models, warm shot light at the muzzle; the RETAIL tier keeps retail exactly (no shot light).

View models, muzzle flash and tracers

Every weapon and tool is held exactly like retail in first and third person, the muzzle flash sits on the end of the barrel instead of filling the screen, and tracers are drawn one per pellet.

  • Other players' weapons recoil and their melee swings animate.
  • Sniper rifles show no flash when aimed, like retail.
  • Shotgun blasts draw a fan of tracers.
Still open
  • No live side-by-side capture with retail yet; the deployed machine-gun flash and the minigun's remote barrel spin are not ported.
Technical details
  • Retail holds (initial_position/orientation, arms offset) for all 65 tools; third-person arm pitch follows Character.draw (+50 when the tool is hidden).
  • Per-weapon muzzle_flash_view_offset / aimed offset / scale / duration; tracers begin 16 blocks out, one per replicated pellet.

Retail death camera

When you die the camera looks at your killer, follows them on a streak, or lets you fly around while you wait — the same death, chase and fly cameras as retail.

  • Recoil also follows the retail kick, stance modifiers and side sway.
Still open
  • Waiting on a live play-test.
Technical details
  • DeathController (camera 5), ChaseController and FlyController; chase unless the killer's streak ≥ 2, fly toward the killer from a streak of 3.

Smoother play on real connections

A single lost input packet used to leave you one frame behind for the rest of the match. The server now fills the gap, so movement stays smooth on ordinary internet connections.

  • Players joining mid-match see the current terrain straight away instead of watching it “sync”.
  • Your scoreboard ping is real, and bots show a believable one.
  • Hits are checked against where targets were on your screen (lag compensation).
Still open
  • Lag compensation has not been tested on real internet ping yet.
  • In busy fights one lost packet can still briefly freeze other players on screen (needs a second channel the stock client cannot read).
Technical details
  • ClientData is ENet UNSEQUENCED like retail; the server simulates missing labels with the held input (input_gap_fill_limit 8). At ~80 ms RTT with 0.5% loss, corrections fell from 145 to 0–1.
  • The per-second countdown is sent unreliably so it cannot stall world updates behind a lost reliable packet.
  • map_air_catchup_enabled = false: 1310 probed dug cells, 0 mismatches without the replay.

Connection watchdog and clearer join errors

If a server stops answering you get the retail “Disconnect in …” countdown instead of a frozen game, and a failed join returns you to the menu with a clear reason.

  • The client checks your local copy of a map and skips the download when it is identical.
  • The loading screen shows each step: checking, loading, receiving and syncing the map.
Still open
  • The watchdog countdown and CRC-matched joins still need a live check.
Technical details
  • RetailConnectionWatchdog after 300 silent loops; 5 s ENet connect timeout (DISCONNECT 11), then a 30 s no-progress timer.
  • MapDataValidation answered with the zlib CRC32 of <assets>/maps/<file>.vxl for full 512×512×240 maps.

Maps, memory and server stalls

Big maps use a fraction of the memory, map changes no longer freeze the server, and explosions no longer cause lag spikes.

  • MayanJungle went from 286 MB to 27 MB of server memory and loads in 0.68 s instead of 1.8 s.
  • A 94-minute soak across all 28 maps and every mode ran with zero errors.
Still open
  • The soak showed a one-time ~40 MB memory step; a 6-hour soak is owed before calling 512 MB hosts safe.
Technical details
  • Per-column fill colour: implicit interior voxels no longer get colour-table entries.
  • nogil VXL loader and a C collapse walk: explosion cost 15–340 ms → 0.3–8 ms under bot load.

Bots

Survivor bots in Zombie now pick a high refuge and wall it in together, bots balance their skill to how the humans are doing, and they handle every mode's objectives better.

  • Bot names read like players.
  • Bots hold fire on spawn-protected players and dig at the real melee speed.
  • A bot steps out when a human needs the slot.
Still open
  • Zombie bots cannot climb into a walled refuge yet, and the rampart ring has no door.
Technical details
  • Zombie refuge election from the .botnav atlas and BlockLine ramparts on a 9×9 ring (smoke run: 0 → 22 wall runs, 0 survivor deaths).
  • Per-team skill balance bounded by skill_balance_* within the configured difficulty band.

Team balance and map vote

Joiners go to the smaller team, uneven teams are fixed between lives (bots first, never a live player or objective carrier), and the map vote offers maps sized for the lobby.

  • Vote kicks need three humans on your team and tell you why they were refused.
  • A full server says “server full” instead of “server out of date”.
Technical details
  • Vote-kick cooldowns 300 s per starter and 45 s after a cancelled vote; bots do not count toward the 3-player minimum.
  • Full-server refusal uses DISCONNECT.ERROR_FULL (4); Beta 0.1 hosts send 3 until updated.

Friends and invites (AoSPlay)

Accepting a friend request was failing for everyone, busy lobbies froze the friends list, and inviting a friend who was already in a lobby did not work. The AoSPlay backend fix has been live since 28 September, so accept and decline work now; the client improvements below ship with the next client build.

  • Friend requests and invites show up within a couple of seconds, with counts on the tabs.
  • Accept an invite while you are in another lobby (LEAVE + JOIN).
  • Invite friends who are offline — the invite waits 10 minutes.
  • A slow or failed connection no longer greys out the whole menu.
Still open
  • The client improvements (LEAVE + JOIN, INVITE (OFFLINE), tab counts, retries) ship with the next client build; a two-player test on the live service is still owed.
Technical details
  • Backend: typed parameters fix PostgreSQL 42P08 on accept/decline; sync pages of 100 events resume at the newest event; lobby writes refresh presence; expiry sweep throttled to once per 5 s.
  • Client: 2 MiB response limit, retries for idempotent writes on 502/503/504, polls cannot starve behind writes, 1.5 s polling while the Friends screen is open.
  • Harness run at 1.1–2.0 s latency with 8% injected 504s: 0 failures.

Steam: Join Game, invites and sign-in

Join Game and Invite to Game from your Steam friends list now open the game and connect you — even when it was closed — and the Sign in through Steam button no longer disappears at random.

  • The sign-in button shows “Connecting to Steam…” and appears on its own if Steam starts later.
  • Friends are never sent to 127.0.0.1 any more.
  • Leaving a match clears your Steam join status.
Still open
  • Needs a two-account, two-machine test with the new build.
Technical details
  • Presence publishes “+connect steam:<host>” or “+connect host:port” for public servers; handles GameRichPresenceJoinRequested_t, GameLobbyJoinRequested_t and launch parameters in both Steam runtimes.
  • Bridge: SteamAppId set before loading the DLL, protocol on a private handle, non-blocking start with 10 s retries.
  • If you ever ran the no-Steam retail client, restart Steam once — its emulator can leave a stale Steam registration.

Client beta builds and Steam groundwork

Next client build

Committed to the client after the Beta 0.1 download (development builds are labelled 0.1.0-beta.3) and shipping with the next client build. The client picked up Steam: it shows you as in-game, hosts and joins player matches over Valve's relay network, and reports its statistics under Ace of Spades itself.

Host and join matches through Steam

Create a match in the client and friends can join through Valve's relays, with AoSPlay's relay as the fallback. A friend's Steam match shows up in the server browser.

  • The game attaches to Steam at launch, so friends see you in-game.
  • Retail achievement names and statistics are reported as Ace of Spades, never as Spacewar.
Technical details
  • SteamNetworkingSockets relay transport listening on the virtual port Steam routes; first PC ↔ Mac joins on 2026-09-23.
  • Join tickets are requested without holding the service lock; a joiner can no longer hang on “Authorizing with AoSPlay”.

Client quality fixes

Install folders with Cyrillic names work, chat counts characters rather than bytes, and a timestamped support log is written on Windows and macOS.

  • The client shows why a server refused your join.
Technical details
  • UTF-8 Windows paths; chat cut on UTF-8 boundaries; support log opened shared so it can be read during a session.

Beta 0.1

Live

The first beta. Every official server moved from the alpha series to BattleSpades Beta 0.1 behind a health check, with no restore needed.

Bots that fight and move like players

Bots run, flank, take cover and fight like players instead of standing still or spinning in place.

  • They keep a slot free for humans and swap out when someone joins.
Technical details
  • Locomotion pass: 4.4 → 7.5 blocks/s and far fewer direction wags; combat realism pass measured with bot review scripts.

Lighter servers

A loaded map costs about 50 MB instead of 235 MB, which brought the small European servers back online.

Technical details
  • Voxel colours moved from a Python dict to a flat open-addressing table; byte-identical after 60,000 random edits on four retail maps.

Identical physics on every platform

Linux and macOS servers now calculate movement bit-for-bit like the retail game, exactly as Windows does.

Technical details
  • Built with -fno-fast-math -ffp-contract=off: all 2040 retail parity cases pass on every platform.
Something not working the way it says here?

Tell us on Discord.

Report a bugHow to report