【MCJE】字符串拼接
本专栏使用版本:Minecraft JE 1.20 pre-6
相信不少人在使用命令会遇到变量限制而不得不使用穷举、遍历、叠加等方法
例如这种情况:使用fill命令填充以两个实体的坐标为区域两个对角确定的一块区域
大家一般会想到,fill命令在执行时可以以命令执行坐标为基准确定目标位置(即相对坐标)
例:/fill ~1 ~3 ~1 ~-1 ~3 ~-1 stone
因为这条命令由我在聊天框直接打出,因此执行位置就是我的位置,所以这条命令便会在我的位置上方3格的东南延长1格与西北延长1格之间的区域生效

但这种方法无法用于上文中提到的情况
因为一条命令内,执行位置只有一个,而要求却提到了两个实体的坐标,fill命令在确定一个执行位置时,仍无法获得另一个实体的坐标
在以前的版本有一种解决办法是遍历,在第一个实体的位置依次走过每一个位置,并在每次走过时放置方块,这种办法既麻烦,而且性能消耗也相对较大,是否有一种办法能直接用原版命令填充这块区域呢?
当然有,这便是本文所讲的内容:通过字符串拼接更改命令并在其中添加变量
带变量的命令
首先,需要先知道普通字符串与字符串形式的原始JSON文本
在nbt中,字符串需要用引号包裹表示
"我是文本"
而原始JSON文本是一种拥有多种功能的文本显示方式
'[{},{},{}...]'
花括号{}内可以填写用引号包裹的键值对
这部分内容不多说明,可自行查看wiki
教程/原始JSON文本 - Minecraft Wiki_BWIKI_哔哩哔哩 (biligame.com)
重点是其中的"score"与"nbt"等
格式如下
{"score":{"name":"分数拥有者","objective":"计分项id"}}
//显示一段分数
{"nbt":"路径","block":"方块坐标"}
{"nbt":"路径","entity":"目标实体"}
{"nbt":"路径","storage":"储存路径"}
//显示一个方块、实体、或储存中某个nbt的值
注:这两着都属于高级原始JSON文本元件
而计分板分数、nbt中的字符串,我们可以通过多种方法更改,通过scoreboard、data、execute中的store等
使用普通的字符串,我们可以直接将一条命令的文本形式显示在聊天框中
例:/tellraw @s "/fill 5 5 5 20 20 20"
使用原始JSON文本与字符串,我们可以直接将一条命令与它的变量组合并显示在聊天框中
例:/tellraw @s ["/fill ",{"score":{"name": "#v_x1","objective": "test"}}," ",{"score":{"name": "#v_y1","objective": "test"}}," ",{"score":{"name": "#v_z1","objective": "test"}}," ",{"score":{"name": "#v_x2","objective": "test"}}," ",{"score":{"name": "#v_y2","objective": "test"}}," ",{"score":{"name": "#v_z2","objective": "test"}}," ",{"nbt":"id","storage":"store:string"}]

其中,-1321,4,-91,-1321,9,-98,minecraft:glass 都是可以方便地更改的变量,分别为两个实体的坐标、玩家手持物品的id
通过这张图,不难发现,此时展示给玩家看的这个文本已经是一条完整的命令了
它能够随着计分板分数、玩家手持的物品(变量)而变化内容
若能够执行,执行的效果也会受变量影响
那么,我们现在只需要想办法把它当作一条命令执行就可以了
但它仅仅是展示给玩家看的文本,并不能直接执行
这时候,大佬们已经发现了一个办法
获取字符串
我们已知的包括以下内容:
1. 实体的自定义名称可以使用普通原始JSON文本,但不能使用高级原始JSON文本元件

2. 告示牌上的文字可以使用包括高级原始JSON文本元件的完整的原始JSON文本

3. 告示牌会将高级原始JSON文本元件解析为以普通原始JSON文本储存的nbt

4. 命令方块中会记录上一次执行命令后的报错,且报错中含有实体名称的字符串

通过上述内容,我们可以先将 “ 带变量的命令 ” 部分中讲述的JSON文本放入告示牌中
让告示牌将高级原始JSON文本元件解析为以普通原始JSON文本储存的nbt
(仔细观察前面第3点图片中的内容,你会发现它与“ 带变量的命令 ” 部分中的变量元件(高级原始JSON文本元件)已变化为了纯字符串的普通原始JSON文本)
再将告示牌转化后的普通原始JSON文本复制到实体中(前面第1点的实体的自定义名称只能使用普通原始JSON文本)
接着,在命令方块中用enchant向实体附魔物品(不重要),将获得一个报错(第4点的图)
而这个报错正好包含实体的名称(最终字符串形式)——也就是 “ 带变量的命令 ” 最后图片中显示的命令,它将直接储存在命令方块“报错”的nbt中
但此时,我们又如何将这条命令从字符串中分出来呢?
截取字符串
在23w03a(1.19.4)版本中,data命令加入了一个值来源:string(与value、from同级)
能够在一个nbt字符串中截取一部分作为值,含有两个选项:开始的字符位置、结束的字符位置,如下
若 开始的字符位置 为3 结束的字符位置 为4
ABCDEFG
123
1234
最后作为值的字符串便是蓝色部分
在1.20 pre-1版本中,这两个位置可以是负数,此时将从最末尾开始截取,如下
若 开始的字符位置 为2 结束的字符位置 为-1
ABCDEFG
12
654321X(负的,X即不填)
最后作为值的字符串便是蓝色部分
这为我们截取命令部分大大提供了方便
最后最后,我们将截取的命令放入命令方块的Command中执行,便可完成最终的执行
如下(核心部分)



效果参考视频 BV1to4y137VA