第七十一章 条件子命令

换源:

  (于2022/7/15重写)

还记得那些被execute替代的指令吗?其中,/testfor、/testforblock、/testforblocks和/scoreboard players test的功能被合并到了条件子命令中,也就是if和unless子命令。

if和unless这两个子命令虽说是子命令,但它们毕竟是多条指令融合而成的,自然而然也就有『子命令』的『子命令』,所以说我们是否可以把子命令的子命令称之为execute的『孙子命令』呢?

(滑稽)

虽然if和unless这两个子命令有完全相同的格式,但它们俩的效果是完全相反的:

if——如果给出的条件为真(true),也就是条件成立,即通过检测,运行指令

unless——如果给出的条件为假(false),也就是条件不成立,即通过检测,运行指令

如果你看不懂上面的描述,没关系,待会我们会举些例子,毕竟上面的描述比较偏向于编程思维。

条件子命令的子命令,截止Minecraft Java1.19版本,一共有六个:

block ——探测指定位置是否为某种方块

blocks ——将指定区域与另外一个指定区域进行对比

entity ——探测指定实体是否存在。

score ——探测指定玩家在指定计分项上的分数是否与另一个玩家在指定计分项上的分数符合指定的关系

data ——探测指定方块、实体和存储NBT是否拥有指定的NBT标签

predicate ——检查指定谓词是否通过

其中,data子命令我们放到以后讲NBT时再来(这玩意儿作为一个孙子命令,竟然还有三个子命令,也就是说execute有曾孙子了),predicate子命令我们在上一章已经遇到过了,所以我们这边就先来看看这剩下的四个子命令:

block、blocks、entity和score

其中,前三者实际上根本就不用讲。为何呢?让我们看一下它们的用法:

... if|unless block ...

... if|unless blocks ...

... if|unless entity ...

是不是有些熟悉?这难不成就是:

Java1.13之前

/testfor [探测NBT是否符合]

/testforblock [数据值:整数]

/testforblock [方块状态]

/testforblocks []

Mojang这是直接移植过来的啊,模式名都不带改一下的。

既然这些子命令和被删除的那些指令用法几乎完全一样,我们这边也就不多讲了,直接上例子。

例子一:

/execute as @e[type=player] at @s if entity @e[distance=..1,nbt={Item:{id:“minecraft:snowball“,tag:{display:{Name:'{“text“:“回城雪球“}'}}}},type=item,limit=1,sort=nearest] run tag @s add hub

这条execute有四个子命令:as、at、if和run,其效果是:

将所有在线且活着的玩家分别作为执行者,他们的位置作为执行位置,他们的旋转角度作为执行朝向,如果执行者周围1米有一个叫做『回城雪球』的雪球掉落物,就给执行者自己添加上标签hub。

其中,我们重点看一下if子命令这一段:

if entity @e[distance=..1,nbt=物品是叫做『回城雪球』的雪球,type=item,limit=1,sort=nearest]

这个if子命令用到了entity,也就是相当于1.13之前的testfor指令,用于探测指定实体是否存在。在这边,entity的参数就不讲了,涉及到nbt,你大概知道是探测一个叫做『回城雪球』的掉落物就行。

让我们试一试将上面这一段if子命令转化为testfor指令:

/testfor @e[r=1,name=回城雪球,type=item,c=1]

是不是立马就理解了?所以,在使用if子命令的block、entity和blocks子命令时,不妨可以回忆回忆以前的指令是怎么个用法。

例子二:

/testforblocks ~-1 ~-1 ~-1 ~1 ~-1 ~1 ~-1 ~2 ~-1

这是我们在第三十七章讲/testforblocks时引用的例子,其作用是『检测执行者脚下3×3的区域是否和头顶3×3的区域完全一样』,现在我们尝试将这一串指令转化为1.13 的版本:

/execute if blocks ~-1 ~-1 ~-1 ~1 ~-1 ~1 ~-1 ~2 ~-1 all

这个1.13 版本的指令和上面的testforblocks例子的效果是完全一样的,唯一需要注意的是比较模式参数从可选变成了必选,并且由于testforblocks默认就是all比较模式,所以转化后要在最后加上个『all』。

你可能会疑惑:run呢?run子命令呢?我那么大一个run呢?

其实,当一个execute指令中含有条件子命令时,就不一定要含有run子命令了。因为条件子命令也可以看做是一个具有功能的,能够返回东西的指令(毕竟原来就是由几条单独指令结合在一起的嘛)。

例子三:

/execute as @a at @s if block ~~-1 ~ redstone_block run camerashake add @s

这条指令并不适用于Java版,而是适用于基岩版。

没错,这个例子是使用目前基岩版还在测试中的新版execute指令写成的,不难发现基岩版的新版execute和Java版的几乎没差别。

这条指令的作用是:

将所有玩家分别作为执行者,将执行者的位置作为执行位置,将执行者的旋转角度作为执行朝向,如果执行位置下方一格方块(玩家脚底下的方块)是红石块,就摇晃玩家的镜头(站久就变鬼畜了)。

其中,指令camerashake是基岩版目前较为冷门的一个指令,因为是新添加的所以还有许多人不太了解。其实基岩版在1.16版本时添加了许多有用的指令,以后可能会专门抽出来几章讲一讲。

既然说到了基岩版的新版execute,那就不妨来看看基岩版的条件子命令格式和Java版有何不同:

... if|unless block [方块数据值|方块状态]...

看看,基岩版做得多么人性化,不一定要填写的参数就不一定要填写,一定要填写的参数就一定要填写,在这一方面Java版的if blocks就做得不好,为什么一定要填写『比较模式』呢?

现在,block、blocks和entity三条子命令我们都会用了,接下来我们来看看score:

... if|unless score

...

... if|unless score

matches ...

虽然score是用来替代scoreboard players test的,但这个格式第一眼给人的感觉却像是另外一个东西:scoreboard players operation

但这两个东西有很大的区别——前者(score)仅仅是对比分数,并不会修改两个分数;后者(scoreboard players operation)虽然也可以对比,但更多的作用是修改分数。

而且,score可比scoreboard players operation要简单多了,因为你并不需要考虑A新A旧,以及有多个比较目标的情况,其中的目标选择器都只能选取一个目标(看来Mojang还是很人性化的对不对?)。

让我们来仔细看看上面的格式,可以发现相比scoreboard players test,新的score不仅仅可以用来测试单个分数,还可以比较两个分数。

其中,前面部分的『A目标』『a计分项』两个参数,以及后面的『B目标』『b计分项』两个参数,就不需要我多说了吧?前者是用于指定『式子』的左侧分数x,后者是用于指定『式子』的右侧分数y。

中间部分的『比较模式』参数,也就是填写在数学上大名鼎鼎的五个符号:

>——如果分数x大于分数y,则为真

>=——如果分数x大于等于分数y,则为真

=——如果分数x等于分数y,则为真