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

5.9 KiB
Raw Permalink Blame History

title, category, mentions, tags
title category mentions tags
NBT深度解析 NBT深度解析
ConsoleTerm
SmokeyStack
ThomasOrs
专家

NBT深度解析

NBT命名二进制标签是一种二进制层级的编码格式正如你熟悉的基于文本层级的JSON格式。因此我们可以用JSON格式举例说明你可能也注意到Minecraft本身在命令中使用JSON来表示NBT如Java版命令或简化的基岩版命令/give/replaceitem)。详见NBT命令。本文将深入解析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文件头,如.mcstructure文件无此头而level.dat有。根元素需作为匿名属性处理(即使键名为空)。

::: code-group

"":{
    "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

读取时反向转换即可还原数值。单字节类型不受影响。