第七十一章 条件子命令

(于2022\/7\/15重写)

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

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

(滑稽)

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

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

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

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

条件子命令的子命令,截止minecraf版本,一共有六个:

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

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

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

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

data ——探测指定方块、实体和存储nbt是否拥有指定的nbt标签zuqi.org 葡萄小说网

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

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

block、blocks、entity和score

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

... if|unless block <方块位置><方块id或标签>...

... if|unless blocks <源区域起始坐标><源区域终止坐标><比较区域下西北角坐标><对比模式:masked|all>...

... if|unless entity <检测目标:目标选择器>...

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

之前

\/testfor <指定目标:目标选择器>[探测nbt是否符合]

\/testforblock <探测位置:坐标><方块id:字符串>[数据值:整数]

\/testforblock <探测位置:坐标><方块id:字符串>[方块状态]

\/testforblocks <源区域起始坐标><源区域终止坐标><比较区域下西北角坐标>[<模式:masked|all>]

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

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

例子一:

\/execute as [type=yer] at if entity [distance=..1,nbt={item:{id:“minecraft:snowball“,tag:{disy:{name:''{“text“:“回城雪球“}''}}}},type=item,limit=1,sort=nearest] run tag add hub

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

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

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

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

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

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

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

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

例子二:

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

这是我们在第三十七章讲\/testforblocks时引用的例子,其作用是『检测执行者脚下3x3的区域是否和头顶3x3的区域完全一样』,现在我们尝试将这一串指令转化为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 at if block ~~-1 ~ redstone_block run camerashake add

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

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

这条指令的作用是:

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

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

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

... if|unless block <坐标><方块id>[方块数据值|方块状态]...

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

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

... if|unless score

<比较模式><b目标><b计分项>...

... if|unless score

matches <范围>...

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

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

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

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

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

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

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

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

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

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

<——如果分数x小于分数y,则为真

举个例子:

\/scoreboard objectives add death deathcount “死亡榜“

\/scoreboard objectives add duibi dummy “分数对比专用“

\/scoreboard yers set many_dead_times duibi 50

\/execute as if score death >= many_dead_times duibi run tellraw [{“text“:“兄弟,你已经死了“},{“score“:{“name“:““,“objective“:“death“},“color“:“red“},{“text“:“次了!“,“color“:“reset“}]

前面的三条指令就不多讲了,你应该知道是干什么的。最后一条execute指令,将会让所有玩家分别作为执行者,如果其死亡次数(death计分项中的分数)大于等于50(也就是many_dead_times这个假玩家在duibi计分项中的值),玩家自己就会收到一条消息:

兄弟,你已经死了x次了!

其中,x指的是这名玩家在计分板death上的分数,也就是他死亡的次数。

除去这个tellraw内的json文本有一部分我们没学过以外,其他部分还是很容易理解的。

至于matches模式的比较就更简单了,这就是原本yers test子命令的功能。其中的『范围』也就是采用和目标选择器一样的『两点法』。举个例子:

\/execute as if score death matches 50.. run 同上

这是上面例子的简化版,功能还是一样的。

值得注意的是,在基岩版中,『两点法』可以使用!来反选。比如:

\/execute if score death matches !10..15

这将会测试执行者自己在death计分板上的分数,如果分数不在10~15(含)的范围内就会测试通过。同样的,基岩版在其他能用到这种『两点法』的地方基本上也能够用『!』来反选,比如目标选择器。

最后,我们来看看前一章节就已经碰到过的predicate子命令:

... if|unless predicate <谓词条件id>...

什么是谓词?我在上一章已经解释过了:

『在我们讲数据包之前(也有可能永远不会讲到),你可以将这东西当作是一个打包好的『判断函数』,在这个『判断函数』里面写了一些东西,可以判断当前游戏的情况是否符合指定的条件,如果符合则通过判断,如果不符合则不通过判断。比如里面写了一个『当前游戏正在下雨』的条件,当这个条件被调用时就会看看现在游戏是否在下雨,如果下雨就会通过判断,你的指令也就能够运行,反之就不会运行。』

举个简单的例子,假设有一位大佬做了一个数据包,其命名空间为『the_dark_forest』,里面有一个叫做『』的谓词条件。这个条件会判断当前世界是否在下雨,如果下的是普通的雨,就随机50%的几率使条件成立,如果下的是暴雨,这个几率会提升到80%。

我们可以通过如下命令来调用这个谓词条件:

\/execute ... if predicate the_dark_forest:israining ...

如果你调用这个谓词条件时,游戏里正在下普通的雨,那么你的指令就有50%的几率能够运行。如果下的是雷暴雨,那么就有80%的几率会运行。如果是晴天,那么不可能会运行。

当然,你也可以将if改为unless来反转条件:

\/execute ... unless predicate the_dark_forest:israining ...

这条指令和上面指令的运行条件完全是反着来的:如果是晴天,那么必定会运行;如果是普通的雨天,有50%的几率会运行;如果是雷暴雨,只剩下20%的几率会运行。

现在你懂了吧?让我们来做几道题目,巩固一下知识。

第一题:请写出下列execute指令成功运行的条件

1\/execute as [type=item] at if block ~~-1 ~ minecraft:grass_block run kill

2\/execute positioned 1.0 1.0 1.0 if block ~~~ minecraft:air if entity [distance=..2,limit=1,sort=nearest]

3\/execute unless blocks ~1 ~1 ~1 ~-1 ~1 ~-1 0 0 0 all

第二题:请写出下列execute指令最大的成功运行次数

1\/execute as [limit=10] rotated as [limit=10] run tp 1 1 1

2\/execute if predicate the_dark_forest:israining

3\/execute if score = score run say hello!

所以这就是我们本章的全部内容,下一章我们将会来初步了解一下存储子命令。

......

......

......

......

......

......

参考答案

第一题:

1所有维度的已加载区块内必须要有掉落物类型的实体,且至少有一个掉落物的下方方块是草方块

2坐标(1.0,1.0,1.0)处的方块必须是一个空气方块,且范围2米内必须要有一个实体存在。

3执行地点上方3x3的范围与范围(0,0,0)-(3,0,3)完全一致,且执行地点上方3x3的范围没有超出世界边界

第二题:

1100(as的参数指定了10个实体,rotated的参数也指定了10个实体)

21(跟if子命令没关系)

30(在java版中,score子命令的两个目标选择器参数都不能指定多个实体)或1(在基岩版中,只要实际只选择到了1个实体就行)

上一章目录+书架下一章