[MC源码解读][1.8] 刷石机故障及刷石机效率讨论

本来昨天想看区块加载/卸载和怪物despawn部分的源码的,但是眼贱看到了庄主接受挑战的视频,虽然说挑战发起者不是我,不过这个设计思路跟我之前发的帖子基本一样,而且原帖我正好路过庄主贴吧的时候看到并且插了几句嘴,于是对刷石机这个问题瞬间又提起了兴趣,于是一天都在查这方面的源码。

刷石机设计

刷石的基本原理是利用岩浆和水的相互作用:

  • 当岩浆流向下方的水时,水变为石头
    ![[图]岩浆遇水下落变成石头][]
  • 当岩浆源其他方向是水时,岩浆变为黑曜石
    ![[图]岩浆源遇水变黑曜石][]
  • 当非源岩浆(级数<=4)其他方向是水时,岩浆变为圆石
    ![[图]非源岩浆与水相互作用][]
    岩浆源的级数是0,在主世界每走一格级数+2,末地和下界每走一格级数+1,下落的岩浆级数=原级数+8。

由于挖掘圆石的速度比挖掘石头要慢,而且石头是选择挖成石头还是圆石的,所以高速刷石机一般采用岩浆在上水在下的方式。又因为站着不动挖掘最多能挖5格,所以一般都是5个刷石单元并排作为一组形成一个刷石机。
![[图]5联刷石机][]

为了达到高速刷石的效果,刷出的石头应该尽快“让位”,即把刷石位空出来,于是需要设计活塞电路,将新刷出的石头推出。各种设计不同的高速刷石机主要区别就在这里。

刷石机故障分析

现在是时候说一下刷石机的“隐患”了。

D大刷石机

首先来看D大的刷石机设计,有一个显而易见的问题:当刷出的石头没有及时处理,以致不能再被B组活塞推出时,刷石点下方的格子会被石头堵住,下次开始刷石时就会推掉岩浆:
![[图]D大刷石机崩溃][]
D大为此做了一个快捷关闭机器的压力板,一定程度缓解了这个问题,但用户体验仍不够好,每次开关机器前后要先把石头挖一下。

ET刷石机

我在设计刷石机时令A组活塞平时处于推出状态,这样一来B组活塞推不动的石头会直接被A组活塞推上去阻塞刷石位,阻止新石头的刷出,从而不会出现D大刷石机的问题。但这样一来却引发了新的问题。

我们来看一下岩浆把水变成石头的过程。
理想情况,因为水的流速比岩浆快,一般情况下应该是水先流进刷石位,然后岩浆流下把水变成石头。
但有时候会事与愿违,岩浆可能会先流下,这时候,下流的岩浆由于级数>8,不会变成圆石,另一方面,水是不能流向岩浆的,这格岩浆会一直存在。
但是岩浆可以流向水并把水替换掉,于是之后岩浆会流进水的格子,如果旁边还有别的水,岩浆就会变成圆石。
![[图]圆石故障][]

在D大的设计中,由于A组活塞平时是关闭的,会留出一个空位让岩浆往下流而不会影响水源,而在下一个周期中C组活塞就会把刷石位的岩浆清空,让机器恢复正常运行。
![[图]D大刷石机故障处理][]

但是我的刷石机就不能幸免了,轻则无法刷石
![[图]ET刷石机故障后果1][]
重则毁掉整个机器(这还不算最严重的……)
![[图]ET刷石机故障后果2][]

我的这个刷石机虽然跟D大的很类似,但是实际上是我自己想出来的,出了这样的问题非常令人不爽(然后才看到了D大的帖子并且学D大加了C组活塞)。想了各种办法解决,但一直无功而返。

那么这个问题究竟是如何产生的?又有没有什么解决的方式呢?

要彻底搞清楚这个问题,我们必须了解一件事:MC中液体流动是怎么计算的?是固定若干时间流动一次?还是周围有空格后多少秒流动一格?

看了液体流动有关的代码后得知,当液体接受到方块更新后,会加入一个优先队列,根据液体的流速,在若干游戏刻后进行一次流动(比如水的流速是5,那就是在5刻后流动),同时,如果这块液体已经在队列中排队准备流动了,那么不会再次排队。

既然液体流动的时间和收到的方块更新有关,这样一来,就有了一个新的问题,在我们的刷石机中,液体(即水和岩浆)什么时候会收到方块更新?

为了简化问题,我们在主世界以刷出单个石头的刷石单元为例,并暂时去掉与刷石无关的C组活塞;
![[图]ET刷石机主要部分][]

可以看到,由于玻璃是不会发出方块更新的,那唯一影响水和岩浆的就只有活塞了,具体来说,那活塞什么时候会发出方块更新?

