List of snap items
Note there is also documentation about snapshots in libtw2.
The network messages NETMSG_SNAP, NETMSG_SNAPEMPTY and NETMSG_SNAPSINGLE
contain snapshots which represent the current game state.
The snapshot data contains snap items which represent things like tees, projectiles and similar.
All of those items are encoded as packed integers.
The snapshot is built by the server and sent to the client.
Size list
When it comes to byte layout that is sent over the network. There are two types of snap items:-
Known size snap items:
There is a list of snap item sizes that is fixed. That list is included in the client and server code. since both parties already know the size it won't be included in the snap. -
Unknown size snap items:
The items of which the client does not know the size yet. Will contain a size field in the snapshot data. Which is filled by the server.
Size list edge case
There are two snap items (obj_player_info_race and obj_game_data_race) that were added after the 0.7 release and their size is technically fixed and they should be included in the known size list. But since there was already a official client release without those items, they are intentionally removed from the list to stay backwards compatible. The client skips all items with a unknown type_id so the server can send snap items unknown to the client as long as the size is included so the client knows how many bytes to ignore.Snap item layout
+---------+----+-----------+
| type_id | id | payload.. |
+---------+----+-----------+
Every type_id has its own ids. So there can be a projectile with id 0 and a
character with id 0.
Here a fully annotated real sample snapshot with the raw bytes on the left
and annotations on the right. It was generated using the
teeworlds_network ruby library
Known size table
type_id | size | name | parameters | description |
---|---|---|---|---|
1 | 10 | obj_player_input |
int m_Direction; int m_TargetX; int m_TargetY; int m_Jump; int m_Fire; int m_Hook; int m_PlayerFlags; int m_WantedWeapon; int m_NextWeapon; int m_PrevWeapon; |
This is a special snap item that is not actually included in the snap.
But instead sent by the client in the system message
NETMSG_INPUT
The m_PlayerFlags field has the following flags:
|
2 | 6 | obj_projectile |
int m_X; int m_Y; int m_VelX; int m_VelY; int m_Type; int m_StartTick; |
desc |
3 | 5 | obj_laser |
int m_X; int m_Y; int m_FromX; int m_FromY; int m_StartTick; |
desc |
4 | 3 | obj_pickup |
int m_X; int m_Y; int m_Type; |
m_Type can be on of those:
|
5 | 3 | obj_flag |
int m_X; int m_Y; int m_Team; |
desc |
6 | 3 | obj_game_data |
int m_GameStartTick; int m_GameStateFlags; int m_GameStateEndTick; |
Possible m_GameStateFlags are:
|
7 | 2 | obj_game_data_team |
int m_TeamscoreRed; int m_TeamscoreBlue; |
desc |
8 | 4 | obj_game_data_flag |
int m_FlagCarrierRed; int m_FlagCarrierBlue; int m_FlagDropTickRed; int m_FlagDropTickBlue; |
The fields m_FlagCarrierRed and m_FlagCarrierBlue
hold either the client id of the person carrying the flag or a negative value.
The negative values have the following meanings:
|
9 | 15 | obj_character_core |
int m_Tick; int m_X; int m_Y; int m_VelX; int m_VelY; int m_Angle; int m_Direction; int m_Jumped; int m_HookedPlayer; int m_HookState; int m_HookTick; int m_HookX; int m_HookY; int m_HookDx; int m_HookDy; |
This item is not being sent in the snap directly.
It is only ever sent as part of obj_character.
So the snap item type id 9 is unused.
m_Jumped is more complex than on and off. There is 0 for off yes. But on is represented on the bit level. Here a snippet from the source code.
m_HookState has those possible values:
<Zwelf>
m_HookTick has the type NetTick
in protocol.py,
but is used as HookDuration. Starting with zero and incrementing one each tick until the roughly 60 ticks = 1.2s are passed.
|
10 | 22 | obj_character |
/* core */ int m_Tick; int m_X; int m_Y; int m_VelX; int m_VelY; int m_Angle; int m_Direction; int m_Jumped; int m_HookedPlayer; int m_HookState; int m_HookTick; int m_HookX; int m_HookY; int m_HookDx; int m_HookDy; /* character extension */ int m_Health; int m_Armor; int m_AmmoCount; int m_Weapon; int m_Emote; int m_AttackTick; int m_TriggeredEvents; |
m_TriggeredEvents can have any of those flags set
|
11 | 3 | obj_player_info |
int m_PlayerFlags; int m_Score; int m_Latency; |
Unpacked by the client in gameclient.cpp
CGameClient::OnNewSnapshot()
|
12 | 4 | obj_spectator_info |
int m_SpecMode; int m_SpectatorID; int m_X; int m_Y; |
m_SpecMode has one of those values:
|
13 | 58 | obj_de_client_info |
int m_Local; int m_Team; int m_aName[4]; int m_aClan[3]; int m_Country; int m_aaSkinPartNames[6][6]; int m_aUseCustomColors[6]; int m_aSkinPartColors[6]; |
Only used for demos |
14 | 5 | obj_de_game_info |
int m_GameFlags; int m_ScoreLimit; int m_TimeLimit; int m_MatchNum; int m_MatchCurrent; |
Only used for demos |
15 | 32 | obj_de_tune_params | int m_aTuneParams[32]; | Only used for demos |
16 | 2 | event_common |
int m_X; int m_Y; |
This item is not being sent in the snap directly. It is only ever sent as part of other events. So the snap item type id 16 is unused. |
17 | 2 | event_explosion |
int m_X; int m_Y; |
desc |
18 | 2 | event_spawn |
int m_X; int m_Y; |
desc |
19 | 2 | event_hammerhit |
int m_X; int m_Y; |
desc |
20 | 3 | event_death |
/* common */ int m_X; int m_Y; /* death */ int m_ClientID; |
desc |
21 | 3 | event_sound_world |
/* common */ int m_X; int m_Y; /* sound_world */ int m_SoundID; |
desc |
22 | 5 | event_damage |
/* common */ int m_X; int m_Y; /* damage */ int m_ClientID; int m_Angle; int m_HealthAmount; int m_ArmorAmount; int m_Self; |
desc |
Unknown size table (0.7.x extension)
type_id | size | name | parameters | description |
---|---|---|---|---|
23 | 1 | obj_player_info_race | int m_RaceStartTick; | desc |
24 | 3 | obj_game_data_race |
int m_BestTime; int m_Precision; int m_RaceFlags; |
desc |