首頁 游戲

Minecraft指令手冊

第七十四章 探究:execute的運行流程

Minecraft指令手冊 你好MC 645 2020-02-12 17:45:20

  (注:非常不推薦在手機上閱讀此章節(jié),請使用平板或電腦閱讀此章)

 ?。ū菊掠玫搅舜罅康淖址嫞锌赡軙霈F(xiàn)嚴(yán)重的錯位情況,可手動調(diào)整字體和大小至最佳狀態(tài))

 ?。ù苏鹿?jié)已于2022年7月17日重寫)

  在第六十九章,我為了提醒你注意各個子命令的順序,專門舉了個例子:

  /execute as @e at @e run tp @s ~~1 ~

  但是你是否有注意到游戲運行這條指令的過程:

  ①將玩家傳送至玩家上方1米的位置(玩家此時抬高了1米)

 ?、趯⑼婕覀魉椭链迕裆戏?米的位置(玩家此時位于村民上方1米)

  ③將玩家傳送至羊上方1米的位置(玩家此時位于羊上方1米)

 ?、軐⒋迕駛魉椭镣婕疑戏?米的位置(村民此時位于玩家原本位置上方1米,玩家此時位于羊上方1米)

 ?、輰⒋迕駛魉椭链迕裆戏?米的位置(村民此時位于村民原本位置上方1米,玩家此時位于羊上方1米)

  ⑥將村民傳送至羊上方1米的位置(村民和玩家此時位于羊上方1米)

 ?、邔⒀騻魉椭镣婕疑戏?米的位置(村民和玩家此時位于羊原本位置上方1米,羊位于玩家原本位置上方1米)

 ?、鄬⒀騻魉椭链迕裆戏?米的位置(村民和玩家此時位于羊原本位置上方1米,羊位于村民原本位置上方1米)

 ?、釋⒀騻魉椭裂蛏戏?米的位置(村民、玩家和羊此時都位于羊原本位置上方1米)

  這個過程有何特殊的呢?

  你仔細(xì)看看第④、⑤、⑦、⑧和⑨條過程,你有沒有什么發(fā)現(xiàn)?

  當(dāng)游戲?qū)⒋迕駛魉椭镣婕疑戏?米的位置時,雖然玩家已經(jīng)被傳送至了羊上方1米的位置,但游戲仍然將村民傳送至玩家原本位置上方1米,而不是羊上方2米的位置。

  這是怎么回事?

  我們設(shè)玩家(2,2,2)為A、村民(3,2,3)為B、羊(4,2,4)為C,游戲在運行execute時,其實它的流程是這樣的:

  execute---A---------B---------C

  游戲先解析as @e,得到了上面的三個目標(biāo)。

  execute---A---------B---------C

  ------------↓---------↓----------↓

  ---------2·2·2-----2·2·2-----2·2·2

  ------------↓---------↓----------↓

  ---------3·2·3-----3·2·3-----3·2·3

  ------------↓---------↓----------↓

  ---------4·2·4-----4·2·4-----4·2·4

  然后游戲會解析at @e,預(yù)先將實體的位置記錄下來。上面為了方便展示,用x·y·z來表示坐標(biāo)。

  execute---A------------------------B-----------------------C

  ------------↓-------------------|----↓------------------|-----↓

  ---------2·2·2—3·2·3—4·2·4-|-2·2·2—3·2·3—4·2·4-|-2·2·2—3·2·3—4·2·4

  ------------↓-------↓-------↓---|----↓------↓-------↓---|----↓-------↓-------↓

  -----------①------②------③---|---④-----⑤------⑥---|---⑦------⑧------⑨

 ?、伲?tp 玩家名 2 3 2

 ?、冢?tp 玩家名 3 3 3

 ?、郏?tp 玩家名 4 3 4

  ④:/tp 村民UUID 2 3 2

 ?、荩?tp 村民UUID 3 3 3

 ?、蓿?tp 村民UUID 4 3 4

 ?、撸?tp 羊UUID 2 3 2

  ⑧:/tp 羊UUID 3 3 3

 ?、幔?tp 羊UUID 4 3 4

  接下來游戲會解析run tp @s ~~1 ~,根據(jù)三要素,將其中的目標(biāo)選擇器和相對坐標(biāo)等參數(shù)具體化(但計分板分?jǐn)?shù)之類的不會具體化,因為沒必要),得到具體的指令(如上)。

  最后,游戲運行具體的指令,也就是本章最開頭的那九個過程。

  其中,最重要的,也是最關(guān)鍵的一點,就在于execute指令解析at @e的過程。

  execute并不是說運行一次解析一次,而是先全部解析了再運行,所以并不會使得『村民傳到玩家傳送過后上方1米的位置』之類的事情發(fā)生。

  能理解吧?

  那問題來了,如果execute再套一個execute會發(fā)生什么?比如我們將上述指令寫成:

  /execute as @e run execute at @e run tp @s ~~1 ~

  其實效果還是一樣的,具體原因就等你自己去推導(dǎo)吧,按照我上面的流程去推導(dǎo)。

  這就是Java execute 1.13+版本的運行流程。如果你還不懂,我們再看一個簡單并且效果比較明顯的例子。

  設(shè)有盔甲架A和B,分別位于主世界的(40,-60,29)和(42,-60,29)??准蹵的生成時間比盔甲架B更早,已加載區(qū)塊中沒有其他盔甲架。在盔甲架A、B旁運行如下指令:

  /execute as @e[type=minecraft:armor_stand] at @s run tp @e[type=minecraft:armor_stand,distance=1..3]~~10 ~

  讓我們分析一下,運行上述指令會發(fā)生什么。

  首先,如果我們按照正常的思維去分析這條指令,就會得到以下結(jié)果:

  A會先將B傳送到自己上方10米的位置,B由于處于那個位置無法選取到A來傳送,最終僅僅B會被傳送到A的上方10米處。

  但其實,如果你真的去運行這條指令,就會發(fā)現(xiàn)A和B都會被傳送到對方原位置的上方10米處。

  為什么?我們按照游戲的思維分析一下就可以了:

  execute---A---------B

  游戲先解析as @e[type=minecraft:armor_stand],得到了上面的兩個目標(biāo):盔甲架A和盔甲架B。

  execute---A--------------B

  ------------↓--------------↓

  -------40·-60·29-----42·-60·29

  然后游戲會解析at @s,預(yù)先將實體的位置記錄下來。

  execute---A--------------B

  ------------↓--------------↓

  -------40·-60·29-----42·-60·29

  ------------↓--------------↓

  -----------①-------------②

 ?、伲?tp 盔甲架B的UUID 40 -50 29

 ?、冢?tp 盔甲架A的UUID 42 -50 29

  接下來游戲會解析run tp @e[type=minecraft:armor_stand,distance=1..3]~~10 ~,根據(jù)三要素,具體化指令,得到具體的指令。由于此時還未傳送,所以目標(biāo)選擇器會分別選擇到『盔甲架A』和『盔甲架B』。

  最后,游戲按照順序執(zhí)行指令,分別將盔甲架A和盔甲架B傳送到對方上面10米高的位置。

  這個例子比較簡單,你應(yīng)該能夠理解吧?

  所以你明白了嗎?

  上面講的是Java1.13更新后的execute指令其運行的具體流程,那么Java1.13更新前的呢?以及基巖版的呢?

  2016年6月22日,MCBBS大佬pca006132在『礦工茶館』發(fā)布了一個猜猜樂(ID:594475),大致的問題如下:

  execute @e ~~~... summon ArmorStand,這個指令在初始實體不同數(shù)目的時候出來的結(jié)果是什么

  沒想到竟然沒人能夠解答這個問題,于是這位大佬在次日講解了這個問題(帖子ID:594698)。他舉了一個簡單的例子:

  當(dāng)初始實體數(shù)為2時,運行execute @e ~~~ execute @e ~~~ summon Armorstand

  這個例子的結(jié)果竟然是8。

  那如果在相同的初始情況下,運行execute @e ~~~ execute @e ~~~ execute @e ~~~ summon Armorstand,即套了三個execute的指令會發(fā)生什么?

  答案是:2048。

  很令人震驚??!那為什么會這樣呢?

  如果我們在Java1.13及以上版本,運行類似的指令,將達(dá)不到一樣的效果,因為在Java1.13之前,execute的運行邏輯是完全不一樣的。

  那么到底是個怎么個邏輯法呢?其實在Java1.13前,execute并不會在運行前先存好各種數(shù)據(jù),而是運行一遍解析一遍。以上面那個嵌套了3層execute的指令為例子,我們來解析一下。

  條件:初始兩個實體A(1,2,1)和B(2,2,2),A比B離執(zhí)行地點更近。

  execute---A----------B

  ------------↓

  ----------1·2·1

  游戲先解析第一個『execute @e ~~~』,得到了上面的結(jié)果。后面我們將會忽略執(zhí)行地點,因為這邊不需要考慮執(zhí)行地點的影響。

  execute---A----------B

  ------------↓

  ---------A——B

  游戲按照順序,先以A為執(zhí)行者運行指令,并解析了第二個『execute @e ~~~』,得到了上面的結(jié)果。

  execute---A----------B

  ------------↓

  ---------A——B

  ---------↓

  ------A——B

  游戲按照順序,再次以A為執(zhí)行者運行指令,并解析了第三個『execute @e ~~~』,得到了上面的結(jié)果。

  execute---A----------B

  ------------↓

  ---------A——B

  ---------↓

  ------A——B

  ------↓-----↓

  ------C-----D

  第三個execute運行指令,產(chǎn)生了新的盔甲架C和D。

  execute------A----------B

  ---------------↓

  ---------A————B

  ---------↓---------↓

  --------+2---B—A—C—D

  游戲回到第二層execute,以目標(biāo)選擇器順序選取B為執(zhí)行者,由于之前已經(jīng)生成了C和D,所以B運行第三層execute指令時,會選取到4個實體來運行指令,最終實體數(shù)量+4(現(xiàn)在為8=2+2+4)。

  execute---A-----------------B

  ------------↓-----------------↓

  ----------+6----B—A—C—D—E—F—G—H

  游戲回到第一層execute,以目標(biāo)選擇器順序選取B為執(zhí)行者。由于已經(jīng)有了八個實體,因此這一次第二層execute會選取到八個實體來運行第三層execute。

  execute---A-------------------------B

  ------------↓-------------------------↓

  ----------+6----B——A——C——D———E———F———G———H

  -----------------↓-----↓-----↓-----↓-------↓-------↓-------↓-------↓

  --增加實體數(shù)---+8--+16--+32-+64--+128--+256---+512--+1024

  --增加后數(shù)量----16---32---64---128----256---512----1024---2048

  隨后,游戲按照順序依次以這八個實體運行指令,實體數(shù)量在此過程中快速增長,最終變?yōu)?048。

  不難發(fā)現(xiàn),每一次第三層的execute指令被運行,都會將當(dāng)前實體數(shù)量×2,而上面一共運行了10次第三層的execute,相當(dāng)于2被乘以了10次2,也就是2×2×2×2×2×2×2×2×2×2×2,即2的11次方,結(jié)果為2048,即2048個實體。

  實在是太令人驚訝了是不是?在Java1.13以下的execute指令中,execute僅僅會在被選取的執(zhí)行者開始執(zhí)行指令時才會進(jìn)行下一步的解析動作,而且不會一下子就將所有執(zhí)行者運行指令的情況全部解析出來再運行指令。

  所以,Java1.13對execute的改動不僅僅是格式上的,還有運行流程上的改動。

  如果你并不能很好理解上面為什么會由2個實體產(chǎn)生出2048個實體,別擔(dān)心,我們繼續(xù)以剛才兩個盔甲架互相傳送為例子,看看類似的指令在Java1.13以下的版本有何不同的效果。

  還是設(shè)有盔甲架A和B,分別位于主世界的(40,60,29)和(42,60,29)??准蹵的比盔甲架B更靠近執(zhí)行地點,已加載區(qū)塊中沒有其他盔甲架。在盔甲架A、B旁運行如下指令:

  /execute @e[type=armor_stand]~~~ teleport @e[type=armor_stand,r=3,rm=1]~~10 ~

  游戲先解析『execute @e[type=armor_stand]~~~』得到如下結(jié)果:

  execute---A----------B

  ------------↓

  -------40·60·29

  然后以A為執(zhí)行者,解析『teleport @e[type=armor_stand,r=3,rm=1]~~10 ~』,得到了如下指令:

  /teleport 盔甲架B的UUID 40 70 29

  運行上述指令,盔甲架B被傳送至(40,70,29)處。隨后游戲以B為執(zhí)行者,先解析執(zhí)行地點參數(shù)『~~~』,得到如下結(jié)果:

  execute---A------------------B

  ------------↓------------------↓

  -------40·60·29---------40·70·29

  --將B傳送至40·70·29

  接下來,游戲以B為執(zhí)行者,再次解析指令,得到如下內(nèi)容:

  選擇器'@e[type=armor_stand,r=3,rm=1]'什么都沒找到

  沒錯,由于B被傳送到了(40,70,29),因此目標(biāo)選擇器就選不到A,自然就無法執(zhí)行指令。最終,正如我們在最開始以正常思維分析的那樣,得到了如下結(jié)果:

  A會先將B傳送到自己上方10米的位置,B由于處于那個位置無法選取到A來傳送,最終僅僅B會被傳送到A的上方10米處。

  雖然在Java1.13更新后,我們的『正常思維』沒用了,但在Java1.13以下版本還是很準(zhǔn)的。

  那在基巖版呢?

  作者在基巖版也測試過了(用的上面的兩個盔甲架tp法),確認(rèn)基巖版不管是舊版還是新版(1.19.10更新的)的execute,都是會得到和Java版1.13以下版本一模一樣的數(shù)據(jù)。

  其中,對于目前還在測試的新版execute,用的是如下指令:

  execute as @e[type=armor_stand] at @s run tp @e[type=armor_stand,r=3,rm=1]~~10 ~

  也就是說,如果你在基巖版運行上面套了3層execute的生成指令,在初始實體數(shù)為2的情況下,也會得到有2048個實體的纟

  ......

  ......

  ......

  :(

  你的電腦遇到問題,需要重新啟動。

  我們只收集某些錯誤信息,然后為你重新啟動。

  ......

  ......

  ......

  ——附錄:跟本章有關(guān)系的MCBBS帖子原鏈接

  www.mcbbs.net/thread-594698-1-1.html

  www.mcbbs.net/thread-594475-1-1.html

 ?。ㄉ鲜鎏泳驯籑CBBS論壇系統(tǒng)自動關(guān)閉)

按 “鍵盤左鍵←” 返回上一章  按 “鍵盤右鍵→” 進(jìn)入下一章  按 “空格鍵” 向下滾動
目錄
目錄
設(shè)置
設(shè)置
書架
加入書架
書頁
返回書頁
指南