Tutorial:SNBT:修订间差异

来自Minecraft Wiki
跳转到导航 跳转到搜索
添加的内容 删除的内容
第127行: 第127行:
|}
|}


=== 数据 ===
== 数据 ==
==== 字符串 ====
=== 字符串 ===
字符串可以作为一种数据。定义如前文所示。
字符串可以作为一种数据。定义如前文所示。


=== 数字 ===
定义整数数值为所有10个阿拉伯数字符号以及{{cd|+}}和{{cd|-}}构成的序列,则有:
SNBT数字的格式可以概括为一个数值和一个类型的英文首字母组合而成。

数字的基本符号构成为:所有10个阿拉伯数字符号以及{{cd|+}}和{{cd|-}}。


==== 字节型 ====
==== 字节型 ====
: 旧版格式:<整数数值> <数值类型尾缀>
{|

|
: 1.21.5新格式:<整数前缀> <整数数值> <s或S或u或U> <数值类型尾缀>
{| class="wikitable" style="text-align:center;"

! SNBT示例
; SNBT示例
| colspan="2" {{snbt|bg=table|<nowiki>1b</nowiki>}}
由于字节的英文为Byte,故带有尾缀b。所以其最简单的形式如下:
|-
{{snbt|bg=block|<nowiki>1b</nowiki>}}
! 符号元

| <整数数值> || <数值类型尾缀>
以上是一个十进制有符号数。与之等价的形式为:
{| style="margin: 0 auto;"
|{{snbt|bg=block|<nowiki>+1B</nowiki>}}
|{{snbt|bg=block|<nowiki>+1b</nowiki>}}
|}
|}
显然,类型尾缀不论大小写均可。且默认符号为正。
| +

|
在1.21.5以后,可以指定整数的计算机存储形式——有符号或无符号。(十六进制、有符号数):
{| class="wikitable" style="text-align:center;"
{{snbt|bg=block|<nowiki>0xA3sb</nowiki>}}
! SNBT示例
“有符号”即英文“Signed”,即这里后缀中的“s”。
| colspan="4" {{snbt|bg=table|<nowiki>0x123ub</nowiki>}}

|-
注意,如果你要使用十六进制数表示字节型数据,必须显式指定“u”或“s”。因为十六进制数中使用A、B、C、D、E、F来分别代表十进制数10、11、12、13、14、15,所以如果你写为:
! 符号元
{{snbt|bg=block|<nowiki>0xA3b</nowiki>}}
| <整数前缀> || <整数数值> || <s或S或u或U> || <数值类型尾缀>

|}
以上数字末尾的小写b不会被判定为字节型尾缀,而是会被视作十六进制数“B”。
|}

* 整数数值必须在字节型范围内,否则转换为字符串。
在使用二进制时,由于默认是有符号数,所以最大只能允许7个比特位:
* 数值类型尾缀取其英文单词的首字母,即b(大小写均可)。
{{snbt|bg=block|<nowiki>0b1111111sb</nowiki>}}
*; 25w09a/1.21.5新增定义:

** 不允许全纯{{cd|0}}开头。
什么?Byte不是8位元组吗?显然,第一个比特位用以表示正负。当第一个比特位为1时表示“负”,为0则为“正”。为了显式定义符号,你可以加上一个“u”以定义为无符号(Unsigned)数:
** 允许有符号或无符号形式。
{{snbt|bg=block|<nowiki>0b11111111ub</nowiki>}}
** 允许十六进制形式,但必须搭配Signed或Unsigned标识。{{cd|0xAsb|0x1Fub|d=pretty}}

** 允许二进制形式。{{cd|0b1011b}}
以上二进制数被计算机读取后会以补码形式转换为十进制数“-1”。什么是补码?很简单,如果符号为正,那么就和普通的二进制数一样。但如果符号为负,那么之后的7个比特位都要“取反并+1”。
** 整数数值允许使用下划线分割以提高可读性。{{cd|0b1_0000001ub}}

** 超出数值范围后不会转换为字符串。
显然,补码是一种特殊的二进制序列,其正数和负数“互补”。比如,{{cd|0b11111111ub}}(十进制数-1)和{{cd|0b00000001ub}}(十进制数1)直接按位相加后为0——多出的第9位进位不会被计算在内,因为他超出了单个Byte的表示范围,即“溢出”。但是,有一个数比较特殊:{{cd|0b10000000ub}},它表示十进制数-128。这是因为,{{cd|0b10000000ub}}和{{cd|0b00000000ub}}如果都表示十进制数0,则不好统一处理。所以不妨将{{cd|0b10000000ub}}指定为一个更大的负数——这样还能扩大所表示的范围。

