Difference between revisions of "Protocol"

From wiki.vg
Jump to navigation Jump to search
m (Removing redundant header and categorizing.)
 
(Add C2S Pickup Spawn packet, also clarify units of measurement slightly)
(6 intermediate revisions by the same user not shown)
Line 94: Line 94:
 
! class="col0" | Absolute
 
! class="col0" | Absolute
 
| class="col1 centeralign" | double
 
| class="col1 centeralign" | double
| class="col2" | Represents an objects '''exact''' location in the world, specified in pixels (each block is 32 pixels).
+
| class="col2" | Represents an objects '''exact''' location in the world, specified in block coordinates.
 
|- class="row2"
 
|- class="row2"
 
! class="col0" | Absolute Integer
 
! class="col0" | Absolute Integer
Line 102: Line 102:
 
! class="col0" | Block
 
! class="col0" | Block
 
| class="col1 centeralign" | int '''or''' byte
 
| class="col1 centeralign" | int '''or''' byte
| class="col2" | Represents a blocks '''exact''' location in the world, as Absolute divided by 32.
+
| class="col2" | Represents a blocks '''exact''' location in the world. Block = Absolute / 32.
 
|- class="row4"
 
|- class="row4"
 
! class="col0" | Chunk
 
! class="col0" | Chunk
 
| class="col1 centeralign" | int '''or''' short
 
| class="col1 centeralign" | int '''or''' short
| class="col2" | Represents the '''exact''' position of a chunk, as Block * 16.
+
| class="col2" | Represents the '''exact''' position of a chunk. Chunk = Block / 16.
 
|}
 
|}
  
Line 137: Line 137:
 
| class="col1 centeralign" | Protocol Version
 
| class="col1 centeralign" | Protocol Version
 
| class="col2 centeralign" | int
 
| class="col2 centeralign" | int
| class="col3 centeralign" | <code>3</code>
+
| class="col3 centeralign" | <code>4</code>
| class="col4" | The latest version of the protocol is 3
+
| class="col4" | The latest version of the protocol is 4
 
|- class="row2"
 
|- class="row2"
 
| class="col0 centeralign" | Username
 
| class="col0 centeralign" | Username
Line 188: Line 188:
 
=== Chat Message (0x03) ===
 
=== Chat Message (0x03) ===
  
The server will check the message to see if it begins with a '/'. If it doesn't, the username of the sender is prepended and sent to all other clients (including the original sender). If it does, the server assumes it to be a command and attempts to process it.
+
The server will check the message to see if it begins with a '/'. If it doesn't, the username of the sender is prepended and sent to all other clients (including the original sender). If it does, the server assumes it to be a command and attempts to process it. A short with the length of the message is prepended to the text sent.  eg: 1 byte header [0x03], 2 byte short [string length], N byte string
  
 
{| class="wikitable"
 
{| class="wikitable"
Line 241: Line 241:
 
! class="col0" | Total Size:
 
! class="col0" | Total Size:
 
| class="col1 rightalign" colspan="4" | 7 bytes + size of payload
 
| class="col1 rightalign" colspan="4" | 7 bytes + size of payload
 +
|}
 +
 +
=== Use Entity? (0x07) ===
 +
This packet is new to version 4 of the protocol, and is believed to be Use Entity.
 +
 +
(This packet data values are not fully verified)
 +
 +
{| class="wikitable"
 +
|- class="row0"
 +
! class="col0" | Packet ID
 +
! class="col1" | Field Name
 +
! class="col2" | Field Type
 +
! class="col3" | Example
 +
! class="col4" | Notes
 +
|- class="row1"
 +
| class="col0 centeralign" rowspan="2" | 0x07
 +
| class="col1 centeralign" | User
 +
| class="col2 centeralign" | int
 +
| class="col3 centeralign" | <code>1298</code>
 +
| class="col4" |
 +
The entity of the player (ignored by the server)
 +
|- class="row2"
 +
| class="col0 centeralign" | Target
 +
| class="col1 centeralign" | int
 +
| class="col2 centeralign" | <code>1805</code>
 +
| class="col3" |
 +
The entity the player has right-clicked on
 +
|- class="row3"
 +
! class="col0" | Total Size:
 +
| class="col1 rightalign" colspan="4" | 9 bytes
 
|}
 
|}
  
Line 569: Line 599:
 
|}
 
|}
  
=== Disconnect (0xFF) ===
+
=== Arm Animation (0x12) ===
  
Sent by the client when it's doing a clean disconnect.
+
Sent whenever someone swings their arm.
  
 
{| class="wikitable"
 
{| class="wikitable"
Line 581: Line 611:
 
! class="col4" | Notes
 
! class="col4" | Notes
 
|- class="row1"
 
|- class="row1"
| class="col0 centeralign" | 0xFF
+
| class="col0 centeralign" rowspan="2" | 0x12
| class="col1 centeralign" | Reason
+
| class="col1 centeralign" | EID
| class="col2 centeralign" | string
+
| class="col2 centeralign" | int
| class="col3 centeralign" | <code>Quitting</code>
+
| class="col3 centeralign" | <code>55534</code>
| class="col4" | The server doesn't appear to do anything with this (yet)
+
| class="col4" | Player ID
 
|- class="row2"
 
|- class="row2"
 +
| class="col0 centeralign" | Animate
 +
| class="col1 centeralign" | bool
 +
| class="col2 centeralign" | <code>1</code>
 +
| class="col3" | If <code>true</code>, animate the arm
 +
|- class="row3"
 
! class="col0" | Total Size:
 
! class="col0" | Total Size:
| class="col1 rightalign" colspan="4" | 3 bytes + length of strings
+
| class="col1 rightalign" colspan="4" | 6 bytes
 
|}
 
|}
  
