Skip to content

Commit 148f084

Browse files
Rework and expand the Items section (#39)
1 parent c38895f commit 148f084

File tree

4 files changed

+707
-45
lines changed

4 files changed

+707
-45
lines changed

docs/datastorage/nbt.md

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
# Named Binary Tag (NBT)
2+
3+
NBT is a format introduced in the earliest days of Minecraft, written by Notch himself. It is widely used throughout the Minecraft codebase for data storage.
4+
5+
## Specification
6+
7+
The NBT spec is similar to the JSON spec, with a few differences:
8+
9+
- Distinct types for bytes, shorts, longs and floats exist, suffixed by `b`, `s`, `l` and `f`, respectively, similar to how they would be represented in Java code.
10+
- Doubles may also be suffixed with `d`, but this is not required, similar to Java code. The optional `i` suffix available in Java for integers is not permitted.
11+
- The suffixes are not case-sensitive. So for example, `64b` is the same as `64B`, and `0.5F` is the same as `0.5f`.
12+
- Booleans do not exist, they are instead represented by bytes. `true` becomes `1b`, `false` becomes `0b`.
13+
- The current implementation treats all non-zero values as `true`, so `2b` would be treated as `true` as well.
14+
- There is no `null` equivalent in NBT.
15+
- Quotes around keys are optional. So a JSON property `"duration": 20` can become both `duration: 20` and `"duration": 20` in NBT.
16+
- What is known in JSON as a sub-object is known in NBT as a **compound tag** (or just compound).
17+
- NBT lists cannot mix and match types, unlike in JSON. The list type is determined by the first element, or defined in code.
18+
- However, lists of lists can mix and match different list types. So a list of two lists, where the first one is a list of strings and the second one is a list of bytes, is allowed.
19+
- There are special **array** types that are different from lists, but follow their scheme of containing elements in square brackets. There are three array types:
20+
- Byte arrays, denoted by a `B;` at the beginning of the array. Example: `[B;0b,30b]`
21+
- Integer arrays, denoted by a `I;` at the beginning of the array. Example: `[I;0,-300]`
22+
- Long arrays, denoted by an `L;` at the beginning of the array. Example: `[L;0l,240l]`
23+
- Trailing commas in lists, arrays and compound tags are allowed.
24+
25+
## NBT Files
26+
27+
Minecraft uses `.nbt` files extensively, for example for structure files in [datapacks][datapack]. Region files (`.mca`) that contain the contents of a region (i.e. a collection of chunks), as well as the various `.dat` files used in different places by the game, are NBT files as well.
28+
29+
NBT files are typically compressed with GZip. As such, they are binary files and cannot be edited directly.
30+
31+
## NBT in Code
32+
33+
Like in JSON, all NBT objects are children of an enclosing object. So let's create one:
34+
35+
```java
36+
CompoundTag tag = new CompoundTag();
37+
```
38+
39+
We can now put our data into that tag:
40+
41+
```java
42+
tag.putInt("Color", 0xffffff);
43+
tag.putString("Level", "minecraft:overworld");
44+
tag.putDouble("IAmRunningOutOfIdeasForNamesHere", 1d);
45+
```
46+
47+
Several helpers exist here, for example, `putIntArray` also has a convenience method that takes a `List<Integer>` in addition to the standard variant that takes an `int[]`.
48+
49+
Of course, we can also get values from that tag:
50+
51+
```java
52+
int color = tag.getInt("Color");
53+
String level = tag.getString("Level");
54+
double d = tag.getDouble("IAmRunningOutOfIdeasForNamesHere");
55+
```
56+
57+
Number types will return 0 if absent. Strings will return `""` if absent. More complex types (lists, arrays, compounds) will throw an exception if absent.
58+
59+
As such, we want to safeguard by checking if a tag element exists:
60+
61+
```java
62+
boolean hasColor = tag.contains("Color");
63+
boolean hasColorMoreExplicitly = tag.contains("Color", Tag.TAG_INT);
64+
```
65+
66+
The `TAG_INT` constant is defined in `Tag`, which is the super interface for all tag types. Most tag types besides `CompoundTag` are mostly internal, for example `ByteTag` or `StringTag`, though the direct `CompoundTag#get` and `#put` methods can work with them if you ever stumble across some.
67+
68+
There is one obvious exception, though: `ListTag`s. Working with these is special because when getting a list tag through `CompoundTag#getList`, you must also specify the list type. So getting a list of strings, for example, would work like this:
69+
70+
```java
71+
ListTag list = tag.getList("SomeListHere", Tag.TAG_STRING);
72+
```
73+
74+
Similarly, when creating a `ListTag`, you must also specify the list type during creation:
75+
76+
```java
77+
ListTag list = new ListTag(List.of("Value1", "Value2"), Tag.TAG_STRING);
78+
```
79+
80+
Finally, working with `CompoundTag`s inside other `CompoundTag`s directly utilizes `CompoundTag#get` and `#put`:
81+
82+
```java
83+
tag.put("Tag", new CompoundTag());
84+
tag.get("Tag");
85+
```
86+
87+
## Usages of NBT
88+
89+
NBT is used in a lot of places in Minecraft. Some of the most common examples include [`ItemStack`][itemstack]s, [`BlockEntity`][blockentity]s and `Entity`s.
90+
91+
## See Also
92+
93+
- [NBT Format on the Minecraft Wiki][nbtwiki]
94+
95+
[blockentity]: ../blockentities/index.md
96+
[datapack]: ../resources/server/index.md
97+
[itemstack]: ../items/index.md#itemstacks
98+
[nbtwiki]: https://minecraft.wiki/w/NBT_format

0 commit comments

Comments
 (0)