为了更方便阅读,你可以使用{{cd|_}}将其进行分割。以下使用下划线将符号位和数值位进行了分隔:
{{snbt|bg=block|<nowiki>0b1_0000000ub</nowiki>}}

这仍能使得命令正常解析。

既然可以表示二进制、十六进制,那么可不可以表示8进制?

目前SNBT还未支持8进制整数格式。而在常见的软件编程中,八进制整数可能以“0”开头。为了避免歧义,以及方便之后更好地扩充功能,1.21.5之后不允许整数直接带有前导0。

另外,在1.21.5以后,如果的数值超出了类型所规定的上限也会直接出错,而不是像旧版本一样转换为字符串。比如:
{{snbt|bg=block|<nowiki>10000b</nowiki>}}

将输出:
{{chat text|{{mcfont|&c解析数字失败:Value out of range. Value:"1000" Radix:10}}}}


特殊形式:
特殊形式:
第250行: 第273行:
** 浮点数数值允许使用下划线分割以提高可读性。{{cd|1_000_000.000_1d}}
** 浮点数数值允许使用下划线分割以提高可读性。{{cd|1_000_000.000_1d}}


==== 结构体 ====
=== 列表 ===
{| class="wikitable" style="text-align:center;"
! SNBT示例
| colspan="7" {{snbt|bg=table|<nowiki>{name: "1", number: 120}</nowiki>}}
|-
! 符号元
|| { || <标签1> || , || <标签2> || , || <...> || }
|}
{| class="wikitable" style="text-align:center;"
! SNBT示例
| colspan="2" {{snbt|bg=table|<nowiki>{}</nowiki>}}
|-
! 符号元
|| { || }
|}

==== 列表 ====
{| class="wikitable" style="text-align:center;"
{| class="wikitable" style="text-align:center;"
! SNBT示例
! SNBT示例
第286行: 第293行:
|}
|}