== Server To Client Packets ==
+
=== Pickup Spawn (0x15) ===
 
 
=== Keep Alive (0x00) ===
 
  
This packet may be sent by the server to keep the connection alive, or may be a relic of UDP testing. No one is really sure.
+
A pickup spawn is sent from the client to the server whenever the client drops an item they are holding. This identical to the pickup spawn packet that is sent from the server to the client.
  
 
{| class="wikitable"
 
{| class="wikitable"
 
|- class="row0"
 
|- class="row0"
! class="col0" | Packet ID
+
! class="col0 centeralign" | Packet ID
 +
! class="col1 rightalign" | Field Name
 +
! class="col2" | Field Type
 +
! class="col3" | Example
 +
! class="col4" | Notes
 
|- class="row1"
 
|- class="row1"
| class="col0 centeralign" | 0x00
+
| class="col0 centeralign" rowspan="9" | 0x15
|}
+
| class="col1" | EID
 
+
| class="col2" | int
=== Login Response (0x01) ===
+
| class="col3" | <code>157617</code>
 
+
| class="col4" | Unique entity ID
Sent by the server if it accepts the clients [[Protocol#Login_Request_.280x01.29|login request]]. If it didn't, it'll send a [[Protocol#Kick_.280xFF.29|kick]] instead.
 
 
 
{| class="wikitable"
 
|- class="row0"
 
! class="col0" | Packet ID
 
! class="col1" | Field Name
 
! class="col2" | Field Type
 
! class="col3" | Example
 
! class="col4" | Notes
 
|- class="row1"
 
| class="col0 centeralign" rowspan="5" | 0x01
 
| class="col1 centeralign" | Unknown
 
| class="col2 centeralign" | int
 
| class="col3 centeralign" | <code>0</code>
 
| class="col4" | Not yet used
 
 
|- class="row2"
 
|- class="row2"
| class="col0 centeralign" | Unknown
+
| class="col0" | Item
| class="col1 centeralign" | string
+
| class="col1" | short
| class="col2 centeralign" | n/a
+
| class="col2" | <code>4</code>
| class="col3" | Not yet used (Possibly the server name?)
+
| class="col3" | The item ID
 
|- class="row3"
 
|- class="row3"
| class="col0 centeralign" | Unknown
+
| class="col0" | Count
| class="col1 centeralign" | string
+
| class="col1" | byte
| class="col2 centeralign" | n/a
+
| class="col2" | <code>1</code>
| class="col3" | Not yet used (Possibly the MOTD? )
+
| class="col3" | The number of items
 
|- class="row4"
 
|- class="row4"
| class="col0 centeralign" | Map Seed
+
| class="col0" | X
| class="col1 centeralign" | long
+
| class="col1" | int
| class="col2 centeralign" | <code>971768181197178410</code>
+
| class="col2" | <code>133</code>
| class="col3" | Used for map generation
+
| class="col3" | Item X as Absolute Integer
 
|- class="row5"
 
|- class="row5"
| class="col0 centeralign" | Dimension
+
| class="col0" | Y
| class="col1 centeralign" | byte
+
| class="col1" | int
| class="col2 centeralign" | <code>0</code>
+
| class="col2" | <code>913</code>
| class="col3" | Used for specifying the players dimension -1 for hell, 0 otherwise
+
| class="col3" | Item Y as Absolute Integer
 
|- class="row6"
 
|- class="row6"
! class="col0" | Total Size:
+
| class="col0" | Z
| class="col1 rightalign" colspan="4" | 18 bytes + length of strings
+
| class="col1" | int
|}
+
| class="col2" | <code>63552</code>
 +
| class="col3" | Item Z as Absolute Integer
 +
|- class="row7"
 +
| class="col0" | Rotation
 +
| class="col1" | byte
 +
| class="col2" | <code>252</code>
 +
| class="col3" | Item rotation as a packed byte
 +
|- class="row8"
 +
| class="col0" | Pitch
 +
| class="col1" | byte
 +
| class="col2" | <code>25</code>
 +
| class="col3" | Item pitch as a packed byte
 +
|- class="row9"
 +
| class="col0" | Roll
 +
| class="col1" | byte
 +
| class="col2" | <code>12</code>
 +
| class="col3" | Item roll as a packed byte
 +
|- class="row10"
 +
! class="col0" | Total Size:
 +
| class="col1 rightalign" colspan="4" | 23 bytes
 +
|}
  
=== Handshake (0x02) ===
+
=== Disconnect (0xFF) ===
  
This is the first packet sent when the client connects and is used for [[Authentication]]. If the hash is '-', then the client continues without doing name authentication. If the hash is a '+', the client sends the server password in the [[Protocol#Login_Request_.280x01.29|login request]].
+
Sent by the client when it's doing a clean disconnect.
  
 
{| class="wikitable"
 
{| class="wikitable"
Line 658: Line 700:
 
! class="col4" | Notes
 
! class="col4" | Notes
 
|- class="row1"
 
|- class="row1"
| class="col0 centeralign" | 0x02
+
| class="col0 centeralign" | 0xFF
| class="col1 centeralign" | Connection Hash
+
| class="col1 centeralign" | Reason
 
| class="col2 centeralign" | string
 
| class="col2 centeralign" | string
| class="col3 rightalign" | <code>2e66f1dc032ab5f0</code>
+
| class="col3 centeralign" | <code>Quitting</code>
| class="col4" | A unique, per-connection hash '''or''' '-' '''or''' '+'
+
| class="col4" | The server doesn't appear to do anything with this (yet)
 
|- class="row2"
 
|- class="row2"
 
! class="col0" | Total Size:
 
! class="col0" | Total Size:
Line 668: Line 710:
 
|}
 
|}
  
=== Chat Message (0x03) ===
+
== Server To Client Packets ==
 +
 
 +
=== Keep Alive (0x00) ===
  
A formatted chat message from the server. Note that it is unreliable to parse chat when it's sent from the server → client as each server can/will format it differently (some use &lt;,&gt; others use [,], etc…)
+
This packet may be sent by the server to keep the connection alive, or may be a relic of UDP testing. No one is really sure.
  
 
{| class="wikitable"
 
{| class="wikitable"
 
|- class="row0"
 
|- class="row0"
 
! class="col0" | Packet ID
 
! class="col0" | Packet ID
! class="col1" | Field Name
 
! class="col2" | Field Type
 
! class="col3" | Example
 
! class="col4" | Notes
 
 
|- class="row1"
 
|- class="row1"
| class="col0 centeralign" | 0x03
+
| class="col0 centeralign" | 0x00
| class="col1 centeralign" | Message
 
| class="col2 centeralign" | string
 
| class="col3 centeralign" | <code>&lt;Bob&gt; Hello World!</code>
 
| class="col4" | User input '''must''' be sanitized server-side
 
|- class="row2"
 
! class="col0" | Total Size:
 
| class="col1 rightalign" colspan="4" | 3 bytes + length of strings
 
 
|}
 
|}
  
=== Time Update (0x04) ===
+
=== Login Response (0x01) ===
  
The default SMP server increments the time by <code>20</code> every second.
+
Sent by the server if it accepts the clients [[Protocol#Login_Request_.280x01.29|login request]]. If it didn't, it'll send a [[Protocol#Kick_.280xFF.29|kick]] instead.
  
 
{| class="wikitable"
 
{| class="wikitable"
Line 702: Line 735:
 
! class="col4" | Notes
 
! class="col4" | Notes
 
|- class="row1"
 
|- class="row1"
| class="col0 centeralign" | 0x04
+
| class="col0 centeralign" rowspan="5" | 0x01
| class="col1 centeralign" | Time
+
| class="col1 centeralign" | Entity ID
| class="col2 centeralign" | long
+
| class="col2 centeralign" | int
| class="col3 centeralign" | <code></code>
+
| class="col3 centeralign" | <code>1298</code>
| class="col4 centeralign" | The world (or region) time in minutes
+
| class="col4" | The Players Entity ID
 
|- class="row2"
 
|- class="row2"
 +
| class="col0 centeralign" | Unknown
 +
| class="col1 centeralign" | string
 +
| class="col2 centeralign" | n/a
 +
| class="col3" | Not yet used (Possibly the server name?)
 +
|- class="row3"
 +
| class="col0 centeralign" | Unknown
 +
| class="col1 centeralign" | string
 +
| class="col2 centeralign" | n/a
 +
| class="col3" | Not yet used (Possibly the MOTD? )
 +
|- class="row4"
 +
| class="col0 centeralign" | Map Seed
 +
| class="col1 centeralign" | long
 +
| class="col2 centeralign" | <code>971768181197178410</code>
 +
| class="col3" | Used for map generation
 +
|- class="row5"
 +
| class="col0 centeralign" | Dimension
 +
| class="col1 centeralign" | byte
 +
| class="col2 centeralign" | <code>0</code>
 +
| class="col3" | Used for specifying the players dimension -1 for hell, 0 otherwise
 +
|- class="row6"
 
! class="col0" | Total Size:
 
! class="col0" | Total Size:
| class="col1 rightalign" colspan="4" | 9 bytes
+
| class="col1 rightalign" colspan="4" | 18 bytes + length of strings
 
|}
 
|}
  
=== Player Inventory (0x05) ===
+
=== Handshake (0x02) ===
  
[[File:Slots2.png|frame]] Sent by the server to set or reset a players inventory. This includes the main inventory, equipped armour and crafting slots. Packets for all three types are sent to initialize the players inventory before spawning them.
+
This is the first packet sent when the client connects and is used for [[Authentication]]. If the hash is '-', then the client continues without doing name authentication. If the hash is a '+', the client sends the server password in the [[Protocol#Login_Request_.280x01.29|login request]].
  
 
{| class="wikitable"
 
{| class="wikitable"
Line 724: Line 777:
 
! class="col4" | Notes
 
! class="col4" | Notes
 
|- class="row1"
 
|- class="row1"
| class="col0 centeralign" rowspan="3" | 0x05
+
| class="col0 centeralign" | 0x02
| class="col1 centeralign" | Type
+
| class="col1 centeralign" | Connection Hash
| class="col2 centeralign" | int
+
| class="col2 centeralign" | string
| class="col3 centeralign" | <code>-1</code>
+
| class="col3 rightalign" | <code>2e66f1dc032ab5f0</code>
| class="col4" | The “type” of inventory being sent (see below)
+
| class="col4" | A unique, per-connection hash '''or''' '-' '''or''' '+'
 
|- class="row2"
 
|- class="row2"
| class="col0 centeralign" | Count
 
| class="col1 centeralign" | short
 
| class="col2 centeralign" | <code>4</code>
 
| class="col3" | The number of inventory items (see below)
 
|- class="row3"
 
| class="col0 centeralign" | Payload
 
| class="col1 centeralign" | …
 
| class="col2 centeralign" | <code></code>
 
| class="col3" | The payload (see below)
 
|- class="row4"
 
 
! class="col0" | Total Size:
 
! class="col0" | Total Size:
| class="col1 rightalign" colspan="4" | 7 bytes + size of payload
+
| class="col1 rightalign" colspan="4" | 3 bytes + length of strings
 
|}
 
|}
  
Type can (currently) be one of three values:
+
=== Chat Message (0x03) ===
 +
 
 +
A formatted chat message from the server. Note that it is unreliable to parse chat when it's sent from the server → client as each server can/will format it differently (some use &lt;,&gt; others use [,], etc…)
  
 
{| class="wikitable"
 
{| class="wikitable"
 
|- class="row0"
 
|- class="row0"
! class="col0" | Inventory Type
+
! class="col0" | Packet ID
! class="col1" | Value
+
! class="col1" | Field Name
! class="col2" | Count
+
! class="col2" | Field Type
 +
! class="col3" | Example
 +
! class="col4" | Notes
 
|- class="row1"
 
|- class="row1"
| class="col0 centeralign" | Main inventory
+
| class="col0 centeralign" | 0x03
| class="col1 centeralign" | -1
+
| class="col1 centeralign" | Message
| class="col2 centeralign" | 36
+
| class="col2 centeralign" | string
 +
| class="col3 centeralign" | <code>&lt;Bob&gt; Hello World!</code>
 +
| class="col4" | User input '''must''' be sanitized server-side
 
|- class="row2"
 
|- class="row2"
| class="col0 centeralign" | Equipped armour
+
! class="col0" | Total Size:
| class="col1 centeralign" | -2
+
| class="col1 rightalign" colspan="4" | 3 bytes + length of strings
| class="col2 centeralign" | 4
 
|- class="row3"
 
| class="col0 centeralign" | Crafting slots
 
| class="col1 centeralign" | -3
 
| class="col2 centeralign" | 4
 
 
|}
 
|}
  
This packet is a bit more tricky to parse than most others because the size of its payload is variable. The payload is an array of shorts (item ID) optionally followed by a byte-short pair (count and health) as long as the item ID does not equal <code>-1</code>, which signifies an empty slot.
+
=== Time Update (0x04) ===
  
<syntaxhighlight lang="python">
+
The default SMP server increments the time by <code>20</code> every second.
offset = 0
 
 
for slot in count:
 
    if payload[offset] as short is not equal to -1:
 
        item_id = payload[offset] as short
 
        offset += 2
 
        count = payload[offset] as byte
 
        offset += 1
 
        health = payload[offset] as short
 
        offset += 2
 
        inventory[slot] = new item(item_id, count, health)
 
    else:
 
        offset += 2
 
</syntaxhighlight>
 
 
 
=== Spawn Position (0x06) ===
 
 
 
Sent by the server after login to specify the players starting location and to initialize compasses. It can be sent at any time afterwords to update the point compasses are focused on.
 
  
 
{| class="wikitable"
 
{| class="wikitable"
Line 795: Line 821:
 
! class="col4" | Notes
 
! class="col4" | Notes
 
|- class="row1"
 
|- class="row1"
| class="col0 centeralign" rowspan="3" | 0x06
+
| class="col0 centeralign" | 0x04
| class="col1 centeralign" | X
+
| class="col1 centeralign" | Time
| class="col2 centeralign" | int
+
| class="col2 centeralign" | long
| class="col3 centeralign" | <code>117</code>
+
| class="col3 centeralign" | <code></code>
| class="col4 centeralign" | Spawn X in block coordinates
+
| class="col4 centeralign" | The world (or region) time in minutes
 
|- class="row2"
 
|- class="row2"
| class="col0 centeralign" | Y
 
| class="col1 centeralign" | int
 
| class="col2 centeralign" | <code>70</code>
 
| class="col3 centeralign" | Spawn Y in block coordinates
 
|- class="row3"
 
| class="col0 centeralign" | Z
 
| class="col1 centeralign" | int
 
| class="col2 centeralign" | <code>-46</code>
 
| class="col3 centeralign" | Spawn Z in block coordinates
 
|- class="row4"
 
 
! class="col0" | Total Size:
 
! class="col0" | Total Size:
| class="col1 rightalign" colspan="4" | 13 bytes
+
| class="col1 rightalign" colspan="4" | 9 bytes
 
|}
 
|}
  
=== Player Position &amp; Look (0x0D) ===
+
=== Player Inventory (0x05) ===
  
A combination of [[Protocol#Player_Look_.280x0C.29|Player Look]] and [[Protocol#Player_Position_.280x0B.29|Player position]].
+
[[File:Slots2.png|frame]] Sent by the server to set or reset a players inventory. This includes the main inventory, equipped armour and crafting slots. Packets for all three types are sent to initialize the players inventory before spawning them.
  
 
{| class="wikitable"
 
{| class="wikitable"
Line 827: Line 843:
 
! class="col4" | Notes
 
! class="col4" | Notes
 
|- class="row1"
 
|- class="row1"
| class="col0 centeralign" rowspan="7" | 0x0D
+
| class="col0 centeralign" rowspan="3" | 0x05
| class="col1 centeralign" | X
+
| class="col1 centeralign" | Type
| class="col2 centeralign" | double
+
| class="col2 centeralign" | int
| class="col3 centeralign" | <code>6.5</code>
+
| class="col3 centeralign" | <code>-1</code>
| class="col4" | Absolute position
+
| class="col4" | The “type” of inventory being sent (see below)
 
|- class="row2"
 
|- class="row2"
| class="col0 centeralign" | Stance
+
| class="col0 centeralign" | Count
| class="col1 centeralign" | double
+
| class="col1 centeralign" | short
| class="col2 centeralign" | <code>67.240000009536743</code>
+
| class="col2 centeralign" | <code>4</code>
| class="col3" | Used to modify the players bounding box when going up stairs, crouching, etc…
+
| class="col3" | The number of inventory items (see below)
 
|- class="row3"
 
|- class="row3"
| class="col0 centeralign" | Y
+
| class="col0 centeralign" | Payload
| class="col1 centeralign" | double
+
| class="col1 centeralign" |
| class="col2 centeralign" | <code>65.620000004768372</code>
+
| class="col2 centeralign" | <code></code>
| class="col3" | Absolute position
+
| class="col3" | The payload (see below)
 
|- class="row4"
 
|- class="row4"
| class="col0 centeralign" | Z
+
! class="col0" | Total Size:
| class="col1 centeralign" | double
+
| class="col1 rightalign" colspan="4" | 7 bytes + size of payload
| class="col2 centeralign" | <code>7.5</code>
+
|}
| class="col3" | Absolute position
+
 
|- class="row5"
+
Type can (currently) be one of three values:
| class="col0 centeralign" | Yaw
+
 
| class="col1 centeralign" | float
 
| class="col2 centeralign" | <code>0.0</code>
 
| class="col3" | Absolute rotation on the X Axis
 
|- class="row6"
 
| class="col0 centeralign" | Pitch
 
| class="col1 centeralign" | float
 
| class="col2 centeralign" | <code>0.0</code>
 
| class="col3" | Absolute rotation on the Y Axis
 
|- class="row7"
 
| class="col0 centeralign" | On Ground
 
| class="col1 centeralign" | bool
 
| class="col2 centeralign" | <code>0</code>
 
| class="col3" |
 
Derived from packet [[#Player_.280x0A.29|0x0A]]
 
|- class="row8"
 
! class="col0" | Total Size:
 
| class="col1 rightalign" colspan="4" | 42 bytes
 
|}
 
 
 
[[File:Icon_exclaim.gif|:!:]] This packet differs from client Player Position &amp; Look packet, the Stance and Y are sent in a different order, however because of the different order this is sent the client will actually use the X,Y,Stance,Z client layout.
 
 
 
=== Add To Inventory (0x11) ===
 
 
 
Sent by the server when a player has become close enough to collect an item on the ground.
 
 
 
 
{| class="wikitable"
 
{| class="wikitable"
 
|- class="row0"
 
|- class="row0"
! class="col0" | Packet ID
+
! class="col0" | Inventory Type
! class="col1" | Field Name
+
! class="col1" | Value
! class="col2" | Field Type
+
! class="col2" | Count
! class="col3" | Example
 
! class="col4" | Notes
 
 
|- class="row1"
 
|- class="row1"
| class="col0 centeralign" rowspan="3" | 0x11
+
| class="col0 centeralign" | Main inventory
| class="col1 centeralign" | Item Type
+
| class="col1 centeralign" | -1
| class="col2 centeralign" | short
+
| class="col2 centeralign" | 36
| class="col3 centeralign" | <code>5</code>
 
| class="col4 leftalign" |
 
 
|- class="row2"
 
|- class="row2"
| class="col0 centeralign" | Count
+
| class="col0 centeralign" | Equipped armour
| class="col1 centeralign" | byte
+
| class="col1 centeralign" | -2
| class="col2 centeralign" | <code>10</code>
+
| class="col2 centeralign" | 4
| class="col3 leftalign" |
 
 
|- class="row3"
 
|- class="row3"
| class="col0 centeralign" | Life
+
| class="col0 centeralign" | Crafting slots
| class="col1 centeralign" | short
+
| class="col1 centeralign" | -3
| class="col2 centeralign" | <code>0</code>
+
| class="col2 centeralign" | 4
| class="col3 leftalign" |
+
|}
|- class="row4"
+
 
! class="col0" | Total Size:
+
This packet is a bit more tricky to parse than most others because the size of its payload is variable. The payload is an array of shorts (item ID) optionally followed by a byte-short pair (count and health) as long as the item ID does not equal <code>-1</code>, which signifies an empty slot.
| class="col1 rightalign" colspan="4" | 6 bytes
 
|}
 
  
“Life” can range from 0x01 (full health) to 0x32 (no health), 0x00 omits the health bar altogether, and is what should be used for blocks.
+
<syntaxhighlight lang="python">
 +
offset = 0
 +
 +
for slot in count:
 +
    if payload[offset] as short is not equal to -1:
 +
        item_id = payload[offset] as short
 +
        offset += 2
 +
        count = payload[offset] as byte
 +
        offset += 1
 +
        health = payload[offset] as short
 +
        offset += 2
 +
        inventory[slot] = new item(item_id, count, health)
 +
    else:
 +
        offset += 2
 +
</syntaxhighlight>
  
=== Arm Animation (0x12) ===
+
=== Spawn Position (0x06) ===
  
Sent whenever someone swings their arm.
+
Sent by the server after login to specify the players starting location and to initialize compasses. It can be sent at any time afterwords to update the point compasses are focused on.
  
 
{| class="wikitable"
 
{| class="wikitable"
Line 916: Line 914:
 
! class="col4" | Notes
 
! class="col4" | Notes
 
|- class="row1"
 
|- class="row1"
| class="col0 centeralign" rowspan="2" | 0x12
+
| class="col0 centeralign" rowspan="3" | 0x06
| class="col1 centeralign" | EID
+
| class="col1 centeralign" | X
 
| class="col2 centeralign" | int
 
| class="col2 centeralign" | int
| class="col3 centeralign" | <code>55534</code>
+
| class="col3 centeralign" | <code>117</code>
| class="col4" | Player ID
+
| class="col4 centeralign" | Spawn X in block coordinates
 
|- class="row2"
 
|- class="row2"
| class="col0 centeralign" | Animate
+
| class="col0 centeralign" | Y
| class="col1 centeralign" | bool
+
| class="col1 centeralign" | int
| class="col2 centeralign" | <code>1</code>
+
| class="col2 centeralign" | <code>70</code>
| class="col3" | If <code>true</code>, animate the arm
+
| class="col3 centeralign" | Spawn Y in block coordinates
 
|- class="row3"
 
|- class="row3"
 +
| class="col0 centeralign" | Z
 +
| class="col1 centeralign" | int
 +
| class="col2 centeralign" | <code>-46</code>
 +
| class="col3 centeralign" | Spawn Z in block coordinates
 +
|- class="row4"
 
! class="col0" | Total Size:
 
! class="col0" | Total Size:
| class="col1 rightalign" colspan="4" | 6 bytes
+
| class="col1 rightalign" colspan="4" | 13 bytes
 
|}
 
|}
  
=== Named Entity Spawn (0x14) ===
+
=== Player Position &amp; Look (0x0D) ===
  
The only named entities (at the moment) are players (either real or NPC/Bot). This packet is sent by the server when a player comes into visible range, '''not''' when a player joins.
+
A combination of [[Protocol#Player_Look_.280x0C.29|Player Look]] and [[Protocol#Player_Position_.280x0B.29|Player position]].
  
 
{| class="wikitable"
 
{| class="wikitable"
 
|- class="row0"
 
|- class="row0"
! class="col0 centeralign" | Packet ID
+
! class="col0" | Packet ID
! class="col1 rightalign" | Field Name
+
! class="col1" | Field Name
 
! class="col2" | Field Type
 
! class="col2" | Field Type
 
! class="col3" | Example
 
! class="col3" | Example
 
! class="col4" | Notes
 
! class="col4" | Notes
 
|- class="row1"
 
|- class="row1"
| class="col0 centeralign" rowspan="8" | 0x14
+
| class="col0 centeralign" rowspan="7" | 0x0D
| class="col1" | EID
+
| class="col1 centeralign" | X
| class="col2" | int
+
| class="col2 centeralign" | double
| class="col3" | <code>94453</code>
+
| class="col3 centeralign" | <code>6.5</code>
| class="col4" | Player ID
+
| class="col4" | Absolute position
 
|- class="row2"
 
|- class="row2"
| class="col0" | Player Name
+
| class="col0 centeralign" | Stance
| class="col1" | string
+
| class="col1 centeralign" | double
| class="col2" | <code>Twdtwd</code>
+
| class="col2 centeralign" | <code>67.240000009536743</code>
| class="col3" |
+
| class="col3" | Used to modify the players bounding box when going up stairs, crouching, etc…
 
|- class="row3"
 
|- class="row3"
| class="col0" | X
+
| class="col0 centeralign" | Y
| class="col1" | int
+
| class="col1 centeralign" | double
| class="col2" | <code>784</code>
+
| class="col2 centeralign" | <code>65.620000004768372</code>
| class="col3" | Player X as Absolute Integer
+
| class="col3" | Absolute position
 
|- class="row4"
 
|- class="row4"
| class="col0" | Y
+
| class="col0 centeralign" | Z
| class="col1" | int
+
| class="col1 centeralign" | double
| class="col2" | <code>2131</code>
+
| class="col2 centeralign" | <code>7.5</code>
| class="col3" | Player Y as Absolute Integer
+
| class="col3" | Absolute position
 
|- class="row5"
 
|- class="row5"
| class="col0" | Z
+
| class="col0 centeralign" | Yaw
| class="col1" | int
+
| class="col1 centeralign" | float
| class="col2" | <code>-752</code>
+
| class="col2 centeralign" | <code>0.0</code>
| class="col3" | Player Z as Absolute Integer
+
| class="col3" | Absolute rotation on the X Axis
 
|- class="row6"
 
|- class="row6"
| class="col0" | Rotation
+
| class="col0 centeralign" | Pitch
| class="col1" | byte
+
| class="col1 centeralign" | float
| class="col2" | <code>0</code>
+
| class="col2 centeralign" | <code>0.0</code>
| class="col3" | Player rotation as a packed byte
+
| class="col3" | Absolute rotation on the Y Axis
 
|- class="row7"
 
|- class="row7"
| class="col0" | Pitch
+
| class="col0 centeralign" | On Ground
| class="col1" | byte
+
| class="col1 centeralign" | bool
| class="col2" | <code>0</code>
+
| class="col2 centeralign" | <code>0</code>
| class="col3" | Player rotation as a packed byte
+
| class="col3" |
 +
Derived from packet [[#Player_.280x0A.29|0x0A]]
 
|- class="row8"
 
|- class="row8"
| class="col0" | Current Item
 
| class="col1" | short
 
| class="col2" | <code>0</code>
 
| class="col3" | The item the player is currently holding
 
|- class="row9"
 
 
! class="col0" | Total Size:
 
! class="col0" | Total Size:
| class="col1 rightalign" colspan="4" | 23 bytes + length of strings
+
| class="col1 rightalign" colspan="4" | 42 bytes
 
|}
 
|}
  
=== Pickup Spawn (0x15) ===
+
[[File:Icon_exclaim.gif|:!:]] This packet differs from client Player Position &amp; Look packet, the Stance and Y are sent in a different order, however because of the different order this is sent the client will actually use the X,Y,Stance,Z client layout.
 +
 
 +
=== Holding Change (0x10) ===
  
A pickup spawn is sent whenever an item on the ground (say a pickaxe thrown on the ground) comes into range of the player.
+
Sent when the player changes the item or block currently being held.
  
 
{| class="wikitable"
 
{| class="wikitable"
 
|- class="row0"
 
|- class="row0"
! class="col0 centeralign" | Packet ID
+
! class="col0" | Packet ID
! class="col1 rightalign" | Field Name
+
! class="col1" | Field Name
 
! class="col2" | Field Type
 
! class="col2" | Field Type
 
! class="col3" | Example
 
! class="col3" | Example
 
! class="col4" | Notes
 
! class="col4" | Notes
 
|- class="row1"
 
|- class="row1"
| class="col0 centeralign" rowspan="9" | 0x15
+
| class="col0 centeralign" rowspan="2" | 0x10
| class="col1" | EID
+
| class="col1 centeralign" | EID?
| class="col2" | int
+
| class="col2 centeralign" | int
| class="col3" | <code>157617</code>
+
| class="col3 centeralign" | <code>6341424</code>
| class="col4" | Unique entity ID
+
| class="col4" | Player EID?
 
|- class="row2"
 
|- class="row2"
| class="col0" | Item
+
| class="col0 centeralign" | Block '''or''' Item ID
| class="col1" | short
+
| class="col1 centeralign" | short
| class="col2" | <code>4</code>
+
| class="col2 centeralign" | <code>1</code>
| class="col3" | The item ID
+
| class="col3" | The block/item to be equipped
 
|- class="row3"
 
|- class="row3"
| class="col0" | Count
 
| class="col1" | byte
 
| class="col2" | <code>1</code>
 
| class="col3" | The number of items
 
|- class="row4"
 
| class="col0" | X
 
| class="col1" | int
 
| class="col2" | <code>133</code>
 
| class="col3" | Item X as Absolute Integer
 
|- class="row5"
 
| class="col0" | Y
 
| class="col1" | int
 
| class="col2" | <code>913</code>
 
| class="col3" | Item Y as Absolute Integer
 
|- class="row6"
 
| class="col0" | Z
 
| class="col1" | int
 
| class="col2" | <code>63552</code>
 
| class="col3" | Item Z as Absolute Integer
 
|- class="row7"
 
| class="col0" | Rotation
 
| class="col1" | byte
 
| class="col2" | <code>252</code>
 
| class="col3" | Item rotation as a packed byte
 
|- class="row8"
 
| class="col0" | Pitch
 
| class="col1" | byte
 
| class="col2" | <code>25</code>
 
| class="col3" | Item pitch as a packed byte
 
|- class="row9"
 
| class="col0" | Roll
 
| class="col1" | byte
 
| class="col2" | <code>12</code>
 
| class="col3" | Item roll as a packed byte
 
|- class="row10"
 
 
! class="col0" | Total Size:
 
! class="col0" | Total Size:
| class="col1 rightalign" colspan="4" | 23 bytes
+
| class="col1 rightalign" colspan="4" | 7 bytes
 +
|}
 +
 
 +
=== Add To Inventory (0x11) ===
 +
 
 +
Sent by the server when a player has become close enough to collect an item on the ground.
 +
 
 +
{| class="wikitable"
 +
|- class="row0"
 +
! class="col0" | Packet ID
 +
! class="col1" | Field Name
 +
! class="col2" | Field Type
 +
! class="col3" | Example
 +
! class="col4" | Notes
 +
|- class="row1"
 +
| class="col0 centeralign" rowspan="3" | 0x11
 +
| class="col1 centeralign" | Item Type
 +
| class="col2 centeralign" | short
 +
| class="col3 centeralign" | <code>5</code>
 +
| class="col4 leftalign" |
 +
|- class="row2"
 +
| class="col0 centeralign" | Count
 +
| class="col1 centeralign" | byte
 +
| class="col2 centeralign" | <code>10</code>
 +
| class="col3 leftalign" |
 +
|- class="row3"
 +
| class="col0 centeralign" | Life
 +
| class="col1 centeralign" | short
 +
| class="col2 centeralign" | <code>0</code>
 +
| class="col3 leftalign" |
 +
|- class="row4"
 +
! class="col0" | Total Size:
 +
| class="col1 rightalign" colspan="4" | 6 bytes
 
|}
 
|}
  
=== Collect Item (0x16) ===
+
“Life” can range from 0x01 (full health) to 0x32 (no health), 0x00 omits the health bar altogether, and is what should be used for blocks.
  
Sent by the server when someone picks up an item lying on the ground - its sole purpose appears to be the animation of the item flying towards you. It doesn't destroy the entity in the client memory ([[Protocol#Destroy_Entity_.280x1D.29|0x1D]] does that), and it doesn't add it to your inventory ([[Protocol#Add_To_Inventory_.280x11.29|0x11]] does that).
+
=== Arm Animation (0x12) ===
 +
 
 +
Sent whenever someone swings their arm.
  
 
{| class="wikitable"
 
{| class="wikitable"
Line 1,062: Line 1,062:
 
! class="col4" | Notes
 
! class="col4" | Notes
 
|- class="row1"
 
|- class="row1"
| class="col0 centeralign" rowspan="2" | 0x16
+
| class="col0 centeralign" rowspan="2" | 0x12
| class="col1 centeralign" | Collected EID
+
| class="col1 centeralign" | EID
 
| class="col2 centeralign" | int
 
| class="col2 centeralign" | int
| class="col3 centeralign" | <code>38</code>
+
| class="col3 centeralign" | <code>55534</code>
| class="col4 leftalign" |
+
| class="col4" | Player ID
 
|- class="row2"
 
|- class="row2"
| class="col0 centeralign" | Collector EID
+
| class="col0 centeralign" | Animate
| class="col1 centeralign" | int
+
| class="col1 centeralign" | bool
| class="col2 centeralign" | <code>20</code>
+
| class="col2 centeralign" | <code>1</code>
| class="col3 leftalign" |
+
| class="col3" | If <code>true</code>, animate the arm
 
|- class="row3"
 
|- class="row3"
 
! class="col0" | Total Size:
 
! class="col0" | Total Size:
| class="col1 rightalign" colspan="4" | 9 bytes
+
| class="col1 rightalign" colspan="4" | 6 bytes
 
|}
 
|}
  
=== Add Object/Vehicle (0x17) ===
+
=== Named Entity Spawn (0x14) ===
  
Sent by the server when an Object/Vehicle is created.
+
The only named entities (at the moment) are players (either real or NPC/Bot). This packet is sent by the server when a player comes into visible range, '''not''' when a player joins.
  
 
{| class="wikitable"
 
{| class="wikitable"
 
|- class="row0"
 
|- class="row0"
! class="col0" | Packet ID
+
! class="col0 centeralign" | Packet ID
! class="col1" | Field Name
+
! class="col1 rightalign" | Field Name
 
! class="col2" | Field Type
 
! class="col2" | Field Type
 
! class="col3" | Example
 
! class="col3" | Example
 
! class="col4" | Notes
 
! class="col4" | Notes
 
|- class="row1"
 
|- class="row1"
| class="col0 centeralign" rowspan="5" | 0x17
+
| class="col0 centeralign" rowspan="8" | 0x14
| class="col1 centeralign" | EID
+
| class="col1" | EID
| class="col2 centeralign" | int
+
| class="col2" | int
| class="col3 centeralign" | <code>62</code>
+
| class="col3" | <code>94453</code>
| class="col4" | Entity ID of the Object
+
| class="col4" | Player ID
 
|- class="row2"
 
|- class="row2"
| class="col0 centeralign" | Type
+
| class="col0" | Player Name
| class="col1 centeralign" | byte
+
| class="col1" | string
| class="col2 centeralign" | <code>11</code>
+
| class="col2" | <code>Twdtwd</code>
| class="col3" | The type of object (see below)
+
| class="col3" |
 
|- class="row3"
 
|- class="row3"
| class="col0 centeralign" | X
+
| class="col0" | X
| class="col1 centeralign" | int
+
| class="col1" | int
| class="col2 centeralign" | <code>16080</code>
+
| class="col2" | <code>784</code>
| class="col3" | The Absolute Integer X Position of the object
+
| class="col3" | Player X as Absolute Integer
 
|- class="row4"
 
|- class="row4"
| class="col0 centeralign" | Y
+
| class="col0" | Y
| class="col1 centeralign" | int
+
| class="col1" | int
| class="col2 centeralign" | <code>2299</code>
+
| class="col2" | <code>2131</code>
| class="col3" | The Absolute Integer Y Position of the object
+
| class="col3" | Player Y as Absolute Integer
 
|- class="row5"
 
|- class="row5"
| class="col0 centeralign" | Z
+
| class="col0" | Z
| class="col1 centeralign" | int
+
| class="col1" | int
| class="col2 centeralign" | <code>592</code>
+
| class="col2" | <code>-752</code>
| class="col3" | The Absolute Integer Z Position of the object
+
| class="col3" | Player Z as Absolute Integer
 
|- class="row6"
 
|- class="row6"
 +
| class="col0" | Rotation
 +
| class="col1" | byte
 +
| class="col2" | <code>0</code>
 +
| class="col3" | Player rotation as a packed byte
 +
|- class="row7"
 +
| class="col0" | Pitch
 +
| class="col1" | byte
 +
| class="col2" | <code>0</code>
 +
| class="col3" | Player rotation as a packed byte
 +
|- class="row8"
 +
| class="col0" | Current Item
 +
| class="col1" | short
 +
| class="col2" | <code>0</code>
 +
| class="col3" | The item the player is currently holding
 +
|- class="row9"
 
! class="col0" | Total Size:
 
! class="col0" | Total Size:
| class="col1 rightalign" colspan="4" | 18 bytes
+
| class="col1 rightalign" colspan="4" | 23 bytes + length of strings
 
|}
 
|}
  
Object Types
+
=== Pickup Spawn (0x15) ===
 +
 
 +
A pickup spawn is sent whenever an item on the ground (say a pickaxe thrown on the ground) comes into range of the player.
  
 
{| class="wikitable"
 
{| class="wikitable"
 
|- class="row0"
 
|- class="row0"
! class="col0" | Type ID
+
! class="col0 centeralign" | Packet ID
! class="col1" | Type Name
+
! class="col1 rightalign" | Field Name
 +
! class="col2" | Field Type
 +
! class="col3" | Example
 +
! class="col4" | Notes
 
|- class="row1"
 
|- class="row1"
| class="col0" | 1
+
| class="col0 centeralign" rowspan="9" | 0x15
| class="col1" | Boats
+
| class="col1" | EID
 +
| class="col2" | int
 +
| class="col3" | <code>157617</code>
 +
| class="col4" | Unique entity ID
 
|- class="row2"
 
|- class="row2"
| class="col0" | 10
+
| class="col0" | Item
| class="col1" | Minecart
+
| class="col1" | short
 +
| class="col2" | <code>4</code>
 +
| class="col3" | The item ID
 
|- class="row3"
 
|- class="row3"
| class="col0" | 11
+
| class="col0" | Count
| class="col1" | Storage Cart
+
| class="col1" | byte
 +
| class="col2" | <code>1</code>
 +
| class="col3" | The number of items
 
|- class="row4"
 
|- class="row4"
| class="col0" | 12
+
| class="col0" | X
| class="col1" | Powered Cart
+
| class="col1" | int
|}
+
| class="col2" | <code>133</code>
 
+
| class="col3" | Item X as Absolute Integer
=== Mob Spawn (0x18) ===
+
|- class="row5"
 
+
| class="col0" | Y
Sent by the server when a Mob Entity is Spawned
+
| class="col1" | int
 
+
| class="col2" | <code>913</code>
{| class="wikitable"
+
| class="col3" | Item Y as Absolute Integer
|- class="row0"
+
|- class="row6"
! class="col0" | Packet ID
+
| class="col0" | Z
! class="col1" | Field Name
+
| class="col1" | int
! class="col2" | Field Type
+
| class="col2" | <code>63552</code>
! class="col3" | Example
+
| class="col3" | Item Z as Absolute Integer
! class="col4" | Notes
+
|- class="row7"
|- class="row1"
+
| class="col0" | Rotation
| class="col0 centeralign" rowspan="7" | 0x18
+
| class="col1" | byte
| class="col1 centeralign" | EID
+
| class="col2" | <code>252</code>
| class="col2 centeralign" | int
+
| class="col3" | Item rotation as a packed byte
| class="col3 centeralign" | <code>446</code>
+
|- class="row8"
| class="col4" | Entity ID
+
| class="col0" | Pitch
|- class="row2"
+
| class="col1" | byte
| class="col0 centeralign" | Type
+
| class="col2" | <code>25</code>
| class="col1 centeralign" | byte
+
| class="col3" | Item pitch as a packed byte
| class="col2 centeralign" | <code>91</code>
+
|- class="row9"
| class="col3" | The type of Mob Entity Type
+
| class="col0" | Roll
|- class="row3"
+
| class="col1" | byte
| class="col0 centeralign" | X
+
| class="col2" | <code>12</code>
| class="col1 centeralign" | int
+
| class="col3" | Item roll as a packed byte
| class="col2 centeralign" | <code>13366</code>
+
|- class="row10"
| class="col3" | The Absolute Integer X Position of the object
+
! class="col0" | Total Size:
|- class="row4"
+
| class="col1 rightalign" colspan="4" | 23 bytes
| class="col0 centeralign" | Y
+
|}
| class="col1 centeralign" | int
+
 
| class="col2 centeralign" | <code>2176</code>
+
=== Collect Item (0x16) ===
| class="col3" | The Absolute Integer Y Position of the object
+
 
|- class="row5"
+
Sent by the server when someone picks up an item lying on the ground - its sole purpose appears to be the animation of the item flying towards you. It doesn't destroy the entity in the client memory ([[Protocol#Destroy_Entity_.280x1D.29|0x1D]] does that), and it doesn't add it to your inventory ([[Protocol#Add_To_Inventory_.280x11.29|0x11]] does that).
| class="col0 centeralign" | Z
+
 
| class="col1 centeralign" | int
+
{| class="wikitable"
| class="col2 centeralign" | <code>1680</code>
+
|- class="row0"
| class="col3" | The Absolute Integer Z Position of the object
 
|- class="row6"
 
| class="col0 centeralign" | Yaw
 
| class="col1 centeralign" | byte
 
| class="col2 centeralign" | <code>-27</code>
 
| class="col3" | The X Axis rotation as a fraction of 360
 
|- class="row7"
 
| class="col0 centeralign" | Pitch
 
| class="col1 centeralign" | byte
 
| class="col2 centeralign" | <code>0</code>
 
| class="col3" | The Y Axis rotation as a fraction of 360
 
|- class="row8"
 
! class="col0" | Total Size:
 
| class="col1 rightalign" colspan="4" | 20 bytes
 
|}
 
 
 
=== Destroy Entity (0x1D) ===
 
 
 
Sent by the server when an Entity is to be destroyed on the client.
 
 
 
{| class="wikitable"
 
|- class="row0"
 
 
! class="col0" | Packet ID
 
! class="col0" | Packet ID
 
! class="col1" | Field Name
 
! class="col1" | Field Name
Line 1,203: Line 1,208:
 
! class="col4" | Notes
 
! class="col4" | Notes
 
|- class="row1"
 
|- class="row1"
| class="col0 centeralign" | 0x1D
+
| class="col0 centeralign" rowspan="2" | 0x16
| class="col1 centeralign" | EID
+
| class="col1 centeralign" | Collected EID
 
| class="col2 centeralign" | int
 
| class="col2 centeralign" | int
| class="col3 centeralign" | <code>446</code>
+
| class="col3 centeralign" | <code>38</code>
| class="col4 centeralign" | Entity ID
+
| class="col4 leftalign" |
 
|- class="row2"
 
|- class="row2"
 +
| class="col0 centeralign" | Collector EID
 +
| class="col1 centeralign" | int
 +
| class="col2 centeralign" | <code>20</code>
 +
| class="col3 leftalign" |
 +
|- class="row3"
 
! class="col0" | Total Size:
 
! class="col0" | Total Size:
| class="col1 rightalign" colspan="4" | 5 bytes
+
| class="col1 rightalign" colspan="4" | 9 bytes
 
|}
 
|}
  
=== Entity (0x1E) ===
+
=== Add Object/Vehicle (0x17) ===
  
Most entity-related packets are subclasses of this packet. When sent from the server to the client, it may initialize the entry.
+
Sent by the server when an Object/Vehicle is created.
  
 
{| class="wikitable"
 
{| class="wikitable"
Line 1,225: Line 1,235:
 
! class="col4" | Notes
 
! class="col4" | Notes
 
|- class="row1"
 
|- class="row1"
| class="col0 centeralign" | 0x1E
+
| class="col0 centeralign" rowspan="5" | 0x17
 
| class="col1 centeralign" | EID
 
| class="col1 centeralign" | EID
 
| class="col2 centeralign" | int
 
| class="col2 centeralign" | int
| class="col3 centeralign" | <code>446</code>
+
| class="col3 centeralign" | <code>62</code>
| class="col4 centeralign" | Entity ID
+
| class="col4" | Entity ID of the Object
 
|- class="row2"
 
|- class="row2"
! class="col0" | Total Size:
+
| class="col0 centeralign" | Type
| class="col1 rightalign" colspan="4" | 5 bytes
+
| class="col1 centeralign" | byte
|}
+
| class="col2 centeralign" | <code>11</code>
 
+
| class="col3" | The type of object (see below)
=== Entity Relative Move (0x1F) ===
+
|- class="row3"
 +
| class="col0 centeralign" | X
 +
| class="col1 centeralign" | int
 +
| class="col2 centeralign" | <code>16080</code>
 +
| class="col3" | The Absolute Integer X Position of the object
 +
|- class="row4"
 +
| class="col0 centeralign" | Y
 +
| class="col1 centeralign" | int
 +
| class="col2 centeralign" | <code>2299</code>
 +
| class="col3" | The Absolute Integer Y Position of the object
 +
|- class="row5"
 +
| class="col0 centeralign" | Z
 +
| class="col1 centeralign" | int
 +
| class="col2 centeralign" | <code>592</code>
 +
| class="col3" | The Absolute Integer Z Position of the object
 +
|- class="row6"
 +
! class="col0" | Total Size:
 +
| class="col1 rightalign" colspan="4" | 18 bytes
 +
|}
  
This packet is sent by the server when an entity moves less then 4 blocks, if an entity moves more then 4 blocks [[Protocol#Entity_Teleport_.280x22.29|Entity Teleport]] should be sent instead.
+
Object Types
  
 
{| class="wikitable"
 
{| class="wikitable"
 
|- class="row0"
 
|- class="row0"
! class="col0" | Packet ID
+
! class="col0" | Type ID
! class="col1" | Field Name
+
! class="col1" | Type Name
! class="col2" | Field Type
 
! class="col3" | Example
 
! class="col4" | Notes
 
 
|- class="row1"
 
|- class="row1"
| class="col0 centeralign" rowspan="4" | 0x1F
+
| class="col0" | 1
| class="col1 centeralign" | EID
+
| class="col1" | Boats
| class="col2 centeralign" | int
 
| class="col3 centeralign" | <code>459</code>
 
| class="col4" | Entity ID
 
 
|- class="row2"
 
|- class="row2"
| class="col0 centeralign" | X
+
| class="col0" | 10
| class="col1 centeralign" | byte
+
| class="col1" | Minecart
| class="col2 centeralign" | <code>1</code>
 
| class="col3" | X axis Relative movement as an Absolute Integer
 
 
|- class="row3"
 
|- class="row3"
| class="col0 centeralign" | Y
+
| class="col0" | 11
| class="col1 centeralign" | byte
+
| class="col1" | Storage Cart
| class="col2 centeralign" | <code>-7</code>
 
| class="col3" | Y axis Relative movement as an Absolute Integer
 
 
|- class="row4"
 
|- class="row4"
| class="col0 centeralign" | Z
+
| class="col0" | 12
| class="col1 centeralign" | byte
+
| class="col1" | Powered Cart
| class="col2 centeralign" | <code>5</code>
 
| class="col3" | Z axis Relative movement as an Absolute Integer
 
|- class="row5"
 
! class="col0" | Total Size:
 
| class="col1 rightalign" colspan="4" | 8 bytes
 
 
|}
 
|}
  
=== Entity Look (0x20) ===
+
=== Mob Spawn (0x18) ===
  
This packet is sent by the server when an entity rotates.
+
Sent by the server when a Mob Entity is Spawned
  
 
{| class="wikitable"
 
{| class="wikitable"
Line 1,284: Line 1,297:
 
! class="col4" | Notes
 
! class="col4" | Notes
 
|- class="row1"
 
|- class="row1"
| class="col0 centeralign" rowspan="3" | 0x20
+
| class="col0 centeralign" rowspan="7" | 0x18
 
| class="col1 centeralign" | EID
 
| class="col1 centeralign" | EID
 
| class="col2 centeralign" | int
 
| class="col2 centeralign" | int
| class="col3 centeralign" | <code>459</code>
+
| class="col3 centeralign" | <code>446</code>
 
| class="col4" | Entity ID
 
| class="col4" | Entity ID
 
|- class="row2"
 
|- class="row2"
| class="col0 centeralign" | Yaw
+
| class="col0 centeralign" | Type
 
| class="col1 centeralign" | byte
 
| class="col1 centeralign" | byte
| class="col2 centeralign" | <code>126</code>
+
| class="col2 centeralign" | <code>91</code>
| class="col3" | The X Axis rotation as a fraction of 360
+
| class="col3" | The type of Mob Entity Type
 
|- class="row3"
 
|- class="row3"
| class="col0 centeralign" | Pitch
+
| class="col0 centeralign" | X
| class="col1 centeralign" | byte
+
| class="col1 centeralign" | int
| class="col2 centeralign" | <code>0</code>
+
| class="col2 centeralign" | <code>13366</code>
| class="col3" | The Y Axis rotation as a fraction of 360
+
| class="col3" | The Absolute Integer X Position of the object
 
|- class="row4"
 
|- class="row4"
! class="col0" | Total Size:
+
| class="col0 centeralign" | Y
| class="col1 rightalign" colspan="4" | 7 bytes
+
| class="col1 centeralign" | int
|}
+
| class="col2 centeralign" | <code>2176</code>
 +
| class="col3" | The Absolute Integer Y Position of the object
 +
|- class="row5"
 +
| class="col0 centeralign" | Z
 +
| class="col1 centeralign" | int
 +
| class="col2 centeralign" | <code>1680</code>
 +
| class="col3" | The Absolute Integer Z Position of the object
 +
|- class="row6"
 +
| class="col0 centeralign" | Yaw
 +
| class="col1 centeralign" | byte
 +
| class="col2 centeralign" | <code>-27</code>
 +
| class="col3" | The X Axis rotation as a fraction of 360
 +
|- class="row7"
 +
| class="col0 centeralign" | Pitch
 +
| class="col1 centeralign" | byte
 +
| class="col2 centeralign" | <code>0</code>
 +
| class="col3" | The Y Axis rotation as a fraction of 360
 +
|- class="row8"
 +
! class="col0" | Total Size:
 +
| class="col1 rightalign" colspan="4" | 20 bytes
 +
|}
 +
 
 +
=== Entity Velocity? (0x1C) ===
 +
This packet is new to version 4 of the protocol, and is believed to be Entity Velocity/Motion.
 +
 
 +
Velocity is believed to in block velocity * 32000 with regards to the speed being server ticks, 200ms
 +
 
 +
e.g. -1343 would move (-1343 / 32000) = -0.04196875 blocks per tick (or -0.20984375 blocks per second)
  
=== Entity Look and Relative Move (0x21) ===
+
Each axis Velocity is capped between -0.9 and 0.9 blocks per tick (Velocity -28800 to 28800)
  
This packet is sent by the server when an entity rotates and moves.
+
(This packet data values are not fully verified)
  
 
{| class="wikitable"
 
{| class="wikitable"
Line 1,316: Line 1,356:
 
! class="col4" | Notes
 
! class="col4" | Notes
 
|- class="row1"
 
|- class="row1"
| class="col0 centeralign" rowspan="6" | 0x21
+
| class="col0 centeralign" rowspan="4" | 0x1C
| class="col1 centeralign" | EID
+
| class="col1 centeralign" | Entity ID
 
| class="col2 centeralign" | int
 
| class="col2 centeralign" | int
| class="col3 centeralign" | <code>459</code>
+
| class="col3 centeralign" | <code>1805</code>
| class="col4" | Entity ID
+
| class="col4" |
 +
The entity ID
 
|- class="row2"
 
|- class="row2"
| class="col0 centeralign" | X
+
| class="col0 centeralign" | Velocity X
| class="col1 centeralign" | byte
+
| class="col1 centeralign" | short
| class="col2 centeralign" | <code>1</code>
+
| class="col2 centeralign" | <code>-1343</code>
| class="col3" | X axis Relative movement as an Absolute Integer
+
| class="col3" |
 +
Velocity on the X axis
 
|- class="row3"
 
|- class="row3"
| class="col0 centeralign" | Y
+
| class="col0 centeralign" | Velocity Y
| class="col1 centeralign" | byte
+
| class="col1 centeralign" | short
| class="col2 centeralign" | <code>-7</code>
+
| class="col2 centeralign" | <code>0</code>
| class="col3" | Y axis Relative movement as an Absolute Integer
+
| class="col3" |
 +
Velocity on the Y axis
 
|- class="row4"
 
|- class="row4"
| class="col0 centeralign" | Z
+
| class="col0 centeralign" | Velocity Z
| class="col1 centeralign" | byte
+
| class="col1 centeralign" | short
| class="col2 centeralign" | <code>5</code>
+
| class="col2 centeralign" | <code>0</code>
| class="col3" | Z axis Relative movement as an Absolute Integer
+
| class="col3" |
 +
Velocity on the Z axis
 
|- class="row5"
 
|- class="row5"
| class="col0 centeralign" | Yaw
+
! class="col0" | Total Size:
| class="col1 centeralign" | byte
+
| class="col1 rightalign" colspan="4" | 11 bytes
| class="col2 centeralign" | <code>126</code>
+
|}
| class="col3" | The X Axis rotation as a fraction of 360
+
 
|- class="row6"
+
 
| class="col0 centeralign" | Pitch
 
| class="col1 centeralign" | byte
 
| class="col2 centeralign" | <code>0</code>
 
| class="col3" | The Y Axis rotation as a fraction of 360
 
|- class="row7"
 
! class="col0" | Total Size:
 
| class="col1 rightalign" colspan="4" | 10 bytes
 
|}
 
  
=== Entity Teleport (0x22) ===
+
=== Destroy Entity (0x1D) ===
  
This packet is sent by the server when an entity moves more then 4 blocks.
+
Sent by the server when an Entity is to be destroyed on the client.
  
 
{| class="wikitable"
 
{| class="wikitable"
Line 1,363: Line 1,399:
 
! class="col4" | Notes
 
! class="col4" | Notes
 
|- class="row1"
 
|- class="row1"
| class="col0 centeralign" rowspan="6" | 0x22
+
| class="col0 centeralign" | 0x1D
 
| class="col1 centeralign" | EID
 
| class="col1 centeralign" | EID
 
| class="col2 centeralign" | int
 
| class="col2 centeralign" | int
| class="col3 centeralign" | <code>459</code>
+
| class="col3 centeralign" | <code>446</code>
| class="col4" | Entity ID
+
| class="col4 centeralign" | Entity ID
 
|- class="row2"
 
|- class="row2"
| class="col0 centeralign" | X
+
! class="col0" | Total Size:
| class="col1 centeralign" | int
+
| class="col1 rightalign" colspan="4" | 5 bytes
| class="col2 centeralign" | <code>14162</code>
+
|}
| class="col3" | X axis position as an Absolute Integer
+
 
|- class="row3"
+
=== Entity (0x1E) ===
| class="col0 centeralign" | Y
 
| class="col1 centeralign" | int
 
| class="col2 centeralign" | <code>2176</code>
 
| class="col3" | Y axis position as an Absolute Integer
 
|- class="row4"
 
| class="col0 centeralign" | Z
 
| class="col1 centeralign" | int
 
| class="col2 centeralign" | <code>1111</code>
 
| class="col3" | Z axis position as an Absolute Integer
 
|- class="row5"
 
| class="col0 centeralign" | Yaw
 
| class="col1 centeralign" | byte
 
| class="col2 centeralign" | <code>126</code>
 
| class="col3" | The X Axis rotation as a fraction of 360
 
|- class="row6"
 
| class="col0 centeralign" | Pitch
 
| class="col1 centeralign" | byte
 
| class="col2 centeralign" | <code>0</code>
 
| class="col3" | The Y Axis rotation as a fraction of 360
 
|- class="row7"
 
! class="col0" | Total Size:
 
| class="col1 rightalign" colspan="4" | 19 bytes
 
|}
 
  
=== Pre-Chunk (0x32) ===
+
Most entity-related packets are subclasses of this packet. When sent from the server to the client, it may initialize the entry.
 
 
This packet is sent by the server to notify the client to initialize (Mode=1) or unload (Mode=0) a chunk. The client is expected to allocate space for a full chunk (currently 16 x 128 x 16 blocks). One or more 0x33 packets will follow, specifying actual data to fill the chunk with.
 
 
 
[[File:Icon_exclaim.gif|:!:]] Whenever you send this packet the client will clear any previous chunk at that spot if one has previously been sent. Clients don't like being in or next to an unloaded chunk, so try not to unload it if players are nearby. If the player appears to be twitching and stuck in place after joining the world, there is probably an unloaded chunk too close to them.
 
  
 
{| class="wikitable"
 
{| class="wikitable"
Line 1,412: Line 1,421:
 
! class="col4" | Notes
 
! class="col4" | Notes
 
|- class="row1"
 
|- class="row1"
| class="col0 centeralign" rowspan="3" | 0x32
+
| class="col0 centeralign" | 0x1E
| class="col1 centeralign" | X
+
| class="col1 centeralign" | EID
 
| class="col2 centeralign" | int
 
| class="col2 centeralign" | int
| class="col3 centeralign" | <code>-9</code>
+
| class="col3 centeralign" | <code>446</code>
| class="col4" | Chunk X Coordinate
+
| class="col4 centeralign" | Entity ID
 
|- class="row2"
 
|- class="row2"
| class="col0 centeralign" | Z
 
| class="col1 centeralign" | int
 
| class="col2 centeralign" | <code>12</code>
 
| class="col3" | Chunk Z Coordinate
 
|- class="row3"
 
| class="col0 centeralign" | Mode
 
| class="col1 centeralign" | bool
 
| class="col2 centeralign" | <code>1</code>
 
| class="col3" | If mode is 0 the client will unload the chunk, otherwise the client will initialize the chunk
 
|- class="row4"
 
 
! class="col0" | Total Size:
 
! class="col0" | Total Size:
| class="col1 rightalign" colspan="4" | 10 bytes
+
| class="col1 rightalign" colspan="4" | 5 bytes
 
|}
 
|}
  
=== Map Chunk (0x33) ===
+
=== Entity Relative Move (0x1F) ===
  
The client will overwrite all '''or part''' of a chunk using the region of data contained in this packet. The server specifies the region to write using a block position and size in X,Y,Z. Note that this region will always be inside a single chunk. (At least using the vanilla server. Unknown if the client has this limitation.)
+
This packet is sent by the server when an entity moves less then 4 blocks, if an entity moves more then 4 blocks [[Protocol#Entity_Teleport_.280x22.29|Entity Teleport]] should be sent instead.
 
 
A server '''can''' send a 0x32 packet prior, allowing the client to initialize the chunk. However this doesn't always happen in practice. Thus the client should initialize the chunk on-demand.
 
  
 
{| class="wikitable"
 
{| class="wikitable"
Line 1,446: Line 1,443:
 
! class="col4" | Notes
 
! class="col4" | Notes
 
|- class="row1"
 
|- class="row1"
| class="col0 centeralign" rowspan="8" | 0x33
+
| class="col0 centeralign" rowspan="4" | 0x1F
| class="col1 centeralign" | X
+
| class="col1 centeralign" | EID
 
| class="col2 centeralign" | int
 
| class="col2 centeralign" | int
| class="col3 centeralign" | <code>128</code>
+
| class="col3 centeralign" | <code>459</code>
| class="col4" | Block X Coordinate
+
| class="col4" | Entity ID
 
|- class="row2"
 
|- class="row2"
 +
| class="col0 centeralign" | X
 +
| class="col1 centeralign" | byte
 +
| class="col2 centeralign" | <code>1</code>
 +
| class="col3" | X axis Relative movement as an Absolute Integer
 +
|- class="row3"
 
| class="col0 centeralign" | Y
 
| class="col0 centeralign" | Y
| class="col1 centeralign" | short
+
| class="col1 centeralign" | byte
| class="col2 centeralign" | <code>0</code>
+
| class="col2 centeralign" | <code>-7</code>
| class="col3" | Block Y Coordinate
+
| class="col3" | Y axis Relative movement as an Absolute Integer
|- class="row3"
+
|- class="row4"
 
| class="col0 centeralign" | Z
 
| class="col0 centeralign" | Z
| class="col1 centeralign" | int
 
| class="col2 centeralign" | <code>-192</code>
 
| class="col3" | Block Z Coordinate
 
|- class="row4"
 
| class="col0 centeralign" | Size_X
 
 
| class="col1 centeralign" | byte
 
| class="col1 centeralign" | byte
| class="col2 centeralign" | <code>15</code>
+
| class="col2 centeralign" | <code>5</code>
| class="col3" | Size_X is Actual X Size -1
+
| class="col3" | Z axis Relative movement as an Absolute Integer
 
|- class="row5"
 
|- class="row5"
| class="col0 centeralign" | Size_Y
 
| class="col1 centeralign" | byte
 
| class="col2 centeralign" | <code>127</code>
 
| class="col3" | Size_Y is Actual Y Size -1
 
|- class="row6"
 
| class="col0 centeralign" | Size_Z
 
| class="col1 centeralign" | byte
 
| class="col2 centeralign" | <code>15</code>
 
| class="col3" | Size_Z is Actual Z Size -1
 
|- class="row7"
 
| class="col0 centeralign" | Compressed size
 
| class="col1 centeralign" | int
 
| class="col2 centeralign" | <code>3663</code>
 
| class="col3" | Size of compressed region data
 
|- class="row8"
 
| class="col0 centeralign" | Compressed data
 
| class="col1 centeralign" | byte array
 
| class="col2 centeralign" | <code>…</code>
 
| class="col3" | The region data is compressed using ZLib Deflate function.
 
|- class="row9"
 
 
! class="col0" | Total Size:
 
! class="col0" | Total Size:
| class="col1 rightalign" colspan="4" | 18 bytes + Compressed chunk size
+
| class="col1 rightalign" colspan="4" | 8 bytes
 
|}
 
|}
  
=====X, Y, Z=====
+
=== Entity Look (0x20) ===
This is the start position of the region, in '''world''' block coordinates.
 
  
To find which chunk is affected, in the same coordinates given by packet 0x32:
+
This packet is sent by the server when an entity rotates.
  ChunkX = X >> 4
 
  ChunkY = Y >> 7
 
  ChunkZ = Z >> 4
 
  
And conversely, which local block in the chunk to start at:
+
{| class="wikitable"
  StartX = X & 15
+
|- class="row0"
  StartY = Y & 127  (not always 0!)
+
! class="col0" | Packet ID
  StartZ = Z & 15
+
! class="col1" | Field Name
 
+
! class="col2" | Field Type
=====SizeX, SizeY, SizeZ=====
+
! class="col3" | Example
This is the size of the region, in blocks. The server will subtract one from the sizes and then cast them to a byte before sending. This is so that chunks as large as 256 are possible (the maximum size of a byte is 255; 256 - 1 = 255).
+
! class="col4" | Notes
 
+
|- class="row1"
=====Compressed data=====
+
| class="col0 centeralign" rowspan="3" | 0x20
The data is compressed using the deflate() function in [http://www.zlib.net/ zlib]. After uncompressing, the data consists of four sections, in order:
+
| class="col1 centeralign" | EID
 
+
| class="col2 centeralign" | int
* <div class="li"> Block type array (1 byte per block)</div>
+
| class="col3 centeralign" | <code>459</code>
* <div class="li"> Block metadata array (half byte/nibble per block)</div>
+
| class="col4" | Entity ID
* <div class="li"> Block Light array (half byte/nibble per block)</div>
+
|- class="row2"
* <div class="li"> Sky Light array (half byte/nibble per block)</div>
+
| class="col0 centeralign" | Yaw
 +
| class="col1 centeralign" | byte
 +
| class="col2 centeralign" | <code>126</code>
 +
| class="col3" | The X Axis rotation as a fraction of 360
 +
|- class="row3"
 +
| class="col0 centeralign" | Pitch
 +
| class="col1 centeralign" | byte
 +
| class="col2 centeralign" | <code>0</code>
 +
| class="col3" | The Y Axis rotation as a fraction of 360
 +
|- class="row4"
 +
! class="col0" | Total Size:
 +
| class="col1 rightalign" colspan="4" | 7 bytes
 +
|}
  
The data is exactly <code>(Size_X+1) * (Size_Y+1) * (Size_Z+1) * 2.5</code> bytes long.
+
=== Entity Look and Relative Move (0x21) ===
  
In other words, there are Size_X number of '''x planes''', each plane made up of Size_Z number of '''z rows''', each row made up of Size_Y blocks indexed by y coordinate in order.
+
This packet is sent by the server when an entity rotates and moves.
  
The block type array is indexed with:
+
{| class="wikitable"
  index = y + (z * (Size_Y+1)) + (x * (Size_Y+1) * (Size_Z+1))
+
|- class="row0"
 
 
The other arrays are similar but you need to divide the index by two after calculating the above. Then each byte contains data for '''two''' blocks.
 
 
 
=== Multi Block Change (0x34) ===
 
 
 
Further investigation shows that this is a multiple-block-change command; if you take the three arrays, and put together elements with the same index, and then decompose the short into coordinates (top 4 bits is X, next 4 bits is Z, bottom 8 bits is Y), you get things like [((8, 7, 4), 11, 0), ((7, 13, 6), 11, 0), ((13, 1, 8), 11, 0), ((7, 6, 6), 11, 0)].
 
 
 
See the Block Change command for description of the general format of a block change.
 
 
 
{| class="wikitable"
 
|- class="row0"
 
 
! class="col0" | Packet ID
 
! class="col0" | Packet ID
 
! class="col1" | Field Name
 
! class="col1" | Field Name
Line 1,538: Line 1,512:
 
! class="col4" | Notes
 
! class="col4" | Notes
 
|- class="row1"
 
|- class="row1"
| class="col0 centeralign" rowspan="6" | 0x34
+
| class="col0 centeralign" rowspan="6" | 0x21
| class="col1 centeralign" | Chunk X
+
| class="col1 centeralign" | EID
 
| class="col2 centeralign" | int
 
| class="col2 centeralign" | int
| class="col3 centeralign" | <code>-9</code>
+
| class="col3 centeralign" | <code>459</code>
| class="col4" | Chunk X Coordinate
+
| class="col4" | Entity ID
 
|- class="row2"
 
|- class="row2"
| class="col0 centeralign" | Chunk Z
+
| class="col0 centeralign" | X
| class="col1 centeralign" | int
+
| class="col1 centeralign" | byte
| class="col2 centeralign" | <code>12</code>
+
| class="col2 centeralign" | <code>1</code>
| class="col3" | Chunk Z Coordinate
+
| class="col3" | X axis Relative movement as an Absolute Integer
 
|- class="row3"
 
|- class="row3"
| class="col0 centeralign" | Array size
+
| class="col0 centeralign" | Y
| class="col1 centeralign" | short
+
| class="col1 centeralign" | byte
| class="col2 centeralign" | <code>2</code>
+
| class="col2 centeralign" | <code>-7</code>
| class="col3" | The total number of elements per array
+
| class="col3" | Y axis Relative movement as an Absolute Integer
 
|- class="row4"
 
|- class="row4"
| class="col0 centeralign" | Coordinate array
+
| class="col0 centeralign" | Z
| class="col1 centeralign" | short array
+
| class="col1 centeralign" | byte
| class="col2 centeralign" | <code></code>
+
| class="col2 centeralign" | <code>5</code>
| class="col3" | The coordinates of the blocks to change
+
| class="col3" | Z axis Relative movement as an Absolute Integer
 
|- class="row5"
 
|- class="row5"
| class="col0 centeralign" | Type array
+
| class="col0 centeralign" | Yaw
| class="col1 centeralign" | byte array
+
| class="col1 centeralign" | byte
| class="col2 centeralign" | <code></code>
+
| class="col2 centeralign" | <code>126</code>
| class="col3" | The type for each block change
+
| class="col3" | The X Axis rotation as a fraction of 360
 
|- class="row6"
 
|- class="row6"
| class="col0 centeralign" | Metadata array
+
| class="col0 centeralign" | Pitch
| class="col1 centeralign" | byte array
+
| class="col1 centeralign" | byte
| class="col2 centeralign" | <code></code>
+
| class="col2 centeralign" | <code>0</code>
| class="col3 leftalign" | The Metadata for each block changed
+
| class="col3" | The Y Axis rotation as a fraction of 360
 
|- class="row7"
 
|- class="row7"
 
! class="col0" | Total Size:
 
! class="col0" | Total Size:
| class="col1 rightalign" colspan="4" | 11 bytes + Arrays
+
| class="col1 rightalign" colspan="4" | 10 bytes
 
|}
 
|}
  
=== Block Change (0x35) ===
+
=== Entity Teleport (0x22) ===
  
[[File:Icon_exclaim.gif|:!:]] Block metadata varies by block type - it should be <code>0x00</code> for most blocks with a few exceptions, shown in the table below.
+
This packet is sent by the server when an entity moves more then 4 blocks.
  
 
{| class="wikitable"
 
{| class="wikitable"
Line 1,585: Line 1,559:
 
! class="col4" | Notes
 
! class="col4" | Notes
 
|- class="row1"
 
|- class="row1"
| class="col0 centeralign" rowspan="5" | 0x35
+
| class="col0 centeralign" rowspan="6" | 0x22
| class="col1 centeralign" | X
+
| class="col1 centeralign" | EID
 
| class="col2 centeralign" | int
 
| class="col2 centeralign" | int
| class="col3 centeralign" | <code>502</code>
+
| class="col3 centeralign" | <code>459</code>
| class="col4" | Block X Coordinate
+
| class="col4" | Entity ID
 
|- class="row2"
 
|- class="row2"
 +
| class="col0 centeralign" | X
 +
| class="col1 centeralign" | int
 +
| class="col2 centeralign" | <code>14162</code>
 +
| class="col3" | X axis position as an Absolute Integer
 +
|- class="row3"
 
| class="col0 centeralign" | Y
 
| class="col0 centeralign" | Y
| class="col1 centeralign" | byte
 
| class="col2 centeralign" | <code>71</code>
 
| class="col3" | Block Y Coordinate
 
|- class="row3"
 
| class="col0 centeralign" | Z
 
 
| class="col1 centeralign" | int
 
| class="col1 centeralign" | int
| class="col2 centeralign" | <code>18</code>
+
| class="col2 centeralign" | <code>2176</code>
| class="col3" | Block Z Coordinate
+
| class="col3" | Y axis position as an Absolute Integer
 
|- class="row4"
 
|- class="row4"
| class="col0 centeralign" | Block Type
+
| class="col0 centeralign" | Z
 +
| class="col1 centeralign" | int
 +
| class="col2 centeralign" | <code>1111</code>
 +
| class="col3" | Z axis position as an Absolute Integer
 +
|- class="row5"
 +
| class="col0 centeralign" | Yaw
 
| class="col1 centeralign" | byte
 
| class="col1 centeralign" | byte
| class="col2 centeralign" | <code>78</code>
+
| class="col2 centeralign" | <code>126</code>
| class="col3" | The new block type for the block
+
| class="col3" | The X Axis rotation as a fraction of 360
|- class="row5"
+
|- class="row6"
| class="col0 centeralign" | Block Metadata
+
| class="col0 centeralign" | Pitch
 
| class="col1 centeralign" | byte
 
| class="col1 centeralign" | byte
 
| class="col2 centeralign" | <code>0</code>
 
| class="col2 centeralign" | <code>0</code>
| class="col3" | The new Metadata for the block
+
| class="col3" | The Y Axis rotation as a fraction of 360
|- class="row6"
+
|- class="row7"
 
! class="col0" | Total Size:
 
! class="col0" | Total Size:
| class="col1 rightalign" colspan="4" | 12 bytes
+
| class="col1 rightalign" colspan="4" | 19 bytes
 
|}
 
|}
  
=== Complex Entities (0x3B) ===
+
=== Attach Entity? (0x27) ===
 +
This packet is new to version 4 of the protocol, and is believed to be Attach Entity.
 +
 
 +
This packet is sent when a player has been attached to an entity (e.g. Minecart)
  
This is a complex packet used to send entities including their entire NBT representation. This packet is currently used for furnaces, chests, signs and mob spawners. This packet is only temporary, and used for rapid prototyping of new types of entities. Specialized packets for each object will eventually be added.
+
(This packet data values are not fully verified)
  
 
{| class="wikitable"
 
{| class="wikitable"
Line 1,627: Line 1,609:
 
! class="col4" | Notes
 
! class="col4" | Notes
 
|- class="row1"
 
|- class="row1"
| class="col0 centeralign" rowspan="5" | 0x3B
+
| class="col0 centeralign" rowspan="2" | 0x27
| class="col1 centeralign" | X
+
| class="col1 centeralign" | Entity ID
| class="col2 centeralign" | int
+
| class="col2 centeralign" | int
| class="col3 centeralign" | <code>32</code>
+
| class="col3 centeralign" | <code>1298</code>
| class="col4" | Entity X in block coordinates
+
| class="col4" |
 +
The player entity ID being attached
 
|- class="row2"
 
|- class="row2"
| class="col0 centeralign" | Y
+
| class="col0 centeralign" | Vehicle ID
| class="col1 centeralign" | short
 
| class="col2 centeralign" | <code>64</code>
 
| class="col3" | Entity Y in block coordinates
 
|- class="row3"
 
| class="col0 centeralign" | Z
 
 
| class="col1 centeralign" | int
 
| class="col1 centeralign" | int
| class="col2 centeralign" | <code>32</code>
+
| class="col2 centeralign" | <code>1805</code>
| class="col3" | Entity Z in block coordinates
 
|- class="row4"
 
| class="col0 centeralign" | Payload Size
 
| class="col1 centeralign" | short
 
| class="col2 centeralign" | <code>84</code>
 
| class="col3" | The size (in bytes) of the payload
 
|- class="row5"
 
| class="col0 centeralign" | Payload
 
| class="col1 centeralign" | byte array
 
| class="col2 centeralign" | <code>…</code>
 
 
| class="col3" |
 
| class="col3" |
The payload is a compressed (GZ) [http://www.minecraft.net/docs/NBT.txt NBT] file
+
The vehicle entity ID attached to (-1 for unattaching)
 +
|- class="row3"
 +
! class="col0" | Total Size:
 +
| class="col1 rightalign" colspan="4" | 9 bytes
 +
|}
 +
 
 +
 
 +
=== Pre-Chunk (0x32) ===
 +
 
 +
This packet is sent by the server to notify the client to initialize (Mode=1) or unload (Mode=0) a chunk. The client is expected to allocate space for a full chunk (currently 16 x 128 x 16 blocks). One or more 0x33 packets will follow, specifying actual data to fill the chunk with.
 +
 
 +
[[File:Icon_exclaim.gif|:!:]] Whenever you send this packet the client will clear any previous chunk at that spot if one has previously been sent. Clients don't like being in or next to an unloaded chunk, so try not to unload it if players are nearby. If the player appears to be twitching and stuck in place after joining the world, there is probably an unloaded chunk too close to them.
 +
 
 +
{| class="wikitable"
 +
|- class="row0"
 +
! class="col0" | Packet ID
 +
! class="col1" | Field Name
 +
! class="col2" | Field Type
 +
! class="col3" | Example
 +
! class="col4" | Notes
 +
|- class="row1"
 +
| class="col0 centeralign" rowspan="3" | 0x32
 +
| class="col1 centeralign" | X
 +
| class="col2 centeralign" | int
 +
| class="col3 centeralign" | <code>-9</code>
 +
| class="col4" | Chunk X Coordinate
 +
|- class="row2"
 +
| class="col0 centeralign" | Z
 +
| class="col1 centeralign" | int
 +
| class="col2 centeralign" | <code>12</code>
 +
| class="col3" | Chunk Z Coordinate
 +
|- class="row3"
 +
| class="col0 centeralign" | Mode
 +
| class="col1 centeralign" | bool
 +
| class="col2 centeralign" | <code>1</code>
 +
| class="col3" | If mode is 0 the client will unload the chunk, otherwise the client will initialize the chunk
 +
|- class="row4"
 +
! class="col0" | Total Size:
 +
| class="col1 rightalign" colspan="4" | 10 bytes
 +
|}
 +
 
 +
=== Map Chunk (0x33) ===
 +
 
 +
The client will overwrite all '''or part''' of a chunk using the region of data contained in this packet. The server specifies the region to write using a block position and size in X,Y,Z. Note that this region will always be inside a single chunk. (At least using the vanilla server. Unknown if the client has this limitation.)
 +
 
 +
A server '''can''' send a 0x32 packet prior, allowing the client to initialize the chunk. However this doesn't always happen in practice. Thus the client should initialize the chunk on-demand.
 +
 
 +
{| class="wikitable"
 +
|- class="row0"
 +
! class="col0" | Packet ID
 +
! class="col1" | Field Name
 +
! class="col2" | Field Type
 +
! class="col3" | Example
 +
! class="col4" | Notes
 +
|- class="row1"
 +
| class="col0 centeralign" rowspan="8" | 0x33
 +
| class="col1 centeralign" | X
 +
| class="col2 centeralign" | int
 +
| class="col3 centeralign" | <code>128</code>
 +
| class="col4" | Block X Coordinate
 +
|- class="row2"
 +
| class="col0 centeralign" | Y
 +
| class="col1 centeralign" | short
 +
| class="col2 centeralign" | <code>0</code>
 +
| class="col3" | Block Y Coordinate
 +
|- class="row3"
 +
| class="col0 centeralign" | Z
 +
| class="col1 centeralign" | int
 +
| class="col2 centeralign" | <code>-192</code>
 +
| class="col3" | Block Z Coordinate
 +
|- class="row4"
 +
| class="col0 centeralign" | Size_X
 +
| class="col1 centeralign" | byte
 +
| class="col2 centeralign" | <code>15</code>
 +
| class="col3" | Size_X is Actual X Size -1
 +
|- class="row5"
 +
| class="col0 centeralign" | Size_Y
 +
| class="col1 centeralign" | byte
 +
| class="col2 centeralign" | <code>127</code>
 +
| class="col3" | Size_Y is Actual Y Size -1
 
|- class="row6"
 
|- class="row6"
! class="col0" | Total Size:
+
| class="col0 centeralign" | Size_Z
| class="col1 rightalign" colspan="4" | 13 bytes + payload
+
| class="col1 centeralign" | byte
|}
+
| class="col2 centeralign" | <code>15</code>
 
+
| class="col3" | Size_Z is Actual Z Size -1
=== Kick (0xFF) ===
+
|- class="row7"
 
+
| class="col0 centeralign" | Compressed size
Sent by the server before it disconnects a client.
+
| class="col1 centeralign" | int
 
+
| class="col2 centeralign" | <code>3663</code>
{| class="wikitable"
+
| class="col3" | Size of compressed region data
|- class="row0"
+
|- class="row8"
! class="col0" | Packet ID
+
| class="col0 centeralign" | Compressed data
! class="col1" | Field Name
+
| class="col1 centeralign" | byte array
! class="col2" | Field Type
+
| class="col2 centeralign" | <code>…</code>
! class="col3" | Example
+
| class="col3" | The region data is compressed using ZLib Deflate function.
! class="col4" | Notes
+
|- class="row9"
|- class="row1"
+
! class="col0" | Total Size:
| class="col0 centeralign" | 0xFF
+
| class="col1 rightalign" colspan="4" | 18 bytes + Compressed chunk size
| class="col1 centeralign" | Reason
+
|}
| class="col2 centeralign" | string
+
 
| class="col3 centeralign" | <code>The server is full!</code>
+
=====X, Y, Z=====
| class="col4" | Displayed to the client when the connection terminates
+
This is the start position of the region, in '''world''' block coordinates.
|- class="row2"
+
 
! class="col0" | Total Size:
+
To find which chunk is affected, in the same coordinates given by packet 0x32:
| class="col1 rightalign" colspan="4" | 3 bytes + length of strings
+
  ChunkX = X >> 4
|}
+
  ChunkY = Y >> 7
 +
  ChunkZ = Z >> 4
 +
 
 +
And conversely, which local block in the chunk to start at:
 +
  StartX = X & 15
 +
  StartY = Y & 127  (not always 0!)
 +
  StartZ = Z & 15
 +
 
 +
=====SizeX, SizeY, SizeZ=====
 +
This is the size of the region, in blocks. The server will subtract one from the sizes and then cast them to a byte before sending. This is so that chunks as large as 256 are possible (the maximum size of a byte is 255; 256 - 1 = 255).
 +
 
 +
=====Compressed data=====
 +
The data is compressed using the deflate() function in [http://www.zlib.net/ zlib]. After uncompressing, the data consists of four sections, in order:
 +
 
 +
* <div class="li"> Block type array (1 byte per block)</div>
 +
* <div class="li"> Block metadata array (half byte/nibble per block)</div>
 +
* <div class="li"> Block Light array (half byte/nibble per block)</div>
 +
* <div class="li"> Sky Light array (half byte/nibble per block)</div>
 +
 
 +
The data is exactly <code>(Size_X+1) * (Size_Y+1) * (Size_Z+1) * 2.5</code> bytes long.
 +
 
 +
In other words, there are Size_X number of '''x planes''', each plane made up of Size_Z number of '''z rows''', each row made up of Size_Y blocks indexed by y coordinate in order.
 +
 
 +
The block type array is indexed with:
 +
  index = y + (z * (Size_Y+1)) + (x * (Size_Y+1) * (Size_Z+1))
 +
 
 +
The other arrays are similar but you need to divide the index by two after calculating the above. Then each byte contains data for '''two''' blocks.
 +
 
 +
=== Multi Block Change (0x34) ===
 +
 
 +
Further investigation shows that this is a multiple-block-change command; if you take the three arrays, and put together elements with the same index, and then decompose the short into coordinates (top 4 bits is X, next 4 bits is Z, bottom 8 bits is Y), you get things like [((8, 7, 4), 11, 0), ((7, 13, 6), 11, 0), ((13, 1, 8), 11, 0), ((7, 6, 6), 11, 0)].
 +
 
 +
See the Block Change command for description of the general format of a block change.
 +
 
 +
{| class="wikitable"
 +
|- class="row0"
 +
! class="col0" | Packet ID
 +
! class="col1" | Field Name
 +
! class="col2" | Field Type
 +
! class="col3" | Example
 +
! class="col4" | Notes
 +
|- class="row1"
 +
| class="col0 centeralign" rowspan="6" | 0x34
 +
| class="col1 centeralign" | Chunk X
 +
| class="col2 centeralign" | int
 +
| class="col3 centeralign" | <code>-9</code>
 +
| class="col4" | Chunk X Coordinate
 +
|- class="row2"
 +
| class="col0 centeralign" | Chunk Z
 +
| class="col1 centeralign" | int
 +
| class="col2 centeralign" | <code>12</code>
 +
| class="col3" | Chunk Z Coordinate
 +
|- class="row3"
 +
| class="col0 centeralign" | Array size
 +
| class="col1 centeralign" | short
 +
| class="col2 centeralign" | <code>2</code>
 +
| class="col3" | The total number of elements per array
 +
|- class="row4"
 +
| class="col0 centeralign" | Coordinate array
 +
| class="col1 centeralign" | short array
 +
| class="col2 centeralign" | <code>…</code>
 +
| class="col3" | The coordinates of the blocks to change
 +
|- class="row5"
 +
| class="col0 centeralign" | Type array
 +
| class="col1 centeralign" | byte array
 +
| class="col2 centeralign" | <code>…</code>
 +
| class="col3" | The type for each block change
 +
|- class="row6"
 +
| class="col0 centeralign" | Metadata array
 +
| class="col1 centeralign" | byte array
 +
| class="col2 centeralign" | <code>…</code>
 +
| class="col3 leftalign" | The Metadata for each block changed
 +
|- class="row7"
 +
! class="col0" | Total Size:
 +
| class="col1 rightalign" colspan="4" | 11 bytes + Arrays
 +
|}
 +
 
 +
=== Block Change (0x35) ===
 +
 
 +
[[File:Icon_exclaim.gif|:!:]] Block metadata varies by block type - it should be <code>0x00</code> for most blocks with a few exceptions, shown in the table below.
 +
 
 +
{| class="wikitable"
 +
|- class="row0"
 +
! class="col0" | Packet ID
 +
! class="col1" | Field Name
 +
! class="col2" | Field Type
 +
! class="col3" | Example
 +
! class="col4" | Notes
 +
|- class="row1"
 +
| class="col0 centeralign" rowspan="5" | 0x35
 +
| class="col1 centeralign" | X
 +
| class="col2 centeralign" | int
 +
| class="col3 centeralign" | <code>502</code>
 +
| class="col4" | Block X Coordinate
 +
|- class="row2"
 +
| class="col0 centeralign" | Y
 +
| class="col1 centeralign" | byte
 +
| class="col2 centeralign" | <code>71</code>
 +
| class="col3" | Block Y Coordinate
 +
|- class="row3"
 +
| class="col0 centeralign" | Z
 +
| class="col1 centeralign" | int
 +
| class="col2 centeralign" | <code>18</code>
 +
| class="col3" | Block Z Coordinate
 +
|- class="row4"
 +
| class="col0 centeralign" | Block Type
 +
| class="col1 centeralign" | byte
 +
| class="col2 centeralign" | <code>78</code>
 +
| class="col3" | The new block type for the block
 +
|- class="row5"
 +
| class="col0 centeralign" | Block Metadata
 +
| class="col1 centeralign" | byte
 +
| class="col2 centeralign" | <code>0</code>
 +
| class="col3" | The new Metadata for the block
 +
|- class="row6"
 +
! class="col0" | Total Size:
 +
| class="col1 rightalign" colspan="4" | 12 bytes
 +
|}
 +
 
 +
=== Complex Entities (0x3B) ===
 +
 
 +
This is a complex packet used to send entities including their entire NBT representation. This packet is currently used for furnaces, chests, signs and mob spawners. This packet is only temporary, and used for rapid prototyping of new types of entities. Specialized packets for each object will eventually be added.
 +
 
 +
{| class="wikitable"
 +
|- class="row0"
 +
! class="col0" | Packet ID
 +
! class="col1" | Field Name
 +
! class="col2" | Field Type
 +
! class="col3" | Example
 +
! class="col4" | Notes
 +
|- class="row1"
 +
| class="col0 centeralign" rowspan="5" | 0x3B
 +
| class="col1 centeralign" | X
 +
| class="col2 centeralign" | int
 +
| class="col3 centeralign" | <code>32</code>
 +
| class="col4" | Entity X in block coordinates
 +
|- class="row2"
 +
| class="col0 centeralign" | Y
 +
| class="col1 centeralign" | short
 +
| class="col2 centeralign" | <code>64</code>
 +
| class="col3" | Entity Y in block coordinates
 +
|- class="row3"
 +
| class="col0 centeralign" | Z
 +
| class="col1 centeralign" | int
 +
| class="col2 centeralign" | <code>32</code>
 +
| class="col3" | Entity Z in block coordinates
 +
|- class="row4"
 +
| class="col0 centeralign" | Payload Size
 +
| class="col1 centeralign" | short
 +
| class="col2 centeralign" | <code>84</code>
 +
| class="col3" | The size (in bytes) of the payload
 +
|- class="row5"
 +
| class="col0 centeralign" | Payload
 +
| class="col1 centeralign" | byte array
 +
| class="col2 centeralign" | <code>…</code>
 +
| class="col3" |
 +
The payload is a compressed (GZ) [http://www.minecraft.net/docs/NBT.txt NBT] file
 +
|- class="row6"
 +
! class="col0" | Total Size:
 +
| class="col1 rightalign" colspan="4" | 13 bytes + payload
 +
|}
 +
 
 +
=== Kick (0xFF) ===
 +
 
 +
Sent by the server before it disconnects a client.
 +
 
 +
{| class="wikitable"
 +
|- class="row0"
 +
! class="col0" | Packet ID
 +
! class="col1" | Field Name
 +
! class="col2" | Field Type
 +
! class="col3" | Example
 +
! class="col4" | Notes
 +
|- class="row1"
 +
| class="col0 centeralign" | 0xFF
 +
| class="col1 centeralign" | Reason
 +
| class="col2 centeralign" | string
 +
| class="col3 centeralign" | <code>The server is full!</code>
 +
| class="col4" | Displayed to the client when the connection terminates
 +
|- class="row2"
 +
! class="col0" | Total Size:
 +
| class="col1 rightalign" colspan="4" | 3 bytes + length of strings
 +
|}
 +
 
 +
== Protocol History ==
 +
 
 +
Provided below is a changelog of the server protocol starting on 2010-08-20.  The wiki history feature may also be used to investigate changes.
  
== Protocol History ==
+
=== 2010-10-11 ===
 
+
* <div class="li"> Protocol version changed to 4</div>
Provided below is a changelog of the server protocol starting on 2010-08-20. The wiki history feature may also be used to investigate changes.
+
* <div class="li"> Packet 0x01 ([[Protocol#Login_Request_.280x01.29|login request]]) changed</div>
 +
* <div class="li"> Packet 0x07 ([[Protocol#Use Entity? (0x07)|Use Entity?]]) added</div>
 +
* <div class="li"> Packet 0x1C ([[Protocol#Entity Velocity? (0x1C)|Entity Velocity?]]) added</div>
 +
* <div class="li"> Packet 0x27 ([[Protocol#Attach Entity? (0x27)|Attach Entity?]]) added</div>
  
 
=== 2010-10-31 ===
 
=== 2010-10-31 ===

Revision as of 09:42, 13 November 2010

This page presents a dissection of the new Minecraft Alpha protocol by aera (Andrew Godwin), ylt (Joe Carter) and TkTech (Tyler Kennedy). Additionally, credit goes to the citizens of #mcc who helped by providing packet dumps and insight. If you're having trouble, check out the FAQ.

Note: While you may use the contents of this page without restriction to create servers, clients, bots, etc… you still need to provide the attribution above if you copy any of the contents of this page for publication elsewhere.

Data Types

All types in Java (and as such Minecraft) are big-endian, that is, the most significant byte comes first. The majority of everyday computers are little endian, and using most programming languages will require converting big endian values to little endian.

Size Range Notes
byte 1 -128 to 127 Signed, two's complement
short 2 -32768 to 32767 Signed, two's complement
int 4 -2147483648 to 2147483647 Signed, two's complement
long 8 -9223372036854775808 to 9223372036854775807 Signed, two's complement
float 4

See this

Single-precision 32-bit IEEE 754 floating point
double 8

See this

Double-precision 64-bit IEEE 754 floating point
string N/A UTF-8 string. Prefixed by a short containing the length of the string
bool 1 0 or 1 Value can be either True (0x01) or False (0x00)

Terminology

This is a fairly lengthy page, and to make it more readable certain terminology must be understood. Terms used on this page and their definition are provided below.

Definition
Player When used in in the singular, Player always refers to the client connected to the server
Entity Entity refers to any item, player or mob in the world. This definition is subject to change as Notch extends the protocol
EID An EID - or Entity ID - is a unique 4-byte integer used to identify a specific entity
XYZ In this document, the axis names are the same as those used by Notch. Y is always the upwards coordinate, while X and Z are parallel to the ground
MOTD Message Of The Day

Units of Measurement

There are several different units of measurement used in the protocol depending on what is being described. For example, it wouldn't make much sense to send the position of a block (which is a constant multiple of 32) in a floating point double.

Type Represents
Absolute double Represents an objects exact location in the world, specified in block coordinates.
Absolute Integer int Represents an objects approximate location in the world, specified in pixels.
This is the Absolute position cast to an integer, thus losing precision.
Block int or byte Represents a blocks exact location in the world. Block = Absolute / 32.
Chunk int or short Represents the exact position of a chunk. Chunk = Block / 16.

Client to Server Packets

Keep Alive (0x00)

This packet may be sent by the client to keep the connection alive, or may be a relic of UDP testing. No one is really sure. What we do know is that the server will disconnect a client if it doesn't receive at least one packet before it increments a variable 1200 times.

Packet ID
0x00

Login Request (0x01)

Sent by the client after the handshake to finish logging in. If the version is outdated or any field is invalid, the server will disconnect the client with a kick. If the client is started in offline mode, the player's username will default to Player, making LAN play with more than one player impossible (without authenticating) as the server will prevent multiple users with the same name.

Packet ID Field Name Field Type Example Notes
0x01 Protocol Version int 4 The latest version of the protocol is 4
Username string TkTech The name of the user attempting to login
Password string Password Used to login to password-protected servers
Map Seed long 0 This value is not required for the client
Dimension byte 0 This value is not required for the client
Total Size: 18 bytes + length of strings

Handshake (0x02)

This is the first packet sent when the client connects and is used for Authentication.

Packet ID Field Name Field Type Example Notes
0x02 Username string TkTech The username of the player attempting to connect
Total Size: 3 bytes + length of strings

Chat Message (0x03)

The server will check the message to see if it begins with a '/'. If it doesn't, the username of the sender is prepended and sent to all other clients (including the original sender). If it does, the server assumes it to be a command and attempts to process it. A short with the length of the message is prepended to the text sent. eg: 1 byte header [0x03], 2 byte short [string length], N byte string

Packet ID Field Name Field Type Example Notes
0x03 Message string Hello World! User input must be sanitized server-side
Total Size: 3 bytes + length of strings

Player Inventory (0x05)

Sent by the client whenever the inventory is modified (item destruction, pickup, crafting, etc…). For details, see here.

Packet ID Field Name Field Type Example Notes
0x05 Type int -1

The “type” of inventory being sent (see here)

Count short 4

The number of inventory items (see here)

Payload

The payload (see here)

Total Size: 7 bytes + size of payload

Use Entity? (0x07)

This packet is new to version 4 of the protocol, and is believed to be Use Entity.

(This packet data values are not fully verified)

Packet ID Field Name Field Type Example Notes
0x07 User int 1298

The entity of the player (ignored by the server)

Target int 1805

The entity the player has right-clicked on

Total Size: 9 bytes

Player (0x0A)

This packet is used to identify the state of the client, with the idea being to send one each game-tick to detect speed hackers. Notch will be optimizing/removing this in the future. This packet was previously referred to as Flying

Packet ID Field Name Field Type Example Notes
0x0A On Ground bool 1 True if the client is on the ground, False otherwise
Total Size: 2 bytes

Player Position (0x0B)

Updates the players XYZ position on the server. If Stance - Y is less than 0.1 or greater than 1.65, the stance is illegal and the client will be kicked with the message “Illegal Stance”.

Packet ID Field Name Field Type Example Notes
0x0B X double 102.809 Absolute position
Y double 70.00 Absolute position
Stance double 71.62 Used to modify the players bounding box when going up stairs, crouching, etc…
Z double 68.30 Absolute position
On Ground bool 1

Derived from packet 0x0A

Total Size: 34 bytes

Player Look (0x0C)

Updates the direction the player is looking in.

Packet ID Field Name Field Type Example Notes
0x0C Yaw float 0.00 Absolute rotation on the X Axis
Pitch float 0.00 Absolute rotation on the Y Axis
On Ground bool 1

Derived from packet 0x0A

Total Size: 10 bytes

Player Position & Look (0x0D)

A combination of Player Look and Player position.

Packet ID Field Name Field Type Example Notes
0x0D X double 6.5 Absolute position
Y double 67.240000009536743 Absolute position
Stance double 65.620000004768372 Used to modify the players bounding box when going up stairs, crouching, etc…
Z double 7.5 Absolute position
Yaw float 0.0 Absolute rotation on the X Axis
Pitch float 0.0 Absolute rotation on the Y Axis
On Ground bool 0

Derived from packet 0x0A

Total Size: 42 bytes

:!: When the server sends this packet to the client, the Stance and Y are swapped, see server Player Position & Look packet.

Player Digging (0x0E)

Sent repeatedly as the player mines a block.

Packet ID Field Name Field Type Example Notes
0x0E Status byte 1 The action the player is taking against the block (see below)
X int 32 Block position
Y byte 64 Block position
Z int 32 Block position
Face byte 3 The face being hit (see below)
Total Size: 12 bytes

Status can (currently) be one of four values:

Meaning Value
Started digging 0
Digging 1
Stopped digging 2
Block broken 3

The face can be one of six values, representing the face being hit:

Value 0 1 2 3 4 5
Offset -Y +Y -Z +Z -X +X

Player Block Placement (0x0F)

Sent when the player places a block or (probably) an item. The coordinates sent in this packet are actually the block being built against, which combined with the direction offset tell you where the block should be placed. This is required to correctly position furnaces, torches, etc…

Packet ID Field Name Field Type Example Notes
0x0F Block or Item ID short 1 The block or item to be placed
X int 32 Block position
Y byte 64 Block position
Z int 32 Block position
Direction byte 3 The offset to use for block/item placement (see below)
Total Size: 13 bytes

The direction can be one of six values, representing the face the block/item is being placed against:

Value 0 1 2 3 4 5
Offset -Y +Y -Z +Z -X +X

Holding Change (0x10)

Sent when the player changes the item or block currently being held.

Packet ID Field Name Field Type Example Notes
0x10 Unused int 6341424 Unused when sent from a client, can be any random value
Block or Item ID short 1 The block/item to be equipped
Total Size: 7 bytes

Arm Animation (0x12)

Sent whenever someone swings their arm.

Packet ID Field Name Field Type Example Notes
0x12 EID int 55534 Player ID
Animate bool 1 If true, animate the arm
Total Size: 6 bytes

Pickup Spawn (0x15)

A pickup spawn is sent from the client to the server whenever the client drops an item they are holding. This identical to the pickup spawn packet that is sent from the server to the client.

Packet ID Field Name Field Type Example Notes
0x15 EID int 157617 Unique entity ID
Item short 4 The item ID
Count byte 1 The number of items
X int 133 Item X as Absolute Integer
Y int 913 Item Y as Absolute Integer
Z int 63552 Item Z as Absolute Integer
Rotation byte 252 Item rotation as a packed byte
Pitch byte 25 Item pitch as a packed byte
Roll byte 12 Item roll as a packed byte
Total Size: 23 bytes

Disconnect (0xFF)

Sent by the client when it's doing a clean disconnect.

Packet ID Field Name Field Type Example Notes
0xFF Reason string Quitting The server doesn't appear to do anything with this (yet)
Total Size: 3 bytes + length of strings

Server To Client Packets

Keep Alive (0x00)

This packet may be sent by the server to keep the connection alive, or may be a relic of UDP testing. No one is really sure.

Packet ID
0x00

Login Response (0x01)

Sent by the server if it accepts the clients login request. If it didn't, it'll send a kick instead.

Packet ID Field Name Field Type Example Notes
0x01 Entity ID int 1298 The Players Entity ID
Unknown string n/a Not yet used (Possibly the server name?)
Unknown string n/a Not yet used (Possibly the MOTD? )
Map Seed long 971768181197178410 Used for map generation
Dimension byte 0 Used for specifying the players dimension -1 for hell, 0 otherwise
Total Size: 18 bytes + length of strings

Handshake (0x02)

This is the first packet sent when the client connects and is used for Authentication. If the hash is '-', then the client continues without doing name authentication. If the hash is a '+', the client sends the server password in the login request.

Packet ID Field Name Field Type Example Notes
0x02 Connection Hash string 2e66f1dc032ab5f0 A unique, per-connection hash or '-' or '+'
Total Size: 3 bytes + length of strings

Chat Message (0x03)

A formatted chat message from the server. Note that it is unreliable to parse chat when it's sent from the server → client as each server can/will format it differently (some use <,> others use [,], etc…)

Packet ID Field Name Field Type Example Notes
0x03 Message string <Bob> Hello World! User input must be sanitized server-side
Total Size: 3 bytes + length of strings

Time Update (0x04)

The default SMP server increments the time by 20 every second.

Packet ID Field Name Field Type Example Notes
0x04 Time long The world (or region) time in minutes
Total Size: 9 bytes

Player Inventory (0x05)

Slots2.png

Sent by the server to set or reset a players inventory. This includes the main inventory, equipped armour and crafting slots. Packets for all three types are sent to initialize the players inventory before spawning them.

Packet ID Field Name Field Type Example Notes
0x05 Type int -1 The “type” of inventory being sent (see below)
Count short 4 The number of inventory items (see below)
Payload The payload (see below)
Total Size: 7 bytes + size of payload

Type can (currently) be one of three values:

Inventory Type Value Count
Main inventory -1 36
Equipped armour -2 4
Crafting slots -3 4

This packet is a bit more tricky to parse than most others because the size of its payload is variable. The payload is an array of shorts (item ID) optionally followed by a byte-short pair (count and health) as long as the item ID does not equal -1, which signifies an empty slot.

 offset = 0
 
 for slot in count:
     if payload[offset] as short is not equal to -1:
         item_id = payload[offset] as short
         offset += 2
         count = payload[offset] as byte
         offset += 1
         health = payload[offset] as short
         offset += 2
         inventory[slot] = new item(item_id, count, health)
     else:
         offset += 2

Spawn Position (0x06)

Sent by the server after login to specify the players starting location and to initialize compasses. It can be sent at any time afterwords to update the point compasses are focused on.

Packet ID Field Name Field Type Example Notes
0x06 X int 117 Spawn X in block coordinates
Y int 70 Spawn Y in block coordinates
Z int -46 Spawn Z in block coordinates
Total Size: 13 bytes

Player Position & Look (0x0D)

A combination of Player Look and Player position.

Packet ID Field Name Field Type Example Notes
0x0D X double 6.5 Absolute position
Stance double 67.240000009536743 Used to modify the players bounding box when going up stairs, crouching, etc…
Y double 65.620000004768372 Absolute position
Z double 7.5 Absolute position
Yaw float 0.0 Absolute rotation on the X Axis
Pitch float 0.0 Absolute rotation on the Y Axis
On Ground bool 0

Derived from packet 0x0A

Total Size: 42 bytes

:!: This packet differs from client Player Position & Look packet, the Stance and Y are sent in a different order, however because of the different order this is sent the client will actually use the X,Y,Stance,Z client layout.

Holding Change (0x10)

Sent when the player changes the item or block currently being held.

Packet ID Field Name Field Type Example Notes
0x10 EID? int 6341424 Player EID?
Block or Item ID short 1 The block/item to be equipped
Total Size: 7 bytes

Add To Inventory (0x11)

Sent by the server when a player has become close enough to collect an item on the ground.

Packet ID Field Name Field Type Example Notes
0x11 Item Type short 5
Count byte 10
Life short 0
Total Size: 6 bytes

“Life” can range from 0x01 (full health) to 0x32 (no health), 0x00 omits the health bar altogether, and is what should be used for blocks.

Arm Animation (0x12)

Sent whenever someone swings their arm.

Packet ID Field Name Field Type Example Notes
0x12 EID int 55534 Player ID
Animate bool 1 If true, animate the arm
Total Size: 6 bytes

Named Entity Spawn (0x14)

The only named entities (at the moment) are players (either real or NPC/Bot). This packet is sent by the server when a player comes into visible range, not when a player joins.

Packet ID Field Name Field Type Example Notes
0x14 EID int 94453 Player ID
Player Name string Twdtwd
X int 784 Player X as Absolute Integer
Y int 2131 Player Y as Absolute Integer
Z int -752 Player Z as Absolute Integer
Rotation byte 0 Player rotation as a packed byte
Pitch byte 0 Player rotation as a packed byte
Current Item short 0 The item the player is currently holding
Total Size: 23 bytes + length of strings

Pickup Spawn (0x15)

A pickup spawn is sent whenever an item on the ground (say a pickaxe thrown on the ground) comes into range of the player.

Packet ID Field Name Field Type Example Notes
0x15 EID int 157617 Unique entity ID
Item short 4 The item ID
Count byte 1 The number of items
X int 133 Item X as Absolute Integer
Y int 913 Item Y as Absolute Integer
Z int 63552 Item Z as Absolute Integer
Rotation byte 252 Item rotation as a packed byte
Pitch byte 25 Item pitch as a packed byte
Roll byte 12 Item roll as a packed byte
Total Size: 23 bytes

Collect Item (0x16)

Sent by the server when someone picks up an item lying on the ground - its sole purpose appears to be the animation of the item flying towards you. It doesn't destroy the entity in the client memory (0x1D does that), and it doesn't add it to your inventory (0x11 does that).

Packet ID Field Name Field Type Example Notes
0x16 Collected EID int 38
Collector EID int 20
Total Size: 9 bytes

Add Object/Vehicle (0x17)

Sent by the server when an Object/Vehicle is created.

Packet ID Field Name Field Type Example Notes
0x17 EID int 62 Entity ID of the Object
Type byte 11 The type of object (see below)
X int 16080 The Absolute Integer X Position of the object
Y int 2299 The Absolute Integer Y Position of the object
Z int 592 The Absolute Integer Z Position of the object
Total Size: 18 bytes

Object Types

Type ID Type Name
1 Boats
10 Minecart
11 Storage Cart
12 Powered Cart

Mob Spawn (0x18)

Sent by the server when a Mob Entity is Spawned

Packet ID Field Name Field Type Example Notes
0x18 EID int 446 Entity ID
Type byte 91 The type of Mob Entity Type
X int 13366 The Absolute Integer X Position of the object
Y int 2176 The Absolute Integer Y Position of the object
Z int 1680 The Absolute Integer Z Position of the object
Yaw byte -27 The X Axis rotation as a fraction of 360
Pitch byte 0 The Y Axis rotation as a fraction of 360
Total Size: 20 bytes

Entity Velocity? (0x1C)

This packet is new to version 4 of the protocol, and is believed to be Entity Velocity/Motion.

Velocity is believed to in block velocity * 32000 with regards to the speed being server ticks, 200ms

e.g. -1343 would move (-1343 / 32000) = -0.04196875 blocks per tick (or -0.20984375 blocks per second)

Each axis Velocity is capped between -0.9 and 0.9 blocks per tick (Velocity -28800 to 28800)

(This packet data values are not fully verified)

Packet ID Field Name Field Type Example Notes
0x1C Entity ID int 1805

The entity ID

Velocity X short -1343

Velocity on the X axis

Velocity Y short 0

Velocity on the Y axis

Velocity Z short 0

Velocity on the Z axis

Total Size: 11 bytes


Destroy Entity (0x1D)

Sent by the server when an Entity is to be destroyed on the client.

Packet ID Field Name Field Type Example Notes
0x1D EID int 446 Entity ID
Total Size: 5 bytes

Entity (0x1E)

Most entity-related packets are subclasses of this packet. When sent from the server to the client, it may initialize the entry.

Packet ID Field Name Field Type Example Notes
0x1E EID int 446 Entity ID
Total Size: 5 bytes

Entity Relative Move (0x1F)

This packet is sent by the server when an entity moves less then 4 blocks, if an entity moves more then 4 blocks Entity Teleport should be sent instead.

Packet ID Field Name Field Type Example Notes
0x1F EID int 459 Entity ID
X byte 1 X axis Relative movement as an Absolute Integer
Y byte -7 Y axis Relative movement as an Absolute Integer
Z byte 5 Z axis Relative movement as an Absolute Integer
Total Size: 8 bytes

Entity Look (0x20)

This packet is sent by the server when an entity rotates.

Packet ID Field Name Field Type Example Notes
0x20 EID int 459 Entity ID
Yaw byte 126 The X Axis rotation as a fraction of 360
Pitch byte 0 The Y Axis rotation as a fraction of 360
Total Size: 7 bytes

Entity Look and Relative Move (0x21)

This packet is sent by the server when an entity rotates and moves.

Packet ID Field Name Field Type Example Notes
0x21 EID int 459 Entity ID
X byte 1 X axis Relative movement as an Absolute Integer
Y byte -7 Y axis Relative movement as an Absolute Integer
Z byte 5 Z axis Relative movement as an Absolute Integer
Yaw byte 126 The X Axis rotation as a fraction of 360
Pitch byte 0 The Y Axis rotation as a fraction of 360
Total Size: 10 bytes

Entity Teleport (0x22)

This packet is sent by the server when an entity moves more then 4 blocks.

Packet ID Field Name Field Type Example Notes
0x22 EID int 459 Entity ID
X int 14162 X axis position as an Absolute Integer
Y int 2176 Y axis position as an Absolute Integer
Z int 1111 Z axis position as an Absolute Integer
Yaw byte 126 The X Axis rotation as a fraction of 360
Pitch byte 0 The Y Axis rotation as a fraction of 360
Total Size: 19 bytes

Attach Entity? (0x27)

This packet is new to version 4 of the protocol, and is believed to be Attach Entity.

This packet is sent when a player has been attached to an entity (e.g. Minecart)

(This packet data values are not fully verified)

Packet ID Field Name Field Type Example Notes
0x27 Entity ID int 1298

The player entity ID being attached

Vehicle ID int 1805

The vehicle entity ID attached to (-1 for unattaching)

Total Size: 9 bytes


Pre-Chunk (0x32)

This packet is sent by the server to notify the client to initialize (Mode=1) or unload (Mode=0) a chunk. The client is expected to allocate space for a full chunk (currently 16 x 128 x 16 blocks). One or more 0x33 packets will follow, specifying actual data to fill the chunk with.

:!: Whenever you send this packet the client will clear any previous chunk at that spot if one has previously been sent. Clients don't like being in or next to an unloaded chunk, so try not to unload it if players are nearby. If the player appears to be twitching and stuck in place after joining the world, there is probably an unloaded chunk too close to them.

Packet ID Field Name Field Type Example Notes
0x32 X int -9 Chunk X Coordinate
Z int 12 Chunk Z Coordinate
Mode bool 1 If mode is 0 the client will unload the chunk, otherwise the client will initialize the chunk
Total Size: 10 bytes

Map Chunk (0x33)

The client will overwrite all or part of a chunk using the region of data contained in this packet. The server specifies the region to write using a block position and size in X,Y,Z. Note that this region will always be inside a single chunk. (At least using the vanilla server. Unknown if the client has this limitation.)

A server can send a 0x32 packet prior, allowing the client to initialize the chunk. However this doesn't always happen in practice. Thus the client should initialize the chunk on-demand.

Packet ID Field Name Field Type Example Notes
0x33 X int 128 Block X Coordinate
Y short 0 Block Y Coordinate
Z int -192 Block Z Coordinate
Size_X byte 15 Size_X is Actual X Size -1
Size_Y byte 127 Size_Y is Actual Y Size -1
Size_Z byte 15 Size_Z is Actual Z Size -1
Compressed size int 3663 Size of compressed region data
Compressed data byte array The region data is compressed using ZLib Deflate function.
Total Size: 18 bytes + Compressed chunk size
X, Y, Z

This is the start position of the region, in world block coordinates.

To find which chunk is affected, in the same coordinates given by packet 0x32:

 ChunkX = X >> 4 
 ChunkY = Y >> 7
 ChunkZ = Z >> 4

And conversely, which local block in the chunk to start at:

 StartX = X & 15
 StartY = Y & 127  (not always 0!)
 StartZ = Z & 15
SizeX, SizeY, SizeZ

This is the size of the region, in blocks. The server will subtract one from the sizes and then cast them to a byte before sending. This is so that chunks as large as 256 are possible (the maximum size of a byte is 255; 256 - 1 = 255).

Compressed data

The data is compressed using the deflate() function in zlib. After uncompressing, the data consists of four sections, in order:

  • Block type array (1 byte per block)
  • Block metadata array (half byte/nibble per block)
  • Block Light array (half byte/nibble per block)
  • Sky Light array (half byte/nibble per block)

The data is exactly (Size_X+1) * (Size_Y+1) * (Size_Z+1) * 2.5 bytes long.

In other words, there are Size_X number of x planes, each plane made up of Size_Z number of z rows, each row made up of Size_Y blocks indexed by y coordinate in order.

The block type array is indexed with:

 index = y + (z * (Size_Y+1)) + (x * (Size_Y+1) * (Size_Z+1))

The other arrays are similar but you need to divide the index by two after calculating the above. Then each byte contains data for two blocks.

Multi Block Change (0x34)

Further investigation shows that this is a multiple-block-change command; if you take the three arrays, and put together elements with the same index, and then decompose the short into coordinates (top 4 bits is X, next 4 bits is Z, bottom 8 bits is Y), you get things like [((8, 7, 4), 11, 0), ((7, 13, 6), 11, 0), ((13, 1, 8), 11, 0), ((7, 6, 6), 11, 0)].

See the Block Change command for description of the general format of a block change.

Packet ID Field Name Field Type Example Notes
0x34 Chunk X int -9 Chunk X Coordinate
Chunk Z int 12 Chunk Z Coordinate
Array size short 2 The total number of elements per array
Coordinate array short array The coordinates of the blocks to change
Type array byte array The type for each block change
Metadata array byte array The Metadata for each block changed
Total Size: 11 bytes + Arrays

Block Change (0x35)

:!: Block metadata varies by block type - it should be 0x00 for most blocks with a few exceptions, shown in the table below.

Packet ID Field Name Field Type Example Notes
0x35 X int 502 Block X Coordinate
Y byte 71 Block Y Coordinate
Z int 18 Block Z Coordinate
Block Type byte 78 The new block type for the block
Block Metadata byte 0 The new Metadata for the block
Total Size: 12 bytes

Complex Entities (0x3B)

This is a complex packet used to send entities including their entire NBT representation. This packet is currently used for furnaces, chests, signs and mob spawners. This packet is only temporary, and used for rapid prototyping of new types of entities. Specialized packets for each object will eventually be added.

Packet ID Field Name Field Type Example Notes
0x3B X int 32 Entity X in block coordinates
Y short 64 Entity Y in block coordinates
Z int 32 Entity Z in block coordinates
Payload Size short 84 The size (in bytes) of the payload
Payload byte array

The payload is a compressed (GZ) NBT file

Total Size: 13 bytes + payload

Kick (0xFF)

Sent by the server before it disconnects a client.

Packet ID Field Name Field Type Example Notes
0xFF Reason string The server is full! Displayed to the client when the connection terminates
Total Size: 3 bytes + length of strings

Protocol History

Provided below is a changelog of the server protocol starting on 2010-08-20. The wiki history feature may also be used to investigate changes.

2010-10-11

2010-10-31

  • Protocol version changed to 3
  • Packet 0x01 (login request) changed

2010-08-20

  • Protocol version reset from 14 to 1
  • Packet 0x04 (time update) added

2010-09-10

  • Protocol version changed to 2
  • Packets 0x05, 0x06, 0x3B added
  • Server-side inventory (no verification)
  • Vanilla adds experimental monsters (only damaged by fire)