Package net.minecraft.nbt
NBT is a simple data structure format used in Minecraft's in-game data serialization. Data stored on disks, modified by commands, and transported via packets are usually in this format. In most cases, NBT is not the runtime form of data; data are instead written to Java class fields using Java types, and during serialization (as part of saving or network transportation) or modification by commands, the code will write the fields to NBT data. NBT data is also known as "NBT element".
Types
There are 13 NBT element types, as shown below. Each NBT type has its own class,
and a NbtType
instance used during deserialization in the TYPE
static field. They also have the "numeric ID" used during serialization and at
NbtCompound.getList(String, int)
method. The ID of the element's type can
be obtained via the NbtElement.getType()
method. There is also a special
ID, NbtElement.NUMBER_TYPE
, which indicates the read value
can be any of the six numeric types; this cannot be used as the list's held type.
Class | Numeric ID | Immutable? | Default | Description |
---|---|---|---|---|
NbtEnd |
0x0 | Yes | (none) | Internal type used during serialization, should not be used directly |
NbtByte |
0x1 | Yes | 0 |
Corresponds to byte |
NbtShort |
0x2 | Yes | 0 |
Corresponds to short |
NbtInt |
0x3 | Yes | 0 |
Corresponds to int |
NbtLong |
0x4 | Yes | 0L |
Corresponds to long |
NbtFloat |
0x5 | Yes | 0.0f |
Corresponds to float |
NbtDouble |
0x6 | Yes | 0.0 |
Corresponds to double |
NbtByteArray |
0x7 | No | Empty array | Corresponds to byte[] |
NbtString |
0x8 | Yes | "" |
Corresponds to String |
NbtList |
0x9 | No | Empty list | List of NBT elements with the same type |
NbtCompound |
0xa | No | Empty compound | Hash map-like object with string keys that can store any NBT elements |
NbtIntArray |
0xb | No | Empty array | Corresponds to int[] |
NbtLongArray |
0xc | No | Empty array | Corresponds to long[] |
NbtEnd
NbtEnd is a special sentinel used to indicate the end of lists and compounds. This is also used as the type of empty lists.
Numeric types
NBT offers 6 numeric types (4 for integers and 2 for decimals), all corresponding
to Java equivalents. There is no unsigned type or char
equivalent. These
inherit AbstractNbtNumber
. To create an instance of these, use the of
static method, and to obtain the value as the Java primitive value, use the
typeValue()
method.
NbtInt nbt = NbtInt.of(100);
int value = nbt.intValue();
One thing to note here is that NBT lacks the boolean type; instead NbtByte
is used when boolean values are needed. See also NbtByte.of(boolean)
method.
NBT typed arrays
There are 3 typed arrays in NBT: NbtByteArray
, NbtIntArray
, and
NbtLongArray
. There are no array types for shorts, floats or doubles. While they
are arrays internally, they also support adding items
at runtime. Like Java arrays, out of bounds access is forbidden and will throw
ArrayIndexOutOfBoundsException
.
NbtList
NbtList is a list of a specific type of NBT elements. Empty lists always have the type
set as NbtEnd
. NbtList.add(int, net.minecraft.nbt.NbtElement)
throws when the type is incompatible, while
NbtList.addElement(int, net.minecraft.nbt.NbtElement)
does nothing and returns false
in that case.
There are type-specific getters which can be used to get the value. They return the default
value when type mismatch occurs or when the index is out of bounds. Note that they do not
cast the value at all.
NbtList list = new NbtList();
list.addElement(0, NbtFloat.of(0.5f));
float firstItem = list.getFloat(0); // 0.5f
float secondItem = list.getFloat(1); // 0.0f (default value)
double firstItemDouble = list.getDouble(0); // 0.0 (no casting)
list.addElement(1, NbtDouble.of(1.0)); // returns false, does nothing
list.add(NbtDouble.of(2.0)); // throws UnsupportedOperationException
NbtCompound
NbtCompound is a hash map-like key-value storage object. It also acts as the root
object for serialized NBTs. The keys are always strings, while the values can be of
any type, and multiple value types can be mixed in a single compound. The order of items
is not guaranteed. There are generic NbtCompound.put(java.lang.String, net.minecraft.nbt.NbtElement)
and NbtCompound.get(java.lang.String)
methods, and there also exist type-specific getters and putters. Like the list getters
mentioned above, they return the default value when the key is missing or type mismatch
occurs. However, unlike lists, they attempt to cast numeric values.
NbtCompound compound = new NbtCompound();
compound.put("Awesomeness", NbtInt.of(90));
// Don't do this! This will crash if the type is incompatible,
// even if they can be casted!
NbtInt awesomenessNbt = (NbtInt)compound.get("Awesomeness");
compound.putLong("Awesomeness", 100L);
int awesomeness = compound.getInt("Awesomeness"); // 100 (after casting)
int evilness = compound.getInt("Evilness"); // 0 (default value)
// Shortcuts for getting and putting a boolean value
// (internally represented as a byte)
compound.putBoolean("Awesome", true);
boolean awesome = compound.getBoolean("Awesome");
compound.put("awesome", NbtDouble.of(1.0)); // key is case-sensitive
Using NBT
As noted before, NBT is a serialized format, not runtime format. Unrecognized custom data stored inside NBT will be lost once the game loads it and saves. Therefore, modifying NBT is usually not the solution for attaching custom data to objects like entities. For this purpose it is recommended to use third-party APIs or use Mixin to add a field to the class.
With that said, here is how to use NBT in the vanilla code:
Methods named readNbt
will read the values from the element, modifying
the current instance. Static methods named fromNbt
will create a new instance
of the class with values from the element. Methods named writeNbt
will add
the NBT data to the passed element. Methods named toNbt
will create and return
a new element with the data.
There are several helper classes for NBTs:
NbtHelper
contains methods for reading and writing game profiles, block states, UUIDs, and block positions. It also contains a method for comparing elements.NbtIo
contains methods for reading and writing NBT compounds on a file.NbtOps
is the class defining interactions with the DataFixerUpper library. The library abstracts operations between data formats (such as JSON or NBT) using "ops". UseNbtOps.INSTANCE
to decode the NBT data using DataFixerUpper.StringNbtReader
reads the stringified NBT (SNBT) and converts to NBT.NbtElementVisitor
and its subclasses allow converting NBT elements to string orText
.NbtScanner
scans the NBT data without reading the whole data at once, allowing efficient decoding when only parts of the data are needed.
NBT compounds can also be transported using PacketByteBuf.writeNbt(net.minecraft.nbt.NbtElement)
and PacketByteBuf.readNbt()
.
-
ClassDescriptionAbstractNbtList<T extends NbtElement>Represents an abstraction of a mutable NBT list which holds elements of the same type.Represents an NBT number.Represents an NBT byte.Represents an NBT byte array.Represents an NBT compound object.Represents an NBT 64-bit floating-point number.Represents an NBT element.Represents the NBT end value.Represents an NBT 32-bit floating-point number.Helper methods for handling NBT.Represents an NBT 32-bit integer.Represents an NBT 32-bit integer array.A set of utility functions for reading, writing, and scanning NBT files.Represents a mutable NBT list.Represents an NBT 64-bit integer.Represents an NBT 64-bit integer array.Used to handle Minecraft NBTs within
dynamics
for DataFixerUpper, allowing generalized serialization logic shared across different type of data structures.Represents an NBT 16-bit integer.Represents an NBT string.Tracks the size of NBT elements in bytes and in depth.NbtType<T extends NbtElement>Represents an NBT type.NbtType.OfFixedSize<T extends NbtElement>Represents an NBT type whose elements have a fixed size, such as primitives.NbtType.OfVariableSize<T extends NbtElement>Represents an NBT type whose elements can have a variable size, such as lists.A class holding known NBT types.A class for reading a stringified NBT.