我看完了活塞的代码(看吐了),并做了一些实验。
发现活塞接受到红石信号改变并完全伸出/收回活塞臂共需要3个游戏刻(1.5 ticks),用0,1,2标号这三个游戏刻,那么和活塞运动有关的位置发出方块更新的时刻如下图:
![[图]活塞更新规律][]

对照上图,可以得到岩浆和水收到更新的时刻表格:

时间(游戏刻)0123456
岩浆
(注:5刻时水和岩浆受到的更新来自于水流进刷石位)

而由于只能进队一次,那么假设在上个周期的最后5个游戏刻水和岩浆都没有收到过更新,那进队情况如下:

时间(游戏刻)0123456
岩浆

这样一来在每个周期的第5游戏刻水流会流下,1-4刻便是岩浆流下的“危险期”。由于在主世界岩浆的流速是30游戏刻,那么如果机器的周期是30游戏刻的整数倍,那么岩浆始终会在30的整数倍时刻收到更新,并在刷石位有空位的时候流下;否则,在一个周期中岩浆流下的时刻不固定,很容易在“危险期”先于水流流下来。
(严格说应该是周期的游戏刻数和30的最大公约数>5就可以避开“危险期”)

那么是否只要周期设置的安全就可以完全避免这个问题呢?很不幸,这个答案是否定的。

我为此纠结了很久。后来发现,游戏中会随机对某些方块进行random tick,随机选择方块来做某些操作,这种机制主要用来控制作物生长(D大介绍过),但是如果选的方块是排过队的液体方块,那么就会对这块液体进行一次流动!(不会从队列中删除,即原来设定的流动时间还会再流动一次)

这样一来,在队列中的液体随时都有流动的可能;对于我的刷石机来说,在危险期内,岩浆随时都可能流下。(关于第0游戏刻是否危险:MC运行的顺序是处理液体正常流动、处理random tick、处理活塞。在0刻时,先岩浆流下把水变成石头,然后random tick什么都做不成,然后活塞把石头拉出,所以0刻不会发生故障。)

如果使用C组活塞,能否解决问题?

好消息是,基本可以满足要求。

简单来说,活塞在第x游戏刻接受到n ticks的信号,活塞臂可以在第x+1~x+2*n游戏刻之间阻挡液体流动。那么我们在0刻给C组活塞2 ticks的信号,即可以把危险期完全覆盖!当然其他2组活塞的时序也要对应改一下,改动后的时序如下图:
![[图]ET刷石机改良][]

这里使用了一个2.5 ticks的负脉冲限制器,图片来源于Minecraft英文wiki。
![[图]2.5T负脉冲限制器][]

坏消息是,机器还是有可能会出现故障。

在第5游戏刻的时候,系统会先判定C组活塞已经完全收回,不阻塞刷石位,于是水流出,如果就在这一游戏刻岩浆被random tick了,就会产生石头。如果这时石头都已经刷满没被采集,那么这个新刷出的石头就会被推上一格,堵塞岩浆。
![[图]ET刷石机新故障][]
这种情况出现的概率确实很低,但不能说一点可能性都没,用的时间长了总会有出问题的时候。

庄主刷石机

现在来看一下庄主的刷石机,按照现在的时序,岩浆可能提前下落的时间为第1-9游戏刻。根据庄主现在的时序,A的活塞臂阻挡岩浆的时间为第1-2游戏刻,第5-8游戏刻,危险期为第3-4游戏刻和第9游戏刻。虽然活塞二次推出可以清空在3-4刻下落的岩浆,但有极低的概率岩浆和水在3-4刻连续受到random tick影响而相遇。

而庄主的设计却巧妙地避开了此问题带来的副作用,即使岩浆下落,并且把水变成了圆石,也不会阻塞机器,下一个周期只要不再被random tick影响,就会恢复正常。
![[图]庄主刷石机故障处理][]

完美刷石机设计

看到这里强迫症表示不服,就没有完美的刷石机么?既不会刷出圆石,也不会机器崩溃的?

好!满足你!

实际上,只要把庄主的刷石机的时序改一下就可以了:将A组活塞的伸出时长改为4.5 ticks即可覆盖全部危险期;为了让水流第一时间流出,B组必须在1 ticks推出,时长必须为1 ticks(1.5也可,但麻烦);C组的时序就比较随意了,2刻之后推一下就可以:
![[图]庄主刷石机时序改良][]

产生4.5 ticks脉冲的电路和上面2.5 ticks脉冲电路类似:
![[图]4.5T脉冲限制器][]

刷石机效率分析

增加刷石机产出的方法

至此,刷石机的各种(已知)故障算是完美解决。于是我们可以来谈谈效率问题了。

上文说到过岩浆在主世界流动的速度为30,故而在主世界中,单排刷石机的时钟周期最低也要30,否则不能每个时钟周期都刷出石头。

而为了进一步提高效率,就可以通过增加刷石机组数的方式了,比如这样:
![[图]D大双核][]
甚至这样:
![[图]ET4核][]

