Minecraft 绿萌被活塞移动时的处理顺序
Kenterisent
2020年07月07日 14:11

Hi,我是Kevin。正如标题所说,今天就算了吧,下次一定讲一下粘液块被移动时的处理顺序

由于本人不会读Java,所以本专栏里面的理论都是我经过大量实践猜出来的结果

(你还别说,真的能准确分析2333)

注意:绿萌被移动时的处理顺序只是符合这个理论,并不代表游戏就这么处理的

(虽然我自己也不清楚qwq)

本专栏共两部分,第一部分讲活塞检测粘液块,第二部分则是伸出/收回

由于Minecraft内活塞只能推12个方块,这里就用Carpet Mod将活塞可推动方块的数量调成1000(不用担心mod的影响,不信自己去试试,我在1.12.2不加这个mod的时候测过了 符合的)

第一部分 活塞检测粘液块

一块绿萌在活塞的推动下是一起运动的,但那只是宏观的一起,游戏一次只能处理一个方块的运动,所以微观层面上这些绿萌还是有顺序的,并且这些顺序是可以检测出来的

这个理论就是帮助分析顺序用的

我的打算是用一些例子来讲解这个理论,不然光给你一堆的理论你也看不懂awa,从一维的绿萌到二维到三维,嗯就这样

接下来有请我们No.1绿萌上场

直线型

直线型的绿萌的分析相对简单一点,小渊也讲过,为了保证实体不发生碰撞,推出顺序只能是从远到近推出,再从远到近到位(方块推出:由原方块变成36号方块,方块到位:由36号方块变为原方块)

接下来就用我的理论来分析一下活塞是怎么检测绿萌的(检测结果和最终顺序不一样,最终顺序是在检测结果上作一些改动,下一部分会讲)

再明确一点,这次的检测是针对推出的,对于收回的检测,又是不一样一点的qwq

首先我们要找到活塞的位置,以及方向(图中活塞你总找的到吧,方向是向右你也知道的吧)

接着活塞要进行检测。从哪里呢?你觉得会是哪里呢,当然是从活塞开始检测啦。

找到在活塞朝向上距离活塞最近的绿萌(图中就是活塞右边的那个A,如果活塞朝上,则选上面的绿萌),给他标上1

我们给这五个绿萌标上序号

所以说A=1

接着再以1为基准去探测四周是否有绿萌(条形绿萌是一维的,不用考虑探测顺序问题)

A能探测到什么呢,他在四周只能找到B(只能探测相邻的),所以就给B标号2,所以说B=2

接着再以B为基准探测未标号的绿萌,B可以探测到A和C,由于A已经标过号了,就不管啦。于是给C标号3,所以C=3

以此类推,这样的过程在这里总共有5次

最后,A=1,B=2,C=3,D=4,E=5,这就是我们探测的结果啦,适用于推出

这个探测结果有什么用呢?下一部分会讲,将会用作移动顺序模板

接下来来讲一下一维绿萌的收回探测顺序

直线型(收回)

由于形状一样,我们就还是由左到右ABCDE标下去了

一开始的探测顺序是一样的,我们会得到A=1,B=2,C=3,D=4,E=5

由于这五个绿萌是向后拉的,所以要将其顺序反一下,即

A=5,B=4,C=3,D=2,E=1(注意一下这些都是探测顺序,不要和移动顺序搞混了)

由于向后拉绿萌的顺序和反方向推绿萌的顺序是相同的,你也可以理解成右边有一个活塞在往左推,这样分析出来的结果也是和这个一样的

接下来我们就要升维了,来分析二维绿萌的移动

我们先来分析竖直平面上的绿萌的运动

有请我们的No.2绿萌登场

平面型1

标好号

接下来我们就放弃吧,这太难了开始分析这个东西的推出

一开始的探测顺序还是差不多的,F=1,G=2,H=3,I=4,J=5

接着我们就碰到难题了,活塞朝向是水平的,碰到竖直方向的粘动要怎么处理??

好,接下来就要来介绍推动,拉动,粘动了

找到活塞的朝向(图中是向右)画一个相同于活塞朝向的箭头,找到于箭头方向相同的绿萌,这些就是推动或拉动的绿萌

剩下的绿萌就都是粘动的了

图中ABFGHIJMN都是推动/拉动的,CDEKLO都是粘动的

