Notes
- client: the game server
- server: the admin panel
- All integers are little-endian, all strings are null-terminated
- Enums are shown in light blue, responses are in light pink, records are in light purple
- Fields with asterik* are always present, if not present, it may not be sent
Connection Flow
Once a socket connection is established, the client (the game server), will send a Auth Record, and the server will either respond with an OK Response, or an Error Response (with an optional message). Once the client gets the OK, it will perform a full sync and send these group of records:
- Game Record
- Finale Record (if finale active)
- Player Record (per player)
- Survivor Record (if survivor)
- Survivor Item Record (if survivor)
- Infected Record (if infected)
The server then will send specific records when they occur (play joins: PlayerRecord, map changes: GameRecord, etc).
Data Types
All data types are little-endian and signed
Name | Value |
Byte | 8-bit signed little-endian integer |
Short | 16-bit signed little-endian integer |
Int | 32-bit signed little-endian integer |
Float | 32-bit signed little-endian float |
String | Null-terminated ASCII String |
Enums
SurvivorState
Bitfield, can be any combination of values (besides None)
Name | Value |
None | 0 |
Black & White | 1 |
In Saferoom | 2 |
Is Calm (intensity = 0) | 4 |
Is Boomed | 8 |
Is Pinned (by special infected) | 16 |
Alive | 32 |
SurvivorMovement
Name | Value |
Idle | 0 |
Incapped | -1 |
Hanging From Ledge | -2 |
Under Attack (SurvivorState.IsPinned should be set) | -3 |
Walking | 1 |
Running | 2 |
Crouched | 3 |
On Ladder | 4 |
SurvivorAction
Name | Value |
None | 0 |
Being Healed | -1 |
Healing | 1 |
Deploying Ammo Pack (unused) | 2 |
Defibbing Teammate | 4 |
Being Defibbed | 5 |
Deploying Fire Ammo | 6 |
Deploying Explosive Ammo | 7 |
Pouring Gas | 8 |
Delivering Cola | 9 |
Pressing Button | 10 |
UsePointScript | 11 |
Builtin Commands
When a Run Command Response is sent, these are the available commands for the builtin
namespace. The format is namespace:command
<param>
indicates a required parameter (<> should not be included)[param]
indicates an optional parameter ([] should not be included)- Any string with spaces should be surrounded with quotes, “my argument”, otherwise it will be split as another argument
Command | Description |
| Informs the server to exit. This ignores if there are any players online. he sourcemod plugins runs |
| Asks the server to stop. If there is players, the Command Response record's result will be 0, if successful, will be 1. |
| Kicks the player. If game server is sourcemod, then can be STEAM_#_#_##### or #userid |
| Bans the player. If game server is sourcemod, then can be STEAM_#_#_##### or #userid. Time will determine how long, 0 for permanent. |
| Returns the number of players, mostly used for testing |
| Removes lobby reservation on compatible source engine servers |
| Not sent to server, but admin panel can start servers when it detects this. |
Packets
Server → Client Packets (Responses)
LiveRecordResponse Enum
Name | Value |
OK | 0 |
Reconnect | 1 |
Error | 2 |
Refresh | 3 |
RunCommand | 4 |
The types Reconnect, Error, and Refresh have no extra arguments, only the response type field is needed
Response: OK
Sent periodically (as a heartbeat) and when the view count changes
Field | Type | Value |
Response Type* | Byte | LiveRecordResponse.OK (0) |
View Count* | Byte | The number of current viewers of live view |
Response: Reconnect
Informs the client to reconnect. The client should wait a few seconds before performing, as this response is used from panel when it is restarting.
Field | Type | Value |
Response Type* | Byte | LiveRecordResponse.Reconnect (1) |
Response: Error
An error occurred, with an optional message. If during first Auth Record, then indicates auth failure, otherwise any other type of error.
Field | Type | Value |
Response Type* | Byte | LiveRecordResponse.Error (2) |
Message* | Byte | An optional message for the error. Blank for no message. |
Response: Refresh
Requests the client to give a full refresh, same as what is performed after successful authentication ((Game+Finale) + Player + (Survivor+SurvivorItems | Infected)) |
Field) | Type | Value |
Response Type* | Byte | LiveRecordResponse.Refresh (3) |
Response: Run Command
Runs a command on the client (game server). The client will return a Command Response Record if the command exists, or an Error Record if it does not.
Namespace is optionally, send a single null terminator to use default. Command Response Records should be sent in order, but an ID can be set to verify as well.
Field | Type | Value |
Response Type* | Byte | LiveRecordResponse.RunCommand (4) |
ID* | Byte | An id for the command, the Command Response Record will contain the same id. |
Command* | String | The command to run |
Namespace* | String | Optional. The namespace of commands, default is "default" or blank, or "builtin" (see Builtin Commands) |
Client → Server Packets (Records)
Multiple records can be included per packet, each record has a header of it’s size, then it’s type. It’s then followed by an ASCII separator 0×1E
which is just useful for debugging purposes.
Sometimes the plugin may send multiple group of records together, they will be separated by 0×0A
(new line), but you should only rely on the size of records.
LiveRecordType Enum
Name | Value |
Game | 0 |
Player | 1 |
Survivor | 2 |
Infected | 3 |
Finale | 4 |
Survivor Items | 5 |
Command Response | 6 |
Auth | 7 |
Meta | 8 |
Record Headers
Field | Type | Value |
Length* | Short | The length of the following record, excluding these bytes. |
Type* | Byte | The type of the record |
Record: Auth
This is only sent on once, on initial connection.
Field | Type | Value |
Type* | Byte | LiveRecordType.Auth (7) |
Version* | Byte | The version of the plugin protocol |
Token* | String | JWT token, generated from panel |
Port | Short | The port the server is running on, for panel to link plugin to server on that port |
Game Version | String | Version of the game |
Record: Command Response
The value of the Result field is determined by the Response Type field.
For non-builtins, response type is always 0 and result is always 1 (unless command does not exist)
Field | Type | Value |
Type* | Byte | LiveRecordType.CommandResponse (6) |
ID* | Byte | The ID that was specified when command was sent |
Response Type* | Byte | -1: Result is an error 0: No response 1: Result is a boolean 2: Result is a int 3: Result is a float |
Result* | Byte | The result of the command, can be boolean or a number. |
Message* | String | The raw text response, may be blank. |
Record: Game
Sent every time a map is loaded, and when starting a transition.
Can be re-sent by sending a Refresh response
Field | Type | Value |
Type* | Byte | LiveRecordType.Game (0) |
Start Timestamp* | Int | Unix timestamp (seconds). When the plugin has started, which can be used as server uptime |
Campaign Start Timestamp* | Int | Unix timestamp (seconds). When the current campaign has started |
Difficulty* | Byte | The difficulty level, in order: Easy(0), Normal(1), Advanced(2), Expert(3) |
State* | Byte | Enum, in order: None, Transitioning(1), Hibernating(2) |
Max Players | Byte | The maximum amount of players that can join. |
Gamemode* | String | The current gamemode |
Map* | String | The current map |
Record: Player
Typically, this record is followed with either SurvivorRecord + SurvivorItemsRecord
or InfectedRecord
unless the state is Disconnected
Field | Type | Value |
Type* | Byte | LiveRecordType.Player (0) |
User ID* | Int | User ID (auto incremented for each user, for a duration of a session) |
SteamID* | String | User's SteamID 2 (STEAM_#:#:#######). Is "BOT" if a fake client |
Player State | Byte | Enum, in order: [0] Normal / In-Game [1] Connected [2] Disconnected [3] Idle |
Join/Leave Timestamp | Byte | Unix timestamp (seconds). If state is Disconnected, is the time when the player disconnected Otherwise, the time will be when the player first joined the campaign. It should not reset on transitions, but it can. |
Name | String | The player's name. |
Record: Survivor
Represents a survivor. If a player is idle, this will be the idle player’s bot’s data.
Field | Type | Value |
Type* | Byte | LiveRecordType.Player (1) |
User ID* | Int | User ID (auto incremented for each user, for a duration of a session) Is the same as the Player record |
Survivor* | Byte | The survivor type 0=Nick, 1=Rochelle, 2=Coach, 3=Ellis 4=Bill, 5=Francis, 6=Zoey, 7=Louis |
Temp Health* | Byte | Temp health, from pills/adrenaline |
Permanent Health* | Byte | Permanent health, assumed to be max 100. |
Flow Progress Percent* | Byte | How far through a campaign as a percent (0-100) the player is. Can go up/down |
Survivor State* | Byte | Survivor state enum, see below |
Movement State* | Byte | Survivor movement enum, see below |
Survivor Action* | Byte | Survivor action enum, see below |
Record: Survivor Items
Slots may be empty (and only include a single null terminator).
Slot 1, if the weapon was weapon_melee, the melee weapon’s name will be given instead. All other weapons retain their weapon_ prefix
Field | Type | Value |
Type* | Byte | LiveRecordType.SurvivorItems (5) |
User ID* | Int | User ID (auto incremented for each user, for a duration of a session) |
Slot 0* | String | The weapon in slot 0 (primary) |
Slot 1* | String | The weapon in slot 1 (secondary, pistols) |
Slot 2* | String | The weapon in slot 2 (throwables) |
Slot3* | String | The weapon in slot 3 (kit/ammo packs) |
Slot 4* | String | The weapon in slot 4 (pills / adrenaline) |
Slot 5* | String | The weapon in slot 5 (any carryables, ex. gascans, gnome) |
Record: Infected
Represents a player-controllable special infected.
There is never a record for Infected with special type witch (7), as it’s not a player-controllable enemy.
Field | Type | Value |
Type* | Byte | LiveRecordType.Infected (3) |
User ID* | Int | User ID (auto incremented for each user, for a duration of a session) |
Current Health* | Short | The infected's current health |
Max Health* | 1Short | The infected's maximum health, such as for tanks |
Special Type* | Byte | Enum, starting at 0, in order: Smoker(1), Boomer(2), Hunter(3), Spitter(4), Jockey(5), Charger(6), Witch(7), Tank(8) |
Victim User ID* | Byte | If infected has a victim (hunted player, smoked player, etc), their user id. |
Record: Finale
Sent every time the finale stage changes, indicates the finale is active
Field | Type | Value |
Type* | Byte | LiveRecordType.Finale (4) |
Finale Stage* | Byte | The current finale stage |
Escape Vehicle Active* | Byte | Is the finale escape vehicle ready? |
Record: Meta
Field | Type | Value |
Type* | Byte | LiveRecordType.Meta (8) |
Steam State | Byte | Boolean, does server have connection to steam? |