At its basic level, a server message consists of the ID of the last client command that it received along with a list of server operations. There are several different types of server operations. To identify which type of operation it is, each operation in the list starts with an 8-bit identifier code. The last operation in the list is identified with a special EOF code.
Structures
top-level format
nop
8 bits |
0x01 nop indicator
|
gamestate
8 bits |
0x02 gamestate indicator
|
32 bits |
server's last command ID
|
(<configstring> | <baseline>)*
|
8 bits |
0x08 EOF indicator
|
32 bits |
client ID
|
32 bits |
randomly generated checksum seed value
|
configstring
8 bits |
0x03 configstring indicator
|
16 bits |
config ID
|
string |
config value
|
baseline
8 bits |
0x04 baseline indicator
|
<entity>
|
server-command
8 bits |
0x05 server-command indicator
|
32 bits |
command ID
|
string |
command value
|
download
8 bits |
0x06 download indicator
|
16 bits |
block number
|
if {block number} == 0x0000: // first block
|
32 bits |
file size
|
if {file size} == 0xFFFFFFFF: // error indicator
|
|
else
|
16 bits |
block size
|
data |
data stream, {block size} bytes long
|
|
|
else
|
16 bits |
block size
|
data |
data stream, {block size} bytes long
|
|
snapshot
8 bits |
0x07 snapshot indicator
|
32 bits |
server time
|
8 bits |
last frame num
|
8 bits |
snapshot flag bits
|
8 bits |
area mask size
|
data |
area mask, {area mask size} bytes long
|
<player-state>
|
<entity>*
|
10 bits |
0x3FF end of entities indicator
|
entity
10 bits |
entity ID
|
1 bit |
removed-entity indicator
|
if removed-entity != 0x1:
|
1 bit |
changed-entity indicator
|
if changed-entity == 0x1:
|
8 bits |
max changed field index
|
loop {max changed field index} times:
|
1 bit |
changed-field indicator
|
if changed-field == 0x1:
|
1 bit |
is-not-zero indicator
|
if is-not-zero == 0x1:
|
|
else:
|
|
|
|
|
|
int-value
N bits |
value, where N depends on field index
|
float-value
1 bit |
full-float indicator
|
if full-float == 0x1:
|
32 bits |
value, as C float
|
|
else:
|
13 bits |
value, as unsigned int; subtract (1<<12) to return signed int
|
|
If a field has floating point values, but its current value is a small integer (< ±4096) without a fractional part, then it is transmitted as a 13-bit unsigned integer instead of transmitting it as a full 32-bit float. To convert a small signed integer that is between -4096 and 4095 to a 13-bit unsigned integer, we simply add 4096 (1<<12) to the number before we send it and then subtract 4096 after it's received.
player-state
8 bits |
max changed field index
|
loop {max changed field index} times:
|
1 bit |
changed-field indicator
|
if changed-field == 0x1:
|
|
|
1 bit |
changed-state indicator
|
if changed-state == 0x1:
|
|
values
1 bit |
changed-values indicator
|
if changed-values == 0x1:
|
16 bits |
changed value bitmask
|
loop for each bit set in {changed value bitmask}:
|
|
|
See also