Java Edition protocol/Data types
This article defines the data types used in the Java Edition protocol. All data sent over the network (except for VarInt and VarLong) is big-endian, that is the bytes are sent from most significant byte to least significant byte. The majority of everyday computers are little-endian, therefore it may be necessary to change the endianness before sending data over the network.
Definitions
[edit | edit source]| Name | Size (bytes) | Encodes | Notes |
|---|---|---|---|
| Boolean | 1 | Either false or true | True is encoded as 0x01, false as 0x00.
|
| Byte | 1 | An integer between -128 and 127 | Signed 8-bit integer, two's complement |
| Unsigned Byte | 1 | An integer between 0 and 255 | Unsigned 8-bit integer |
| Short | 2 | An integer between -32768 and 32767 | Signed 16-bit integer, two's complement |
| Unsigned Short | 2 | An integer between 0 and 65535 | Unsigned 16-bit integer |
| Int | 4 | An integer between -2147483648 and 2147483647 | Signed 32-bit integer, two's complement |
| Long | 8 | An integer between -9223372036854775808 and 9223372036854775807 | Signed 64-bit integer, two's complement |
| Float | 4 | A single-precision 32-bit IEEE 754 floating point number | |
| Double | 8 | A double-precision 64-bit IEEE 754 floating point number | |
| String (n) | ≥ 1 ≤ (n×3) + 3 |
A sequence of Unicode scalar values | UTF-8 string prefixed with its size in bytes as a VarInt. Maximum length of n characters, which varies by context. The encoding used on the wire is regular UTF-8, not Java's "slight modification". However, the length of the string for purposes of the length limit is its number of UTF-16 code units, that is, scalar values > U+FFFF are counted as two. Up to n × 3 bytes can be used to encode a UTF-8 string comprising n code units when converted to UTF-16, and both of those limits are checked. Maximum n value is 32767. The + 3 is due to the max size of a valid length VarInt.
|
| Text Component | Varies | See Text component format | Encoded as a NBT Tag, with the type of tag used depending on the case:
|
| JSON Text Component | ≥ 1 ≤ (262144×3) + 3 |
See Text component format | The maximum permitted length when decoding is 262144, but the vanilla server since 1.20.3 refuses to encode longer than 32767. This may be a bug. |
| Identifier | ≥ 1 ≤ (32767×3) + 3 |
See Identifier below | Encoded as a String with max length of 32767. |
| VarInt | ≥ 1 ≤ 5 |
An integer between -2147483648 and 2147483647 | Variable-length data encoding a two's complement signed 32-bit integer; more info in their section |
| VarLong | ≥ 1 ≤ 10 |
An integer between -9223372036854775808 and 9223372036854775807 | Variable-length data encoding a two's complement signed 64-bit integer; more info in their section |
| Entity Metadata | Varies | Miscellaneous information about an entity | See Entity metadata#Entity Metadata Format |
| Slot | Varies | An item stack in an inventory or container | See Slot Data |
| Hashed Slot | Varies | Similar to Slot, but with the data component values being sent as a hash instead of their actual contents | See Slot Data#Hashed Format |
| NBT | Varies | Depends on context | See NBT |
| Position | 8 | An integer/block position: x (-33554432 to 33554431), z (-33554432 to 33554431), y (-2048 to 2047) | x as a 26-bit integer, followed by z as a 26-bit integer, followed by y as a 12-bit integer (all signed, two's complement). See also the section below. |
| Angle | 1 | A rotation angle in steps of 1/256 of a full turn | Whether or not this is signed does not matter, since the resulting angles are the same. |
| UUID | 16 | A UUID | Encoded as an unsigned 128-bit integer (or two unsigned 64-bit integers: the most significant 64 bits and then the least significant 64 bits) |
| BitSet | Varies | See #BitSet below | A length-prefixed bit set. |
| Fixed BitSet (n) | ceil(n / 8) | See #Fixed BitSet below | A bit set with a fixed length of n bits. |
| Optional X | 0 or size of X | A field of type X, or nothing | Whether or not the field is present must be known from the context. |
| Prefixed Optional X | size of Boolean + (is present ? Size of X : 0) | A boolean and if present, a field of type X | The boolean is true if the field is present. |
| Array of X | length times size of X | Zero or more fields of type X | The length must be known from the context. |
| Prefixed Array of X | size of VarInt + size of X * length | See #Prefixed Array below | A length-prefixed array. |
| X Enum | size of X | A specific value from a given list | The list of possible values and how each is encoded as an X must be known from the context. An invalid value sent by either side will usually result in the client being disconnected with an error or even crashing. |
| EnumSet (n) | ceil(n / 8) | Fixed BitSet (n) | A bitset associated to an enum where each bit corresponds to an enum variant. The number of enum variants n must be known from the context. |
| Byte Array | Varies | Depends on context | This is just a sequence of zero or more bytes, its meaning should be explained somewhere else, e.g. in the packet description. The length must also be known from the context. |
| ID or X | size of VarInt + (size of X or 0) | See #ID or X below | Either a registry ID or an inline data definition of type X. |
| ID Set | Varies | See #ID Set below | Set of registry IDs specified either inline or as a reference to a tag. |
| Sound Event | Varies | See #Sound Event below | Parameters for a sound event. |
| Chat Type | Varies | See #Chat Type below | Parameters for a direct chat type. |
| Teleport Flags | 4 | See #Teleport Flags below | Bit field specifying how a teleportation is to be applied on each axis. |
| Recipe Display | Varies | See Recipes#Recipe Display structure | Description of a recipe for use for use by the client. |
| Slot Display | Varies | See Recipes#Slot Display structure | Description of a recipe ingredient slot for use for use by the client. |
| Chunk Data | Varies | See #Chunk Data below | |
| Light Data | Varies | See #Light Data below | |
| X or Y | size of Boolean + (isX ? size of X : size of Y) | A boolean and X or Y | The boolean is true if X is encoded and false if Y is encoded. |
| Game Profile | Varies | See #Game Profile below | A Minecraft player profile. |
| Resolvable Profile | Varies | See #Resolvable Profile below | |
| Debug Subscription Event | Varies | See #Debug Subscription Event below | |
| Debug Subscription Update | Varies | See #Debug Subscription Update below | |
| LpVec3 | Varies | See #LpVec3 below | Usually used for low velocities. |
Identifier
[edit | edit source]Identifiers are a namespaced location, in the form of minecraft:thing. If the namespace is not provided, it defaults to minecraft (i.e. thing is minecraft:thing). Custom content should always be in its own namespace, not the default one. Both the namespace and value can use all lowercase alphanumeric characters (a-z and 0-9), dot (.), dash (-), and underscore (_). In addition, values can use slash (/). The naming convention is lower_case_with_underscores. More information.
For ease of determining whether a namespace or value is valid, here are regular expressions for each:
- Namespace:
[a-z0-9.-_] - Value:
[a-z0-9.-_/]
VarInt and VarLong
[edit | edit source]Variable-length format such that smaller numbers use fewer bytes. These are very similar to Protocol Buffer Varints: the 7 least significant bits are used to encode the value and the most significant bit indicates whether there's another byte after it for the next part of the number. The least significant group is written first, followed by each of the more significant groups; thus, VarInts are effectively little endian (however, groups are 7 bits, not 8).
VarInts are never longer than 5 bytes, and VarLongs are never longer than 10 bytes. Within these limits, unnecessarily long encodings (e.g. 81 00 to encode 1) are allowed.
Pseudocode to read and write VarInts and VarLongs:
private static final int SEGMENT_BITS = 0x7F;
private static final int CONTINUE_BIT = 0x80;
public int readVarInt() {
int value = 0;
int position = 0;
byte currentByte;
while (true) {
currentByte = readByte();
value |= (currentByte & SEGMENT_BITS) << position;
if ((currentByte & CONTINUE_BIT) == 0) break;
position += 7;
if (position >= 32) throw new RuntimeException("VarInt is too big");
}
return value;
}
public long readVarLong() {
long value = 0;
int position = 0;
byte currentByte;
while (true) {
currentByte = readByte();
value |= (long) (currentByte & SEGMENT_BITS) << position;
if ((currentByte & CONTINUE_BIT) == 0) break;
position += 7;
if (position >= 64) throw new RuntimeException("VarLong is too big");
}
return value;
}
public void writeVarInt(int value) {
while (true) {
if ((value & ~SEGMENT_BITS) == 0) {
writeByte(value);
return;
}
writeByte((value & SEGMENT_BITS) | CONTINUE_BIT);
// Note: >>> means that the leftmost bits are filled with zeroes regardless of the sign,
// rather than being filled with copies of the sign bit to preserve the sign.
// In languages that don't have a ">>>" operator, This behavior can often be selected by
// performing the shift on an unsigned type.
value >>>= 7;
}
}
public void writeVarLong(long value) {
while (true) {
if ((value & ~((long) SEGMENT_BITS)) == 0) {
writeByte(value);
return;
}
writeByte((value & SEGMENT_BITS) | CONTINUE_BIT);
// Note: >>> means that the leftmost bits are filled with zeroes regardless of the sign,
// rather than being filled with copies of the sign bit to preserve the sign.
// In languages that don't have a ">>>" operator, This behavior can often be selected by
// performing the shift on an unsigned type.
value >>>= 7;
}
}
- Minecraft's VarInts are all signed, but do not use the ZigZag encoding. Protocol buffers have 3 types of Varints:
uint32(normal encoding, unsigned),sint32(ZigZag encoding, signed), andint32(normal encoding, signed). Minecraft's are theint32variety. Because Minecraft uses the normal encoding instead of ZigZag encoding, negative values always use the maximum number of bytes. - Minecraft's VarInts are never longer than 5 bytes and its VarLongs will never be longer than 10 bytes, while Protocol Buffer Varints will always use 10 bytes when encoding negative numbers, even if it's an
int32.
Sample VarInts:
| Value | Hex bytes | Decimal bytes |
|---|---|---|
| 0 | 0x00 | 0 |
| 1 | 0x01 | 1 |
| 2 | 0x02 | 2 |
| 127 | 0x7f | 127 |
| 128 | 0x80 0x01 | 128 1 |
| 255 | 0xff 0x01 | 255 1 |
| 25565 | 0xdd 0xc7 0x01 | 221 199 1 |
| 2097151 | 0xff 0xff 0x7f | 255 255 127 |
| 2147483647 | 0xff 0xff 0xff 0xff 0x07 | 255 255 255 255 7 |
| -1 | 0xff 0xff 0xff 0xff 0x0f | 255 255 255 255 15 |
| -2147483648 | 0x80 0x80 0x80 0x80 0x08 | 128 128 128 128 8 |
Sample VarLongs:
| Value | Hex bytes | Decimal bytes |
|---|---|---|
| 0 | 0x00 | 0 |
| 1 | 0x01 | 1 |
| 2 | 0x02 | 2 |
| 127 | 0x7f | 127 |
| 128 | 0x80 0x01 | 128 1 |
| 255 | 0xff 0x01 | 255 1 |
| 2147483647 | 0xff 0xff 0xff 0xff 0x07 | 255 255 255 255 7 |
| 9223372036854775807 | 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0x7f | 255 255 255 255 255 255 255 255 127 |
| -1 | 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0x01 | 255 255 255 255 255 255 255 255 255 1 |
| -2147483648 | 0x80 0x80 0x80 0x80 0xf8 0xff 0xff 0xff 0xff 0x01 | 128 128 128 128 248 255 255 255 255 1 |
| -9223372036854775808 | 0x80 0x80 0x80 0x80 0x80 0x80 0x80 0x80 0x80 0x01 | 128 128 128 128 128 128 128 128 128 1 |
Position
[edit | edit source]Note: What you are seeing here is the latest version of the Data types article, but the position type was different before 1.14.
64-bit value split into three signed integer parts:
- x: 26 MSBs
- z: 26 middle bits
- y: 12 LSBs
For example, a 64-bit position can be broken down as follows:
Example value (big endian): 01000110000001110110001100 10110000010101101101001000 001100111111
- The red value is the X coordinate, which is
18357644in this example. - The blue value is the Z coordinate, which is
-20882616in this example. - The green value is the Y coordinate, which is
831in this example.
Encoded as follows:
((x & 0x3FFFFFF) << 38) | ((z & 0x3FFFFFF) << 12) | (y & 0xFFF)
And decoded as:
val = read_long(); x = val >> 38; y = val << 52 >> 52; z = val << 26 >> 38;
Note: The above assumes that the right shift operator sign extends the value (this is called an arithmetic shift), so that the signedness of the coordinates is preserved. In many languages, this requires the integer type of val to be signed. In the absence of such an operator, the following may be useful:
if x >= 1 << 25 { x -= 1 << 26 }
if y >= 1 << 11 { y -= 1 << 12 }
if z >= 1 << 25 { z -= 1 << 26 }
Fixed-point numbers
[edit | edit source]Some fields may be stored as fixed-point numbers, where a certain number of bits represent the signed integer part (number to the left of the decimal point) and the rest represent the fractional part (to the right). Floating point numbers (float and double), in contrast, keep the number itself (mantissa) in one chunk, while the location of the decimal point (exponent) is stored beside it. Essentially, while fixed-point numbers have lower range than floating point numbers, their fractional precision is greater for higher values.
Prior to version 1.9 a fixed-point format with 5 fraction bits and 27 integer bits was used to send entity positions to the client. Some uses of fixed point remain in modern versions, but they differ from that format.
Most programming languages lack support for fractional integers directly, but you can represent them as integers. The following C or Java-like pseudocode converts a double to a fixed-point integer with n fraction bits:
x_fixed = (int)(x_double * (1 << n));
And back again:
x_double = (double)x_fixed / (1 << n);
Arrays
[edit | edit source]The types Array and Prefixed Array represent a collection of X in a specified order.
Array
[edit | edit source]Represents a list where the length is not encoded. The length must be known from the context. If the array is empty nothing will be encoded.
A String Array with the values ["Hello", "World!"] has the following data when encoded:
| Field Name | Field Type | Value |
|---|---|---|
| First element | String | Hello |
| Second element | String | World! |
Prefixed Array
[edit | edit source]Represents an array prefixed by its length. If the array is empty the length will still be encoded.
| Field Name | Field Type |
|---|---|
| Length | VarInt |
| Data | Array of X |
Bit sets
[edit | edit source]The types BitSet and Fixed BitSet represent packed lists of bits. The vanilla implementation uses Java's BitSet class.
BitSet
[edit | edit source]Bit sets of type BitSet are prefixed by their length in longs.
| Field Name | Field Type | Meaning |
|---|---|---|
| Length | VarInt | Number of longs in the following array. May be 0 (if no bits are set). |
| Data | Array of Long | A packed representation of the bit set as created by BitSet.toLongArray.
|
The ith bit is set when (Data[i / 64] & (1 << (i % 64))) != 0, where i starts at 0.
Fixed BitSet
[edit | edit source]Bit sets of type Fixed BitSet (n) have a fixed length of n bits, encoded as ceil(n / 8) bytes. Note that this is different from BitSet, which uses longs.
| Field Name | Field Type | Meaning |
|---|---|---|
| Data | Byte Array (n) | A packed representation of the bit set as created by BitSet.toByteArray, padded with zeroes at the end to fit the specified length.
|
The ith bit is set when (Data[i / 8] & (1 << (i % 8))) != 0, where i starts at 0. This encoding is not equivalent to the long array in BitSet.
Registry references
[edit | edit source]ID or X
[edit | edit source]Represents a data record of type X, either inline, or by reference to a registry implied by context.
| Field Name | Field Type | Meaning |
|---|---|---|
| ID | VarInt | 0 if value of type X is given inline; otherwise registry ID + 1. |
| Value | Optional X | Only present if ID is 0. |
ID Set
[edit | edit source]Represents a set of IDs in a certain registry (implied by context), either directly (enumerated IDs) or indirectly (tag name).
| Field Name | Field Type | Meaning |
|---|---|---|
| Type | VarInt | Value used to determine the data that follows. It can be either:
|
| Tag Name | Optional Identifier | The registry tag defining the ID set. Only present if Type is 0. |
| IDs | Optional Array of VarInt | An array of registry IDs. Only present if Type is not 0. The size of the array is equal to Type - 1.
|
Registry data
[edit | edit source]These types are commonly used in conjuction with ID or X to specify custom data inline.
Sound Event
[edit | edit source]Describes a sound that can be played.
| Name | Type | Description |
|---|---|---|
| Sound Name | Identifier | |
| Has Fixed Range | Boolean | Whether this sound has a fixed range, as opposed to a variable volume based on distance. |
| Fixed Range | Optional Float | The maximum range of the sound. Only present if Has Fixed Range is true. |
Chat Type
[edit | edit source]Describes a direct chat type that a message can be sent with.
| Name | Type | Description |
|---|---|---|
| Chat | (See below) | |
| Narration | (See below) |
The chat type decorations look like:
| Name | Type | Description |
|---|---|---|
| Translation Key | String | |
| Parameters | Prefixed Array of VarInt Enum | 0: sender, 1: target, 2: content |
| Style | NBT |
Teleport Flags
[edit | edit source]A bit field represented as an Int, specifying how a teleportation is to be applied on each axis.
In the lower 8 bits of the bit field, a set bit means the teleportation on the corresponding axis is relative, and an unset bit that it is absolute.
| Hex Mask | Field |
|---|---|
| 0x0001 | Relative X |
| 0x0002 | Relative Y |
| 0x0004 | Relative Z |
| 0x0008 | Relative Yaw |
| 0x0010 | Relative Pitch |
| 0x0020 | Relative Velocity X |
| 0x0040 | Relative Velocity Y |
| 0x0080 | Relative Velocity Z |
| 0x0100 | Rotate velocity according to the change in rotation, before applying the velocity change in this packet. Combining this with absolute rotation works as expected—the difference in rotation is still used. |
Chunk Data
[edit | edit source]| Field Name | Field Type | Notes | ||
|---|---|---|---|---|
| Heightmaps | Prefixed Array of Heightmap | See Chunk Format#Heightmap structure | ||
| Data | Prefixed Array of Byte | See Chunk Format#Data structure | ||
| Block Entities | Packed XZ | Prefixed Array | Unsigned Byte | The packed section coordinates are relative to the chunk they are in. Values 0-15 are valid. packed_xz = ((blockX & 15) << 4) | (blockZ & 15) // encode x = packed_xz >> 4, z = packed_xz & 15 // decode |
| Y | Short | The height relative to the world | ||
| Type | VarInt | The type of block entity | ||
| Data | NBT | The block entity's data, without the X, Y, and Z values | ||
Light Data
[edit | edit source]| Field Name | Field Type | Notes | ||
|---|---|---|---|---|
| Sky Light Mask | BitSet | BitSet containing bits for each section in the world + 2. Each set bit indicates that the corresponding 16×16×16 chunk section has data in the Sky Light array below. The least significant bit is for blocks 16 blocks to 1 block below the min world height (one section below the world), while the most significant bit covers blocks 1 to 16 blocks above the max world height (one section above the world). | ||
| Block Light Mask | BitSet | BitSet containing bits for each section in the world + 2. Each set bit indicates that the corresponding 16×16×16 chunk section has data in the Block Light array below. The order of bits is the same as in Sky Light Mask. | ||
| Empty Sky Light Mask | BitSet | BitSet containing bits for each section in the world + 2. Each set bit indicates that the corresponding 16×16×16 chunk section has all zeros for its Sky Light data. The order of bits is the same as in Sky Light Mask. | ||
| Empty Block Light Mask | BitSet | BitSet containing bits for each section in the world + 2. Each set bit indicates that the corresponding 16×16×16 chunk section has all zeros for its Block Light data. The order of bits is the same as in Sky Light Mask. | ||
| Sky Light arrays | Sky Light array | Prefixed Array | Prefixed Array (2048) of Byte | The length of any inner array is always 2048; There is 1 array for each bit set to true in the sky light mask, starting with the lowest value. Half a byte per light value. |
| Block Light arrays | Block Light array | Prefixed Array | Prefixed Array (2048) of Byte | The length of any inner array is always 2048; There is 1 array for each bit set to true in the block light mask, starting with the lowest value. Half a byte per light value. |
Game Profile
[edit | edit source]Describes a Minecraft player profile.
| Name | Type | Description | |||
|---|---|---|---|---|---|
| UUID | UUID | ||||
| Username | String (16) | ||||
| Properties | Name | Prefixed Array (16) | String (64) | ||
| Value | String (32767) | ||||
| Signature | Prefixed Optional String (1024) | ||||
The Properties field looks like the response of querying a player's skin and cape from Mojang's official API, with the difference being the usage of the protocol format instead of JSON. That is, each player will usually have one property with Name being “textures” and Value being a JSON string encoded using Base64. An empty properties array is also acceptable, and will cause clients to display the player with one of the default skins depending on their UUID. For more information, refer to the aforementioned Mojang API page.
Resolvable Profile
[edit | edit source]| Name | Type | Meaning | |||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Profile Kind | VarInt Enum | Defines how the next field is read; either partial or complete. | |||||||||||||||||||||||||||||||||||||
| Unpack | Varies |
| |||||||||||||||||||||||||||||||||||||
| Body | Optional Identifier | An override for the skin texture to use, from the player's textures directory.
| |||||||||||||||||||||||||||||||||||||
| Cape | Optional Identifier | An override for the cape texture to use, same format as body. | |||||||||||||||||||||||||||||||||||||
| Elytra | Optional Identifier | An override for the elytra texture to use, same format as body. | |||||||||||||||||||||||||||||||||||||
| Model | Optional VarInt | WIDE = 0, SLIM = 1 | |||||||||||||||||||||||||||||||||||||
Debug subscriptions
[edit | edit source]Types used in certain packets that are meant to help with debugging the game.
Debug Subscription Event
[edit | edit source]| Name | Type | Description |
|---|---|---|
| Debug subscription type | VarInt Enum | ID of the debug subscription type for the next field. |
| Data | Debug Subscription Data | Value of the debug subscription. |
Debug Subscription Update
[edit | edit source]| Name | Type | Description |
|---|---|---|
| Subscription type | VarInt Enum | ID of the debug subscription type for the next field. |
| Data | Prefixed Optional Debug Subscription Data | Value of the debug subscription. |
Debug Subscription Data
[edit | edit source]| Subscription Type | Field Name | Field Type | Meaning |
|---|---|---|---|
| 0: Dedicated server tick time | no fields | ||
| 1: Bee | Hive position | Prefixed Optional Position | |
| Flower position | Prefixed Optional Position | ||
| Travel ticks | VarInt | ||
| Blacklisted hives | Prefixed Array of Position | ||
| 2: Villager brain | Name | String | |
| Profession | String | ||
| XP | Int | ||
| Health | Float | ||
| Max health | Float | ||
| Inventory | String | ||
| Wants golem | Boolean | ||
| Anger level | Int | ||
| Activities | Prefixed Array of String | ||
| Behaviors | Prefixed Array of String | ||
| Memories | Prefixed Array of String | ||
| Gossips | Prefixed Array of String | ||
| POIs | Prefixed Array of Position | ||
| Potential POIs | Prefixed Array of Position | ||
| 3: Breeze | Attack target | Prefixed Optional VarInt | |
| Jump target | Prefixed Optional Position | ||
| 4: Goal selector | Priority | VarInt | |
| Is running | Boolean | ||
| Name | String (255) | ||
| 5: Entity path | Reached | Boolean | |
| Next block index | Int | ||
| Block position | Position | ||
| Nodes | Prefixed Array of Debug Path Node | ||
| Target nodes | Prefixed Array of Debug Path Node | ||
| Open set | Prefixed Array of Debug Path Node | ||
| Closed set | Prefixed Array of Debug Path Node | ||
| Max node distance | Float | ||
| 6: Entity block intersection | ID | VarInt Enum | IN_BLOCK = 0, IN_FLUID = 1, IN_AIR = 2 |
| 7: Bee hive | Type | VarInt Enum | ID in the minecraft:block registry.
|
| Occupant count | VarInt | ||
| Honey level | VarInt | ||
| Sedated | Boolean | ||
| 8: POI | Position | Position | |
| Type | VarInt Enum | ID in the minecraft:point_of_interest_type registry.
| |
| Free ticket count | VarInt | ||
| 9: Redstone wire orientation | ID | VarInt | |
| 10: Village section | no fields | ||
| 11: Raid | Positions | Prefixed Array of Position | |
| 12: Structure | Structures | Prefixed Array of Debug Structure Info | |
| 13: Game event listener | Listener radius | VarInt | |
| 14: Neighbor update | Position | Position | |
| 15: Game event | Event | VarInt Enum | ID in the minecraft:game_event registry.
|
| X | Double | ||
| Y | Double | ||
| Z | Double | ||
Debug Path Node
[edit | edit source]| Field name | Field type | Meaning |
|---|---|---|
| X | Int | |
| Y | Int | |
| Z | Int | |
| Walked distance | Float | |
| Cost malus | Float | |
| Closed | Boolean | |
| Type | VarInt Enum | BLOCKED = 0, OPEN = 1, WALKABLE = 2, WALKABLE_DOOR = 3, TRAPDOOR = 4, POWDER_SNOW = 5, DANGER_POWDER_SNOW = 6, FENCE = 7, LAVA = 8, WATER = 9, WATER_BORDER = 10, RAIL = 11, UNPASSABLE_RAIL = 12, DANGER_FIRE = 13, DAMAGE_FIRE = 14, DANGER_OTHER = 15, DAMAGE_OTHER = 16, DOOR_OPEN = 17, DOOR_WOOD_CLOSED = 18, DOOR_IRON_CLOSED = 19, BREACH = 20, LEAVES = 21, STICKY_HONEY = 22, COCOA = 23, DAMAGE_CAUTIOUS = 24, DANGER_TRAPDOOR = 25 |
| F | Float |
Debug Structure Info
[edit | edit source]| Field name | Field type | Meaning | ||
|---|---|---|---|---|
| Bounding box min | Position | |||
| Bounding box max | Position | |||
| Pieces | Piece bounding box min | Prefixed Array | Position | |
| Piece bounding box max | Position | |||
| Is start | Boolean | |||
LpVec3
[edit | edit source]Encodes 3 doubles in (usually) 6 bytes. Only used in Java Edition protocol/Packets#Spawn Entity and Java Edition Protocol/Packets#Set Entity Velocity.
If the absolute maximum of every double is beneath , it will only encode it as a single byte containing 0x00.
If the rounded up absolute maximum of every double is below 3, the continuation flag will not be set, and the absolute maximum is sent as 2 unsigned bits.
If the rounded up absolute maximum of every double is above 3, the continuation flag will be set, and the least significant two bits will be sent. The rest will be sent afterwards as a VarInt.
The protocol packs the doubles by dividing by their combined absolute maximum (Thus scaling them to a range of -1 to 1). Afterwards, they will be scaled to the range 0 to 1 and multiplied by 32766, to scale them to the range of a 16 bit short. As the resulting number will always be positive, so the sign bit can be discarded and thus represented as a 15 bit unsigned value.
| Packed X | Packet Y | Packed Z | Continuation Flag | Scale Factor |
|---|---|---|---|---|
| 15 bits | 15 bits | 15 bits | 1 bit | 2 bits |
The protocol then sends the first 2 bytes in little-endian, and the last 4 bytes in big-endian:
| 1st | 2nd | 3rd | 4th | 5th | 6th |
|---|---|---|---|---|---|
| Byte 1 | Byte 2 | Byte 6 | Byte 5 | Byte 4 | Byte 3 |
Pseudocode to read and write LpVec3:
private static final double MAX_QUANTIZED_VALUE = 32766.0;
private static long pack(double value) {
return Math.round((value * 0.5 + 0.5) * MAX_QUANTIZED_VALUE));
}
private static double unpack(long value) {
return Math.min((double)(value & 32767L), MAX_QUANTIZED_VALUE) * 2.0 / MAX_QUANTIZED_VALUE - 1.0;
}
public static Vec3 readLpVec3() {
int byte1 = readUnsignedByte();
if (byte1 == 0) {
return Vec3(0.0, 0.0, 0.0);
}
int byte2 = readUnsignedByte();
long bytes3To4 = readUnsignedInt();
long packed = bytes3To4 << 16) | (long)(byte2 << 8) | (long)byte1;
long scaleFactor = byte1 & 3;
if ((byte1 & 4) == 4) {
scaleFactor |= ((long)readVarInt() & 0xFFFFFFFFL) << 2L;
}
double scaleFactorD = (double)scaleFactor;
return Vec3(
unpack(packed >> 3L) * scaleFactorD,
unpack(packed >> 18L) * scaleFactorD,
unpack(packed >> 33L) * scaleFactorD
);
}
// Ensure vec3's coordinates are not nan, and clamped between -1.7179869183e10 and 1.7179869183e10
public static writeLpVec3(Vec3 vec3) {
double maxCoordinate = Math.max(Math.abs(vec3.x), Math.max(Math.abs(vec3.y), Math.abs(vec3.z)));
if (maxCoordinate < 3.051944088384301e-5) {
writeByte(0);
} else {
long maxCoordinateI = (long)maxCoordinate;
long scaleFactor = maxCoordinate > (double)maxCoordinateI ? maxCoordinateI + 1L : maxCoordinateI;
boolean needContinuation = (scaleFactor & 3L) != scaleFactor;
long packedScale = needContinuation ? scaleFactor & 3L | 4L : scaleFactor;
long packedX = pack(vec3.x / (double)scaleFactor) << 3L;
long packedY = pack(vec3.y / (double)scaleFactor) << 18L;
long packedZ = pack(vec3.z / (double)scaleFactor) << 33L;
long packed = packedZ | packedY | packedX | packedScale;
writeByte((byte)packed);
writeByte((byte)(packed >> 8L));
writeInt((int)(packed >> 16L));
if (needContinuation) {
writeVarInt((int)(scaleFactor >> 2L));
}
}
}
Sample LpVec3:
| Value | Hex bytes | Decimal bytes |
|---|---|---|
| (0.0, 0.0, 0.0) | 0x00 | 0 |
| (1.0, 0.0, -1.0) | 0xF1 0xFF 0x00 0x00 0xFF 0xFF | 241 255 0 0 255 255 |
| (10.0, 0.2, -5.0) | 0xF6 0xFF 0x40 0x01 0x05 0x1F 0x02 | 246 255 64 1 5 31 2 |
| (123457.0, 15.071, 0.0) | 0xF5 0xFF 0x7F 0xFF 0x00 0x07 0x90 0xF1 0x01 | 245 255 127 255 0 7 144 241 1 |
Navigation
[edit | edit source]Derivative works must be licensed using the same or a compatible license.