(=°ω°)丿


[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] 的僵尸。



在命令中我们可以看到,僵尸的所有数据都被一对 {} 包裹了起来,我们将僵尸的所有数据包括最外面的那一层 {} 叫做 数据标签



而键值又被分为了很多类型,例如:



具体见下表:


键值的数据类型
说明
键值对举例
字节(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)
只有 truefalse 两种取值。在 NBT 中,truefalse 用字节的 1b0b 代替。
Glowing:1b"Bold":true




第二节:数据的获取


还是以第一节中的僵尸为例:



我们假设 @e[type=zombie,limit=1,sort=nearest] 可以选中该僵尸。


我们使用 data get 命令来获取指定键名的键值对的键值。



实际上,data get entity 命令的语法是这样的:



除实体外,data get 命令也可以用于获取方块或 storage 的 NBT 数据。



同时有 4 点需要注意:





第三节:数据的移除


我们使用 data remove 命令来移除指定键名的键值对。


同样,data remove 的目标也可以是方块、实体或 storage。





第四节:NBT 路径


怎么写 NBT 路径才能得到想要的键值对的键值是 data 命令中一个常见的问题。


为了方便演示,我们使用 storage 来存储数据。


可以参考:
【CBL|SPG】[1.14] NBT 路径:从入门到胡了
https://github.com/SPGoding/mcbbs-threads/blob/master/tutorials/nbt-path/markdown.md




例 1:一个简单的例子


请看以下过程:





为了方便阅读,我们在接下来以一个执行命令的过程为例时,使用以下格式:





例 2:套娃





我们可以将每个复合标签 {} 类比为一个文件夹,则我们这次:



在 Windows 中,Grass 的路径应该这么写:Stone\Dirt\Grass,就像 .minecraft\saves\<地图名称>\datapacks,但在 NBT 中,要把 \ 改成 .,把 Stone\Dirt\Grass 改成 Stone.Dirt.Grass




例 3:一个较为复杂的例子



你能找出有几个键值对并且判断它们之间的位置关系吗?


为了看起来方便,我们可以像下面一样分多行写。


代码:

  1. {
  2.     Stone:{
  3.   Dirt:{
  4.    Grass:1b,
  5.    Tree:4b
  6.   },
  7.   Farmland:{
  8.    Flower:3b
  9.   },
  10.   Ore:5b
  11.     },
  12.     Planks:2b
  13. }

列表如下:


Stone
Dirt
Grass:1b
Stone
Dirt
Tree:4b
Stone
Farmland
Flower:3b
Stone
Ore:5b
Planks:2b

共 8 个键值对,其中有 3 个键值对的键值是复合标签。





例 4:复合标签内元素的筛选





使用 Compound{条件} 可以对复合标签中的元素进行筛选,条件为空时表示不设置筛选条件。




例 5:列表



使用不同的路径会得到不同的结果,例如:



具体见下表:


路径
结果
筛选出
不填
{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 个元素




List[] 指列表 List 里所有的元素,List[n] 指列表 Numbers 里第 (n+1) 个元素,List[-n] 指列表 List 里倒数第 n 个元素。




例 6:列表内元素的筛选



路径
结果
筛选出
不填
{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"




使用 List[{条件}] 对列表中的元素进行筛选,List[{}] 只能选中数据类型为复合标签的元素。




例 7:数组


数组和列表类似,下面以整型数组为例。



路径
结果
筛选出
不填
{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 个元素


例 8:几个例子


请看以下过程:



单句命令:





第五节:数据的合并


我们使用 data merge 命令将指定的复合标签合并至方块、实体或 storage 的数据标签,类似于文件夹的合并,相同文件名的文件(相同键名的键值对)会被覆盖。



请看以下过程:



第六节:数据的修改


我们使用 data modify 命令来修改指定键名的键值对的键值。



过程 1:



过程 2:



注意:



第七节:数据的检测及统计


我们使用 execute if data 命令来检测和统计数据。


可以参考:
【教程】[1.15] execute 命令入门教程
https://www.mcbbs.net/thread-989501-1-1.html


请看以下过程:



<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 的长度


可以参考:
【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 取代。



<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 是否完全相同,例如:





结语


对,我写完了。


估计没什么人会把这个帖子看完的.jpg




Xiao2
我是不是运气太好了
刚想恶补这部分的内容
execute被我遇到了
今天data又被我遇到了

灬忘却灬
Ssssssssssssssssssssss

kayn-
好详细,爱了,感谢大佬分享

jason_sun
之前在百度一直找,都是些很零星的,今天刚来就找到这么详细的,厉害了

(=°ω°)丿
防止卡审核,就在这里说了。


data remove 无法移除的键值对


1. 无法直接移除根路径,例如:


代码:

  1. data remove block ~ ~ ~ {}
  2. data remove entity @s {}
  3. data remove storage foo:example {}

2. 无法移除方块和实体的根路径下的第 1 层键值对,例如:



3. 其他键值对,例如:


代码:

  1. data remove entity @s Pos[0]
  2. data remove entity @s Motion[]



另外,不是所有的键值对修改都有用,例如你在主世界运行:



你会发现盔甲架的维度已经变成 1(使用 data get 得到)但它还是呆在主世界原地不动。