比如说在J点,他可以探测两个粘动的绿萌:E和K。由于探测一次只能标号一个(粘动探测依次只能标号一个,推动/拉动又不一样一点的),那他要先标哪个呢?

这就要涉及到粘动探测标号顺序了

在竖直平面内,先探测下面(-y方向)的,再探测上面(+y方向)的

有了这个,我们就可以标号啦

很容易就能得出J下面一个标号的是K,即K=6

每当探测完一个粘动探测(推动,拉动探测比较复杂 等下再说awa),就要回到起点(标号1的绿萌)重新探测(图中就是回到F重新探测,但是标号是不会清掉的,不然白探测了awa)

回到1之后继续探测,你会发现所有能探测到的绿萌都是标号的了(虽然说只有一个)碰到这种情况要怎么做呢?直接去检测下一个绿萌(标号2的)然而你会发现还是一样的情况,那就去检测标号3的,情况还是一样的话就去检测标号4的...以此类推

图中检测到标号5的时候,当K还未被标号的时候,他能检测到E和K,然后根据粘动检测顺序来决定先标号的,但是现在能检测到的未标号的绿萌只有E,那就给E标号,标号7,即E=7

接着又要回到标号1的绿萌去检测,过程和上面一样,到标号6的绿萌的时候,探测到了未被标号的绿萌L,就给L标号8,即L=8

随后可以得出D=9

接下来继续回到起点,按照数字顺序依次探测。探测到8号绿萌(绿萌L)的时候,他探测到了O,你们知道MNO这三个之间不是粘动,根据活塞朝向可以判断出反向平行是拉动,所以MNO三个之间是拉动的,即O拉N,N拉M

探测如果探测到了推动和拉动,那要怎么办呢?

探测 拉动优先级>推动>粘动  推/拉动的优先级有多高呢?可以直接无视探测一个方块就回起点的原则,直接继续探测,探测到底为止(探测不到推动/拉动    当然这个不回起点的探测只能探测推动/拉动,不能探测粘动  FGHIJ的探测也是不回起点的,探测到底的时候就是探测到J 然后探测到的绿萌全部是粘动,就回起点)(可以理解成探测完一个绿萌就给这个绿萌标号,然后再在这个标号的绿萌上再探测一次是否有推动或拉动的绿萌可以标号 若有 则继续标号 若无,一般情况下回到起点,特殊情况等下在讲)

由此,当探测到O的时候,发现了拉动的绿萌,于是不回起点继续探测,得出O=10,N=11,M=12

探测到M的时候,已经探测不到未标号的推动/l拉动的绿萌了,于是回起点

由于是拉动,探测结果要反一反,即O=12,N=11,M=10,前面的顺序不变

回到起点之后一样的过程,探测到9号绿萌的时候发现了C,就去给C标号13,然后在C上继续探测是否有推动/拉动,他发现了B,就给B标号14,同理A标号15。因为ABC之间是拉动,所以顺序改成A=13,B=14,C=15

至此我们已经把No.2绿萌全部分析探测完了,得出的探测结果是

(A,B,C,D,E,F,G,...,M,N,O)=(13,14,15,9,7,1,2,3,4,5,6,8,10,11,12)

(1,2,3,4,....,15)=(F,G,H,I,J,K,E,L,D,M,N,O,A,B,C)

注意这些只是探测结果,不是最终的移动顺序

接着来分析这东西的收回

平面型(收回)

原理还是一样,标号和前面那个一样,首先探测到F=1,G=2,H=3,I=4,J=5。由于这五个之间是拉动,则倒序,的F=5,G=4,H=3,I=2,J=1。接着按照数字顺序依次探测,这里是从J开始,再根据粘动探测顺序得出K=6,E=7,L=8,D=9。

回到起到你,依次探测,探测到8号(绿萌L)的时候发现O,于是给O标号10,再在O上探测是否有水平方向探测(推动/拉动)发现了N,于是给N标号11。同理M标号12

前面有说过在一个方向拉绿萌的顺序等于在相反方向上推绿萌(活塞高度一样)

所以MNO之间是推动而不是拉动,MNO标号不用倒序

同理C=13,B=14,A=15

平面型1伸出探测顺序

平面型1收回探测顺序

接下来有请No.3绿萌登场

平面型2

这个的分析就要用到方向了

如图所示

(这个时候看上面的上面那张图)左边是+x方向,右边是-x方向,上面+y下面-y,垂直向内是+z,垂直向外是-z

