[MCBE]最优美与最恶劣的游戏漏洞:无限方块解析
8848yyds
编辑于 2025年06月22日 20:45

前言

素未谋面的朋友,你好。若你能看到这篇专栏,便意味着这个bug即将/已经被官方修复。但是不要感到遗憾,一切bug终有尽时,但这并不妨碍我们深挖其中机制。

无限方块是我的世界基岩版一个诞生自1.19.50的恶性bug,其恶劣程度足以跻身mc诞生至今的最恶性的bug之列,官方曾于1.19.51尝试对此bug进行过修复。但实际上,无限方块一直存在。但鉴于无限方块可能对游戏环境造成恶劣影响,有关无限方块的讨论始终在极小的范围内进行,知晓无限方块存在与其制作方法的人寥寥无几。

这篇专栏将以尽可能通俗的语言详细阐述有关无限方块的一切,包括其产生原理,相关机制的应用与修复方法。

一切基于游戏版本1.21.2。

$1 简要介绍

首先,什么是无限方块?

无限方块的本质上是一个被单独分离出来的movingBlockActor,即一个坐标不存在movingBlock方块,仅存在movingBlock的方块实体movingBlockActor。

是不是看着很玄乎?没关系,第二章将对此进行详细阐述。

了解完无限方块的本质,接下来就该讲讲无限方块的用途了。

无限方块的用途即是他的名字:一个可以无限再生无限获取的方块。这个方块具有一个非常特殊的性质,无论你是通过挖掘,还是爆炸,亦或是尝试改变他的状态,他都会在1gt内重新“fill”原有的方块。这意味着,我们可以通过这种方式,无限刷游戏中取绝大多数存在的方块。

$2 产生原理

2.1 基础知识

机制1——活塞移动方块逻辑:判断哪些方块应当被移动/移动时被破坏,并将这两类方块所在的坐标记录在俩队列a与b中 -> 不加校验地破坏队列b中所记录坐标的方块 -> 不加校验地移动队列a中所记录坐标的方块。

机制2——方块实体(BlockActor):从代码的角度上看,方块实体是对方块(Block)的补充,他用来记录同一方块不同坐标下的数据。更深入的解析可以参考网页链接。正常情况下,放置本身有对应方块实体的方块时,会同时创建方块的方块实体,移除本身有对应方块实体的方块时,会同时不加校验地移除对应坐标的方块实体。值得注意的是,如果一个坐标已经有方块实体了,他将不会创建新的方块实体而是继承旧的。

机制3——movingBlock与movingBlockActor(以下简称mb与mba):在mc中,mb是一种特殊方块。活塞移动方块本质上是先将方块转化成mb,再将mb转化回方块的。而。而mba则是mb的方块实体。与大部分方块类似,mb本身只包含了mb方块的基本性质,而mba则是记录他所移动的坐标的Block,extraBlock,movingEntity,以及mb所属的活塞的坐标。

机制4——有关mb转b:一般来说,mb转b的过程中都是由活塞主导的。但是,如果mba中记录的活塞坐标不存在活塞时,mba将主动在自身所在的位置放置自身所记录的方块。

2.2 产生无限方块的4个逻辑漏洞

漏洞1:活塞只会记录需要移动的方块的坐标,而不会在移动时再次检测需要移动的坐标的位置的方块合不合法。

漏洞2:当mba中记录的方块为空气时,他会每gt不加校验地将坐标后方的方块移动到坐标位置。

漏洞3:当mba中记录的方块不可移动时,mba中记录的方块会被设置为air,但是记录的方块实体不会清空。

漏洞4:失去mba中记录的活塞的mba,会在不校验自身位置的方块的情况下,每gt尝试放置mba中记录的方块(包括方块实体以及extraBlock)。

2.3 bug的触发

以上逻辑漏洞的触发条件,实际上也是一个bug,但本人认为这个bug更像是无限方块的触发器而非产生无限方块的bug链中的一环,因而没有放到无限方块的逻辑漏洞中——漏洞5:两格方块,如门,床,两格花草,当其中一侧(两格花草是上半部分)被活塞破坏时,会不加校验的破坏另一侧的方块。

下图是一个常见的无限方块制作结构。自下而上分别是活塞/粘性活塞,即将制作成无限方块的方块,祭品,二格草的上半部分。我们以abcd分别代称这4个位置的坐标。其中二格草的上半部分可以通过堆积pt来保留。

现在,让我们梳理一下bug的触发逻辑。

首先,根据机制1,当活塞尝试推动时,会先记录待破坏的坐标d,即高草所在位置,与待移动的坐标b,c,即钻石块,淡蓝色玻璃的位置。

然后,活塞会先破坏坐标d的方块,d坐标的方块被置为air。

与此同时,根据漏洞5,由于高草的上半部分被活塞破坏,其下方一格会被不加校验地连带破坏,也就是c坐标也被置为air。

继续,活塞将尝试移动待移动的坐标b,c。移动后,坐标c,d将产生俩mb,他们对应的mba中将分别记录方块air与钻石块。

