Messages
Demo messages are stored in sequential order as the engine records them. A message always starts with a tagged type followed by the current session tick, a slot index and the type-specific message data.
- Overview
- C
- C++
- C#
- JS
- TS
- Go
- Rust
- Zig
Name | Type | Size in bytes | Size in bits | Value |
---|---|---|---|---|
Type | MessageType | 1 | 8 | - |
Tick1 | int | 4 | 32 | - |
SlotNE 2 | byte | 1 | 8 | - |
Data | MessageData | - | - | - |
1 Old engines might not even include the message tick after the stop byte. |
2 The term slot here refers to the selected split-screen index. This byte is only used in engines which support split-screen mode.
typedef struct {
message_type type;
int tick;
char slot;
message_data_t* data;
} message_t;
struct message_t {
message_type type;
int32_t tick;
std::byte slot;
message_data_t* data;
};
class Message {
public MessageType Type { get; set; }
public int Tick { get; set; }
public byte Slot { get; set; }
public MessageData Data { get; set; }
}
class Message {
/** @type {MessageType} */
type;
/** @type {number} */
tick;
/** @type {number} */
slot;
/** @type {MessageData} */
data;
}
export class Message {
public type?: MessageType;
public tick?: number;
public slot?: number;
public data?: MessageData;
}
type Message struct {
Type MessageType
Tick int32
Slot int8
Data MessageData
}
pub struct Message {
pub r#type: MessageType,
pub tick: i32,
pub slot: i8,
pub data: MessageData,
}
const Message = struct {
type: message_type,
tick: i32,
slot: i8,
data: message_data,
};
Types
- Overview
- C
- C++
- C#
- JS
- TS
- Go
- Rust
- Zig
Type | Value | Description |
---|---|---|
SignOn | 1 | - |
Packet | 2 | - |
SyncTick | 3 | - |
ConsoleCmd | 4 | - |
UserCmd | 5 | - |
DataTables | 6 | - |
Stop | 7 | - |
CustomData | 8 | - |
StringTables | 9 | 8 for old engine. |
enum message_type {
MT_SIGN_ON = 1,
MT_PACKET = 2,
MT_SYNC_TICK = 3,
MT_CONSOLE_CMD = 4,
MT_USER_CMD = 5,
MT_DATA_TABLES = 6,
MT_STOP = 7,
MT_CUSTOM_DATA = 8,
MT_STRING_TABLES = 9,
};
enum class message_type {
SIGN_ON = 1,
PACKET = 2,
SYNC_TICK = 3,
CONSOLE_CMD = 4,
USER_CMD = 5,
DATA_TABLES = 6,
STOP = 7,
CUSTOM_DATA = 8,
STRING_TABLES = 9,
};
enum MessageType : byte {
SignOn = 1,
Packet = 2,
SyncTick = 3,
ConsoleCmd = 4,
UserCmd = 5,
DataTables = 6,
Stop = 7,
CustomData = 8,
StringTables = 9,
};
const MessageType = {
SignOn = 1,
Packet = 2,
SyncTick = 3,
ConsoleCmd = 4,
UserCmd = 5,
DataTables = 6,
Stop = 7,
CustomData = 8,
StringTables = 9,
}
export enum MessageType {
SignOn = 1,
Packet = 2,
SyncTick = 3,
ConsoleCmd = 4,
UserCmd = 5,
DataTables = 6,
Stop = 7,
CustomData = 8,
StringTables = 9,
}
type MessageType byte
const (
SignOn MessageType = 1,
Packet = 2,
SyncTick = 3,
ConsoleCmd = 4,
UserCmd = 5,
DataTables = 6,
Stop = 7,
CustomData = 8,
StringTables = 9,
)
pub enum MessageType {
SignOn = 1,
Packet = 2,
SyncTick = 3,
ConsoleCmd = 4,
UserCmd = 5,
DataTables = 6,
Stop = 7,
CustomData = 8,
StringTables = 9,
}
const MessageType = enum {
sign_on = 1,
packet = 2,
sync_tick = 3,
console_cmd = 4,
user_cmd = 5,
data_tables = 6,
stop = 7,
custom_data = 8,
string_tables = 9,
};
Pseudocode Example
To keep this example simple the stop message might contain additional data which is not read here. We also ignore the fact that that reading past the buffer might be possible when parsing corrupted demos.
loop {
let message_type = read_le_i8();
if message_type == 0x07 {
break;
}
let tick = read_le_i32();
let slot = read_le_i8();
read_message_data(message_type);
}