跳到主要内容

2.3.4 *旧版的/execute

温馨提醒

本条目内容只在以下情况下生效:

  • 低于 1.19.50 的国际版版本
  • 低于 3.0 的中国版版本
  • 引擎版本为低于 1.19.50 的行为包
  • 格式版本为低于 1.19.50 的可执行命令的实体、动画控制器等文件

为以防万一(毕竟可能真的有极少数情况下,在现阶段还有开发者需要这些东西),所以我们还是简单提一下,让各位读者了解到过往的/execute命令。然而,我们仍需再次强调:这些内容已经过时,因此全篇内容都是扩展内容,仅作为简单了解!如果你不愿意了解这些的话,跳过这一节也是没有问题的。

然而,如果你是旧版本过来的玩家,并且急切地想要知道新旧语法之间的转换方法,你可以在这一节找到答案。

在前三节,我们所了解到的命令都称为新版/execute命令。有新就有旧,什么是旧版的/execute命令呢?旧版命令的原理又是什么呢?

/execute的发展简史

一切起源于 Java 版 1.13 的那次大改。在 JE(Java 版,Java Edition,简称 JE)1.13 中,你可能已经知道这个版本经历过一次“惨无人道”的扁平化。然而,JE 1.13 的那次更改还远不止于此。实际上,JE 1.13 的那次更新,还带来了我们现在所熟知的/execute格式。在 JE 1.13 以前,使用的也是/execute旧版语法。

基岩版(Bedrock Edition,简称 BE)是什么时候开始同步的呢?这就要起源于 BE 1.19.10 的一次更新。在这个更新中,Mojang 大改了以前的旧版/execute命令,和 JE 看齐。然而,当时加入的语法并不多,并且归于一个称为“即将到来的创作者更新”实验性玩法中。随着 1.19.20、1.19.30、1.19.40 等版本的陆续推出,同步了 JE 的更多子命令。最终,/execute于 1.19.50 版本正式加入游戏,旧版语法从此成为历史。

然而,相比于 JE,BE 并没有加入其中的一些重要命令,例如存储子命令store。而且,JE 也在 1.19 时期继续加入了大量的子命令,例如修饰子命令onsummon,条件子命令if dimensionif function等。可以说,目前 BE 的/execute仍然是 JE 的“残血版”,它仍然在追赶 JE 的路上。

旧版/execute的语法 新版的等效语法

让我们现在关注一下以前的语法。相比于现在,以前的语法堪称“简洁”:

旧版/execute语法
execute <源实体: target> <位置: x y z> <命令: command>
execute <源实体: target> <位置: x y z> detect <检测位置: x y z> <方块: Block> <数据值: int> <命令: command>

这是什么意思呢?它并没有aspositioned那样清晰的提示词提示这个参数是做什么的。然而,这些参数都是和新版的子命令语法一一对应的:

  • <源实体: target>:等同于as <源实体: target>。是的,它修改执行者。
  • <位置: x y z>:等同于at @s positioned <位置: x y z>。它负责以执行者的位置为基准,并修改位置。
  • detect <检测位置: x y z> <方块: Block> <数据值: int>:等同于if block <位置: x y z> <方块: Block> <方块状态: block states>。这个语法因为还没有讲到方块状态这个概念,所以我们就暂时跳过这个子命令了。然而你也知道,这一段应当是检测某个位置是否为某个方块的。
    • 其中,数据值方块状态是一一对应的。可能你会问,它们连类型都不相同怎么会是一一对应的?这涉及到另一段方块数据值被移除的历史,我们在讲到方块状态的时候会再细说。
  • <命令: command>:等同于run <命令: command>。它负责以修改过后的执行者和执行环境参数,执行命令。

也就是说,上面的两条语法都可以等效为下面的新版/execute

等效的新版/execute语法
execute as <源实体: target> at @s positioned <位置: x y z> run <命令: command>
execute as <源实体: target> at @s positioned <位置: x y z> if block <位置: x y z> <方块: Block> <方块状态: block states> run <命令: command>

看到这里,你应该就知道以前的两条命令代表什么含义了:

  • 语法 1 的含义为:完全以源实体的身份,在位置执行命令
  • 语法 2 的含义为:在语法 1 的基础上,检查检测位置是否为特定数据值(现在都使用方块状态)的方块,然后才执行命令

新语法与旧语法的优势劣势对比

显然,相比于以前的旧语法,新语法更加灵活,功能上更加强大。

  • 旧语法的条件检测只支持if block类型,而不支持if entityif blocksif score类型。
    • 虽然可以通过更改执行者的方式来变相地实现if entity的功能,然而这么做也会更改执行环境参数,这就带来了很多不便。
    • 虽然可以通过使特定名称的稳定实体(例如名为 abc 的盔甲架)保存分值信息,来变相地实现if score允许假名的功能(这个内容等我们下一节再学习),然而这么做不仅不便于存储变量,还会因为实体可能过多而导致卡顿。
    • 至于if blocks,旧版语法则是几乎束手无策,只能用更复杂的逻辑来实现。
  • 旧语法因为会同时修改执行者和所有的执行环境参数,所以灵活性明显更差。
    • 例如,我们在练习 2.3-1 的第 6 题:写一条命令,令所有羊传送到它们附近的一只牛的位置,并面向离(0,0,0)最近的一只猪
      那么,就要修改执行者为羊,但是这将同时修改执行位置为羊的位置。
      想单独修改执行位置?很遗憾,旧版语法并不存在positioned as这种语法,所以位置你只能写为~~~了。
      那么,后面的tp命令,就只能调用/tp <目标: target> <位置: target>语法,因为其他的位置参量都是x y z类型,然而你并没有通过/execute获取牛的位置。
      但是不要忘了我们还要求羊面向猪的位置!这个/tp命令是做不到的。啊欧……死局了。看来这个功能用旧语法一条命令是做不到的或很难做到的。
    • 再例如,如果使用命令方块(这是一种专门用来执行命令的方块。这种情况下,不存在执行者,但是执行位置、朝向和维度是确定的)执行命令。
      对于新语法,尚可使用positioned ~~~来保存命令方块的位置信息。
      然而旧语法中一旦指定了执行者,那么执行位置就将再也回不到命令方块,因为你无法使用旧版的语法选中命令方块的执行者——别忘了它不存在!
  • 最后就是可读性的问题。假设你是一个什么也不懂的小白,直接点开这篇文章,请问下面两条命令,哪条你更容易看得懂?这答案是显然的。
    • /execute @a ~~~ setblock ~~~ air
    • /execute as @a at @s run setblock ~~~ air