信标式刷石机效率分析

由于刷石机可以增加组数,效率的瓶颈成为了石头的处理速度。对于信标式刷石机来说,效率的瓶颈来自史蒂夫的挖掘速度。

先对各位路人解释一下什么叫信标式刷石机吧。这个概念应该最先由D大提出(至少我是最先从他的这个帖子接触的),利用高速刷石机产生石头,然后利用钻石镐附魔效率V(因为wiki的信息和1.8不符所以不贴地址了)+信标急迫II效果,达到极快的破坏方块速度,快速采集石头。
![[图]快速采集][]

很多朋友不理解为什么要用钻石镐采集不用凋零,对这类机器喷的很厉害。我总结原因有这么几点:

  1. 凋零头打起来看RP。
  2. 困住凋零不容易,很危险,特别是在1.8。
  3. 凋零工厂建造更麻烦。
  4. 实际上信标式刷石机主体部分和凋零式一样的,只是处理石头方式不一样。
  5. 这种机器本身就是一种乐趣。(其实上面4条都是编的_(:зゝ∠)_

那究竟多少组是史蒂夫挖掘速度的上限呢?带着这个问题我又看了一下关于挖掘速度的代码,具体信息我会另写帖子,在这里只写结论:在钻石镐+效率V+信标急迫II效果下,可以达到每游戏刻破坏1个方块的速度,也是游戏中破坏方块的最高速度。

那么在主世界中,理论上“6核”可以达到最高效率,为1200石头/分钟(5*6=30)。而在末地,因为岩浆流速为10,只要相当于每个“核”“超频”了3倍,只要“双核”就可以达到最高效率。

凋零式刷石机效率讨论(TODO)

当然上面所说的效率仅限信标式刷石机,凋零式刷石机应该同理,效率瓶颈在于凋零破坏方块的速度。我还没有研究过凋零,暂时无法给出结论。

结语

于是到此我们的讨论可以暂告一段落了。这篇文章前前后后写了整整2天多,大量时间对着代码看,脑子有时候会乱,如果有错误请指出,多多包涵。

[[图]信标式刷石机]: //images0.cnblogs.com/blog/552320/201502/050243257038972.png
[[图]岩浆遇水下落变成石头]: //images0.cnblogs.com/blog/552320/201502/050245554537255.png
[[图]岩浆源遇水变黑曜石]: //images0.cnblogs.com/blog/552320/201502/050251135464034.png
[[图]非源岩浆与水相互作用]: //images0.cnblogs.com/blog/552320/201502/050251399532569.png
[[图]5联刷石机]: //images0.cnblogs.com/blog/552320/201502/050252007342183.png
[[图]D大刷石机]: //images0.cnblogs.com/blog/552320/201502/050252199379982.png
[[图]ET刷石机]: //images0.cnblogs.com/blog/552320/201502/050252395786084.png
[[图]庄主刷石机]: //images0.cnblogs.com/blog/552320/201502/050252554995581.png
[[图]D大刷石机崩溃]: //images0.cnblogs.com/blog/552320/201502/050253159215853.png
[[图]圆石故障]: //images0.cnblogs.com/blog/552320/201502/050314234689096.png
[[图]D大刷石机故障处理]: //images0.cnblogs.com/blog/552320/201502/050254253594333.png
[[图]ET刷石机故障后果1]: //images0.cnblogs.com/blog/552320/201502/050253485782964.png
[[图]ET刷石机故障后果2]: //images0.cnblogs.com/blog/552320/201502/050254088745964.png
[[图]ET刷石机主要部分]: //images0.cnblogs.com/blog/552320/201502/050258170154706.png
[[图]活塞更新规律]: //images0.cnblogs.com/blog/552320/201502/050259098437545.png
[[图]ET刷石机改良]: //images0.cnblogs.com/blog/552320/201502/050259331873076.png
[[图]2.5T负脉冲限制器]: //images0.cnblogs.com/blog/552320/201502/050327029688860.png
[[图]ET刷石机新故障]: //images0.cnblogs.com/blog/552320/201502/050300583744469.png
[[图]庄主刷石机故障处理]: //images0.cnblogs.com/blog/552320/201502/050259588747225.png
[[图]庄主刷石机时序改良]: //images0.cnblogs.com/blog/552320/201502/050300301879890.png
[[图]4.5T脉冲限制器]: //images0.cnblogs.com/blog/552320/201502/050321544373503.png
[[图]D大双核]: //images0.cnblogs.com/blog/552320/201502/050324357498251.png
[[图]ET4核]: //images0.cnblogs.com/blog/552320/201502/050324487342018.png
[[图]快速采集]: //images0.cnblogs.com/blog/552320/201502/050328546714587.png

posted on 2015-02-05 03:40  etflly  阅读(5213)  评论(0编辑  收藏  举报

导航