|
|
Line 1: |
Line 1: |
| This page documents the changes from the [[Protocol|last stable Minecraft release]] (currently 1.1) to the current pre-release | | This page documents the changes from the [[Protocol|last stable Minecraft release]] (currently 1.2.3) to the current pre-release (or weekly release). |
| | |
| | There are currently no pre-releases past the current official release. |
|
| |
|
| == New packets == | | == New packets == |
|
| |
|
| === Entity Head Look (0x23) ===
| | ''none'' |
| | |
| Changes the direction an entity's head is facing.
| |
| | |
| {| 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" | 0x23
| |
| | class="col1 centeralign" | Entity ID
| |
| | class="col2 centeralign" | int
| |
| | class="col3 centeralign" |
| |
| | class="col4" |
| |
| |- class="row2"
| |
| | class="col0 centeralign" | Head Yaw
| |
| | class="col1 centeralign" | byte
| |
| | class="col2 centeralign" |
| |
| | class="col3" | Head yaw in steps of 2π/256
| |
| |- class="row3"
| |
| ! class="col0" | Total Size:
| |
| | class="col1 rightalign" colspan="4" | 6 bytes
| |
| |}
| |
| | |
| === Update Tile Entity (0x84) ===
| |
| | |
| Essentially a block update on a tile entity.
| |
| | |
| {| 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="7" | 0x84
| |
| | class="col1 centeralign" | X
| |
| | class="col2 centeralign" | int
| |
| | class="col3 centeralign" |
| |
| | class="col4" |
| |
| |- class="row2"
| |
| | class="col0 centeralign" | Y
| |
| | class="col1 centeralign" | short
| |
| | class="col2 centeralign" |
| |
| | class="col3" |
| |
| |- class="row3"
| |
| | class="col0 centeralign" | Z
| |
| | class="col1 centeralign" | int
| |
| | class="col2 centeralign" |
| |
| | class="col3" |
| |
| |- class="row4"
| |
| | class="col0 centeralign" | Action
| |
| | class="col1 centeralign" | byte
| |
| | class="col2 centeralign" |
| |
| | class="col3" | The type of update to perform
| |
| |- class="row5"
| |
| | class="col0 centeralign" | Custom 1
| |
| | class="col1 centeralign" | int
| |
| | class="col2 centeralign" |
| |
| | class="col3" | Varies
| |
| |- class="row6"
| |
| | class="col0 centeralign" | Custom 2
| |
| | class="col1 centeralign" | int
| |
| | class="col2 centeralign" |
| |
| | class="col3" | Varies
| |
| |- class="row7"
| |
| | class="col0 centeralign" | Custom 3
| |
| | class="col1 centeralign" | int
| |
| | class="col2 centeralign" |
| |
| | class="col3" | Varies
| |
| |- class="row8"
| |
| ! class="col0" | Total Size:
| |
| | class="col1 rightalign" colspan="4" | 24 bytes
| |
| |}
| |
| | |
| ==== Actions ====
| |
| | |
| * '''1''': Set mob displayed inside a mob spawner. Custom 1 contains the [[Entities#Mobs|mob type]]
| |
|
| |
|
| == Changed packets == | | == Changed packets == |
|
| |
|
| === [[Protocol#Login_Request_.280x01.29|Login Request (0x01)]] ===
| | ''none'' |
| | |
| World height field is no longer used, always 0.
| |
| | |
| Map seed field removed
| |
| | |
| {| 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" | 0x01
| |
| | class="col1 centeralign" | Entity ID
| |
| | class="col2 centeralign" | int
| |
| | class="col3 centeralign" | <code>1298</code>
| |
| | class="col4" | The Players Entity ID
| |
| |- class="row2"
| |
| | class="col0 centeralign" | Not used
| |
| | class="col1 centeralign" | string
| |
| | class="col2 centeralign" | (empty string)
| |
| | class="col3" | Not used
| |
| |- class="row3"
| |
| | class="col0 centeralign" | Level Type
| |
| | class="col1 centeralign" | string
| |
| | class="col2 centeralign" | default
| |
| | class="col3" | default or SUPERFLAT; level-type in server.properties
| |
| |- class="row4"
| |
| | class="col0 centeralign" | Server mode
| |
| | class="col1 centeralign" | int
| |
| | class="col2 centeralign" | <code>0</code>
| |
| | class="col3" | 0 for survival, 1 for creative
| |
| |- class="row5"
| |
| | class="col0 centeralign" | Dimension
| |
| | class="col1 centeralign" | int
| |
| | class="col2 centeralign" | <code>0</code>
| |
| | class="col3" | <code>-1</code>: The Nether, <code>0</code>: The Overworld, <code>1</code>: The End
| |
| |- class="row6"
| |
| | class="col0 centeralign" | Difficulty
| |
| | class="col1 centeralign" | byte
| |
| | class="col2 centeralign" | <code>1</code>
| |
| | class="col3" | <code>0</code> thru <code>3</code> for Peaceful, Easy, Normal, Hard
| |
| |- class="row7"
| |
| | class="col0 centeralign" | World height
| |
| | class="col1 centeralign" | byte
| |
| | class="col2 centeralign" | <code>0</code>
| |
| | class="col3" | Probably not used anymore since Map Chunk is hardcoded to 256 blocks.
| |
| |- class="row8"
| |
| | class="col0 centeralign" | Max players
| |
| | class="col1 centeralign" | unsigned byte
| |
| | class="col2 centeralign" | <code>8</code>
| |
| | class="col3" | Used by the client to draw the player list
| |
| |- class="row9"
| |
| ! class="col0" | Total Size:
| |
| | class="col1 rightalign" colspan="4" | 19 bytes + length of strings
| |
| |}
| |
| | |
| === [[Protocol#Handshake_.280x02.29|Handshake (0x02)]] ===
| |
| | |
| ==== Client to Server ====
| |
| | |
| The hostname and port were added to this packet, most likely to allow [http://en.wikipedia.org/wiki/Virtual_hosting virtual hosting] .([https://github.com/sadimusi/MVHP/blob/master/mvhp.py sample implementation])
| |
| | |
| {| 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" | 0x02
| |
| | class="col1 centeralign" | UsernameAndHost
| |
| | class="col2 centeralign" | string
| |
| | class="col3 centeralign" | <code>TkTech;localhost:25565</code>
| |
| | class="col4" | The username of the player attempting to connect, and the host he is connecting to, seperated by a semicolon.
| |
| |- class="row2"
| |
| ! class="col0" | Total Size:
| |
| | class="col1 rightalign" colspan="4" | 3 bytes + length of strings
| |
| |}
| |
| | |
| === [[Protocol#Respawn_.280x09.29|Respawn (0x09)]] ===
| |
| | |
| Dimension is now an int, slightly bizarrely. I wonder if they intended to make world_height an int, in line with 0x01 login?
| |
| | |
| Map seed field removed
| |
| | |
| {| 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" | 0x09
| |
| | class="col1 centeralign" | Dimension
| |
| | class="col2 centeralign" | int
| |
| | class="col3 centeralign" | <code>1</code>
| |
| | class="col4" | <code>-1</code>: The Nether, <code>0</code>: The Overworld, <code>1</code>: The End
| |
| |- class="row2"
| |
| | class="col1 centeralign" | Difficulty
| |
| | class="col2 centeralign" | byte
| |
| | class="col3 centeralign" | <code>1</code>
| |
| | class="col4" | <code>0</code> thru <code>3</code> for Peaceful, Easy, Normal, Hard. <code>1</code> is always sent c->s
| |
| |- class="row2"
| |
| | class="col1 centeralign" | Creative mode
| |
| | class="col2 centeralign" | byte
| |
| | class="col3 centeralign" | <code>1</code>
| |
| | class="col4" | <code>0</code> for survival, <code>1</code> for creative.
| |
| |- class="row1"
| |
| | class="col1 centeralign" | World height
| |
| | class="col2 centeralign" | short
| |
| | class="col3 centeralign" | <code>128</code>
| |
| | class="col4" | Defaults to <code>128</code>
| |
| |- class="row1"
| |
| | class="col1 centeralign" | Level Type
| |
| | class="col2 centeralign" | string
| |
| | class="col3 centeralign" | DEFAULT
| |
| | class="col4" | See 0x01 login
| |
| |- class="row2"
| |
| ! class="col0" | Total Size:
| |
| | class="col1 rightalign" colspan="4" | 11 bytes + length of string
| |
| |}
| |
| | |
| === [[Protocol#Mob_Spawn_.280x18.29|Mob Spawn (0x18)]] ===
| |
| | |
| New byte field: head yaw
| |
| | |
| This needs confirmation!
| |
| | |
| {| 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="9" | 0x18
| |
| | class="col1 centeralign" | EID
| |
| | class="col2 centeralign" | int
| |
| | class="col3 centeralign" | <code>446</code>
| |
| | class="col4" | Entity ID
| |
| |- class="row2"
| |
| | class="col0 centeralign" | Type
| |
| | class="col1 centeralign" | byte
| |
| | class="col2 centeralign" | <code>91</code>
| |
| | class="col3" | The type of mob. See [[Entities#Mobs]]
| |
| |- class="row3"
| |
| | class="col0 centeralign" | X
| |
| | class="col1 centeralign" | int
| |
| | class="col2 centeralign" | <code>13366</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>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 yaw in steps of 2π/256
| |
| |- class="row7"
| |
| | class="col0 centeralign" | Pitch
| |
| | class="col1 centeralign" | byte
| |
| | class="col2 centeralign" | <code>0</code>
| |
| | class="col3" | The pitch in steps of 2π/256
| |
| |- class="row8"
| |
| | class="col0 centeralign" | '''Head Yaw'''
| |
| | class="col1 centeralign" | byte
| |
| | class="col2 centeralign" |
| |
| | class="col3" | Head yaw in steps of 2π/256
| |
| |- class="row9"
| |
| | class="col0 centeralign" | Metadata
| |
| | class="col1 centeralign" | Metadata
| |
| | class="col2 centeralign" | <code>127</code>
| |
| | class="col3" | Varies by mob, see [[Entities]]
| |
| |- class="row10"
| |
| ! class="col0" | Total Size:
| |
| | class="col1 rightalign" colspan="4" | 21 bytes + Metadata (at least 1)
| |
| |}
| |
| | |
| === [[Protocol#Map_Chunk_.280x33.29|Map Chunk (0x33)]] ===
| |
| | |
| This is currently a ''best guess''
| |
| | |
| Here's a packet capture: https://gist.github.com/1835702
| |
| | |
| {| 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" |
| |
| | class="col4" | Chunk X Coordinate (*16 to get true X)
| |
| |- class="row2"
| |
| | class="col0 centeralign" | Z
| |
| | class="col1 centeralign" | int
| |
| | class="col2 centeralign" |
| |
| | class="col3" | Chunk Z Coordinate (*16 to get true Z)
| |
| |- class="row3"
| |
| | class="col0 centeralign" | Ground-up contiguous
| |
| | class="col1 centeralign" | boolean
| |
| | class="col2 centeralign" |
| |
| | class="col3" | This is True if the chunks consists of a contiguous column of non-air (i.e., indicated with a '1' in the bitmask) chunks starting at Y=0, followed by any number of unsent chunks containing only air.
| |
| |- class="row4"
| |
| | class="col0 centeralign" | Primary bit map
| |
| | class="col1 centeralign" | short
| |
| | class="col2 centeralign" | 15
| |
| | class="col3" | Bitmask with 1 for every 16x16x16 chunk which data follows in the compressed data.
| |
| |- class="row5"
| |
| | class="col0 centeralign" | Add bit map
| |
| | class="col1 centeralign" | short
| |
| | class="col2 centeralign" | 0
| |
| | class="col3" | Same as above, but this is used exclusively for the 'add' portion of the payload
| |
| |- class="row6"
| |
| | class="col0 centeralign" | Compressed size
| |
| | class="col1 centeralign" | int
| |
| | class="col2 centeralign" |
| |
| | class="col3" | Size of compressed region data.
| |
| |- class="row7"
| |
| | class="col0 centeralign" | Unused int
| |
| | class="col1 centeralign" | int
| |
| | class="col2 centeralign" | 0
| |
| | class="col3" | Doesn't seem to be used by the client. Always 0. I expect this is Mod API stuff.
| |
| |- class="row8"
| |
| | class="col0 centeralign" | Compressed data
| |
| | class="col1 centeralign" | unsigned 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="col1 rightalign" colspan="4" | 22 bytes + Compressed chunk size
| |
| |}
| |
| | |
| The payload is a set of 16x16x16 chunks, sharing the same X and Z chunk coordinates. What is and isn't sent is provided by the two bitmask fields. The least significant bit is '1' if the chunk spanning from Y=0 to Y=15 is not completely air, and so forth. For block IDs, metadata, and lighting, the primary bitmask is used. A secondary bitmask is used for 'add' data, which is mojang's means of provided Block IDs past 256. In vanilla minecraft, you can expect this to always be zero.
| |
| | |
| The data is compressed using the deflate() function in [http://www.zlib.net/ zlib]. After uncompressing, the data consists of five (or six) sequential sections, in order:
| |
| | |
| * Block type array (1 byte per block, 4096 bytes per chunk)
| |
| * Block metadata array (half byte per block, 2048 bytes per chunk)
| |
| * Block light array (half byte per block, 2048 bytes per chunk)
| |
| * Sky light array (half byte per block, 2048 bytes per chunk)
| |
| * Add array (half byte per block, 2048 bytes per chunk, uses second bitmask)
| |
| * Biome array (1 byte per XZ column, 256 bytes total, only sent if 'ground up contiguous' is true)
| |
| | |
| In each section except biome data, your loop should look something like this:
| |
| <code>
| |
| //Loop over 16x16x16 chunks in the 16x256x16 column
| |
| for (i=0;i<16;i++) {
| |
| //If the bitmask indicates this chunk has been sent...
| |
| if (bitmask & 1 << i) {
| |
| //Read data...
| |
| cubic_chunk_data = io.read(4096); //2048 for the other arrays, where you'll need to split the data
| |
|
| |
| for(int j=0; j<len(cubic_chunk_data); j++) {
| |
| //Retrieve x,y,z and data from each element in cubic_chunk_array
| |
|
| |
| //Byte arrays
| |
| x = chunk_x*16 + (j & 0xF0) >> 4;
| |
| y = i*16 + j & 0x0F;
| |
| z = chunk_z*16 + j >> 8;
| |
| data = cubic_chunk_data[j]
| |
|
| |
| //Nibble arrays
| |
| data1 = cubic_chunk_data[j] & 0x0F;
| |
| data2 = cubic_chunk_data[j] >> 4;
| |
|
| |
| k = 2*j;
| |
| x1 = chunk_x*16 + (k & 0xF0) >> 4;
| |
| y1 = i*16 + k & 0x0F;
| |
| z1 = chunk_z*16 + k >> 8;
| |
|
| |
| k++;
| |
| x2 = chunk_x*16 + (k & 0xF0) >> 4;
| |
| y2 = i*16 + k & 0x0F;
| |
| z2 = chunk_z*16 + k >> 8;
| |
| }
| |
| }
| |
| }
| |
| </code>
| |
| | |
| Each biome byte can have the values from 0 to 22, higher will cause the client to crash.
| |
| | |
| The 'add' array uses the second bitmask. Block IDs are presumed to be <code>block_id | add << 8</code>
| |
| | |
| === Multi Block Change (0x34) ===
| |
| | |
| Like 0x33, this follows a new format. Arrays are now interlaced rather than sequential!
| |
| | |
| {| 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" | 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" | Record count
| |
| | class="col1 centeralign" | short
| |
| | class="col2 centeralign" |
| |
| | class="col3" | The number of blocks affected
| |
| |- class="row2"
| |
| | class="col0 centeralign" | Data size
| |
| | class="col1 centeralign" | int
| |
| | class="col2 centeralign" |
| |
| | class="col3" | The total size of the data, in bytes. Should always be 4*record count - please confirm.
| |
| |- class="row4"
| |
| | class="col0 centeralign" | Data
| |
| | class="col1 centeralign" |
| |
| | class="col2 centeralign" | <code>…</code>
| |
| | class="col3" | Coordinates, type, and metadata of blocks to change.
| |
| |- class="row5"
| |
| ! class="col0" | Total Size:
| |
| | class="col1 rightalign" colspan="4" | 15 bytes + Arrays
| |
| |}
| |
| | |
| Each record is four bytes.
| |
| | |
| {| class="wikitable"
| |
| |- class="row0"
| |
| ! class="col0" | Bit mask
| |
| ! class="col1" | Width
| |
| ! class="col2" | Meaning
| |
| |- class="row1"
| |
| | class="col0" | 00 00 00 0F
| |
| | class="col1" | 4 bits
| |
| | class="col2" | Block metadata
| |
| |- class="row2"
| |
| | class="col0" | 00 00 FF F0
| |
| | class="col1" | 12 bits
| |
| | class="col2" | Block ID
| |
| |- class="row3"
| |
| | class="col0" | 00 FF 00 00
| |
| | class="col1" | 8 bits
| |
| | class="col2" | Y co-ordinate
| |
| |- class="row4"
| |
| | class="col0" | 0F 00 00 00
| |
| | class="col1" | 4 bits
| |
| | class="col2" | Z co-ordinate, relative to chunk
| |
| |- class="row5"
| |
| | class="col0" | F0 00 00 00
| |
| | class="col1" | 4 bits
| |
| | class="col2" | X co-ordinate, relative to chunk
| |
| |}
| |
|
| |
|
| == Protocol History == | | == Protocol History == |
|
| |
|
| === 2012-02-23 ===
| | ''n/a'' |
| * 12w08a
| |
| * Protocol version is now 28
| |
| * Updated packets: 0x01, 0x09, 0x34
| |
| | |
| === 2012-02-15 ===
| |
| * 12w07a
| |
| * Protocol version is now 27
| |
| * Updated packets: 0x01, 0x09, 0x33
| |
| | |
| === 2012-02-09 ===
| |
| * 12w06a
| |
| * Protocol version is now 25
| |
| * New packet: 0x84
| |
| | |
| === 2012-01-26 ===
| |
| * 12w04a
| |
| * Protocol version has not been changed
| |
| * Handshake Packet by client (0x02) now contains the server host and port
| |
| * Window Open Packet (0x64): WindowTitle is now longer than accepted by older clients. Contains a keyword such as "container.furnace"
| |
| | |
| === 2012-01-19 ===
| |
| * 12w03a
| |
| * Protocol version is now 24
| |
| * New packet: 0x23
| |
| * MobSpawn: new field, 1 byte inserted before metadata.
| |