接下来,根据漏洞2,由于坐标d位置的mba记录的方块是air,他将继续尝试将坐标后方的方块移动到坐标d位置。此时坐标d位置的mba记录的方块将变成mb,记录的方块实体将由空变成记录了钻石块的mba。

下1gt,根据漏洞3,由于坐标d位置的mba记录的方块mb不可移动,他记录的方块将被置为air,但是记录的方块实体不会因此而置空。

再下1gt,根据机制4,活塞主导坐标d的mb转b,此时d坐标的方块将变成该坐标原mba记录的方块air,同时d坐标的方块实体则变成了该坐标原mba记录的方块实体——记录了钻石块的mba。此即方块实体分离。

最后,我们打掉活塞,由于漏洞4,失去mba中记录的活塞的mba,会在不校验自身位置的方块的情况下,每gt尝试放置mba中记录的方块,也就是每gt在坐标d的位置放置钻石。而又由于钻石本身没有方块实体,所以钻石被移除时该坐标的mba也不会被移除,从此产生了无限钻石。

此刻,无限方块便成功诞生了,我们也知晓了无限方块本质——

单独分离出来的mb的方块实体mba。

如你所见,无限方块的产生充满了巧合与幸运。我们很难再从游戏中找到一条如此优美的bug链了。

很难想象Mojang是如何在没有刻意设计的前提下完成这部分的开发的)

2.4 总结

漏洞1产生了记录坐标为air的mba;

漏洞2移动了不可移动的方块mb,产生了mb的mb;

漏洞3分离了mb的方块实体;

漏洞4则是无限方块工作的前提。

$3 延展

那么无限方块仅仅只是刷取方块这么简单?当然不是。如果仅仅只是如此,那么他便远远称不上是整个mc历史上最恶性的bug之一。

如果你足够细心,想必你已经发现一个恐怖的事实,那就是:在基岩版中,方块实体是能被单独分离出来的!

那么分离方块实体又意味着什么?这里简单说明一下,mc中,相当一部分游戏内行为是通过方块实体来完成的。例如,漏斗的运行,容器的存储,都是通过方块实体实现的。这也意味着通过分离方块实体,我们可以制作一个虚空存储装置。进一步的,由于蓝冰没有方块实体,我们可以制作含漏斗方块实体的蓝冰,以此来提高机器的上限。

但这都不是这个bug的上限!

我们都知道,我的世界基岩版是使用c++编写的,而c++中有一个相当重要的概念——虚表。但是,在基岩版中,大部分方块调用方块实体的函数时,是不会校验方块实体的类型的(推测是在调用方块实体的过程中使用了强制转换)。这也意味着,我们可以通过分离方块实体,来实现相当多的UB(undefined behavior,未定义行为),即方块实体虚表的错误调用。比如,让潜影盒继承箱子的方块实体,来实现盒套盒套盒套盒套盒;又比如,1.20.60-,让钟继承其他方块的方块实体,在钟掉落时便能获取其他方块的掉落物,即获取非法方块(本质上是钟掉落时是通过方块实体的来生成掉落物的)。此外,还能通过类似的方式,来实现诸如破基岩飞行器,无基岩凋零笼,活塞隔空推方块,基于告示牌的游戏内任意函数的调用,等等。

而这些,还仅仅只是由无限方块延展的分离方块实体这一项bug的产物。实际上,除去分离方块实体,还有移动会被活塞破坏的方块,0t活塞等衍生bug,这里不过多赘述。

以上内容的最终解释权归芙芙所有。

$4 修复方式

4个逻辑漏洞对于无限方块的制作来说缺一不可,个人更倾向于修复漏洞2与漏洞3。

贸然修复漏洞1与漏洞4如果可能会导致其他未定义行为。

漏洞2修复方法:移除PistonBlockActor::_moveCollidedEntities函数中有关mba中包含的方块是否是Air的判定。即删除if(Block::isAir(movingblockactor.mWrappedBlock)) pistonBlockActor::_spawnMovingBlock; else字段,让函数直接执行else中的逻辑。

漏洞3修复方法:移除MovingBlockActor::tick函数中有关mba中保存的方块是否可移动的判定。即删除if(movingBlockActor.mWrappedBlock->hasProperty(BlockProperty::Immovable) || movingBlockActor.mWrappedExtraBlock->hasProperty(BlockProperty::Immovable)) { defaultBlockPtr = BlockTypeRegistry::getDefaultBlockState(&BedrockBlockNames::Air,1); movingBlockActor.mWrappedBlock = defaultBlockPtr; movingBlockActor.mWrappedExtraBlock = defaultBlockPtr;}这段逻辑。

漏洞4个人推测可能与防止区块保存时意外出现了保存了活塞所在区块已更新,但是mb所在区块保存未更新的情况。但是我们仍然可以降低其出错的概率,比如在mba放置方块之前先判断该位置的方块是否为mb。

这里提供一个修复方块实体分离/无限方块的levilamina插件:https://github.com/kuangby/InfiniteBlockFixer

其他

关于无限方块源码级研究主要是我与奈茶泡芙合作完成,工作开始于24年8月,结束于25年年初。

专栏于25年4月编写完成,将于合适的时间公开。

鸣谢无限方块发现者panda4994万岁。