Round-trip clock synchronization. The server returns its loop count while keeping the retail client one simulation tick ahead.
client_time · server_loop_count
Binary field manual
A source-checked catalog of all retail Ace of Spades: Battle Builder packet IDs: direction, field order, encoding, byte width, implementation status, and the corrected layouts observed by the BattleSpades runtime.
The layouts below describe the decoded application packet. Byte zero is always the one-byte packet ID. ENet transport headers, the outer 0x30/0x31/0x32wrapper, LZF chunk framing, and any compression savings are not included in the displayed size.
Most numeric values are little-endian. A fixed16consumes two bytes and stores a sign-magnitude value at 1/64 precision. Orientation uses its own measured 1/8192 encoding. Strings are UTF-8-compatible bytes terminated by 00.
ENet → wrapper prefix → LZF chunks → packet ID → payload
Search by ID, packet name, field, feature, or behavior. Open an entry for its complete layout in exact wire order.
Round-trip clock synchronization. The server returns its loop count while keeping the retail client one simulation tick ahead.
client_time · server_loop_countRequests a Miner dynamite placement. The server validates tool, stock, range, and support before creating entity type 10 and owning the fuse and blast.
loop_count · position · faceThe 30 Hz unreliable snapshot stream for remote players, moving entities, and rocket turrets. P is the player count, E contains variable Entity records, and T is the turret count.
loop_count · player_count · players[].player_id · players[].position+17 fieldsA separate moving-entity delta stream retained in the retail protocol surface. BattleSpades currently carries entity changes through other active paths.
loop_count · entity_count · entities[]Buffered client input applied at its matching simulation tick. Bit 7 of the player byte enables the palette; bits 0–6 hold the player ID.
loop_count · player_and_palette · tool_id · orientation_x+6 fieldsSets local health for spawn, healing, or damage feedback and supplies a source direction for presentation.
hp · damage_type · source_positionA client firearm request. The server validates cadence, origin, orientation, weapon state, and penetration before resolving authoritative hits.
loop_count · shooter_id · shot_on_world_update · origin+5 fieldsRequests a block colour mutation. The server validates the paint tool, range, and voxel solidity, then journals the authoritative RGB change for late joiners.
loop_count · x · y · z+1 fieldsReplays a remote firearm shot for observers, producing the native muzzle, gunshot, and character animation without duplicating the shooter's local prediction.
loop_count · shooter_id · tool_id · shot_on_world_update+1 fieldsReports an authoritative player hit. All observers can show blood, while only the matching local shooter receives the hit-confirm sound and crosshair response.
damage_by · damaged · blood · positionUses an oriented item such as a legacy grenade-family object. The server validates the active tool, cadence, and stock before accepting or relaying it.
loop_count · player_id · tool · value+2 fieldsUpdates the selected palette colour for block, flare, and Block Cannon tools. The sender already applies its UI choice, so the server broadcasts to observers.
player_id · colorToggles the retail user-generated-content editor mode. The layout exists, but BattleSpades does not currently activate the UGC editor workflow.
modeSubmits a class, equipment list, prefab selection, and optional UGC tools as one life-boundary loadout transaction.
player_id · class_id · instant · loadout_count+5 fieldsLegacy roster-entry shape. BattleSpades intentionally sends CreatePlayer (28) for roster state because this packet stores pickup verbatim and has no safe 0xFF sentinel path.
player_id · demo_player · team · class_id+12 fieldsThe client's join announcement. Names are normalized to a case-insensitively unique 15-byte wire value before any CreatePlayer response.
team · class_id · forced_team · local_language+1 fieldsApplies one server-owned entity mutation: state, position, velocity, carrier, forward vector, target, fuse, or ammo.
entity_id · action · state · position+6 fieldsChanges an existing player's presentation state. Active modes use action 8 for a through-terrain/high-minimap marker.
player_id · action · high_minimap_visibility · chase_camMoves the client's point-of-interest focus marker to a world position.
target_positionRemoves an entity previously announced to the current GameScene.
entity_idInvokes the visual impact callback for an authoritative hit on a damageable entity.
entity_id · impact_position · typeCreates a map entity, light, deployable, pickup, or projectile. I and F are the integer- and fixed-property counts carried inside the record.
entity_id · entity_type · state · player_id+14 fieldsRegisters a map-owned ambient controller. Empty point lists create a global bed; authored points create local emitters.
name · loop_id · point_count · points[]Plays a one-shot or looping positional/UI sound, including pickup, round, kill, and observer-only block-tool cues.
sound_id · flags · volume · time+3 fieldsStarts the streaming ambient GameSound registered by packet 22 and supplies its playback flags, volume, time, position, and attenuation.
name · flags · volume · time+3 fieldsStops the looping sound associated with a loop ID.
loop_idStarts a named music track at an encoded playback offset.
name · seconds_playedStops the current music track.
ID-only packetCreates a player character and also serves as the active roster format. Class, loadout, and all selected prefab names come from one committed selection.
player_id · demo_player · class_id · team+9 fieldsSignals the builder that a queued prefab placement has finished.
ID-only packetRequests a bounded KV6 prefab expansion. The server validates selection, stock, world contact, reservations, orientation, and cell range.
loop_count · prefab_name · player_id · prefab_yaw+7 fieldsRequests a UGC prefab carve over a bounded block-index range, ultimately using the verified Damage (37) block-destroy path.
loop_count · player_id · prefab_name · from_block_index+2 fieldsPlaces one voxel using the player's current colour and the specified build type.
loop_count · player_id · x · y+2 fieldsPlaces one voxel with explicit RGB, used for prefabs, observers, terrain repair, and persistent Block Cannon impacts.
loop_count · player_id · x · y+2 fieldsMarks one voxel as occupied by a player/building workflow.
loop_count · player_id · x · y+1 fieldsRequests liberation/destruction of one voxel, primarily through the spade dig path.
loop_count · player_id · x · y+1 fieldsRequests the client to gib/explode a player's corpse for death presentation.
player_id · show_explosion_effectBroadcasts authoritative block or player damage. Damage type selects exact-cell, area, melee, drill, snowball, and other native expansion behavior.
player_id · type · damage · face+4 fieldsCarries BlockManager damaged, occupied, and user-owned dictionaries—not VXL topology or a removed-voxel resynchronization stream.
record_count · records[]A server-authored batch of compact block items. The recovered retail client path is currently a no-op stub.
record_count · records[].has_color · records[].coordinates · records[].colorThe retail 1.x client's normal multi-block placement request. The server rasterizes and validates the line between both voxel endpoints.
loop_count · player_id · x1 · y1+4 fieldsCreates a coloured, optionally tracking billboard/icon on the minimap.
entity_id · key · color · position+2 fieldsClears a minimap billboard by entity identifier.
entity_idCreates a bounded minimap zone and icon. BattleSpades uses it for the CTF base area at mode start and during late-join replay.
key · color · min_x · min_y+7 fieldsClears the minimap zone matching an exact six-coordinate voxel bounding box.
min_x · min_y · min_z · max_x+2 fieldsThe per-spawn GameScene snapshot: lighting, physics, mode, teams, class locks, prefabs, static entities, screenshot cameras, and rollover state.
player_id · fog_color · gravity · light_color+33 fieldsBroadcasts a death/kill event and its native HUD metadata.
player_id · killer_id · kill_type · respawn_time+3 fieldsOpens, updates, closes, or casts into the native kick/next-map vote overlay.
player_id · message_type · candidate_count · candidates[].name+4 fieldsRequests the start or cancellation path for a player kick vote.
player_id · target_id · reasonCarries player chat and server announcements. Types 0/1 are player channels, type 2 is a private system reply, and type 3 is the global top-screen CHAT_BIG presentation.
player_id · chat_type · valueDisplays a string-table announcement with positional parameters and optional parameter localization.
chat_type · localise_parameters · string_id · parameter_count+2 fieldsSelects the retail mesh-environment manifest used for sky, clouds, mist, waves, sun, transforms, and UV animation.
valueTriggers the native full-GameScene rollover boundary after end-of-round presentation and map preflight.
ID-only packetOpens the native end-of-round game-statistics screen when a compatible level screenshot exists.
ID-only packetBegins the legacy map-data transfer family. The active BattleSpades path uses MapSyncStart (55).
ID-only packetStarts the active VXL map synchronization stream, normally under wrapper prefix 0x32.
ID-only packetCarries one chunk in the legacy map-data transfer family.
percent_complete · data_size · dataCarries one bounded chunk of the active VXL map stream.
percent_complete · data_size · dataTerminates the legacy map-data transfer family.
ID-only packetTerminates the active VXL map stream and advances the loader handshake.
ID-only packetExchanges the map file CRC. The server answers with its authoritative file checksum before streaming.
crcStarts a legacy resource-pack transfer with its byte length and checksum.
size · checksumAcknowledges or rejects the pending resource-pack transfer.
valueCarries raw resource-pack bytes. No inner length prefix is present; the decoded packet boundary supplies the length.
dataRemoves a player slot from the current roster and scene.
player_idConfigures a generic capture/build progress bar with current progress, rate, and a two-colour gradient.
progress · rate · color1 · color2Describes one or more rank/score changes for end-of-match progression presentation.
rank_up_count · rank_ups[].score_reason · rank_ups[].old_score · rank_ups[].new_scoreBuilds the end-of-round scoreboard/statistics widget for a team and a list of typed player-stat rows.
stat_count · team_id · stats[].player_id · stats[].typeDefines custom UGC objective identifiers and integer values for a mode.
mode · objective_count · objectives[].id · objectives[].valueRefills one player resource category. Type 0 is full-life/general restock; physical ammo crates must use type 3.
player_id · typeConfirms an authoritative objective pickup and initializes the carried tool and burden state.
player_id · pickup_id · burdensomeRequests and replicates an objective drop with authoritative identity, position, and capped throw velocity.
loop_count · player_id · pickup_id · position+1 fieldsForces the scoreboard overlay open or releases that override.
forcedSelects one of nine hard-coded end/mode messages for a fixed duration; it is not an arbitrary-text packet.
message_id · durationOverrides the active fog colour and persists that override into later spawn/rejoin snapshots.
colorChanges the GameScene time-scale multiplier for a mode rule.
scaleRequests a reload and confirms its completion/state to clients.
player_id · tool_id · is_doneRequests a team switch for a player slot.
player_id · teamRequests a class switch for a player slot.
player_id · class_idLocks or unlocks joining a team.
team_id · lockedLocks or unlocks class selection for a team.
team_id · lockedLocks or unlocks score changes for a team.
team_id · lockedEnables or disables infinite block stock for a team.
team_id · infinite_blocksToggles team radar/minimap visibility while an authoritative radar station exists.
team_id · visibleUpdates the native HUD round countdown in seconds.
timerApplies a lightweight mid-game team or player score update to the HUD.
type · reason · specifier · valueRequests use of the nearest valid interactive object; BattleSpades uses it to mount or dismount an unoccupied machine gun.
ID-only packetRequests placement of a type-7 mounted machine gun. The server owns yaw, team, health, occupancy, and join persistence after validation.
loop_count · player_id · position · yawRequests an Engineer/Rocketeer turret placement. Target selection, projectile creation, health, and persistence remain server-owned.
loop_count · player_id · position · yawRequests a landmine placement. The server validates it, then owns the four-second arm time, buried proximity detection, and blast.
loop_count · player_id · positionRequests a type-30 MedPack placement. The server owns its three team uses, 25-HP increments, health, and destruction.
loop_count · player_id · position · faceRequests a type-36 radar station placement. The server owns its lifetime and team minimap reveal.
loop_count · player_id · positionRequests an oriented type-38 C4 placement with server-owned stock and ownership tracking.
loop_count · position · faceRequests detonation of only the sender's currently live C4 charges.
loop_countReplicates sanitized Block Sucker state while the server performs the authoritative timed voxel pull and block grant.
loop_count · shooter_id · state · shotRequests a loadout/tool-gated disguise state, later replicated through WorldUpdate state bit 0x02.
loop_count · activeDisables an entity without destroying or removing its scene record.
entity_idPlaces or removes a UGC object at a literal voxel coordinate.
loop_count · position · ugc_item_id · placingTransfers an initial batch of UGC scene objects.
item_count · items[].mode · items[].ugc_item_id · items[].x+2 fieldsRequests the UGC entity set for a game mode. The retail class name preserves its original `Reqest` misspelling.
game_mode · in_ugc_modeCarries a compact UGC workflow message identifier.
message_idReports UGC map-loading progress from the host.
percent_completeCarries length-prefixed PNG map information/preview data for a UGC map.
png_length · png_dataCarries one player's voice-chat frame.
player_id · data_size · dataRequests the flare tool's ten-block-cost voxel light placement. The server validates tool, range, contact, colour, and late-join persistence.
loop_count · positionThe retail client's first application handshake packet. It carries the opaque Steam session ticket that a Steam-enabled game server must validate before accepting the player's identity.
ticket_size · ticketUpdates a territory/base ownership and capture state for territory-control modes.
base_index · action · controlled_by · attacked_by+1 fieldsDraws temporary development primitives. Type 0 is a box, type 1 a sphere, and types 2–4 carry only the common header.
type · colour · frames · corner_min+3 fieldsConstrains a player or mode to a six-coordinate voxel zone.
min_x · min_y · min_z · max_x+2 fieldsSchedules one or more retail help/tutorial localization IDs after a delay.
delay · message_count · message_ids[]Reports whether the client is currently in a menu for handshake and idle gating.
in_menuCarries a NUL-terminated server password in the legacy authentication family.
passwordRequests that the client provide a server password.
ID-only packetSubmits the requested NUL-terminated server password.
passwordThe first loader packet: server identity, mode copy, map filename/checksum, presentation capabilities, rule toggles, disabled equipment/classes, movement multipliers, and ground palettes.
server_steam_id · server_ip · server_port · mode_name+45 fieldsForces the receiving player onto a team, optionally immediately.
team_id · instantA position-only input shape retained for compatibility tooling. The targeted retail 1.x client does not send it in normal play.
positionDisplays objective progress for a team as either a percentage or a numerator/denominator pair.
team_id · flags · percent · numerator+2 fieldsSets a counted per-team/per-surface ground-colour palette.
color_count · colors[]These are development-handler IDs, not original Protocol 168 packets. They stay outside the searchable retail catalog so another implementation cannot mistake them for a stable client contract.
Capture a clean retail client in one controlled scenario and preserve exact bytes and behavior.
Trace native/decompiled read and write order, constants, branches, and crash-sensitive sentinels.
Decode defensively, bound variable data, and keep transport, simulation, and presentation ownership separate.
Replay tests and two-client sessions before changing a field from provisional to live-verified.
Yes. Every size and formula on this page includes the one-byte application packet ID. ENet headers, the 0x30/0x31/0x32 wrapper prefix, LZF chunk framing, and compression effects are outside the listed size.
Most integers, fixed-point values, and floating-point values are little-endian. Colour triplets are written blue, green, red. HelpMessage is an unusual provisional exception whose recovered writer uses a big-endian float for delay.
No. Planned means a packet class exists in the recovered retail surface but BattleSpades does not activate it. Those entries are marked Provisional where a clean live-client capture or receiver-path validation is still missing.
Strings, lists, entity properties, map chunks, and other counted payloads are variable length. Their formulas show the fixed shell plus each repeated record, string terminator, or raw byte count.
No. IDs 241–243 are BattleSpades development-handler reservations for opt-in parity tooling. They are intentionally separated from the 119 retail IDs and do not claim a stable original-client wire layout.