==== 数组 ====
=== 数组 ===
{| class="wikitable" style="text-align:center;"
{| class="wikitable" style="text-align:center;"
! SNBT示例
! SNBT示例
第306行: 第313行:
** 符号元{{cd|[<数组类型标识>;}}被拆分:{{cd|[|<数组类型标识>|;|d=pretty}}
** 符号元{{cd|[<数组类型标识>;}}被拆分:{{cd|[|<数组类型标识>|;|d=pretty}}
** 数据的类型不必严格一致,但必须都为整数,且小于所在数组类型的数值上限。允许{{cd|[I ;, 1, 2b, 3]}}但不允许{{cd|[I; 1L, 2, 3]}}
** 数据的类型不必严格一致,但必须都为整数,且小于所在数组类型的数值上限。允许{{cd|[I ;, 1, 2b, 3]}}但不允许{{cd|[I; 1L, 2, 3]}}

=== 标签复合体 ===
{| class="wikitable" style="text-align:center;"
! SNBT示例
| colspan="7" {{snbt|bg=table|<nowiki>{name: "1", number: 120}</nowiki>}}
|-
! 符号元
|| { || <标签1> || , || <标签2> || , || <...> || }
|}
{| class="wikitable" style="text-align:center;"
! SNBT示例
| colspan="2" {{snbt|bg=table|<nowiki>{}</nowiki>}}
|-
! 符号元
|| { || }
|}


=== 标签 ===
=== 标签 ===

2025年3月9日 (日) 07:12的版本

本文章所述内容仅适用于Java版

本文主要内容为SNBT的书写规则。

基本概念

符号

SNBT由一系列的基本符号构成,这些符号均为半角英文字符。

界限符号

界限符号分界符号即表示一个语义部分边界的符号,可简称为界符

  • []
  • {}
  • ,
  • "'
  • \
其他符号
  • 26个英文小写字母和大写字母、10个阿拉伯数字
  • 空白符
  • 剩余常见的Minecraft可输入和可显示的字符

以上符号即SNBT中所用到的所有基本符号。需要注意的是,中文的逗号、引号等与以上所示的英文逗号、引号等是不同的符号。相应地,所对应的全角字符也是不同的字符。

另外,对于SNBT所允许的其他符号,本文并不讨论那些不被原版Minecraft所支持的字符,包括无法输入到游戏的字符或无法被游戏正常读取或显示的字符。

符号元

符号元是一个包含一系列符号的具有独立意义的整体。

映射表

映射表(Map)中可存在多个键值对。

映射表可以用一个表格来表示:

a b c
1 2 3

这个表格中,表头代表“键”。第二行代表所对应的“值”。

映射表只要保证键相同,且键对应的值相同,则两映射表就相同。例如以下的映射表和上文映射表是相同的:

b c a
2 3 1

在同一个映射表中,每个键都是唯一的。例如以下的映射表是不存在的:

a a a
1 2 3

列表

列表(List)只是单纯地列出同类数据:

1 2 3

列表中的每个元素都具有潜在顺序,故以下是一个不同的列表:

3 2 1

NBT的符号化

NBT的结构是对若干个标签的组合和嵌套。在对NBT进行符号化的过程中也必须以此为核心。

以下是基于符号元的SNBT定义:

字符串

定义字符串内容为所有Minecraft可允许输入和显示的字符,则有:

SNBT示例(作为数据时)
"你好 minecraft wiki"
SNBT示例(作为标签名时) "minecraft:lore"
符号元 <字符串开始符> <字符串内容> <字符串结束符>
  • 字符串内容左右要么同时为双引号,要么同时为单引号。
  • 若字符串开始和结束符都为",则对字符串内容中的每一个",必须保证其前一个字符为转义符\
  • 若字符串开始和结束符都为',则对字符串内容中的每一个',必须保证其前一个字符为转义符\
  • 对于字符串内容中的每一个\,必须保证其前一个字符为转义符\
    25w09a/1.21.5新增定义:
    • 可使用特定形式的Unicode转义序列。示例:\x12(2位16进制转义)、\u1234(4位16进制转义)、\U12345678(8位16进制转义)、\N{Snowman}(命名Unicode字符)。
    • 内置空白符转义序列:\b、​\s、​\t、​\n、​\f\r
  • 对于有名标签,字符串内容即标签名。

若字符串内容仅包含:

  • 0123456789:数字0到9。
  • abcdefghijklmnopqrstuvwxyz:小写英文字母a到z。
  • ABCDEFGHIJKLMNOPQRSTUVWXYZ:大写英文字母A到Z。
  • +:加号。
  • -:减号。
  • .:点号。
  • _:下划线。
    25w09a/1.21.5新增定义:
    • 且还必须满足:字符串内容以英文字母开头。

则可简化为:

SNBT示例(作为数据时) tob
SNBT示例(作为标签名时) Count
符号元 <字符串内容>

数据

字符串

字符串可以作为一种数据。定义如前文所示。

数字

SNBT数字的格式可以概括为一个数值和一个类型的英文首字母组合而成。

数字的基本符号构成为:所有10个阿拉伯数字符号以及+-

字节型

旧版格式:<整数数值> <数值类型尾缀>
1.21.5新格式:<整数前缀> <整数数值> <s或S或u或U> <数值类型尾缀>
SNBT示例

由于字节的英文为Byte,故带有尾缀b。所以其最简单的形式如下:

1b

以上是一个十进制有符号数。与之等价的形式为:

+1B
+1b

显然,类型尾缀不论大小写均可。且默认符号为正。

在1.21.5以后,可以指定整数的计算机存储形式——有符号或无符号。(十六进制、有符号数):

0xA3sb

“有符号”即英文“Signed”,即这里后缀中的“s”。

注意,如果你要使用十六进制数表示字节型数据,必须显式指定“u”或“s”。因为十六进制数中使用A、B、C、D、E、F来分别代表十进制数10、11、12、13、14、15,所以如果你写为:

0xA3b

以上数字末尾的小写b不会被判定为字节型尾缀,而是会被视作十六进制数“B”。

在使用二进制时,由于默认是有符号数,所以最大只能允许7个比特位:

0b1111111sb

什么?Byte不是8位元组吗?显然,第一个比特位用以表示正负。当第一个比特位为1时表示“负”,为0则为“正”。为了显式定义符号,你可以加上一个“u”以定义为无符号(Unsigned)数:

0b11111111ub

以上二进制数被计算机读取后会以补码形式转换为十进制数“-1”。什么是补码?很简单,如果符号为正,那么就和普通的二进制数一样。但如果符号为负,那么之后的7个比特位都要“取反并+1”。

显然,补码是一种特殊的二进制序列,其正数和负数“互补”。比如,0b11111111ub(十进制数-1)和0b00000001ub(十进制数1)直接按位相加后为0——多出的第9位进位不会被计算在内,因为他超出了单个Byte的表示范围,即“溢出”。但是,有一个数比较特殊:0b10000000ub,它表示十进制数-128。这是因为,0b10000000ub0b00000000ub如果都表示十进制数0,则不好统一处理。所以不妨将0b10000000ub指定为一个更大的负数——这样还能扩大所表示的范围。

为了更方便阅读,你可以使用_将其进行分割。以下使用下划线将符号位和数值位进行了分隔:

0b1_0000000ub

这仍能使得命令正常解析。

既然可以表示二进制、十六进制,那么可不可以表示8进制?

目前SNBT还未支持8进制整数格式。而在常见的软件编程中,八进制整数可能以“0”开头。为了避免歧义,以及方便之后更好地扩充功能,1.21.5之后不允许整数直接带有前导0。

另外,在1.21.5以后,如果的数值超出了类型所规定的上限也会直接出错,而不是像旧版本一样转换为字符串。比如:

10000b

将输出:

解析数字失败:Value out of range. Value:"1000" Radix:10

特殊形式:

SNBT示例
true
符号元 <true或false>
  • true用于等价表示1b,false用于等价表示0b。

整型

SNBT示例
123
符号元 <整数数值>
+
SNBT示例
12345uI
符号元 <整数前缀> <整数数值> <s或S或u或U> <数值类型尾缀>
  • 整数数值必须在整型范围内,否则转换为字符串。
    25w09a/1.21.5新增定义:
    • 不允许全纯0开头。
    • 允许有符号或无符号形式。
    • 允许十六进制形式。0xABCD0xabcd
    • 允许二进制形式。0b1011
    • 整数数值允许使用下划线分割以提高可读性。0xF_A_B_C
    • 超出数值范围后不会转换为字符串。

长整型、短整型

SNBT示例
123456789L
符号元 <整数数值> <数值类型尾缀>
+
SNBT示例
12345sL
符号元 <整数前缀> <整数数值> <s或S或u或U> <数值类型尾缀>
  • 整数数值必须在长整型(若类型尾缀为L)、短整型范围内(若类型尾缀为s),否则转换为字符串。
  • 数值类型尾缀取其英文单词的首字母,长整型为L,短整型为s(大小写均可)。
    25w09a/1.21.5新增定义:
    • 不允许全纯0开头。
    • 允许有符号或无符号形式。
    • 允许十六进制形式。0xABCD0xabcd
    • 允许二进制形式。0b1011
    • 整数数值允许使用下划线分割以提高可读性。1_000_000_000_000L
    • 超出数值范围后不会转换为字符串。

对整数数值进行扩充,定义带小数点.以及E的整数数值为浮点数数值,则有:

浮点数

SNBT示例 1E-21f
SNBT示例
0.032d
符号元 <浮点数数值> <数值类型尾缀>
  • 数值类型尾缀为f或d(大小写均可)
    25w09a/1.21.5新增定义:
    • 指数标识大小写均可。1E-211e-21
    • 浮点数数值允许使用下划线分割以提高可读性。1_000_000.000_1d

列表

SNBT示例
[1, 2, 3, 4, 5]
符号元 [ <数据1> , <数据2> , <...> ]
  • 列表中的所有数据的类型必须一致,也即,必须使用同一种符号元来表示。
    25w09a/1.21.5新增定义:
    • 允许列表内数据类型不同。[1, "", {"text":"123"}]
SNBT示例
[]
符号元 [ ]

数组

SNBT示例
[I; 1, 2, 3]
符号元 [<数组类型标识>; <数据1> , <数据2> , <...> ]
SNBT示例
[I;]
符号元 [<数组类型标识>; ]
  • 数组类型标识:只能为I(整型数组)或L(长整型数组)或B(字节型数组)。
  • 数组中的所有数据的类型必须一致,也即,必须使用同一种符号元来表示,且必须为数组类型标识所标定的类型。
    25w09a/1.21.5新增定义:
    • 符号元[<数组类型标识>;被拆分:[、​<数组类型标识>;
    • 数据的类型不必严格一致,但必须都为整数,且小于所在数组类型的数值上限。允许[I ;, 1, 2b, 3]但不允许[I; 1L, 2, 3]

标签复合体

SNBT示例
{name: "1", number: 120}
符号元 { <标签1> , <标签2> , <...> }
SNBT示例
{}
符号元 { }

标签

有名标签
SNBT示例
components: {"minecraft:custom_name": "example"}
符号元 <字符串> : <数据>
无名标签
SNBT示例
{name: "Wit Pig", Age: 14324}
符号元 <数据>

SNBT的渲染

游戏内对SNBT的各语义部分渲染不同颜色:

  • 将作为标签名的“字符串内容”渲染为
     亮蓝色。
  • 将不作为标签名的“字符串内容”渲染为
     亮绿色。
  • 将“数值”渲染为
     金色。
  • 将“数值类型后缀”和“数组类型标识”渲染为
     红色。
  • 将界符渲染为
     白色。

展开形式

由于SNBT各符号元之间可以插入任意数量的空白符,所以允许SNBT表示为带缩进的类JSON形式:

{
  type: "block",
  block_state: {
    Name: "grass_block",
    Properties: {
      snowy: 1b
    }
  }
}

wiki树状图

单数据类型标签

对于有名标签,定义为:

符号元 任意类型 <标签名> <对该标签含义或数据的描述>

对于无名标签,定义可以为:

符号元 任意类型 <对该标签含义或数据的描述>

以上的符号元表示中,为了方便起见,任意类型图标也被描述为一种符号。

一般情况下,任意类型图标代表该标签的数据可以写为前文所定义的任意数据的形式。相应图标所对应数据的符号元规则为:

多数据类型标签

有时候,标签的数据可能不止一种写法,所以标签名前会有多个图标:

符号元 任意类型任意类型<...> <标签名> <对该标签含义或数据的描述>
符号元 任意类型任意类型<...> <对该标签含义或数据的描述>

需要注意的是,多数据类型需要分别考虑不同类型的数据。对于数值型标签、字符串标签,无需考虑与之相连的子标签(因为它们都不可能具有子标签)。但对于复合标签、列表、数组等,可能还需根据自身类型和周围的提示信息来选择合适的分支和子标签。

树状图的SNBT表示

若页面说明了某树状图可表示为SNBT,则该树状图即§ 展开形式的SNBT。在书写与树状图对应的SNBT时,可以参照如下方法:

  1. 将图标和标签名(字段)的位置调换。
  2. 若某节点不仅有图标,还有标签名,则该节点代表一个字符串和标签形成的键值对,其父节点一定是一个复合标签。
  3. 若某节点仅为一个图标,则该节点就代表一个标签(数据),其父节点一定是一个数组或列表。

树状图示例:

  • NBT复合标签/JSON对象
    • 单精度浮点数log
    • NBT列表/JSON数组ts
      • 双精度浮点数

调换后:

  • NBT复合标签/JSON对象
    • log 单精度浮点数
    • ts NBT列表/JSON数组
      • 双精度浮点数

压缩后的SNBT示例:

{log: 1.0f, ts: [1.0d, 2.0d, 3.0d]}

可选性

当你使用SNBT来配置数据时,有些标签是必须写明,而有些是可有可无的。

在树状图的节点图标右侧,默认没有任何标注,即代表该标签(字段)是可选的。如果标注了红色星号,则代表必选。

树状图示例:

  • NBT复合标签/JSON对象
    • 单精度浮点数log
    • NBT列表/JSON数组*ts
      • 双精度浮点数

SNBT示例:

{log: 1.0f, ts: [1.0d, 2.0d, 3.0d]}
{ts: []}

不允许:

{log: 1.0f}

使用

实体数据格式
execute if entity @s[nbt={SelectedItem:{id:'minecraft:stick',count:1}}]
  • 检测执行者主手是否持有1根木棍。
data merge entity @n[type=minecraft:sheep] {Color:1}
  • 修改最近一只绵羊的颜色为橙色。
物品修饰器
item modify entity @s weapon.mainhand {function:'set_count', count:1, add:true}
  • 为执行者主手所持物品的数量加1。
物品堆叠组件
give @p minecraft:stick[minecraft:custom_data={my_name:'minecraft wiki', '金箍棒': true}]
  • 给予最近玩家一个带有自定义数据{my_name:'minecraft wiki', '金箍棒': true}的木棍。
谓词
execute if predicate {condition:'time_check', value:{min:13000}, period:24000}
  • 判断当前维度的时间是否在夜晚night过后。

导航