Files
netease-modsdk-wiki/docs/wiki/nbt/nbt-in-depth.md
2025-03-20 11:52:46 +08:00

102 lines
5.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: NBT深度解析
category: NBT深度解析
mentions:
- ConsoleTerm
- SmokeyStack
- ThomasOrs
tags:
- 专家
---
# NBT深度解析
<!--@include: @/wiki/bedrock-wiki-mirror.md-->
NBT命名二进制标签是一种二进制层级的编码格式正如你熟悉的基于文本层级的JSON格式。因此我们可以用JSON格式举例说明你可能也注意到Minecraft本身在命令中使用JSON来表示NBT如Java版命令或简化的基岩版命令`/give``/replaceitem`)。详见[NBT命令](/wiki/commands/nbt-commands)。本文将深入解析NBT的运作原理、读取方式以及`Minecraft BE`如何应用它其详细程度远超你在命令中接触的NBT表象。
## NBT标签与数据类型
与JSON类似NBT具备类型识别系统。例如JSON通过`{}`符号识别复合对象,通过`"`识别字符串。要理解NBT需要掌握复合对象的起始标记和各类型的读取方式。
NBT基于二进制操作最小单位为8位字节。各类型占用固定字节数不存在半字节情况。注意类型名称可能有不同叫法但二进制标识符ID始终由1字节表示。
| 名称 | 二进制ID | 二进制大小 | 描述 |
| :----------------: | -------: | :--------------- | :------------------------------------------------------------------------------------------------------------------------------- |
| 字节 | 0x01 | 1字节8位 | 单字节类型 |
| Int16短整型 | 0x02 | 2字节16位 | 双字节类型 |
| Int32整型 | 0x03 | 4字节32位 | 四字节类型 |
| Int64长整型 | 0x04 | 8字节64位 | 八字节类型 |
| 浮点 | 0x05 | 4字节32位 | 常规精度浮点数 |
| 双精度 | 0x06 | 8字节64位 | 高精度浮点数 |
| 字符串 | 0x08 | 预定义长度 | UTF-8编码文本前接2字节长度标识 |
| 列表 | 0x09 | 预定义长度 | 元素类型统一前接4字节元素数量 |
| 复合标签 | 0x0A (10)| 未定义长度 | 通过遍历键值对读取,直到遇到结束标记 |
| 复合标签结束标记 | 0x00 | 0字节 | 仅作为复合标签结束标识 |
| 字节列表 | 0x07 | 预定义长度 | 基岩版不常用 |
| 整型列表 | 0x0B (11)| 预定义长度 | 基岩版不常用 |
| 长整型列表 | 0x0C (12)| 预定义长度 | 基岩版不常用 |
注意NBT没有布尔类型需用字节类型的1/0表示true/false。
## NBT标签读写方法
所有数值类型按字节长度读取,基岩版采用[小端序](#小端序)编码与Java版的大端序相反。
### 类型读取
始终读取1字节确定后续数据类型。
### 数值读取
根据类型确定字节数如类型3读取4字节。所有数值使用[小端序](#小端序)处理。
### 字符串读取
先读取2字节长度标识Int16再按对应字节数读取UTF-8编码内容。
### 列表读取
1. 读取列表元素类型1字节
2. 读取元素数量Int324字节
3. 按数量循环读取元素
注意:字节列表/整型列表/长整型列表的读取方式不同
### 复合标签读取
1. 读取类型标记:
- 0x00结束读取
- 其他类型:继续读取键值对
2. 读取键名字符串
3. 读取对应类型值
## 基岩版NBT文件解析
注意文件开头的[基岩版NBT文件头](#基岩版nbt文件头),如`.mcstructure`文件无此头而`level.dat`有。根元素需作为匿名属性处理(即使键名为空)。
::: code-group
```json [.mcstructure示例]
"":{
"format_version":1,
"size":[],//...
"structure":{},//...
"structure_world_origin":[]//..
}
```
:::
:::warning
此示例表明即使根元素键名通常为空,仍需进行读取操作。
:::
## NBT写入规范
写入流程与读取逆向操作,需先掌握读取原理。
## 基岩版NBT文件头
包含两个4字节数值
1. 固定值80x08000000
2. NBT结构体字节数不含头部的8字节
示例:
- `08 00 00 00` - `bf 00 00 00`
- <固定值8> <NBT结构体大小>
## 小端序
数字按字节逆序存储的编码方式:
- Int16 `0x5a72` → 字节数组 `[0x72, 0x5a]`
- Int64 `0x11223344aabbccdd` → 存储为 `dd cc bb aa 44 33 22 11`
读取时反向转换即可还原数值。单字节类型不受影响。