Difference between revisions of "Data types"

From wiki.vg
Jump to navigation Jump to search
(Merge position (hopefully this is correct) and particles)
(→‎Definitions: Add Sound Event. This is most likely a temporary solution; would be better to have these in Registry Data.)
 
(62 intermediate revisions by 22 users not shown)
Line 1: Line 1:
<noinclude>This article defines the '''data types''' used in the [[protocol]]. </noinclude>All data sent over the network (except for VarInt and VarLong) is [[wikipedia:Endianness#Big-endian|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.
+
<noinclude>This article defines the '''data types''' used in the [[protocol]]. </noinclude>All data sent over the network (except for VarInt and VarLong) is [[wikipedia:Endianness#Big-endian|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.<includeonly>
<noinclude>
+
{{#ifeq: {{PAGEID}}|{{PAGEID:Protocol}}| {{#ifeq: {{REVISIONID}}|{{REVISIONID:Protocol}}||{{Warning2|NOTE: This information is from the '''most recent''' version of the [[Data types]] article and may not be correct for this protocol version.  Check that article's history for any differences that happened since this version.}}}}}}
 +
</includeonly><noinclude>
 
== Definitions ==
 
== Definitions ==
 
</noinclude>
 
</noinclude>
 +
 
{| class="wikitable"
 
{| class="wikitable"
 
  |-
 
  |-
Line 10: Line 12:
 
  ! Notes
 
  ! Notes
 
  |-
 
  |-
  ! Boolean
+
  ! id=Type:Boolean | {{Type|Boolean}}
 
  | 1
 
  | 1
 
  | Either false or true
 
  | Either false or true
 
  | True is encoded as <code>0x01</code>, false as <code>0x00</code>.
 
  | True is encoded as <code>0x01</code>, false as <code>0x00</code>.
 
  |-
 
  |-
  ! Byte
+
  ! id=Type:Byte | {{Type|Byte}}
 
  | 1
 
  | 1
 
  | An integer between -128 and 127
 
  | An integer between -128 and 127
 
  | Signed 8-bit integer, [[wikipedia:Two's complement|two's complement]]
 
  | Signed 8-bit integer, [[wikipedia:Two's complement|two's complement]]
 
  |-
 
  |-
  ! Unsigned Byte
+
  ! id=Type:Unsigned_Byte | {{Type|Unsigned Byte}}
 
  | 1
 
  | 1
 
  | An integer between 0 and 255
 
  | An integer between 0 and 255
 
  | Unsigned 8-bit integer
 
  | Unsigned 8-bit integer
 
  |-
 
  |-
  ! Short
+
  ! id=Type:Short | {{Type|Short}}
 
  | 2
 
  | 2
 
  | An integer between -32768 and 32767
 
  | An integer between -32768 and 32767
 
  | Signed 16-bit integer, two's complement
 
  | Signed 16-bit integer, two's complement
 
  |-
 
  |-
  ! Unsigned Short
+
  ! id=Type:Unsigned_Short | {{Type|Unsigned Short}}
 
  | 2
 
  | 2
 
  | An integer between 0 and 65535
 
  | An integer between 0 and 65535
 
  | Unsigned 16-bit integer
 
  | Unsigned 16-bit integer
 
  |-
 
  |-
  ! Int
+
  ! id=Type:Int | {{Type|Int}}
 
  | 4
 
  | 4
 
  | An integer between -2147483648 and 2147483647
 
  | An integer between -2147483648 and 2147483647
 
  | Signed 32-bit integer, two's complement
 
  | Signed 32-bit integer, two's complement
 
  |-
 
  |-
  ! Long
+
  ! id=Type:Long | {{Type|Long}}
 
  | 8
 
  | 8
 
  | An integer between -9223372036854775808 and 9223372036854775807
 
  | An integer between -9223372036854775808 and 9223372036854775807
 
  | Signed 64-bit integer, two's complement
 
  | Signed 64-bit integer, two's complement
 
  |-
 
  |-
  ! Float
+
  ! id=Type:Float | {{Type|Float}}
 
  | 4
 
  | 4
 
  | A [[wikipedia:Single-precision floating-point format|single-precision 32-bit IEEE 754 floating point number]]
 
  | A [[wikipedia:Single-precision floating-point format|single-precision 32-bit IEEE 754 floating point number]]
 
  |  
 
  |  
 
  |-
 
  |-
  ! Double
+
  ! id=Type:Double | {{Type|Double}}
 
  | 8
 
  | 8
 
  | A [[wikipedia:Double-precision floating-point format|double-precision 64-bit IEEE 754 floating point number]]
 
  | A [[wikipedia:Double-precision floating-point format|double-precision 64-bit IEEE 754 floating point number]]
 
  |  
 
  |  
 
  |-
 
  |-
  ! String (n)
+
  ! id=Type:String | {{Type|String}} (n)
  | ≥ 1 <br />≤ (n&times;4) + 3
+
  | ≥ 1 <br />≤ (n&times;3) + 3
 
  | A sequence of [[wikipedia:Unicode|Unicode]] [http://unicode.org/glossary/#unicode_scalar_value scalar values]
 
  | A sequence of [[wikipedia:Unicode|Unicode]] [http://unicode.org/glossary/#unicode_scalar_value scalar values]
  | [[wikipedia:UTF-8|UTF-8]] string prefixed with its size in bytes as a VarInt.  Maximum length of <code>n</code> characters, which varies by context; up to <code>n &times; 4</code> bytes can be used to encode <code>n</code> characters and both of those limits are checked.  Maximum <code>n</code> value is 32767.  The + 3 is due to the max size of a valid length VarInt.
+
  | [[wikipedia:UTF-8|UTF-8]] string prefixed with its size in bytes as a VarInt.  Maximum length of <code>n</code> characters, which varies by context.  The encoding used on the wire is regular UTF-8, ''not'' [https://docs.oracle.com/en/java/javase/18/docs/api/java.base/java/io/DataInput.html#modified-utf-8 Java's "slight modification"].  However, the length of the string for purposes of the length limit is its number of [[wikipedia:UTF-16|UTF-16]] code units, that is, scalar values > U+FFFF are counted as two. Up to <code>n &times; 3</code> bytes can be used to encode a UTF-8 string comprising <code>n</code> code units when converted to UTF-16, and both of those limits are checked.  Maximum <code>n</code> value is 32767.  The + 3 is due to the max size of a valid length VarInt.
 
  |-
 
  |-
  ! Chat
+
  ! id=Type:Text_Component | {{Type|Text Component}}
  | ≥ 1 <br />≤ (32767&times;4) + 3
+
| Varies
  | See [[Chat]]
+
| See [[Text formatting#Text components]]
  | Encoded as a String with max length of 32767.
+
| Encoded as a [[NBT|NBT Tag]], with the type of tag used depending on the case:
 +
* As a [[NBT#Specification:string_tag|String Tag]]: For components only containing text (no styling, no events etc.).
 +
* As a [[NBT#Specification:compound_tag|Compound Tag]]: Every other case.
 +
|-
 +
! id=Type:JSON_Text_Component | {{Type|JSON Text Component}}
 +
  | ≥ 1 <br />≤ (262144&times;3) + 3
 +
  | See [[Text formatting#Text components]]
 +
  | The maximum permitted length when decoding is 262144, but the Notchian server since 1.20.3 refuses to encode longer than 32767. This may be a bug.
 
  |-
 
  |-
  ! Identifier
+
  ! id=Type:Identifier | {{Type|Identifier}}
  | ≥ 1 <br />≤ (32767&times;4) + 3
+
  | ≥ 1 <br />≤ (32767&times;3) + 3
 
  | See [[#Identifier|Identifier]] below
 
  | See [[#Identifier|Identifier]] below
 
  | Encoded as a String with max length of 32767.
 
  | Encoded as a String with max length of 32767.
 
  |-  
 
  |-  
  ! VarInt
+
  ! id=Type:VarInt | {{Type|VarInt}}
 
  | ≥ 1 <br />≤ 5
 
  | ≥ 1 <br />≤ 5
 
  | An integer between -2147483648 and 2147483647
 
  | An integer between -2147483648 and 2147483647
 
  | Variable-length data encoding a two's complement signed 32-bit integer; more info in [[#VarInt and VarLong|their section]]
 
  | Variable-length data encoding a two's complement signed 32-bit integer; more info in [[#VarInt and VarLong|their section]]
 
  |-
 
  |-
  ! VarLong
+
  ! id=Type:VarLong | {{Type|VarLong}}
 
  | ≥ 1 <br />≤ 10
 
  | ≥ 1 <br />≤ 10
 
  | An integer between -9223372036854775808 and 9223372036854775807
 
  | An integer between -9223372036854775808 and 9223372036854775807
 
  | Variable-length data encoding a two's complement signed 64-bit integer; more info in [[#VarInt and VarLong|their section]]
 
  | Variable-length data encoding a two's complement signed 64-bit integer; more info in [[#VarInt and VarLong|their section]]
 
  |-
 
  |-
  ! Entity Metadata
+
  ! id=Type:Entity_Metadata | {{Type|Entity Metadata}}
 
  | Varies
 
  | Varies
 
  | Miscellaneous information about an entity
 
  | Miscellaneous information about an entity
  | See [[Entities#Entity Metadata Format]]
+
  | See [[Entity_metadata#Entity Metadata Format]]
 
  |-  
 
  |-  
  ! Slot
+
  ! id=Type:Slot | {{Type|Slot}}
 
  | Varies
 
  | Varies
 
  | An item stack in an inventory or container
 
  | An item stack in an inventory or container
 
  | See [[Slot Data]]
 
  | See [[Slot Data]]
 
  |-
 
  |-
  ! NBT Tag
+
  ! id=Type:NBT | {{Type|NBT}}
 
  | Varies
 
  | Varies
 
  | Depends on context
 
  | Depends on context
 
  | See [[NBT]]
 
  | See [[NBT]]
 
  |-
 
  |-
  ! Position  
+
  ! id=Type:Position | {{Type|Position}}
 
  | 8
 
  | 8
  | An integer/block position: x (-33554432 to 33554431), y (-2048 to 2047), z (-33554432 to 33554431)
+
  | An integer/block position: x (-33554432 to 33554431), z (-33554432 to 33554431), y (-2048 to 2047)
  | x as a 26-bit integer, followed by y as a 12-bit integer, followed by z as a 26-bit integer (all signed, two's complement). See also [[#Position|the section below]].
+
  | 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 [[#Position|the section below]].
 
  |-
 
  |-
  ! Angle
+
  ! id=Type:Angle | {{Type|Angle}}
 
  | 1
 
  | 1
 
  | A rotation angle in steps of 1/256 of a full turn
 
  | 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.
 
  | Whether or not this is signed does not matter, since the resulting angles are the same.
 
  |-
 
  |-
  ! UUID
+
  ! id=Type:UUID | {{Type|UUID}}
 
  | 16
 
  | 16
 
  | A [[wikipedia:Universally_unique_identifier|UUID]]
 
  | A [[wikipedia:Universally_unique_identifier|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)
 
  | 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)
 
  |-
 
  |-
  ! Optional X
+
  ! id=Type:BitSet | {{Type|BitSet}}
 +
| Varies
 +
| See [[#BitSet]] below
 +
| A length-prefixed bit set.
 +
|-
 +
! id=Type:Fixed_BitSet | {{Type|Fixed BitSet}} (n)
 +
| ceil(n / 8)
 +
| See [[#Fixed BitSet]] below
 +
| A bit set with a fixed length of <var>n</var> bits.
 +
|-
 +
! id=Type:Optional | {{Type|Optional}} X
 
  | 0 or size of X
 
  | 0 or size of X
 
  | A field of type X, or nothing
 
  | A field of type X, or nothing
 
  | Whether or not the field is present must be known from the context.
 
  | Whether or not the field is present must be known from the context.
 
  |-
 
  |-
  ! Array of X
+
  ! id=Type:Array | {{Type|Array}} of X
 
  | count times size of X
 
  | count times size of X
 
  | Zero or more fields of type X
 
  | Zero or more fields of type X
 
  | The count must be known from the context.
 
  | The count must be known from the context.
 
  |-
 
  |-
  ! X Enum
+
  ! id=Type:Enum | X {{Type|Enum}}
 
  | size of X
 
  | size of X
 
  | A specific value from a given list
 
  | 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.
 
  | 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.
 
  |-
 
  |-
  ! Byte Array
+
  ! id=Type:Byte_Array | {{Type|Byte Array}}
 
  | Varies
 
  | Varies
 
  | Depends on context
 
  | 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.
 
  | 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=Type:ID_or | {{Type|ID or}} X
 +
| size of {{Type|VarInt}} + (size of X or 0)
 +
| See [[#ID or X]] below
 +
| Either a registry ID or an inline data definition of type X.
 +
|-
 +
! id=Type:ID_Set | {{Type|ID Set}}
 +
| Varies
 +
| See [[#ID Set]] below
 +
| Set of registry IDs specified either inline or as a reference to a tag.
 +
|-
 +
! id=Type:Sound_Event | {{Type|Sound Event}}
 +
| Varies
 +
| See [[#Sound Event]] below
 +
| Parameters for a sound event.
 
  |}
 
  |}
  
 
<noinclude>== Identifier ==</noinclude><includeonly>=== Identifier ===</includeonly>
 
<noinclude>== Identifier ==</noinclude><includeonly>=== Identifier ===</includeonly>
  
Identifiers are a namespaced location, in the form of <code>minecraft:thing</code>.  If the namespace is not provided, it defaults to <code>minecraft</code> (i.e. <code>thing</code> is <code>minecraft:thing</code>.  Custom content should always be in its own namespace, not the default one.  The namespace should only use the characters <code>01​​234​5​6​78​9abcdefghijklmnopqrstuvwxyz-_</code>; actual names may contain more symbols. The naming convention is <code>lower_case_with_underscores</code>.  [https://minecraft.net/en-us/article/minecraft-snapshot-17w43a More information].
+
Identifiers are a namespaced location, in the form of <code>minecraft:thing</code>.  If the namespace is not provided, it defaults to <code>minecraft</code> (i.e. <code>thing</code> is <code>minecraft:thing</code>).  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 (<code>.</code>), dash (<code>-</code>), and underscore (<code>_</code>). In addition, values can use slash (<code>/</code>). The naming convention is <code>lower_case_with_underscores</code>.  [https://minecraft.net/en-us/article/minecraft-snapshot-17w43a More information].
 +
For ease of determining whether a namespace or value is valid, here are regular expressions for each:
 +
* Namespace: <code>[a-z0-9.-_]</code>
 +
* Value: <code>[a-z0-9.-_/]</code>
  
 
<noinclude>== VarInt and VarLong ==</noinclude><includeonly>=== VarInt and VarLong ===</includeonly>
 
<noinclude>== VarInt and VarLong ==</noinclude><includeonly>=== VarInt and VarLong ===</includeonly>
  
Variable-length format such that smaller numbers use fewer bytes.  These are very similar to [http://developers.google.com/protocol-buffers/docs/encoding#varints 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).
+
{{:VarInt_And_VarLong}}
 +
 
 +
<noinclude>== Position ==</noinclude><includeonly>=== Position ===</includeonly>
 +
 
 +
<b>Note:</b> What you are seeing here is the latest version of the [[Data types]] article, but the position type was [https://wiki.vg/index.php?title=Data_types&oldid=14345#Position different before 1.14].
 +
 
 +
64-bit value split into three '''signed''' integer parts:
 +
 
 +
* x: 26 MSBs
 +
* z: 26 middle bits
 +
* y: 12 LSBs
  
VarInts are never longer than 5 bytes, and VarLongs are never longer than 10 bytes.
+
For example, a 64-bit position can be broken down as follows:
  
Pseudocode to read and write VarInts and VarLongs:
+
Example value (big endian): <code><span style="outline: solid 2px rgb(255, 0, 0)">01000110000001110110001100</span> <span style="outline: solid 2px rgb(0, 0, 255)">10110000010101101101001000</span> <span style="outline: solid 2px rgb(0, 255, 0)">001100111111</span></code><br>
 +
* The red value is the X coordinate, which is <code>18357644</code> in this example.<br>
 +
* The blue value is the Z coordinate, which is <code>-20882616</code> in this example.<br>
 +
* The green value is the Y coordinate, which is <code>831</code> in this example.<br>
  
<syntaxhighlight lang="java">
+
Encoded as follows:
public static int readVarInt() {
 
    int numRead = 0;
 
    int result = 0;
 
    byte read;
 
    do {
 
        read = readByte();
 
        int value = (read & 0b01111111);
 
        result |= (value << (7 * numRead));
 
  
        numRead++;
+
((x & 0x3FFFFFF) << 38) | ((z & 0x3FFFFFF) << 12) | (y & 0xFFF)
        if (numRead > 5) {
 
            throw new RuntimeException("VarInt is too big");
 
        }
 
    } while ((read & 0b10000000) != 0);
 
  
    return result;
+
And decoded as:
}
 
</syntaxhighlight>
 
<syntaxhighlight lang="java">
 
public static long readVarLong() {
 
    int numRead = 0;
 
    long result = 0;
 
    byte read;
 
    do {
 
        read = readByte();
 
        int value = (read & 0b01111111);
 
        result |= (value << (7 * numRead));
 
  
        numRead++;
+
val = read_long();
        if (numRead > 10) {
+
x = val >> 38;
            throw new RuntimeException("VarLong is too big");
+
y = val << 52 >> 52;
        }
+
z = val << 26 >> 38;
    } while ((read & 0b10000000) != 0);
 
  
    return result;
+
Note: The above assumes that the right shift operator sign extends the value (this is called an [https://en.wikipedia.org/wiki/Arithmetic_shift arithmetic shift]), so that the signedness of the coordinates is preserved. In many languages, this requires the integer type of <code>val</code> to be signed. In the absence of such an operator, the following may be useful:
}
 
</syntaxhighlight>
 
<syntaxhighlight lang="java">
 
public static void writeVarInt(int value) {
 
    do {
 
        byte temp = (byte)(value & 0b01111111);
 
        // Note: >>> means that the sign bit is shifted with the rest of the number rather than being left alone
 
        value >>>= 7;
 
        if (value != 0) {
 
            temp |= 0b10000000;
 
        }
 
        writeByte(temp);
 
    } while (value != 0);
 
}
 
</syntaxhighlight>
 
<syntaxhighlight lang="java">
 
public static void writeVarLong(long value) {
 
    do {
 
        byte temp = (byte)(value & 0b01111111);
 
        // Note: >>> means that the sign bit is shifted with the rest of the number rather than being left alone
 
        value >>>= 7;
 
        if (value != 0) {
 
            temp |= 0b10000000;
 
        }
 
        writeByte(temp);
 
    } while (value != 0);
 
}
 
</syntaxhighlight>
 
  
{{Warning2|Note that Minecraft's VarInts are not encoded using Protocol Buffers; it's just similar. If you try to use Protocol Buffers Varints with Minecraft's VarInts, you'll get incorrect results in some cases.  The major differences:
+
  if x >= 1 << 25 { x -= 1 << 26 }
*Minecraft's VarInts are all signed, but do not use the ZigZag encoding.  Protocol buffers have 3 types of Varints: <code>uint32</code> (normal encoding, unsigned), <code>sint32</code> (ZigZag encoding, signed), and <code>int32</code> (normal encoding, signed).  Minecraft's are the <code>int32</code> variety. Because Minecraft uses the normal encoding instead of ZigZag encoding, negative values always use the maximum number of bytes.
+
if y >= 1 << 11 { y -= 1 << 12 }
*Minecraft's VarInts are never be 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 <code>int32</code>.}}
+
  if z >= 1 << 25 { z -= 1 << 26 }
  
Sample VarInts:
+
<noinclude>== Fixed-point numbers ==</noinclude><includeonly>=== Fixed-point numbers ===</includeonly>
  
{| class="wikitable"
+
Some fields may be stored as [https://en.wikipedia.org/wiki/Fixed-point_arithmetic 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.
! 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
 
|-
 
| -1 || 0xff 0xff 0xff 0xff 0x0f || 255 255 255 255 15
 
|-
 
| -2147483648 || 0x80 0x80 0x80 0x80 0x08 || 128 128 128 128 8
 
|}
 
  
Sample VarLongs:
+
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.
  
{| class="wikitable"
+
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 <var>n</var> fraction bits:
! 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
 
|}
 
  
<noinclude>== Position ==</noinclude><includeonly>=== Position ===</includeonly>
+
  x_fixed = (int)(x_double * (1 << n));
  
64-bit value split in to three parts
+
And back again:
  
* x: 26 MSBs
+
  x_double = (double)x_fixed / (1 << n);
* z: 26 middle bits
 
* y: 12 LSBs
 
  
Encoded as followed:
+
<noinclude>== Bit sets ==</noinclude><includeonly>=== Bit sets ===</includeonly>
  
((x & 0x3FFFFFF) << 38) | ((z & 0x3FFFFFF) << 12) | (y & 0xFFF)
+
The types {{Type|BitSet}} and {{Type|Fixed BitSet}} represent packed lists of bits. The Notchian implementation uses Java's [https://docs.oracle.com/javase/8/docs/api/java/util/BitSet.html <code>BitSet</code>] class.
  
And decoded as:
+
<noinclude>=== BitSet ===</noinclude><includeonly>==== BitSet ====</includeonly>
  
val = read_unsigned_long();
+
Bit sets of type BitSet are prefixed by their length in longs.
x = val >> 38;
 
y = val & 0xFFF;
 
z = (val << 26 >> 38);
 
  
Note: The details of bit shifting are rather language dependent; the above may work in Java but probably won't in other languages without some tweaking. In particular, you will usually receive positive numbers even if the actual coordinates are negative. This can be fixed by adding something like the following:
+
{| class="wikitable"
 +
! Field Name
 +
! Field Type
 +
! Meaning
 +
|-
 +
| Length
 +
| {{Type|VarInt}}
 +
| Number of longs in the following array. May be 0 (if no bits are set).
 +
|-
 +
| Data
 +
| {{Type|Array}} of {{Type|Long}}
 +
| A packed representation of the bit set as created by [https://docs.oracle.com/javase/8/docs/api/java/util/BitSet.html#toLongArray-- <code>BitSet.toLongArray</code>].
 +
|}
  
if x >= 2^25 { x -= 2^26 }
+
The <var>i</var>th bit is set when <code>(Data[i / 64] & (1 << (i % 64))) != 0</code>, where <var>i</var> starts at 0.
if y >= 2^11 { y -= 2^12 }
 
if z >= 2^25 { z -= 2^26 }
 
  
<noinclude>== Fixed-point numbers ==</noinclude><includeonly>=== Fixed-point numbers ===</includeonly>
+
<noinclude>=== Fixed BitSet ===</noinclude><includeonly>==== Fixed BitSet ====</includeonly>
  
Some fields may be stored as [https://en.wikipedia.org/wiki/Fixed-point_arithmetic fixed-point numbers], where a certain number of bits represents the signed integer part (number to the left of the decimal point) and the rest represents the fractional part (to the right). Floating points (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.  
+
Bit sets of type Fixed BitSet (n) have a fixed length of <var>n</var> bits, encoded as <code>ceil(n / 8)</code> bytes. Note that this is different from BitSet, which uses longs.
  
Essentially, while fixed-point numbers have lower range than floating points, their fractional precision is greater for higher values. This makes them ideal for representing global coordinates of an entity in Minecraft, as it's more important to store the integer part accurately than position them more precisely within a single block (or meter).  
+
{| class="wikitable"
 +
! Field Name
 +
! Field Type
 +
! Meaning
 +
|-
 +
| Data
 +
| {{Type|Byte Array}} (n)
 +
| A packed representation of the bit set as created by [https://docs.oracle.com/javase/8/docs/api/java/util/BitSet.html#toByteArray-- <code>BitSet.toByteArray</code>], padded with zeroes at the end to fit the specified length.
 +
|}
  
Coordinates are often represented as a 32-bit integer, where 5 of the least-significant bits are dedicated to the fractional part, and the rest store the integer part.
+
The <var>i</var>th bit is set when <code>(Data[i / 8] & (1 << (i % 8))) != 0</code>, where <var>i</var> starts at 0. This encoding is ''not'' equivalent to the long array in BitSet.
  
Java lacks support for fractional integers directly, but you can represent them as integers. To convert from a double to this integer representation, use the following formulas:
+
<noinclude>== Registry references ==</noinclude><includeonly>=== Registry references ===</includeonly>
  abs_int = (int) (double * 32.0D);
 
And back again:
 
  
  double = (double) (abs_int / 32.0D);
+
<noinclude>=== ID or X ===</noinclude><includeonly>==== ID or X ====</includeonly>
  
<noinclude>== Particle ==</noinclude><includeonly>=== Particle ===</includeonly>
+
Represents a data record of type X, either inline, or by reference to a registry implied by context.
  
 
{| class="wikitable"
 
{| class="wikitable"
Line 311: Line 276:
 
  |-
 
  |-
 
  | ID
 
  | ID
  | VarInt
+
  | {{Type|VarInt}}
  | The ID of the particle type, see below.
+
  | 0 if value of type X is given inline; otherwise registry ID + 1.
 
  |-
 
  |-
  | Data
+
  | Value
  | Varies
+
  | {{Type|Optional}} X
  | Varies based on the particle type, see below.
+
  | Only present if ID is 0.
 
  |}
 
  |}
 +
 +
<noinclude>=== ID Set ===</noinclude><includeonly>==== ID Set ====</includeonly>
 +
 +
Represents a set of IDs in a certain registry (implied by context), either directly (enumerated IDs) or indirectly (tag name).
  
 
{| class="wikitable"
 
{| class="wikitable"
 +
! Field Name
 +
! Field Type
 +
! Meaning
 
  |-
 
  |-
  ! Particle Name
+
  | Type
  ! Particle ID
+
  | {{Type|VarInt}}
  ! Data
+
  | Value used to determine the data that follows. It can be either:
 +
* 0 - Represents a named set of IDs defined by a tag.
 +
* Anything else - Represents an ad-hoc set of IDs enumerated inline.
 
  |-
 
  |-
  | <code>minecraft:ambient_entity_effect</code>
+
  | Tag Name
  | 0
+
  | {{Type|Optional}} {{Type|Identifier}}
  | None
+
  | The registry tag defining the ID set. Only present if Type is 0.
 
  |-
 
  |-
  | <code>minecraft:angry_villager</code>
+
  | IDs
  | 1
+
| {{Type|Optional}} {{Type|Array}} of {{Type|VarInt}}
  | None
+
| An array of registry IDs. Only present if Type is not 0.<br>The size of the array is equal to <code>Type - 1</code>.
 +
  |}
 +
 
 +
<noinclude>== Registry data ==</noinclude><includeonly>=== Registry data ===</includeonly>
 +
 
 +
These types are commonly used in conjuction with {{Type|ID or}} X to specify custom data inline.
 +
 
 +
<noinclude>=== Sound Event ===</noinclude><includeonly>==== Sound Event ====</includeonly>
 +
 
 +
Describes a sound that can be played.
 +
 
 +
{| class="wikitable"
 +
! Name
 +
! Type
 +
  ! Description
 
  |-
 
  |-
  | <code>minecraft:barrier</code>
+
  | Sound Name
  | 2
+
  | {{Type|Identifier}}
| None
 
|-
 
| <code>minecraft:block</code>
 
| 3
 
 
  |
 
  |
{| class="wikitable"
 
  ! Field Name
 
  ! Field Type
 
  ! Meaning
 
  |-
 
  | BlockState
 
  | VarInt
 
  | The ID of the block state.
 
  |}
 
|-
 
| <code>minecraft:bubble</code>
 
| 4
 
| None
 
|-
 
| <code>minecraft:cloud</code>
 
| 5
 
| None
 
|-
 
| <code>minecraft:crit</code>
 
| 6
 
| None
 
|-
 
| <code>minecraft:damage_indicator</code>
 
| 7
 
| None
 
|-
 
| <code>minecraft:dragon_breath</code>
 
| 8
 
| None
 
|-
 
| <code>minecraft:dripping_lava</code>
 
| 9
 
| None
 
|-
 
| <code>minecraft:falling_lava</code>
 
| 10
 
| None
 
 
  |-
 
  |-
  | <code>minecraft:landing_lava</code>
+
  | Has Fixed Range
  | 11
+
  | {{Type|Boolean}}
  | None
+
  | Whether this sound has a fixed range, as opposed to a variable volume based on distance.
 
  |-
 
  |-
  | <code>minecraft:dripping_water</code>
+
  | Fixed Range
  | 12
+
  | {{Type|Optional}} {{Type|Float}}
| None
+
  | The maximum range of the sound. Only present if Has Fixed Range is true.
|-
 
| <code>minecraft:falling_water</code>
 
| 13
 
| None
 
|-
 
| <code>minecraft:dust</code>
 
| 14
 
|
 
{| class="wikitable"
 
  ! Field Name
 
  ! Field Type
 
  ! Meaning
 
  |-
 
  | Red
 
  | Float
 
  | Red value, 0-1
 
  |-
 
  | Green
 
  | Float
 
  | Green value, 0-1
 
  |-
 
  | Blue
 
  | Float
 
  | Blue value, 0-1
 
  |-
 
  | Scale
 
  | Float
 
  | The scale, will be clamped between 0.01 and 4.
 
  |}
 
  |-
 
| <code>minecraft:effect</code>
 
| 15
 
| None
 
|-
 
| <code>minecraft:elder_guardian</code>
 
| 16
 
| None
 
|-
 
| <code>minecraft:enchanted_hit</code>
 
| 17
 
| None
 
|-
 
| <code>minecraft:enchant</code>
 
| 18
 
| None
 
|-
 
| <code>minecraft:end_rod</code>
 
| 19
 
| None
 
|-
 
| <code>minecraft:entity_effect</code>
 
| 20
 
| None
 
|-
 
| <code>minecraft:explosion_emitter</code>
 
| 21
 
| None
 
|-
 
| <code>minecraft:explosion</code>
 
| 22
 
| None
 
|-
 
| <code>minecraft:falling_dust</code>
 
| 23
 
|
 
{| class="wikitable"
 
  ! Field Name
 
  ! Field Type
 
  ! Meaning
 
  |-
 
  | BlockState
 
  | VarInt
 
  | The ID of the block state.
 
  |}
 
|-
 
| <code>minecraft:firework</code>
 
| 24
 
| None
 
|-
 
| <code>minecraft:fishing</code>
 
| 25
 
| None
 
|-
 
| <code>minecraft:flame</code>
 
| 26
 
| None
 
|-
 
| <code>minecraft:flash</code>
 
| 27
 
| None
 
|-
 
| <code>minecraft:happy_villager</code>
 
| 28
 
| None
 
|-
 
| <code>minecraft:composter</code>
 
| 29
 
| None
 
|-
 
| <code>minecraft:heart</code>
 
| 30
 
| None
 
|-
 
| <code>minecraft:instant_effect</code>
 
| 31
 
| None
 
|-
 
| <code>minecraft:item</code>
 
| 32
 
|
 
{| class="wikitable"
 
  ! Field Name
 
  ! Field Type
 
  ! Meaning
 
  |-
 
  | Item
 
  | [[Slot]]
 
  | The item that will be used.
 
  |}
 
|-
 
| <code>minecraft:item_slime</code>
 
| 33
 
| None
 
|-
 
| <code>minecraft:item_snowball</code>
 
| 34
 
| None
 
|-
 
| <code>minecraft:large_smoke</code>
 
| 35
 
| None
 
|-
 
| <code>minecraft:lava</code>
 
| 36
 
| None
 
|-
 
| <code>minecraft:mycelium</code>
 
| 37
 
| None
 
|-
 
| <code>minecraft:note</code>
 
| 38
 
| None
 
|-
 
| <code>minecraft:poof</code>
 
| 39
 
| None
 
|-
 
| <code>minecraft:portal</code>
 
| 40
 
| None
 
|-
 
| <code>minecraft:rain</code>
 
| 41
 
| None
 
|-
 
| <code>minecraft:smoke</code>
 
| 42
 
| None
 
|-
 
| <code>minecraft:sneeze</code>
 
| 43
 
| None
 
|-
 
| <code>minecraft:spit</code>
 
| 44
 
| None
 
|-
 
| <code>minecraft:squid_ink</code>
 
| 45
 
| None
 
|-
 
| <code>minecraft:sweep_attack</code>
 
| 46
 
| None
 
|-
 
| <code>minecraft:totem_of_undying</code>
 
| 47
 
| None
 
|-
 
| <code>minecraft:underwater</code>
 
| 48
 
| None
 
|-
 
| <code>minecraft:splash</code>
 
| 49
 
| None
 
|-
 
| <code>minecraft:witch</code>
 
| 50
 
| None
 
|-
 
| <code>minecraft:bubble_pop</code>
 
| 51
 
| None
 
|-
 
| <code>minecraft:current_down</code>
 
| 52
 
| None
 
|-
 
| <code>minecraft:bubble_column_up</code>
 
| 53
 
| None
 
|-
 
| <code>minecraft:nautilus</code>
 
| 54
 
| None
 
|-
 
| <code>minecraft:dolphin</code>
 
| 55
 
| None
 
|-
 
| <code>minecraft:campfire_cosy_smoke</code>
 
| 56
 
| None
 
|-
 
| <code>minecraft:campfire_signal_smoke</code>
 
| 57
 
| None
 
 
  |}
 
  |}
  
Line 609: Line 337:
 
[[Category:Protocol Details]]
 
[[Category:Protocol Details]]
 
[[Category:Minecraft Modern]]
 
[[Category:Minecraft Modern]]
 +
</noinclude>

Latest revision as of 09:26, 21 November 2024

This article defines the data types used in the 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

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 formatting#Text components Encoded as a NBT Tag, with the type of tag used depending on the case:
  • As a String Tag: For components only containing text (no styling, no events etc.).
  • As a Compound Tag: Every other case.
JSON Text Component ≥ 1
≤ (262144×3) + 3
See Text formatting#Text components The maximum permitted length when decoding is 262144, but the Notchian 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
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.
Array of X count times size of X Zero or more fields of type X The count must be known from the context.
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.
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.

Identifier

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

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 sign bit is shifted with the rest of the number rather than being left alone
        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 sign bit is shifted with the rest of the number rather than being left alone
        value >>>= 7;
    }
}

Warning.png Note Minecraft's VarInts are identical to LEB128 with the slight change of throwing a exception if it goes over a set amount of bytes.

Warning.png Note that Minecraft's VarInts are not encoded using Protocol Buffers; it's just similar. If you try to use Protocol Buffers Varints with Minecraft's VarInts, you'll get incorrect results in some cases. The major differences:

  • 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), and int32 (normal encoding, signed). Minecraft's are the int32 variety. 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

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 18357644 in this example.
  • The blue value is the Z coordinate, which is -20882616 in this example.
  • The green value is the Y coordinate, which is 831 in 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

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);

Bit sets

The types BitSet and Fixed BitSet represent packed lists of bits. The Notchian implementation uses Java's BitSet class.

BitSet

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

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

ID or X

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

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:
  • 0 - Represents a named set of IDs defined by a tag.
  • Anything else - Represents an ad-hoc set of IDs enumerated inline.
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

These types are commonly used in conjuction with ID or X to specify custom data inline.

Sound Event

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.