[1.15] 常见的数据操作方法:入门教程
前言
本文基于 Minecraft Java 1.15.2 版本,将主要讲述常见的数据操作方法。
本文的部分内容引用自 Minecraft Wiki,感谢 chyx、Spgoding 两位大佬以及 Spgoding 的 Datapack Helper Plus 和 土球球 的 MCBBS Markdown To BBCode Converter 在本文撰写的过程中提供的帮助。
阅读本文需要一定的命令基础,如无特殊说明,命令皆在玩家的聊天栏内执行,如在阅读过程中发现本文存在错误,请指出。
本文最后一次较大的更新在 2020 年 8 月 9 日。
第一节:键值对、键名 和 键值
data 命令允许执行者获取、合并、修改或移除方块、实体或 storage 的 NBT 数据,在学习 data 命令之前我们要先了解一些与 NBT 数据有关的知识。
例如我们要召唤一只血量为 15.0f、自定义名称为 '"233"'、朝向为 [45.0f,90.0f] 的僵尸。
- summon zombie ~ ~ ~ {Health:15.0f,CustomName:'"233"',Rotation:[45.0f,90.0f]}
在命令中我们可以看到,僵尸的所有数据都被一对 {} 包裹了起来,我们将僵尸的所有数据包括最外面的那一层 {} 叫做 数据标签。
- 在这对 {} 中放了 3 个 元素({} 里的每个元素都是一个 键值对):Health:15.0f、CustomName:'"233"' 和 Rotation:[45.0f,90.0f]。
- 这 3 个键值对之间被我们用 , 隔了开来。
- 一个键值对又被 : 分成了两个部分,左边的部分叫 键名,右边的部分叫 键值,例如:
键值对 键名 键值 Health:15.0f Health 15.0f CustomName:'"233"' CustomName "233" Rotation:[45.0f,90.0f] Rotation [45.0f,90.0f]
而键值又被分为了很多类型,例如:
- Health:15.0f 中的 15.0f 是 float(单精度浮点型)。
- CustomName:'"233"' 中的 '"233"' 是 string(字符串)。
- Rotation:[45.0f,90.0f] 中的 [45.0f,90.0f] 是 list(列表)。
- 列表 [45.0f,90.0f] 中的 2 个元素([] 中的每个元素又是一个新的键值):45.0f 和 90.0f 是 float(单精度浮点型)。
- 列表 [45.0f,90.0f] 中的 2 个元素([] 中的每个元素又是一个新的键值):45.0f 和 90.0f 是 float(单精度浮点型)。
具体见下表:
| 键值的数据类型 |
| 说明 |
| 键值对举例 |
| 字节(byte) |
| 范围在 [-128, 127] 内的整数。 |
| Count:12b |
| 短整型(short) |
| 范围在 [-3 2768, 3 2767] 内的整数。 |
| lvl:3s |
| 整型(int) |
| 范围在 [-21 4748 3648, 21 4748 3647] 内的整数。 |
| HideFlags:63 |
| 长整型(long) |
| 范围在 [-2^63, 2^63-1] 内的整数。 |
| UUIDLeast:233l |
| 单精度浮点型(float) |
| 范围在 [-3.4×10^38, 3.4×10^38] 内的有理数。 |
| Health:15.0f |
| 双精度浮点型(double) |
| 范围在 [-1.7×10^308, 1.7×10^308] 内的有理数。 |
| Pos:[1.2d,3.4d,5.6d] 中的元素 |
| 字符串(string) |
| 一串字符,如果内容包含不在 a-z A-Z 0-9 _ . 内的字符则必须要在整个字符串前后加上一对 "" 或 ''。 |
| id:"minecraft:stone" |
| 列表(list) |
| 值的序列,用 , 分隔并用 [] 包含。 |
| Rotation:[45.0f,90.0f] |
| 复合标签(compound) |
| 键值对的序列,用 , 分隔并用 {} 包含。 |
| display:{Name:'"foo"',Color:233} |
| 字节数组(byte-array) |
| 字节的序列,用 , 分隔并用 [] 包含,首个元素前方需要加入 B;。 |
| ByteArray:[B;1B,2B,3B] |
| 整型数组(int-array) |
| 整型的序列,用 , 分隔内容并用 [] 包含,首个元素前方需要加入 I;。 |
| UUID:[I;12,34,56,78] |
| 长整型数组(long-array) |
| 整型的序列,用 , 分隔内容并用 [] 包含,首个元素前方需要加入 L;。 |
| LongArray:[L;123L,456L,789L] |
| 布尔型(boolean) |
| 只有 true 和 false 两种取值。在 NBT 中,true 和 false 用字节的 1b 和 0b 代替。 |
| Glowing:1b、"Bold":true |
- 数据标签可以看做是一个类型为复合标签的键值。
- 我们可以将每个键值对类比为一个文件,将键值的数据类型为复合标签的键值对类比为一个文件夹,里面可以放其他文件。
- 键名是文件的名称,键值是文件里的内容。
- 和其他数据类型不同的是,列表和数组的 [] 里可以放多个键值。
- 列表和数组里的元素的数据类型必须相同,在列表中,所有元素的数据类型由第一个元素决定,例如:
- 列表 [123,"stone",{}] 是不存在的。
- 列表 [123,"stone",{}] 是不存在的。
- 复合标签和列表可以套娃,例如:
- SelectedItem:{tag:{display:{Name:'"foo"'}}}
- List:[[1,2,3],[4,5,6],[7,8,9]]
- ArmorItems:[{},{},{},{id:"stone",Count:1b}]
- 了解键值的数据类型可以让我们在只有语法的情况下自己写出例子,更好地帮助我们阅读 Wiki 和其他教程。
第二节:数据的获取
还是以第一节中的僵尸为例:
- summon zombie ~ ~ ~ {Health:15.0f,CustomName:'"233"',Rotation:[45.0f,90.0f]}
我们假设 @e[type=zombie,limit=1,sort=nearest] 可以选中该僵尸。
我们使用 data get 命令来获取指定键名的键值对的键值。
- data get entity @e[type=zombie,limit=1,sort=nearest]
- 获取该僵尸的数据标签。
- 获取该僵尸的数据标签。
- data get entity @e[type=zombie,limit=1,sort=nearest] Health
- 获取该僵尸的血量,返回:15.0f。
- 获取该僵尸的血量,返回:15.0f。
- data get entity @e[type=zombie,limit=1,sort=nearest] Health 2
- 获取该僵尸的血量并将结果乘以 2,返回:30。
- 获取该僵尸的血量并将结果乘以 2,返回:30。
- data get entity @e[type=zombie,limit=1,sort=nearest] CustomName
- 获取该僵尸的自定义名称,返回:'"233"'。
- 获取该僵尸的自定义名称,返回:'"233"'。
- data get entity @e[type=zombie,limit=1,sort=nearest] Rotation
- 获取该僵尸的朝向,返回:[45.0f,90.0f]。
- 获取该僵尸的朝向,返回:[45.0f,90.0f]。
实际上,data get entity 命令的语法是这样的:
- data get entity <实体> [<NBT路径>] [<倍率>]
除实体外,data get 命令也可以用于获取方块或 storage 的 NBT 数据。
- 语法:
- data get block <方块坐标> [<NBT路径>] [<倍率>]
- data get storage <storage> [<NBT路径>] [<倍率>]
- 例子:
- data get block ~ ~ ~
- 获取当前所在位置的方块实体的数据标签。
- 获取当前所在位置的方块实体的数据标签。
- data get block ~ ~ ~ CustomName
- 获取当前所在位置的方块实体的自定义名称。
- 获取当前所在位置的方块实体的自定义名称。
- data get block ~ ~ ~ Items[{Slot:0b}].Count 2
- 获取当前所在位置的箱子(或木桶/潜影盒等)里第 1 个槽位的物品的数量并乘以 2。
- 获取当前所在位置的箱子(或木桶/潜影盒等)里第 1 个槽位的物品的数量并乘以 2。
- data get storage foo:example
- 获取 id 为 foo:example 的 storage 的数据标签。
- 获取 id 为 foo:example 的 storage 的数据标签。
- data get block ~ ~ ~
同时有 4 点需要注意:
- data 命令只允许单个实体、方块或 storage,例如,想要获取多个实体的数据,请配合使用 execute as:
- execute as @e[type=zombie] run data get entity @s Health
- 获取所有僵尸的血量。
- 获取所有僵尸的血量。
- execute as @e[type=zombie] run data get entity @s Health
- data get 只接受单个 NBT 值,例如你可以使用 data get 获取 Rotation,但是:
- data get entity @e[type=zombie,limit=1,sort=nearest] Rotation[]
- 直接获取 Rotation 中的所有元素,不行。
- 直接获取 Rotation 中的所有元素,不行。
- data get entity @e[type=zombie,limit=1,sort=nearest] Rotation[0]
- 获取 Rotation 中的第 1 个元素,可以。
- 获取 Rotation 中的第 1 个元素,可以。
- data get entity @e[type=zombie,limit=1,sort=nearest] Rotation[1]
- 获取 Rotation 中的第 2 个元素,可以。
- 获取 Rotation 中的第 2 个元素,可以。
- data get entity @e[type=zombie,limit=1,sort=nearest] Rotation[]
- 倍率只适用于数字标签,例如:
- data get block ~ ~ ~ CustomName 2
- 获取当前所在位置的方块实体的自定义名称并乘以 2,不行。
- 获取当前所在位置的方块实体的自定义名称并乘以 2,不行。
- data get entity @s Health 2
- 获取命令执行者的血量并乘以 2,可以。
- 获取命令执行者的血量并乘以 2,可以。
- data get block ~ ~ ~ CustomName 2
- 使用倍率参数获得的键值的数据类型是整型,例如命令执行者的血量是 15.7f:
- data get entity @s Health
- 返回:15.7f。
- 返回:15.7f。
- data get entity @s Health 1
- 返回:15。
- 返回:15。
- data get entity @s Health 2
- 返回:31。
- 返回:31。
- data get entity @s Health
第三节:数据的移除
我们使用 data remove 命令来移除指定键名的键值对。
同样,data remove 的目标也可以是方块、实体或 storage。
- 语法:
- data remove block <方块坐标> <路径>
- data remove entity <实体> <路径>
- data remove storage <storage> <路径>
- 例子:
- data remove block ~ ~ ~ CustomName
- 移除当前所在位置的方块实体的自定义名称。
- 移除当前所在位置的方块实体的自定义名称。
- data remove block ~ ~ ~ Items[{Slot:0b}]
- 移除当前所在位置的箱子(或木桶/潜影盒等)里第 1 个槽位的物品。
- 移除当前所在位置的箱子(或木桶/潜影盒等)里第 1 个槽位的物品。
- data remove entity @e[type=zombie,limit=1] HandItems[]
- 移除一只僵尸两只手上所持的所有物品。
- 移除一只僵尸两只手上所持的所有物品。
- data remove storage foo:example Stone
- 移除 id 为 foo:example 的 storage 中路径为 Stone 的 NBT 数据。
- 移除 id 为 foo:example 的 storage 中路径为 Stone 的 NBT 数据。
- data remove block ~ ~ ~ CustomName
- 注意:
- data get 只接受单个 NBT 值,但是 data remove 支持多个。
- data remove 中的路径是必填的,例如:data remove block ~ ~ ~ 是未知的命令。
- 有些键值对是移除不了的,例如实体的 Health。
第四节:NBT 路径
怎么写 NBT 路径才能得到想要的键值对的键值是 data 命令中一个常见的问题。
为了方便演示,我们使用 storage 来存储数据。
可以参考:
【CBL|SPG】[1.14] NBT 路径:从入门到胡了
https://github.com/SPGoding/mcbbs-threads/blob/master/tutorials/nbt-path/markdown.md
例 1:一个简单的例子
请看以下过程:
- data get storage foo:example
- 获取 id 为 foo:example 的 storage 的值。
- 每个 storage 一开始都是一个空的复合标签 {}。
- data merge storage foo:example {Dirt:1b}
- 将复合标签 {Dirt:1b} 合并到 storage,类似于文件夹的合并,相同文件名的文件(相同键名的键值对)会被覆盖。
- 将复合标签 {Dirt:1b} 合并到 storage,类似于文件夹的合并,相同文件名的文件(相同键名的键值对)会被覆盖。
- data get storage foo:example
- 再次获取 storage 的值。
- 返回:{Dirt:1b}
- data get storage foo:example Dirt
- 获取键值对 Dirt 的键值。
- 返回:1b
- data remove storage foo:example Dirt
- 移除键值对 Dirt,以确保下一个例子中 storage 是空的。
- 移除键值对 Dirt,以确保下一个例子中 storage 是空的。
为了方便阅读,我们在接下来以一个执行命令的过程为例时,使用以下格式:
- 执行的命令
- 注释
- 命令返回的结果/命令执行后的结果
例 2:套娃
- data merge storage foo:example {Stone:{Dirt:{Grass:1b}}}
- 将复合标签 {Stone:{Dirt:{Grass:1b}}} 合并到 storage。
- 将复合标签 {Stone:{Dirt:{Grass:1b}}} 合并到 storage。
- data get storage foo:example
- {Stone:{Dirt:{Grass:1b}}}
- {Stone:{Dirt:{Grass:1b}}}
- data get storage foo:example Stone
- {Dirt:{Grass:1b}}
- {Dirt:{Grass:1b}}
- data get storage foo:example Stone.Dirt
- {Grass:1b}
- {Grass:1b}
- data get storage foo:example Stone.Dirt.Grass
- 1b
- 1b
- data remove storage foo:example Stone
- 移除键值对 Stone。
- 移除键值对 Stone。
我们可以将每个复合标签 {} 类比为一个文件夹,则我们这次:
- 向 storage 文件夹里放了一个 Stone 文件夹。
- 向 Stone 文件夹里放了一个 Dirt 文件夹。
- 向 Dirt 文件夹里放了一个文件名为 Grass、内容为 1b 的文件。
在 Windows 中,Grass 的路径应该这么写:Stone\Dirt\Grass,就像 .minecraft\saves\<地图名称>\datapacks,但在 NBT 中,要把 \ 改成 .,把 Stone\Dirt\Grass 改成 Stone.Dirt.Grass。
例 3:一个较为复杂的例子
- data merge storage foo:example {Stone:{Dirt:{Grass:1b,Tree:4b},Farmland:{Flower:3b},Ore:5b},Planks:2b}
- 将 NBT 数据存储到 storage 里。
- 将 NBT 数据存储到 storage 里。
你能找出有几个键值对并且判断它们之间的位置关系吗?
为了看起来方便,我们可以像下面一样分多行写。
代码:
- {
- Stone:{
- Dirt:{
- Grass:1b,
- Tree:4b
- },
- Farmland:{
- Flower:3b
- },
- Ore:5b
- },
- Planks:2b
- }
列表如下:
| Stone |
| Dirt |
| Grass:1b |
| Stone |
| Dirt |
| Tree:4b |
| Stone |
| Farmland |
| Flower:3b |
| Stone |
| Ore:5b |
| Planks:2b |
共 8 个键值对,其中有 3 个键值对的键值是复合标签。
- data remove storage foo:example Stone
- 移除键值对 Stone。
- 移除键值对 Stone。
例 4:复合标签内元素的筛选
- data merge storage foo:example {Stone:{Dirt:1b}}
- 将复合标签 {Stone:{Dirt:1b}} 合并到 storage。
- 将复合标签 {Stone:{Dirt:1b}} 合并到 storage。
- data get storage foo:example Stone
- {Dirt:1b}
- {Dirt:1b}
- data get storage foo:example Stone{Dirt:1b}
- 通过添加条件 {Dirt:1b} 对复合标签 Stone 中的元素进行筛选。
- {Dirt:1b}
- data get storage foo:example Stone{Dirt:2b}
- 没有相匹配的元素。
- 没有相匹配的元素。
- data get storage foo:example Stone{}
- {} 表示不设置筛选条件。
- {Dirt:1b}
- data get storage foo:example Stone.Dirt
- 1b
- 1b
- data get storage foo:example Stone{Dirt:1b}.Dirt
- 1b
- 1b
- data merge storage foo:example Stone
- 移除键值对 stone。
- 移除键值对 stone。
使用 Compound{条件} 可以对复合标签中的元素进行筛选,条件为空时表示不设置筛选条件。
例 5:列表
- data merge storage foo:example {Numbers:[1,2,3,4,5]}
- 将复合标签 {Numbers:[1,2,3,4,5]} 合并到 storage。
- 将复合标签 {Numbers:[1,2,3,4,5]} 合并到 storage。
使用不同的路径会得到不同的结果,例如:
- data get storage foo:example Numbers[0]
- 返回:1
- 返回:1
- data remove storage foo:example Numbers[]
- 移除列表 Numbers 里的所有元素。
- 得到:{Numbers:[]}
具体见下表:
| 路径 |
| 结果 |
| 筛选出 |
| 不填 |
| {Numbers:[1,2,3,4,5]} |
| Numbers |
| [1,2,3,4,5] |
| 键值对 Numbers 的键值 |
| Numbers[] |
| 1,2,3,4,5 |
| 列表 Numbers 里所有的元素 |
| Numbers[0] 或 Numbers[-5] |
| 1 |
| 第 1 个 或 倒数第 5 个元素 |
| Numbers[1] 或 Numbers[-4] |
| 2 |
| 第 2 个 或 倒数第 4 个元素 |
| Numbers[2] 或 Numbers[-3] |
| 3 |
| 第 3 个 或 倒数第 3 个元素 |
| Numbers[3] 或 Numbers[-2] |
| 4 |
| 第 4 个 或 倒数第 2 个元素 |
| Numbers[4] 或 Numbers[-1] |
| 5 |
| 第 5 个 或 倒数第 1 个元素 |
- data remove storage foo:example Numbers
- 移除键值对 Numbers。
- 移除键值对 Numbers。
List[] 指列表 List 里所有的元素,List[n] 指列表 Numbers 里第 (n+1) 个元素,List[-n] 指列表 List 里倒数第 n 个元素。
例 6:列表内元素的筛选
- data merge storage foo:example {Items:[{id:"stone",Count:1b},{id:"dirt",Count:2b},{id:"grass",Count:2b}]}
- 将 NBT 数据存储 storage 里。
- 将 NBT 数据存储 storage 里。
| 路径 |
| 结果 |
| 筛选出 |
| 不填 |
| {Items:[{id:"stone",Count:1b},{id:"dirt",Count:2b},{id:"grass",Count:2b}]} |
| Items[] |
| {id:"stone",Count:1b},{id:"dirt",Count:2b},{id:"grass",Count:2b} |
| 列表 Items 里所有的元素 |
| Items[1] |
| {id:"dirt",Count:2b} |
| 第 2 个元素 |
| Items[{}] |
| {id:"stone",Count:1b},{id:"dirt",Count:2b},{id:"grass",Count:2b} |
| 所有数据类型为复合标签的元素 |
| Items[{id:"grass"}] |
| {id:"grass",Count:2b} |
| 所有满足 {id:"grass"} 的元素 |
| Items[{Count:2b}] |
| {id:"dirt",Count:2b},{id:"grass",Count:2b} |
| 所有满足 {Count:2b} 的元素 |
| Items[{id:"grass",Count:2b}] |
| {id:"grass",Count:2b} |
| 设置了 2 个筛选条件 |
| Items[{id:"grass"}].Count |
| 2b |
| Items[{Count:2b}].id |
| "dirt","grass" |
- data remove storage foo:example Items
- 移除键值对 Items。
- 移除键值对 Items。
使用 List[{条件}] 对列表中的元素进行筛选,List[{}] 只能选中数据类型为复合标签的元素。
例 7:数组
数组和列表类似,下面以整型数组为例。
- data merge storage foo:example {Numbers:[I;1,2,3]}
- 将复合标签 {Numbers:[I;1,2,3]} 合并到 storage。
- 将复合标签 {Numbers:[I;1,2,3]} 合并到 storage。
| 路径 |
| 结果 |
| 筛选出 |
| 不填 |
| {Numbers:[I;1,2,3]} |
| Numbers |
| [I;1,2,3] |
| 键值对 Numbers 的键值 |
| Numbers[] |
| 1,2,3 |
| 数组 Numbers 里所有的元素 |
| Numbers[0] 或 Numbers[-3] |
| 1 |
| 第 1 个 或 倒数第 3 个元素 |
| Numbers[1] 或 Numbers[-2] |
| 2 |
| 第 2 个 或 倒数第 2 个元素 |
| Numbers[2] 或 Numbers[-1] |
| 3 |
| 第 3 个 或 倒数第 1 个元素 |
- data remove storage foo:example Numbers
- 移除键值对 Numbers。
- 移除键值对 Numbers。
例 8:几个例子
请看以下过程:
- summon zombie ~ ~ ~ {Attributes:[{Name:"generic.maxHealth",Base:25.0d}],Health:15.0f,Rotation:[45.0f,90.0f],HandItems:[{id:"stone",Count:1b},{}],Tags:["foo"]}
- 召唤一只僵尸。
- 召唤一只僵尸。
- data get entity @e[type=zombie,tag=foo,limit=1] Health
- 获取该僵尸的血量。
- 15.0f
- data get entity @e[type=zombie,tag=foo,limit=1] Rotation[1]
- 获取该僵尸的朝向列表中的第 2 个元素。
- 90.0f
- data get entity @e[type=zombie,tag=foo,limit=1] HandItems[0].id
- 获取该僵尸主手所持物品的 id。
- "stone"
- data get entity @e[type=zombie,tag=foo,limit=1] Attributes[{Name:"generic.maxHealth"}].Base
- 获取该僵尸的血量上限。
- 25.0d
- kill @e[type=zombie,tag=foo]
- 移除该僵尸。
- 移除该僵尸。
单句命令:
- data get entity @s SelectedItem.tag.display.Name
- 获取命令执行者手持物品的自定义名称。
- 获取命令执行者手持物品的自定义名称。
- data remove block ~ ~ ~ Items[{Count:3b}]
- 移除当前所在位置处的箱子(或木桶/潜影盒等)里所有物品数量为 3 的槽位。
- 移除当前所在位置处的箱子(或木桶/潜影盒等)里所有物品数量为 3 的槽位。
- data remove block ~ ~ ~ Items[{id:"minecraft:iron_sword"}].tag.Enchantments[{id:"minecraft:sharpness"}]
- 移除当前所在位置处的箱子(或木桶/潜影盒等)里所有铁剑的锋利附魔。
- 移除当前所在位置处的箱子(或木桶/潜影盒等)里所有铁剑的锋利附魔。
第五节:数据的合并
我们使用 data merge 命令将指定的复合标签合并至方块、实体或 storage 的数据标签,类似于文件夹的合并,相同文件名的文件(相同键名的键值对)会被覆盖。
- 语法:
- data merge block <方块坐标> <nbt>
- data merge entity <实体> <nbt>
- data merge storage <storage> <nbt>
- 例子:
- data merge block ~ ~ ~ {CustomName:'"233"'}
- 将当前所在位置处的方块实体的自定义名称设置为 '"233"'。
- 将当前所在位置处的方块实体的自定义名称设置为 '"233"'。
- data merge entity @e[type=zombie,limit=1] {Rotation:[45.0f,90.0f]}
- 将一只僵尸的朝向设置为 [45.0f,90.0f]。
- 将一只僵尸的朝向设置为 [45.0f,90.0f]。
- data merge entity @e[type=zombie,limit=1] {Health:20.0f,HandItems:[{id:"stone",Count:1b},{}]}
- 将一只僵尸的血量设置为 20f,主手所持物品设置为一块石头,副手所持物品设置为空。
- 将一只僵尸的血量设置为 20f,主手所持物品设置为一块石头,副手所持物品设置为空。
- data merge block ~ ~ ~ {CustomName:'"233"'}
请看以下过程:
- data merge storage foo:example {Stone:1b,Dirt:{Grass:3b,Planks:4b}}
- 将 {Stone:1b,Dirt:{Grass:3b,Planks:4b}} 合并到空的 storage。
- {Stone:1b,Dirt:{Grass:3b,Planks:4b}}
- data merge storage foo:example {Stone:5b,Flower:6b,Dirt:{Farmland:7b}}
- 将 {Stone:5b,Flower:6b,Dirt:{Farmland:7b}} 合并到 storage。
- {Stone:5b,Flower:6b,Dirt:{Grass:3b,Planks:4b,Farmland:7b}}
- 移除所有键值对,命令略。
第六节:数据的修改
我们使用 data modify 命令来修改指定键名的键值对的键值。
- 语法:
- data modify 命令可以分成三部分:
- 要修改哪里的键值。
- data modify block <方块坐标> <路径>
- data modify entity <实体> <路径>
- data modify storage <storage> <路径>
- 要将键值怎么样。
- (append|insert <索引>|merge|prepend|set)
- prepend:将键值插入到列表或数组的最前面。
- append:将键值插入到列表或数组的末尾。
- insert <索引>:将键值插入到列表或数组的第 <索引> 个元素后。
- merge:将复合标签和复合标签合并。
- set:将键值替换,对复合标签无效。
- (append|insert <索引>|merge|prepend|set)
- 修改成什么,既可以设置成指定的值,也可以从其他地方复制。
- value <nbt>
- from block <方块坐标> <路径>
- from entity <实体> <路径>
- from storage <storage> <路径>
- 要修改哪里的键值。
- data modify 命令可以分成三部分:
- 例子:
- data modify block ~ ~ ~ CustomName set value '"233"'
- 将当前所在位置处的方块实体的自定义名称设置为 '"233"'。
- 效果等价于 data merge block ~ ~ ~ {CustomName:'"233"'}
- 将 {CustomName:'"233"'} 合并到当前所在位置处的方块实体。
- 也可以写成 data modify block ~ ~ ~ {} merge value {CustomName:'"233"'}
- 可以用 {} 表示根路径。
- 可以用 {} 表示根路径。
- data modify block ~ ~ ~ Items[{id:"minecraft:firework_rocket"}].tag.Fireworks{Flight:1b}.Flight set value 3b
- 将当前所在位置处的箱子(或木桶/潜影盒等)里所有飞行高度为 1b 的烟花火箭的飞行高度设置为 3b。
- 将当前所在位置处的箱子(或木桶/潜影盒等)里所有飞行高度为 1b 的烟花火箭的飞行高度设置为 3b。
- data modify block ~ ~ ~ CustomName set from entity @e[type=zombie,limit=1] CustomName
- 将一只僵尸的自定义名称名称复制到当前所在位置处的方块实体的自定义名称。
- 将一只僵尸的自定义名称名称复制到当前所在位置处的方块实体的自定义名称。
- data modify block ~ ~ ~ {} merge from block ~ ~1 ~
- 将当前所在位置 ~ ~1 ~ 处的方块实体的数据标签合并到当前所在位置处的方块实体。
- 将当前所在位置 ~ ~1 ~ 处的方块实体的数据标签合并到当前所在位置处的方块实体。
- data modify entity @e[type=zombie,limit=1] HandItems[0].id set value "stone"
- 将一只僵尸主手所持物品的 id 设置为石头。
- 将一只僵尸主手所持物品的 id 设置为石头。
- data modify entity @e[type=zombie,limit=1] HandItems[0] set from entity @s SelectedItem
- 将命令执行者的手持物品复制到一只僵尸主手所持物品。
- 将命令执行者的手持物品复制到一只僵尸主手所持物品。
- data modify entity @e[type=item,limit=1] Item.tag.display.Name set from entity @s SelectedItem.tag.pages[0]
- 将命令执行者主手所持成书的第一页所写的内容复制到一个掉落物的自定义名称。
- 将命令执行者主手所持成书的第一页所写的内容复制到一个掉落物的自定义名称。
- data modify block ~ ~ ~ CustomName set value '"233"'
过程 1:
- data merge storage foo:example {List:[1,2,3],Array:[B;1B,2B,3B]}
- {List:[1,2,3],Array:[B;1B,2B,3B]}
- {List:[1,2,3],Array:[B;1B,2B,3B]}
- data modify storage foo:example List append value 4
- data modify storage foo:example Array append value 5B
- {List:[1,2,3,4],Array:[B;1B,2B,3B,5B]}
- {List:[1,2,3,4],Array:[B;1B,2B,3B,5B]}
- data modify storage foo:example List prepend value 6
- data modify storage foo:example Array prepend value 7
- {List:[6,1,2,3,4],Array:[B;7B,1B,2B,3B,5B]}
- {List:[6,1,2,3,4],Array:[B;7B,1B,2B,3B,5B]}
- data modify storage foo:example List insert 2 value 8
- data modify storage foo:example Array insert -2 value 9B
- {List:[6,1,8,2,3,4],Array:[B;7B,1B,2B,3B,9B,5B]}
- {List:[6,1,8,2,3,4],Array:[B;7B,1B,2B,3B,9B,5B]}
- data modify storage foo:example List insert 0 value 10
- data modify storage foo:example Array insert -4 value 0
- {List:[10,6,1,8,2,3,4],Array:[B;7B,1B,2B,0B,3B,9B,5B]}
- {List:[10,6,1,8,2,3,4],Array:[B;7B,1B,2B,0B,3B,9B,5B]}
- 移除所有键值对,命令略。
过程 2:
- data merge storage foo:example {Stone:{Dirt:1b,Grass:2b},Planks:{Dirt:3b,Flower:4b}}
- {Stone:{Dirt:1b,Grass:2b},Planks:{Dirt:3b,Flower:4b}}
- {Stone:{Dirt:1b,Grass:2b},Planks:{Dirt:3b,Flower:4b}}
- data modify storage foo:example Stone merge value {Farmland:5b}
- {Stone:{Dirt:1b,Grass:2b,Farmland:5b},Planks:{Dirt:3b,Flower:4b}}
- {Stone:{Dirt:1b,Grass:2b,Farmland:5b},Planks:{Dirt:3b,Flower:4b}}
- data modify storage foo:example Stone merge from storage foo:example Planks
- {Stone:{Dirt:3b,Grass:2b,Farmland:5b,Flower:4b},Planks:{Dirt:3b,Flower:4b}}
- {Stone:{Dirt:3b,Grass:2b,Farmland:5b,Flower:4b},Planks:{Dirt:3b,Flower:4b}}
- data modify storage foo:example {} merge value {Ore:6b}
- 效果等价于 data merge storage foo:example {Ore:6b}
- {Stone:{Dirt:3b,Grass:2b,Farmland:5b,Flower:4b},Planks:{Dirt:3b,Flower:4b},Ore:6b}
- 移除所有键值对,命令略。
注意:
- 不同数据类型的键值会复制失败,可以选择使用 execute store 命令转换数据类型,例如:
- 将命令执行者手持物品的数量存为一只僵尸的血量(血量是 float,物品数量是 byte)。
- 错误示范:data modify entity @e[type=zombie,limit=1] Health set from entity @s SelectedItem.Count
- 正确示范:execute store result entity @e[type=zombie,limit=1] Health float 1 run data get entity @s SelectedItem.Count
- 同样,你也不能将一个 byte 插入到全是 float 的列表中。
- 将命令执行者手持物品的数量存为一只僵尸的血量(血量是 float,物品数量是 byte)。
- 但是,数组可以自动转换数据类型,例如你可以将一个 byte 插入到全是 int 的数组中,数组会自动将 byte 的数据类型转换成 int。
第七节:数据的检测及统计
我们使用 execute if data 命令来检测和统计数据。
可以参考:
【教程】[1.15] execute 命令入门教程
https://www.mcbbs.net/thread-989501-1-1.html
请看以下过程:
- data merge storage foo:example {String:"foo",List:[1,2,2,3],Array:[B;1B,2B,3B],Compound:{Stone:1b,Dirt:2b,Grass:3b}}
- scoreboard objectives add foo dummy
- 初始化。
- 初始化。
- execute if data storage foo:example <NBT>
| <NBT> |
| 返回值 |
| 含义(是否存在) |
| Compound |
| 1 |
| 键值对 Compound |
| Compound{} |
| 1 |
| 复合标签 Compound 满足 {} |
| {Compound:{}} |
| 1 |
| 数据标签满足 {Compound:{}} |
| Compound{Stone:1b} |
| 1 |
| 复合标签 Compound 满足 {Stone:1b} |
| {Compound:{Stone:1b}} |
| 1 |
| 数据标签满足 {Compound:{Stone:1b}} |
| List |
| 1 |
| 键值对 List |
| List[1] |
| 1 |
| 列表 List 中的第 2 个元素 |
| {List:[1]} |
| 1 |
| 列表 List 中值为 1 的元素 |
| {List:[]} |
| 0 |
| 列表 List 中没有元素 |
| Array |
| 1 |
| 键值对 Array |
| Array[1] |
| 1 |
| 数组 Array 中的第 2 个元素 |
| {Array:[1B]} |
| 0 |
| 数组 Array 有且只有一个元素 1B |
| {Array:[]} |
| 0 |
| 列表 Array 中没有元素 |
| <NBT> |
| 返回值 |
| 含义(统计) |
| List[] |
| 4 |
| 列表 List 中元素的个数 |
| Array[] |
| 3 |
| 数组 Array 中元素的个数 |
| String |
| "foo" |
| 字符串 String 的长度 |
- execute store result score #temp foo if data storage foo:example String
- #temp 的记分板分数变为 3。
- #temp 的记分板分数变为 3。
可以参考:
【CBL|SPG】[1.14.4] 命令返回值列表
https://www.mcbbs.net/thread-808124-1-1.html
注意,在 1.15,execute store result run data get 中的部分功能被 execute store result if data 取代。
- execute if data storage foo:example <NBT>
<NBT> 为以下值时条件均可通过,且计数均为 1:
{List:[1]}、{List:[2]}、{List:[1,2]}、{List:[2,1]}、{List:[1,1,2]}
列表在检测时是无序的,可以将其看作一个集合,只考虑元素的数据类型和种类,不考虑数量以及位置,只要 <NBT> 是其子集即可,除了空集 {List:[]} 必须在列表 List 内没有元素时才能通过。
数组在检测时需要完全一致才能通过,包括元素的数据类型、种类、数量和位置。
execute store success 可以存储命令执行成功的次数,可以通过尝试存储数据 A 到数据 B 来判断 A、B 是否完全相同,例如:
- data modify storage foo:example UUIDLeast set from entity @r UUIDLeast
- 将随机一名玩家的 UUIDLeast 存储到 storage
- 将随机一名玩家的 UUIDLeast 存储到 storage
- execute store success storage foo:example Different byte 1 run data modify storage foo:example UUIDLeast set from entity @s UUIDLeast
- 尝试用命令执行者的 UUIDLeast 覆盖原来的 UUIDLeast,如果覆盖成功,则说明 UUIDLeast 不同,Different 的值变为 1b,否则变为 0b。
- 尝试用命令执行者的 UUIDLeast 覆盖原来的 UUIDLeast,如果覆盖成功,则说明 UUIDLeast 不同,Different 的值变为 1b,否则变为 0b。
- 移除所有键值对,命令略。
结语
对,我写完了。
估计没什么人会把这个帖子看完的.jpg
我是不是运气太好了
刚想恶补这部分的内容
execute被我遇到了
今天data又被我遇到了
刚想恶补这部分的内容
execute被我遇到了
今天data又被我遇到了
Ssssssssssssssssssssss
好详细,爱了,感谢大佬分享
之前在百度一直找,都是些很零星的,今天刚来就找到这么详细的,厉害了
防止卡审核,就在这里说了。
data remove 无法移除的键值对
1. 无法直接移除根路径,例如:
2. 无法移除方块和实体的根路径下的第 1 层键值对,例如:
3. 其他键值对,例如:
另外,不是所有的键值对修改都有用,例如你在主世界运行:
你会发现盔甲架的维度已经变成 1(使用 data get 得到)但它还是呆在主世界原地不动。
data remove 无法移除的键值对
1. 无法直接移除根路径,例如:
代码:
- data remove block ~ ~ ~ {}
- data remove entity @s {}
- data remove storage foo:example {}
2. 无法移除方块和实体的根路径下的第 1 层键值对,例如:
- 你不能:
代码:
- data remove block ~ ~ ~ CustomName
- data remove entity @s Health
- data remove entity @s HandItems
- data remove block ~ ~ ~ CustomName
- 你可以:
代码:
- data remove block ~ ~ ~ Items[{id:"minecraft:stone"}]
- data remove entity @s HandItems[0]
- data remove entity @s ArmorItems[{Count:1b}].tag
- data remove storage foo:example Stone
- data remove block ~ ~ ~ Items[{id:"minecraft:stone"}]
3. 其他键值对,例如:
代码:
- data remove entity @s Pos[0]
- data remove entity @s Motion[]
另外,不是所有的键值对修改都有用,例如你在主世界运行:
- data modify entity @e[type=armor_stand,limit=1] Dimension set value 1
你会发现盔甲架的维度已经变成 1(使用 data get 得到)但它还是呆在主世界原地不动。