execute基础
execute 格式大要
execute <实体> <x> <y> <z> <命令>
让<实体>在指定位置(x、y、z坐标。如果是相对坐标则以实体位置为判定点)执行指定命令
execute <实体> <x> <y> <z> detect <方块id> <方块数据值> <x2> <y2> <z2> <命令>
当实体在指定位置(x2、y2、z2坐标。如果是相对坐标则以执行位置为准。执行位置即x、y、z坐标的位置)检测到指定方块(id及数据值必须吻合。如果数据值为-1则代表所有数据值都吻合)时,则在执行位置执行命令(执行位置不是检测到方块的位置,而是先前x、y、z坐标的位置)
由于本教程主要是指出execute有什么主要用法, 而detect比较少用(起码我比较少用), 而且那用法一般也比较简单, 因此本教程不会探讨execute detect的特殊用法
注意
- execute选择到的实体不需要有op权限也可以执行命令(虽然这应该是常识, 然而不知道为什么总会有人问这个问题)
- execute里面可以嵌套execute(然而得注意, 这可能会让执行次数变得极高)。就好像叫别人去命令别人做事的样子。
例子:
execute pca ~ ~ ~ setblock ~ ~ ~ command_block
如果pca的坐标是0 64 0, 则会在0 64 0的位置放置一个命令方块
execute pca ~ ~5 ~ detect ~ ~-5 ~ air 0 setblock ~ ~ ~ command_block
如果pca的坐标是0 64 0, 如果0 64 0是空气,则会在0 69 0的位置放置一个命令方块
execute @e ~ ~ ~ execute @e ~ ~ ~ say hi
如果有两个实体, 则会让该两个实体say hi(每个两次)
execute的运行方式
execute会让选择到的所有实体一个一个的逐个执行命令。
当那些实体全部执行完命令, 这execute命令才算是执行完成。
(所以大量execute嵌套很可能会导致game tick过长)
实体执行命令的次序就是选择器选择实体的顺序
选择器会优先选择在执行的世界的实体/玩家
(先选择最近的实体,当那些实体的距离一样时,它就会优先选择存在最久的)
execute命令的SuccessCount就是成功让多少实体执行命令。
至于AffectedEntities即使成功也只会是1(只是执行了很多次而已)
例子
execute @e ~ ~ ~ say hi
假设实体的排列是A B C D
, 命令方块放在最左边。
执行结果:
[A]hi
[B]hi
[C]hi
[D]hi
execute @e ~ ~ ~ execute @e ~ ~ ~ say hi
假设实体的排列是A B
, 命令方块放在最左边。
执行结果:
[A]hi
[B]hi
[B]hi
[A]hi
(原因和选择器的特性和执行坐标的改变有关, 你们猜猜为什么吧:D)
使用execute改变执行坐标
execute命令能够改变命令的执行坐标, 这对系统的可移植性作出了极大的贡献, 和选择器配合的好甚至能够做到一些原本需要多条命令才能做到的事情。
标记(marker)
为了系统的可移植性, 我们会避免用绝对坐标去标记不同的位置, 甚至连相对坐标也会避免使用。
然而, 有时候我们的命令还是需要知道某些位置才能工作的(比如是要关闭某个命令方块)
这个时候, 我们会把一个特定名字的实体(一般是AreaEffectCloud, 因为即使有大量的AreaEffectCloud对性能的影响是最微小的)放在指定的位置, 然后透过execute该实体去执行需要该坐标的命令(因为execute后执行坐标)
例子
(mark:(名字) 就是在下一个命令方块的位置放置一个指定名字的AreaEffectCloud)
say hi
execute @e[name=1] ~ ~ ~ blockdata ~ ~ ~ {auto:0b}
mark:1
say 这不会执行
由于第二条命令(execute ... blockdata ...)先改变了执行坐标(改为第三条命令的命令方块位置), 再把原地的命令方块关掉。因此就能够关闭第三条命令的命令方块, 从而阻止其执行
特殊用法
有一些execute的特殊用法, 透过巧妙地更改执行坐标和使用选择器, 就能够做到一些原本要几条命令才能做好的事情
本部分由于本人难以说清如何想到此脑洞, 所以只能对用法进行解释, 希望能启发诸位想到更多新奇有趣的用法
生成一直线的实体
(本用法和其他章节的增加执行数量的用法配搭可有更佳的结果)
(本用法有一个限制: 命令的执行坐标必须在开始的那端, 否则可能会造成重叠的现象)
execute @e[name=marker,c=-1] ~ ~ ~ summon ArmorStand ~(间隔) ~ ~ {CustomName:"marker"}
marker就是生成的那些实体的名字, 而间隔部分不一定是要x轴的, 放在任何地方也可以, 甚至三个轴上同时有间隔也并无不可
相信大家也看明白了, 本命令就是透过选择最远的那个marker去生成别的marker, 不停执行则可以生成一串的实体
调换执行
通过execute里让不同实体执行命令的特性, 我们可以做到在实体间调换执行, 以达到某些特殊用途。
相信这样写没人知道我在说啥, 所以接下来会给出两个例子
辗转相除法
就是不停a %= b, b %= a...直至一方为0
按照一般的思路,这个做法得两条命令, 毕竟a %= b, b %= a是两个不同的东西吧。
然而问题来了, 这样子还怎么放在execute里1gt内完成啊?
所以, 就有了一个方法的诞生:
execute @e[tag=num] ~ ~ ~ scoreboard players operation @e[c=1] scb %= @e[c=-1,tag=num] scb
这个方法其实就是这样的: 让a和b去分别把自己的分数%=最远的那个(就是另外一个)的分数
至于怎么做到大量执行次数就留待之后的环节继续讲解了
1 game tick分队
这方法和暴力增加执行次数有点关系
1gt内把一堆实体平均分到n队里, 多出来的实体放在随机队伍里。
这问题有几个难题, 首先怎么做到分配在一个队伍里呢? 这个我们可以使用分数(这是优化了的方法)
放置一堆代表队伍的marker, 它们的team分数代表那队伍, 然后让随机实体的分数=那个队伍的分数
/scoreboard players operation @r[score_team=0,type=!LightningBolt] team = @r[tag=teams,c=1,type=ArmorStand] team
然后, 我们会让所有队伍都有一个实体(由于多出来的实体要放在随机队伍里, 因此我们会随机排序那些队伍)
/execute @r[type=ArmorStand,tag=teams,c=n(n就是队伍数)] ~ ~ ~ /scoreboard players operation @r[score_team=0,type=!LightningBolt] team = @e[tag=teams,c=1,type=ArmorStand] team
然后的部分就是: 让所有需要加入队伍的实体执行一遍上面的部分, 并且加上避免过长执行时间的限制execute(确定还有没有team=0的实体存在)
/execute @e[score_team=0] ~ ~ ~ execute @e[score_team=0,c=1] ~ ~ ~ execute @r[type=ArmorStand,tag=teams,c=n(n就是队伍数)] ~ ~ ~ scoreboard players operation @r[score_team=0,type=!LightningBolt] team = @e[tag=teams,c=1,type=ArmorStand] team
execute暴力增加执行次数
这些方法只适用于执行一条命令的时候
警告: 这些方法建议不要在高频系统里使用(尤其是服务器), 即使使用也请减少执行量, 否则后果严重
实体穷举
这方法适用于需要执行指定次数的命令
方法就是给大量实体一个索引值(1-n或是0-(n-1)), 然后减去需要执行的次数, 然后execute分数<=-1/0的实体去执行命令
http://www.mcbbs.net/thread-629637-1-1.html 这帖子里的自我复制系统可以用别的方法做到以达到瞬间: 1000个实体, 分别有独立的索引值, 减去次数后execute分数<=0的实体去
execute @e[name=marker,c=-1] ~ ~ ~ summon ArmorStand ~(间隔) ~ ~ {CustomName:"marker"}
然后execute所有marker去clone/放置stb并激活
execute嵌套(指数增加执行次数)
实体穷举的办法需要大量实体, 如果不愿意放置大量实体的话可以使用execute嵌套的办法去增加执行次数
execute 实体 ~ ~ ~
*n出来的执行次数会是实体数^n那么多, 因此是增加执行次数的一个好办法
注意: 这办法没法确保执行多少次, 请加入一个execute去检查条件是否已经满足(那条件检测建议放在第二个execute大量实体之前的位置, 否则用途可能会比较小, 见上方1gt分队), 否则会让game tick时间大幅延长, 对服务器造成严重负担
暴力增加次数的特殊情况: CBer的execute问题
问题很简单:
execute @e ~ ~ ~ execute @e ~ ~ ~ execute @e ~ ~ ~ summon ArmorStand
初始实体为2个, 执行完了之后实体数会是多少? 并且为什么是那个数量
这个问题有很多人认为是8(2^3), 然而之后证实了是2048, 而且也找到一个合理解释了, 以下就来为大家解释一下
execute @e ~ ~ ~ execute @e ~ ~ ~ summon Armorstand
execute @e ~ ~ ~
[当前实体数为2, 于是下面会执行两次]
execute @e ~ ~ ~
[当前实体数为2, 于是下面会执行两次]
summon Armorstand
summon Armorstand
execute @e ~ ~ ~
[当前实体数为4, 于是下面会执行四次]
summon Armorstand
summon Armorstand
summon Armorstand
summon Armorstand
从此可以见到, execute的运作就是先选择实体,然后由选择了的实体去执行命令
选择器在选择好了实体之后就不会改变(比如execute @e ~ ~ ~ summon ArmorStand,初始实体数为2,那就只会执行2次),所以第一个execute的数目是不会无限增加下去的
不过,后面嵌套的那些execute会根据执行时存在的实体去选择,所以那个执行次数会变大的很快(因此就不是2^嵌套数那么多个实体)
所以如果要透过execute嵌套去生成实体, 请先小心计算之后会生成的实体量, 以免发生以外的情况
execute与stats
execute和stats配搭使用可以做到好像同时使用了一条命令和修改记分板分数的样子, 可以省却大量的穷举。
然而这也是有限制的, 首先: SuccessCount是整个命令执行完毕才改变分数的而不是一边执行一边增加分数。
其次, execute做成的SuccessCount是会被覆盖而不是继续增加的, 以下会说明嵌套execute时SuccessCount的变化
实体: A, B, C
命令: execute @e ~ ~ ~ execute @e ~ ~ ~ say hi
第一个execute:
[执行者SuccessCount=0]
A: execute:
A: say hi
[A SuccessCount=1]
B: say hi
[B SuccessCount=1]
C: say hi
[C SuccessCount=1]
[A SuccessCount = 3]
B: execute:
B: say hi
[B SuccessCount=1]
A: say hi
[A SuccessCount=1]
C: say hi
[C SuccessCount=1]
[B SuccessCount = 3]
C: execute:
C: say hi
[C SuccessCount=1]
B: say hi
[B SuccessCount=1]
A: say hi
[A SuccessCount=1]
[C SuccessCount = 3]
[执行者SuccessCount=3]
最后不同实体的分数:
A = 1
B = 1
C = 3
执行者 = 3
例子: 1 game tick内给实体增加索引值
这道例子出自CBL新手群问答比赛
索引值可以是1-n, 也可以是0 - (1-n)
方法:
//绑定stats部分(略...)
execute @e[tag=markers] ~ ~ ~ testfor @e[score_SC=0]
解释: 当第一个实体执行testfor的时候, 自然所有实体的SC(SuccessCount分数)都是0了, 所以其索引值(也是SC记分板)为n。之后, 第二个实体执行的时候就有一个实体SC分数大于0, 于是其SC分数只有n-1了。如此类推, 到最后就只能选择到自己, 于是SC分数就是1了
结尾
我老了, 没法研究那么多, 也没时间研究那么多了, 只好把一些歪理论交给各位了, 希望大家能借鉴这里的一点脑洞去创造新的execute用法。
由于是赶着写的教程, 所以可能不太全面, 如有错漏敬请指正, 我会尽快修改/加上的了
如果有有趣的execute作品我会加到下面的列表里的了。如果阁下认为您的作品有比较有趣的脑洞(execute相关), 欢迎回复/私聊我, 如果我觉得有借鉴价值的话就会放在下面的了。
有趣的execute作品列表
- http://www.mcbbs.net/thread-588273-1-1.html execute辗转相除法, 这是我比较旧的作品了, 从这教程的看法来说或许比较差吧, 然而在当时也算是比较有趣的东西了
- http://www.mcbbs.net/thread-514093-1-1.html execute配对实体的方法, 使用stats。这个版本比较旧也比较bug, 不过希望还能用和能给各位一点脑洞吧
- http://www.mcbbs.net/thread-594698-1-1.html 比较深入的解释嵌套execute summon问题, 对脑洞或许没什么帮助, 然而相信对理解execute的运作方面有一点作用