Minecraft:Java Edition protocol/VarInt and VarLong
More actions
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: <syntaxhighlight lang="java"> int readVarInt() {
int value = 0;
for (int position = 0; position < 32; position += 7) {
byte currentByte = readByte();
// Note: In C this must be performed on an unsigned type to avoid undefined overflow
// behavior with negative VarInts.
value |= (int)(currentByte & 0x7F) << position;
if ((currentByte & 0x80) == 0)
return value;
}
error("VarInt too big");
} </syntaxhighlight> <syntaxhighlight lang="java"> void writeVarInt(int value) {
while ((value & ~0x7F) != 0) {
writeByte((value & 0x7F) | 0x80);
// 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;
}
writeByte(value);
} </syntaxhighlight>
The above code may be adapted for VarLongs by changing the type of value to long and the for loop condition to position < 64.
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 |