1 NBT 格式
NBT, 全称Named Binary Tag, 是一种二进制文件格式, 用作储存Minecraft的游戏资料。
这类型档案的后缀一般为.dat(MC文件里, 其他软件的.dat文件用的绝对是别的格式...)
要打开NBT档案, 一般需要特殊软件/库, 以下有一个普遍认为比较好的软件, 及一个python的nbt库
- NBTExplorer 一个挺常用的软件。
当然, 我们这是浅谈命令, 自然不是说NBT文件格式了...
命令里的NBT, 讲的是是另外一种格式, 在下面会详细说明。
命令里的NBT能够修改实体(玩家除外)、方块的某些属性, 也能够检查实体(包括玩家)、方块的某些属性是否符合要求。
每个标签的格式如下:
标签名称:值(list里的标签没有标签名称, 只有值)
每个标签之间用逗号(,)相隔,比如
{NoGravity:1b,Invisible:1b}
NoGravity:1b就是一个标签,而NoGravity就是标签的名称,1b就是其值
Invisible:1b就是另一个标签,Invisible就是标签的名称,1b就是其值
1.1 数值类
1.1.1 TAG_Byte
例子:1b
这个是代表什么呢?这个是用作储存数值用的。它能够储存的数值范围为-128 至 127。这个除了能够储存数值之外,它也能够储存Boolean值(True/False),这个时候它的范围为0 (False)和1 (True)。
使用的时候需要注意一点,当你用在检测的指令上(比如testfor和scoreboard),数值后需要补上b字来指明它那个数值是Byte
1.1.2 TAG_Short
例子:1s
这个也是储存数值用,数值的范围为-32,768 至 32,767。
使用的时候需要注意一点,当你用在检测的指令上(比如testfor和scoreboard),数值后需要补上s字来指明它那个数值是Short
1.1.3 TAG_Int
例子:1
这个也是储存数值用,数值的范围为-2,147,483,648 至 2,147,483,647。
使用的时候需要注意一点,就是数值后不能补上i字
1.1.4 TAG_Long
例子:0l
这个也是储存数值用,数值的范围为-9,223,372,036,854,775,808 至 9,223,372,036,854,775,807。
使用的时候需要注意一点,当你用在检测的指令上(比如testfor和scoreboard),数值后需要补上l字来指明它那个数值是Long
1.1.5 TAG_Float
例子:1.0f
只有这个和Double可以储存小数。其最大值也比long大得多,然而它的精确度会随着数值的大小而变化(绝对值越大,它的精确度就越小)。可以使用科学记数法,如5.3e-3
。可以弄无限,数值为3.5e38f
数值后需要补上f字来指明它那个数值是float。
1.1.6 TAG_Double
例子:1d
只有这个和Float可以储存小数。其最大值也比long大得多,然而它的精确度会随着数值的大小而变化(绝对值越大,它的精确度就越小)。
如果你的数值里有小数点,那么就默认为double,可以不写d字在数值之后,然而如果没有小数点,就需要写d在数值后面以标明是double。可以使用科学记数法,如5.3e-3
。可以弄无限,数值为1.8e308
当你用在检测的指令上(比如testfor和scoreboard),数值后需要补上d字来指明它那个数值是double
1.1.7 TAG_Int_Array
例子:[I;123,456]
注意: 前面必须为 I;
Int_Array只能储存Int,不能储存其他数值
Int_Array检测的时候是检测整个数值的,而List检测的时候可以只检测某几个子标签,比如玩家手上有一个烟花,这个时候玩家的NBT应该是
{SelectedItem:{tag:{Fireworks:{Explosions:[{Type:1b,Colors:[I;7599255,62976]}]}}}}
(Colors就是一个Int_Array)
如果我们只是把Colors:[I;7599255,62976]换为Colors:[I;7599255]
它的结果是不符合的(因为Colors括号里的是其数值而不是其子标签)
1.1.8 Tag_Byte_Array
例子:[B;123b,2b]
注意: 前面必须为 B;
和Int_Array类似,只能储存byte,不能储存其他数值。
检查时也是检查整个数值的,而不是某几个子标签。
1.2 字符
1.2.1 TAG_String
例子:
- "armor_stand"
- armor_stand
这个类型可以储存字串, 不一定需要""包围。
然而要小心,如果字串内有非a-z A-Z . _ + -
的字符,如空格、逗号等,就需要用"把整个字串括住,而里面的字符需要转义。
字串需要转义
转义的方法是:每个\符号前方要加上一个\符号,"符号之间的每个"符号前方也要加上一个\符号
所以"""
转义后会变成"\""
,再转义会变成"\\\""
,再转义就会变成"\\\\\\\""
1.3 母标签类
List和Compound可以互相堆叠, 然而堆叠层数不能超过512层...
1.3.1 TAG_List
这个是一个母标签的类型,它的子标签的类型全部都是相同的丶没有标签名称并且会被一个[]括住。
例子:
Items:[{id:"minecraft:stone",Count:1b},{id:"minecraft:glass",Count:1b}]
Items就是一个List类型的NBT,而{id:"minecraft:stone",Count:1b}和{id:"minecraft:glass",Count:1b}就是其子标签(id和Count并不算是其子标签!!!),在这个例子里,其子标签的类型就是Compound。
这个类型相当特别,你可以检测其中的一/几个子标签,比如你检测Items:[{id:"minecraft:glass",Count:1b}],它的输出是成功的。
然而,当你更改List的子标签时,它会把所有的子标签更新(覆盖)。比如说你用blockdata把那个箱子的NBT更改为Items:[{id:"minecraft:glass",Count:2b}],那个箱子里的石头会被删除。
(如果你用entitydata得到他的NBT,你应该会看见类似的东西: 标签名:[0:值1,1:值2,2:值3]之类的东西,其实那个0/1/2就是个编号,大可以忽略它,因为你不能只改变某个编号的值,也不能只探测某个特定编号的值)
注意: 现在list前方不能够有key([key:value,key:value]),否则会出现错误。(以前key会被忽略)
此外, 检测[]就能检测空list标签(一旦里面有任何子标签, 则不会成功)
1.3.2 TAG_Compound
例子:{id:"ArmorStand"}
这个也是一个母标签的类型,其子标签需要用{}括住,并且需要有标签名称。比如Riding:{id:"ArmorStand",CustomName:"AS1",Riding:{id:"ArmorStand",CustomName:"AS2"}}。
标签名称如果出现非a-z A-Z . _ + -
的字符,如minecraft:stone
,就需要使用""括住。如"minecraft:stone":"value。
注意, 标签名称、子标签也可以有多余空格, 比如 { abcd : cdefg }。
命令执行时会自动清除那些空格, 上方的例子就和{abcd:cdefg}等价。
你能够只检测/修改Compound里的一个子标签, 只需要填写它们的名称就可以了。
然而这也代表了你无法删除Compound里的任何标签。
Compound和List的最大分别(在NBT里)是List无法透过命令独立变更其中的子标签的值,而Compound则可以。
1.4 获取方块/实体(非玩家)NBT
1.4.1 实体
我们可以透过
/entitydata <指定的实体> {}
来得到那个实体的NBT
比如
/entitydata @e[c=1,type=!Player] {}
1.4.2 方块
我们可以透过
/blockdata <x> <y> <z> {}
来得到其NBT
比如
/blockdata ~ ~-1 ~ {}
那个输出会有一行"The data tag did not change:",然后就是那些NBT
当然,在聊天栏看是比较辛苦的,我们可以把这个命令放在命令方块里激活,然后ctrl a 那个输出栏,然后再ctrl c复制那个输出,之后放在一个你觉得方便的文字编辑器那里,比如记事本等
1.5 阅读NBT文档
使用NBT, 我们需要知道那标签的用途以及格式。
而描述标签的用途和格式的文件, 就是NBT文档了。
本教程里会提供一些NBT的文档。
然而版本更新后, 本教程里的文档或许会不够详尽, 那时候就需要到wiki查阅了。
wiki链接:
1.5.1 NBT树状图简介
树状图格式如下:
- 母标签a
- 母标签b
- 子标签c
- 子标签d
- 子标签e
- 母标签b
b和e就是a的子标签。c和d就是b的子标签。
一般来说树状图标签前面会有一个图标, 代表该标签的类型。
把鼠标放在上方就能查看其类型了(看得多了也能直接从图标查看其类型)。
1.5.2 Compound
如果那个母标签的类型是compound,那么它的子标签就是它能够包括的标签
- Pose
- Body
- x-角度
- y-角度
- z-角度
- LeftArm
- x-角度
- y-角度
- z-角度
- RightArm
- x-角度
- y-角度
- z-角度
- LeftLeg
- x-角度
- y-角度
- z-角度
- RightLeg
- x-角度
- y-角度
- z-角度
- Head
- x-角度
- y-角度
- z-角度
- Body
以命令NBT的写法(缩排和分行是为了方便阅读, 实际上命令是不会有分行和缩排的。而且也没必要写那么多, 对compound来说), 就是
Pose:{
Body:[<x角度>d,<y角度>d,<z角度>d],
LeftArm:[<x角度>d,<y角度>d,<z角度>d],
RightArm:[<x角度>d,<y角度>d,<z角度>d],
LeftLeg:[<x角度>d,<y角度>d,<z角度>d],
RightLeg:[<x角度>d,<y角度>d,<z角度>d],
Head:[<x角度>d,<y角度>d,<z角度>d]
}
1.5.3 List
对于List来说, 有两种情况。
(i) 固定子标签
- Head
- x-角度
- y-角度
- z-角度
这里就是一个例子。
Head:[a,b,c]
a代表x角度, b代表y角度, c代表z角度
里面不同位置的子标签有不同含义
(ii) 不固定子标签
- Tags
- a tag(一个标签)
NBT: Tags:["一个标签","第二个标签","第三个标签"]
每次看见a xxxx(一个 xxx),就代表里面子标签的数量是不固定的, 而且子标签的顺序不是太重要(船的Passengers除外, 那牵涉到实体的位置)
1.6 特殊NBT种类
1.6.1 认读的nbt
就是只能检测, 修改了没用的nbt。
例子: OnGround
1.6.2 未必存在的nbt
当不需要它的时候, 它未必存在(事实上很多nbt都是这样)
例子: 物品的Slot标签
1.6.3 只能在出生时设定的nbt
就是出生后或许会消失, 或许修改后没用的nbt
例子: Passengers, UUIDLeast, UUIDMost, id
1.7 常见格式
1.7.1 实体格式
- 一个compound
- id: 实体id, 决定实体种类, 如minecraft:ArmorStand
- ...(其他tag)
例子:
{id:"minecraft:ArmorStand",NoGravity:1b}
1.7.2 物品格式
- 一个compound
- id: 物品id, 决定物品种类, 如minecraft:diamond_sword
- Count: 物品数量
- Slot: 所在物品栏id, 可能不存在
- Damage: 物品损伤值/数据值, 默认为0
- tag: 物品的其他nbt标签, 里面可能有: display, ench等
例子:
{id:minecraft:diamond_sword,Count:1b,Damage:0s,tag:{display:{Name:"sword"}}}
1.8 母标签 Base Tag
在命令里, 我们或许会使用base tag这个词。而在wiki是看不到这个词的, 这是我们定义来方便说明NBT的。
Base tag就是代表该NBT的母标签。我们为不同NBT的母标签根据用途定义名称。
比如说, Count的base tag就是item, ench的base tag就是tag, 如此类推。
详细可以看JSON文件, 里面的格式如下
- <base tag名称>
- type, tag类型(如果是<base tag名称>, 则代表是compound, 内容则见该base tag)
- subtype, 子tag类型, 如果tag类型是list则会出现
- count, 子tag数量, 如果是0则代表不限制, 如果tag类型是list则会出现
1.9 自定义NBT
物品的tag里的nbt可以自定义。
透过自定义nbt, 玩家可以简单地识别特殊物品, 无论该物品在玩家手上还是在掉落物的状态。
自定义nbt需要严格跟从nbt格式, 需要定义其类型, 如test:1b
详细可见: http://www.mcbbs.net/thread-463290-1-1.html