# Sync Everything about the packets that synchronize the game states. In this document, packets are distinguished by their length and command byte. For example a 16BC41 describes the packet with a length of 16 bytes and a command byte with value `0x41` in the header. When the game is paused, only 16BC31 and 16BC32 packets are sent. ## Periodic ### 16BC41 A simple incremental counter that will increments every time a 16BC41 packet is sent. Packets are transmitted in intervals of 120ms. ```ruby def 16BC41 int32 :network_source_id int32 :network_dest_id int8 :command int8 :option1 int8 :option2 int8 :option3 int32 :individual_counter end ``` *:network_source_id*
Works the same way as outlined in [02-header.md](02-header.md). *:network_dest_id*
The destination of the packet. 16BC41 is one of the few packet types, where this value is not set to zero. *:command*
Always has the value `0x41`. *:option{1-3}*
These are options with unknown effects. They work the same way as outlined in [02-header.md](02-header.md). *:individual_counter*
The individual counter of the player who sent the packet. It increments by 1 with every 16BC41 sync command. For individual players, this counter starts with values that are 1200 units (two players) or 2000 units (three players, `0x7d0`) apart from each other. In the latter example player 1 starts with the value `0x7d0`, player 2 with `0xfa0` and player 3 with `0x1770`. If the differences between these values is not a multiple of 2000, this indicates a de-sync. ### 16BC31 Makes sure that the game time of players stays synced. It always receives an answer in form of 16BC32. Packets are transmitted in intervals of 8s. ```ruby def 16BC31 int32 :network_source_id int32 :network_dest_id int8 :command int8 :option1 int8 :option2 int8 :option3 int32 :time_passed end ``` *:network_source_id*
Works the same way as outlined in [02-header.md](02-header.md). *:network_dest_id*
The destination of the packet. 16BC31 is one of the few packet types, where this value is not set to zero. *:command*
Always has the value `0x31`. *:option{1-3}*
All 3 options are always zero for this command. *:time_passed*
Time passed in milliseconds since the game started for the player. The difference between player 1 and player 2 was roughly 3,220 ms during tests. Note that for 16BC31 packets present in the lobby, this value represents milliseconds **since the application** started instead. ### 16BC32 The answer for a 16BC31 packet. Packets are transmitted in intervals of 8s. ```ruby def 16BC32 int32 :network_source_id int32 :network_dest_id int8 :command int8 :option1 int8 :option2 int8 :option3 int32 :time_passed end ``` *:network_source_id*
Works the same way as outlined in [02-header.md](02-header.md). *:network_dest_id*
The destination of the packet. 16BC32 is one of the few packet types, where this value is not set to zero. *:command*
Always has the value `0x32`. *:option{1-3}*
They work the same way as outlined in [02-header.md](02-header.md). *:time_passed*
Has the exact same value as the 16BC31 packet. ### 24BC35 Syncing the connection between players in lobby. Packets are transmitted in intervals of 2s. ```ruby def 24BC35 int32 :network_source_id int32 :network_dest_id int8 :command int8 :option1 int8 :option2 int8 :option3 int32 :connecting1 int32 :unknown int32 :connecting2 end ``` *:network_source_id*
Works the same way as outlined in [02-header.md](02-header.md). *:network_dest_id*
This value is always zero. *:command*
Always has the value `0x35`. *:option1*
`0x35` for both host and regular players when initiating the connection. Otherwise it has the value `0x30`. *:option2*
`0x32` for the host and `0xf8` for regular players when initiating the connection. Otherwise it has the value `0x5d`. *:option3*
`0x00` for the host and `0x0a` for regular players when initiating the connection. Otherwise it has the value `0x00`. *:connecting1*
This field is only used to initiate a connection to a lobby. It always has the value `0x32d2a4` for the host and `0x503a87` for regular players when initiating a connection. Once the connecting player has joined the lobby, the value remains zero for all following packets. *:unknown*
Field with unknown purpose. The value in here is unique for every player and sent with every packet. *:connecting2*
This field is only used to initiate a connection to a lobby. It always has the value `0x5016b5` for the host and `0x32b5c4` for regular players when initiating a connection. Once the connecting player has joined the lobby, the value remains `0xFFFFFFFF` for all following packets. ### 26BC53 Only sent by the host from the lobby and not by other players. Sent in intervals of 3s. ```ruby def 26BC53 byte20 :header int16 :unknown1 int16 :unknown2 int16 :communication_turn end ``` *:header*
The standard header. Works the same way as outlined in [02-header.md](02-header.md). *:unknown1*
A field with unknown purpose. Changes between values of `0x04` and `0x08`. *:unknown2*
Another field with unknown purpose. Possibly ping. *:communication_turn*
The current communication turn as a 16 bit value. ### 32BC44 Syncs up the communication turns in the game. Packets are transmitted in intervals of 120ms. ```ruby def 32BC44 byte20 :header int8 :command2 int8 :unknown1 int8 :unknown2 int8 :unknown3 int32 :communication_turn_offset int8 :ping1 int8 :ping2 int8 :unknown4 int8 :unknown5 end ``` *:header*
The standard header. Works the same way as outlined in [02-header.md](02-header.md). *:command2*
Always has the value of the command byte from the header `0x44`. It is unknown whether this is supposed to be the same as *:command* or if it has other use cases. *:unknown1*
Possibly used to communicate the connection status. The value is different for every player, but consistent for most packets throughout the game. An exception are packets sent at the start of a game. The first 32BC44 packet sent by the lobby host always has the value `0x96` in this field. All other players will have the value `0xce` in their first packet. Sometimes the value of the fields *:unknown{1-3}* and *:unknown5* will be `0x00`, but no reason for this behavior could be found. *:unknown2*
Like *:unknown1* it is probably used to communicate the connection status. Values for the very first 32BC44 packet are `0x98` for the lobby host and `0x32` for all other players. Sometimes the value of the fields *:unknown{1-3}* and *:unknown5* will be `0x00`. *:unknown3*
Has the value `0xf7` most of the time. Sometimes the value of the fields *:unknown{1-3}* and *:unknown5* will be `0x00`. *:communication_turn_offset*
If the game desyncs, this field indicates the last communication turn where the game was in sync for the player sending this packet. While the game is synced, the value should match up with *:communication_turn* in the header. *:ping1*
The difference between the ping from the current turn and the ping from the previous turn. *:ping2*
Average time to receive an answer from the player the packet was sent to. Uses the ping times for the last 10-15 32BC44 packets for calculation. *:unknown4*
Byte with unknown purpose. It will have the value `0x4c` for the player who was the lobby host and a different value for all other players (one player: `0x48`; two players: both `0x47`). When *:unknown{1-3}* and *:unknown5* have the value `0x00`, the value for *:unknown4* will always be `0x32`. *:unknown5*
Has the value `0xf7` most of the time. Sometimes the value of the fields *:unknown{1-3}* and *:unknown5* will be `0x00`. ### 56BC4D Syncs up the communication turns in the game. Seems to check if some values are the same for every player. In every interval, the values of 56BC4D stay the same for all players (except for the last 4 bytes). Packets are transmitted in intervals of 8s - 16s. ```ruby def 56BC4D byte20 :header int32 :unknown1 int32 :communication_turn_check int32 :unknown2 int32 :unknown3 int32 :unknown3 int32 :unknown5 int32 :unknown6 int32 :unknown7 int32 :unknown8 end ``` *:header*
The standard header. Works the same way as outlined in [02-header.md](02-header.md). *:communication_turn_check*
The communication turn which is validated. Always has the value (*:communication_turn* - 2). *:unknown{1-7}*
These are the same for all players during a given interval. Some of them seem to be counters, while others change values with an unknown pattern. *:unknown8*
Different for every interval and every player. ## Non-Periodic ### 24BC51 Utilized after dropping a player due to connection loss or de-sync. ```ruby def 24BC51 byte20 :header int32 :unknown3 end ``` *:header*
The standard header. Works the same way as outlined in [02-header.md](02-header.md). *:last_synced_communication_turn*
The number of the communication turn that the remaining players will continue the game from. ### 24BC52 Used for readying in the lobby. ```ruby def 24BC52 int32 :network_source_id int32 :network_dest_id int8 :command int8 :option1 int8 :option2 int8 :option3 int8 :unknown int8 :player_id int8 :unknown2 int32 :zero int32 :unknown3 end ``` *:network_source_id*
Works the same way as outlined in [02-header.md](02-header.md). *:network_dest_id*
This value is always zero. *:command*
Always has the value `0x52`. *:option1*
Is `0x01` when readying and `0x00` when unreadying. *:option2*
Is `0x1e` when readying and `0x00` when unreadying. *:option3*
Is `0x00` when readying or unreadying. *:unknown*
Field with unknown purpose. Always has value `0x01`. *:player_id*
The ID of the player who is readying. Is `0x00` when player is unreadying. *:unknown2*
Field with unknown purpose. Always has value `0x01` when player is readying. Is `0x00` when player is unreadying. *:zero*
These 4 bytes are always zero. *:unknown3*
Field with unknown purpose. Always has value `0x04` when player is readying. Is `0x00` when player is unreadying.