从功能性上来讲,新语法可以实现完全的平替,灵活性大幅提升,可读性也更加的好。然而,如果我们不从功能性考虑的话,新语法还是存在一些缺点:

  • 相较于旧语法,它更冗长了。虽然这确保了可读性,然而对于手机版玩家,要打的字就更多了。
  • 以及,新版语法因为其复杂性,学习难度相比于以前也更加的大。要想学习以前的命令,我们只需要知道源实体的身份,在位置执行命令 是什么意思,而大可不必学习执行者和执行环境参数这种复杂的基本概念,然而新语法中,这些基本概念是根本绕不开的。
  • 以及一个最关键的问题:1.19.50 的更新移除了旧语法。虽然 Mojang 做了一定的向下兼容适配,然而这还是给那些从未接触过新语法的开发者打了一个措手不及。对于那些只想停留在过去而不愿学习新语法的开发者来说,这次的更新堪称灾难。

一些旧版语法的实例

我们现在使用旧版语法来完成我们之前布置的一些习题。当然,你也看到,像是传送到实体眼部、方块正中心、或是检测一片区域这种需求,用旧版语法是不太可能实现的(这里不要把话说死——万一真的有人实现了呢?)。所以我们避开这类题目,挑一些能实现的来实现。

下面我们给出的命令中,高亮的代码是新版语法的答案,你可以进行对比。

练习 2.3-1 第 3 题,写一条“勇敢的村民”的命令——杀死所有村民附近 5 格的僵尸!

设定执行者为村民。完全使村民执行这条命令也是很容易实现的:

/execute @e[type=villager] ~~~ kill @e[type=zombie,r=5]
/execute as @e[type=villager] at @s run kill @e[type=zombie,r=5]

练习 2.3-1 第 6 题,写一条命令,令所有羊传送到它们附近的一只牛的位置,并面向离(0,0,0)最近的一只猪。

适才我们分析过这道题。用一条命令实现这一点是不太可能的。然而两条命令实现却有可能。我们可以先将羊传送过去,然后再把它原地 tp 并面向猪:

/execute @e[type=sheep] ~~~ tp @s @e[type=cow,c=1]
/execute @e[type=sheep] ~~~ tp @s ~~~ facing @e[x=0,y=0,z=0,c=1,type=pig]
/execute as @e[type=sheep] at @s positioned as @e[type=cow,c=1] facing entity @e[x=0,y=0,z=0,c=1,type=pig] feet run tp @s ~~~~~

练习 2.3-2 第 5 题,我们现在假设要使用绊线钩实现这样的开门效果:当玩家靠近铁门 2 格以内,并且背包中有绊线钩时,则在门的下方放置一个红石块以开门,并清除玩家的绊线钩。假设铁门的位置位于(0,-60,0),试写出两条命令,依次执行,以符合需求。
命令 1:_____
命令 2:_____

因为不存在if entity这样的条件子命令,我们直接修改执行者。所幸这题的条件并没有涉及更多实体和更多执行者,因此还是很简单的。将“检测(0,-60,0)附近的玩家”的需求更改为“使(0,-60,0)附近的玩家执行……”,便可以变相地实现检测的效果。在以前,这是很常用的手段。

/execute @a[x=0,y=-60,z=0,r=2,hasitem={item=tripwire_hook}] 0 -60 0 setblock ~~-1~ redstone_block
/execute @a[x=0,y=-60,z=0,r=2,hasitem={item=tripwire_hook}] 0 -60 0 clear @s tripwire_hook
/execute positioned 0 -60 0 if entity @a[r=2,hasitem={item=tripwire_hook}] run setblock ~~-1~ redstone_block
/execute positioned 0 -60 0 as @a[r=2,hasitem={item=tripwire_hook}] run clear @s tripwire_hook

练习 2.3-2 第 7 题,在地图《冒险世界:筑梦》中,有一种道具为「御风珠」,当它砸中淡蓝色带釉陶瓦时,则会将所有玩家传送到附近。现在我们简化这个需求,假设有一个淡蓝色带釉陶瓦位于(-244,32,23),当检测到该位置附近 2 格内有雪球时,则传送所有玩家到该陶瓦下方 3 格,并面向正北方。试写出此命令。

同样地,将待检测的实体直接更改为执行者。

/execute @e[x=-244,y=32,z=23,r=2,type=snowball] -244 32 23 tp @a ~~-2~ 180 0
/execute positioned -244 32 23 if entity @e[r=2,type=snowball] run tp @a ~~-2~ 180 0