为什么要用到方向呢?因为粘动探测顺序是-y,+y,-z,+z,-x,+x

图中粘性活塞朝向向上,所以中间那一条都是推动,两侧那两条也是推动,三条中间那两个是粘动

大致分析一下伸出

中间那一条由下到上分别是1,2,3,4,5,接着回起点继续探测。探测到2时发现-x方向和+x方向均有年东方绿萌,根据粘动探测顺序得-x先,所以先标号右边那个粘动,再标号左边那个。剩下的就是两侧那两条了

平面型2伸出探测顺序

收回也是按照收回的套路走,粘动探测顺序还是一样

平面型2收回探测顺序

有请No.4绿萌登场

平面型3

标号

先来分析伸出

G=1,H=2,I=3,J=4,F=5

当在5号上面检测时发现C,于是给C标号6,然后在C上继续检测是否有推动/拉动,发现B和D,且B是拉动,D是推动,根据前面说过的优先级拉动>推动,所以B=7,A=8

因为ABC之间是拉动,所以顺序要倒序,即A=6,B=7,C=8

当检测到推拉分叉时(这里就是之前说的特殊情况)(即含有推动探测和拉动探测的分叉,此处就是绿萌C),根据优先级拉动>推动,应优先探测拉动,拉动探测完了(探测到底了,最后一次探测发现没有推动/拉动探测,此处指探测到A时发现探测不到拉动/推动的绿萌了)应该要返回到上一个推拉分叉继续探测(此处就是回到绿萌C)

所以要回到上一个推拉分叉处(此处即绿萌C)进行探测。探测到D,则D标号9,在D上继续检测是否有推动/拉动,发现E,给E标号10。这里你会发现ABCDE的标号是连着的

这也确实是个小技巧,当活塞朝向是水平的,同一横排的绿萌(中间没有空气)的标号是连着的。假如说再E和J之间再加一个绿萌,那这个绿萌和F的标号就不是连着的,因为中间隔了一个空气。如果说在此基础上再在D和I之间加一个绿萌 那这个绿萌和前面那个绿萌和F的标号就是连着的了。活塞朝向是竖直的话,同一纵列的绿萌(中间没有空气)的标号也是连着的。

这就是伸出了。收回也一样,无非就是CDE之间变成拉动了,ABC之间变成推动了,顺序改一下就行

平面型3伸出探测顺序

平面型3收回探测顺序

顺带说一句,当某个绿萌既可以是粘动的又可以是推/拉动的,那么分析的时候就按照优先级来,也就是按照推/拉动来

平面型4

例如这个,伸出探测顺序就是左下角是1,最底下一排由左到右分别是1,2,3,4

倒数第二排由左到右是5,6,7,8

右上角是16

收回的话 右下角是1 最底下一排从右到左分别是1,2,3,4

倒数第二排从右到左是5,6,7,8

左上角是16

3维的分析也差不多,该介绍的理论也都介绍了。你可以把三维看成多个二维组合而成的,然后每个二维都探测分析过去就行了

讲了那么多探测顺序的分析,那最终运作顺序和探测顺序有什么关系呢?

第二部分 绿萌的伸出/收回

其实关系很简单的,最终运行顺序就是探测顺序的倒序,原先探测顺序里1号在运作顺序里就是最后一个运作的,2号则是倒数第二个...探测顺序里面最后一个则是第一个运作的

那这种顺序要怎么检验呢?

第一种检验方法

第二种检验方法

你还可以用绿萌发出的更新来检测,例如让绿萌更新到活塞,活塞拉红石块接命令方块也是可以的

总结一下

绿萌的移动微观顺序符合我这个探测理论(但并不代表游戏代码就是这么写的)

从于活塞臂(收回状态下应该是活塞板)推着的那个绿萌开始探测

每探测到一个绿萌(方块)就给这个绿萌(方块)标号,并且在这个绿萌(方块)上探测是否还有拉动/推动的绿萌(方块),若有,则标号,并且在这个绿萌(方块)上继续进行探测(只探测推动/拉动)。若无,且之前检测到过推拉分叉,则返回到上一个推拉分叉去探测

优先级:拉动>推动>粘动

若某部分绿萌为拉动的,则探测完要将这部分倒序

粘动探测顺序:-y,+y,-z,+z,-x,+x

探测顺序:拉动,推动,粘动

将探测顺序转变为运作顺序:只需将探测顺序倒序即可