NBT¶
NBT(Named Binary Tag)是一种二进制级别的数据编码格式,用于在Minecraft中存储结构化数据。在基岩版中,NBT被广泛应用于实体、物品、方块实体、存档等多个方面的数据序列化与反序列化。
概述¶
NBT最初由Notch为Minecraft Java版设计,后被基岩版沿用并在编码细节上做出了修改。NBT的核心思想是使用一系列带有名称的标签(Tag)来组织数据,每个标签由类型、名称和值三部分构成。标签可以嵌套,从而形成树状的层级结构,用以表达复杂的数据关系。
与JSON等文本格式相比,NBT是一种紧凑的二进制格式,读写效率更高,更适合游戏运行时的大量数据存取场景。但也因此,NBT文件无法直接用文本编辑器查看或编辑,通常需要借助专用工具进行操作。
数据类型¶
NBT定义了以下数据类型,每种类型由一个唯一的类型ID标识:
| 类型 | 类型ID | 大小 | 描述 |
|---|---|---|---|
| End | 0x00 | 1字节 | 标记复合标签(Compound Tag)的结束 |
| Byte | 0x01 | 1字节 | 8位有符号整数 |
| Short | 0x02 | 2字节 | 16位有符号整数 |
| Int | 0x03 | 4字节 | 32位有符号整数 |
| Long | 0x04 | 8字节 | 64位有符号整数 |
| Float | 0x05 | 4字节 | 32位IEEE 754单精度浮点数 |
| Double | 0x06 | 8字节 | 64位IEEE 754双精度浮点数 |
| Byte Array | 0x07 | 可变 | 字节型数组,前缀一个Int表示长度 |
| String | 0x08 | 可变 | UTF-8编码字符串,前缀一个Short表示长度 |
| List | 0x09 | 可变 | 同类型标签的有序列表,前缀一个Byte表示元素类型和一个Int表示长度 |
| Compound | 0x0A | 可变 | 由若干具名标签组成的无序集合,以End标签结束 |
| Int Array | 0x0B | 可变 | 整型数组,前缀一个Int表示长度 |
| Long Array | 0x0C | 可变 | 长整型数组,前缀一个Int表示长度 |
NBT中不存在专用的布尔类型。布尔值通过Byte类型模拟,1代表真,0代表假。
字节序¶
基岩版NBT使用小端序(Little-Endian)编码,即多字节数值的低位字节在前、高位字节在后。这与Java版使用的大端序(Big-Endian)相反,是基岩版NBT与Java版NBT之间最主要的差异之一。
此外,基岩版在网络传输场景中使用一种称为网络小端序(Network Little-Endian)的变体编码。在该编码中,Int和Long类型使用可变长整数(VarInt)表示,以减小网络传输的数据量。
文件头¶
基岩版的部分NBT文件(如level.dat)在数据正文之前包含一个8字节的文件头(Header)。文件头由两个小端序的32位整数组成:
- 第一个整数:存储版本号(在level.dat中表示存档版本,其他文件中通常为
8)。 - 第二个整数:NBT数据正文的字节长度(不包括文件头本身的8个字节)。
并非所有NBT文件都包含文件头。例如,.mcstructure结构文件中的NBT数据不包含文件头。
存储位置¶
NBT在基岩版中应用于多种数据存储场景:
存档数据库¶
基岩版使用经过修改的Google LevelDB作为存档的底层数据库,配合Zlib压缩。数据库中以下类型的键值对存储NBT数据:
- 方块实体数据(键标签
0x31):存储箱子、告示牌、酿造台等方块实体的状态。 - 实体数据(键标签
0x32):存储世界中所有非玩家实体的状态。 - 计划刻数据(键标签
0x33):存储待执行的计划刻信息。 - 玩家数据:本地玩家以
~local_player为键存储,远程玩家以player_<客户端ID>为键存储。
存档配置文件¶
level.dat文件存储了世界的全局配置信息,包括世界名称、游戏模式、游戏规则、种子、天气状态等。该文件包含前述8字节文件头。
结构文件¶
.mcstructure文件使用NBT存储由结构方块导出的建筑结构数据,包括方块布局、方块实体数据和实体数据。该文件不包含文件头。
物品数据¶
物品在NBT中的常见标签包括:
与Java版NBT的差异¶
基岩版NBT与Java版NBT在概念上一致,但在以下方面存在差异:
| 差异 | 基岩版 | Java版 |
|---|---|---|
| 字节序 | 小端序 | 大端序 |
| 存储方式 | LevelDB数据库 | 区域文件(Region File) |
| 根元素 | 存在根元素名称(通常为空字符串) | 存在根元素名称 |
| 网络传输 | 网络小端序(使用VarInt) | 大端序 |
| 文件头 | 部分文件包含8字节文件头 | 通常使用GZip压缩 |
编辑注意事项¶
直接编辑NBT数据存在一定风险。安全的做法是只修改游戏本身能够产生的值,例如修改书与笔的文本内容、物品的显示名称和描述文本等。超出游戏正常范围的修改(如设置超过上限的属性值、写入无效的标签类型等)可能导致数据损坏或游戏行为异常。对于需要自定义交易或自定义掉落等功能,建议优先使用战利品表等数据驱动的方式实现,而非直接修改NBT。