冷域LYOfficial
更新抑制原理与CCE强转抑制效果的分析

注:作者并非专业研究人员,仅凭爱好学习研究分析得出本文,若阅读发现问题请评论或私信指出,感谢支持!
引入
众所周知,更新抑制的方式有栈溢出更新抑制和内存溢出更新抑制,而在Java版1.19(22w11a)之后,栈溢出更新抑制的特性被移除,无法再通过填满栈让游戏抛出栈溢出异常,从而达到更新抑制。
在此前一些版本中可用的基于栈溢出更新抑制的更新抑制器,到了1.19变成了更新跳略器,在1.20以上版本彻底无法使用了。且随1.20版本大改,许多物品复制的特性都被修复,这使得高版本更新抑制和物品复制变得更加困难。
听不懂?那我们来简单描述一下……
更新跳略是什么?
在Minecraft中,连锁方块只能更新100 0000次,如果通过某些手段使更新次数超过了100 0000次,更新跳略就会发生,即强制跳过方块更新。这一段是写在代码里的规则,不属于Bug,玩家可以利用更新跳略来切下界传送门,从而为农场达到极高效率。
如下图,是TecoCraft的史莱姆农场,使用更新抑制器(1.16.5版本,在1.19为更新跳略)切出的y0单层地狱门,将主世界史莱姆区块的史莱姆生成时传送至地狱处死,双维度处理可以大大提高农场效率。


然而,更新跳略并不能用来做物品复制,只有更新抑制能做到这个。
更新抑制是什么?
强制游戏跳过该游戏刻中部分方块更新及其之后需要执行的代码的做法,它允许玩家引起部分方块的方块更新,而其他方块不会发生方块更新。

——Minecraft 中文 Wiki
按照常理,游戏循环发生异常或出现不该发生的情况会抛出故障,从而使服务端关闭,即常说的“崩服”。但如果是由玩家产生的方块更新造成了崩溃,虽然会被捕获但没有处理,服务器还可以正常运行。
也就是说,玩家可以产生不被处理的崩溃且不造成崩服,此时会触发更新抑制。
方块更新是什么?
放置或破坏方块、红石更新(如改变中继器延迟、激活侦测器、打开陷阱箱、激活动力铁轨)、玩家交互(开关门、活板门、栅栏门、拉杆)、红石元件运作(如发射器发射、阳光传感器状态改变、TNT爆炸)、作物生长……
以上这些都是方块更新。
然而,与玩家有关的方块更新如放置或破坏方块、玩家交互(开关门、活板门、栅栏门、拉杆),是玩家改变了这个方块的状态,属于玩家行为,其他都是基于计划刻或其他方块事件更新或实体更新。
可以由玩家交互改变状态的方块举例:

简单来说,方块更新可以分为玩家更新和其他更新,这两者是不同的。
然而,红石的更新是有位置性和方向性的,在《红石理论进阶》中我们就提到过:
每个更新源更新周围的6个方块时符合简单理论(-x +x -y +y -z +z),但7个更新源的更新先后顺序会随位置变化。转为汉语就是“西,东,下,上,北,南 ”。

以上是红石更新顺序(侦测器除外)。
更新抑制器是什么?
更新抑制器是抑制方块更新的一种装置,可以避免方块更新,从而实现切门、浮空沙、浮空铁轨等按照常理无法完成的操作。
在过去(1.19之前),达到更新抑制的简单办法就是第一种栈溢出更新抑制,往栈堆里填东西,也就是一直产生更新到更新不到方块为止。
首先,我们说一下更新抑制器需要用到的材料——BUD方块。
BUD方块,全名方块更新感应器(Block Update Detector),英文缩写为BUD,可以用来检测附近的NC更新,可以忽略一些不稳定的更新,例如铁轨和活塞。而BUD态即未触发的检测器,BUD态方块一旦更新就会立即运算,可以用来向栈里堆叠大量无用信息。
很抽象?我们解释一下。

上图是TecoCraft史莱姆农场旁边的更新抑制器,是一个大型的动力铁轨阵列,动力铁轨就属于BUD方块,可以被红石激活,也可以检测方块更新。可以做成图中排式结构,当然也可以是一层层的塔型结构,拉下拉杆激活铁轨,当被更新的动力铁轨达到一定数量,就会造成栈溢出,之后的操作不会被计算,达成更新抑制的效果。
上面我们提到,红石更新顺序是“西,东,下,上,北,南 ”,玩家拉下拉杆激活铁轨,铁轨更新会优先向西更新,如果向西更新内容超过栈容量,就会溢出,剩余向西的更新和其余几个方向的更新就会被忽略。
栈溢出更新抑制是什么?
栈溢出更新抑制即按照上文所述方案,通过堆栈溢出达到更新抑制的方法。
这种方法在1.19之前的版本中十分适用,是普遍的更新抑制器,然而在1.19变成了更新跳略器,功能被砍,在1.20以上版本彻底无法使用了。因此便有大佬研究出了新的更新抑制方法——内存溢出更新抑制。
内存溢出更新抑制是什么?
顾名思义,栈溢出更新抑制是要填满栈,内存溢出更新抑制就是填满内存,使游戏抛出内存溢出异常从而达到更新抑制的方法。
正如上所述,新版本栈溢出更新抑制的特性被移除。若用之前的栈溢出更新抑制办法,高版本无法再切门刷物品就是不可行的了。
和栈溢出更新抑制,想要实现内存溢出更新抑制,首先要让服务端崩溃,但又要避免游戏崩溃。
这种填充游戏内存让服务端崩溃的方法叫做内存溢出更新抑制(Out of Memory)简称OOM。
如何造成数据溢出?
不知各位有没有了解2b2t的禁人塔和禁人书,往一个区块里面塞大量带数据的实体方块,比如告示牌,一加载这个区块,你就要下载非常大量的数据,造成玩家数据溢出,从而被服务器踢出,禁人书即向书中写大量内容从而超出玩家数据容量,使玩家被服务器踢出。
上面的禁人方法便是通过特殊操作使玩家数据溢出达到目的的。而要造成服务器崩溃,需要使服务器栈或内存溢出。
如何做到内存溢出更新抑制?
如上所述,让我们来看看他们禁人的一种作案工具——书与笔。
写满乱码的书可以储存大量数据,像禁人塔一样,将它们放在未加载区块内,一旦被同时加载会占用大量内存,再借助活塞,将活塞的下图数据存在列表中,一旦更新相关区块,这些活塞信息会被突然加载,可以迅速填满所有内存。

为什么需要强转抑制?
想要真正实现OOM,需要造很大的一台内存溢出更新抑制器,工程量难以想象。
在2023年07月31日,清华联盟工坊(THUnion)主服务器在经历了十天的奋力尝试和二十余次的失败后,成功完成了世界第一次在 1.19+ 生存模式下进行的更新抑制,成为了世界第一个拥有更新抑制的 1.19+ 生存服务器。
这么大的工程,建一台就费劲,服务器里那么多需要更新抑制器的工程,难道每个机器旁边都要建一台吗?
这时候我们就需要CCE更新抑制了,它的实现主要靠一个潜影盒,而想要得到这个潜影盒,仅需要建造一台更新抑制器。
什么是CCE强转抑制?
讲了这么多,都是引入内容,现在我们来讲一下CCE。
强转抑制(Cast Suppression),或CCE更新抑制(CCE Suppression),是通过让游戏在玩家引起方块更新时抛出ClassCastException类型转换异常的更新抑制方式。

——Minecraft 中文 Wiki
CCE更新抑制是由国内大佬Void0发现的,其CCE是ClassCastException的简称,是一种Java运行异常,即类型转换异常。
通过方块实体替换技术,通过玩家操作使一个方块替换,而改方块的实体数据仍然保留。当我们在对这个方块进行激活操作时,由于实体数据未变,该方块将要执行原方块的动作,但由于该方块并非原来的方块,服务端会强制将其转换为原方块,导致该方块对象类型被异常转换,Java就会抛出CCE异常,从而使游戏崩溃。
在Minecraft中,可用的CCE抛出有很多,然而均容易导致崩服,不能在避免服务端崩溃的情况下进一步操作,这使得更新抑制无法发挥作用。
Void0查找发现:
当一个潜影盒计算自己的比较器输出的时候,它会获得自己的方块实体,强制类型转换为一个物品栏,然后丢进 calculateComparatorOutput() 这个函数。 [5]
众所周知,比较器可以检测容器内物品栏物品多少并输出信号,而潜影盒是有物品栏的,可以被比较器检测,并由比较器输出信号。
如果通过方块实体替换技术,将其他没有物品栏的方块替换为潜影盒,比较器想要计算潜影盒内容量并输出的时候,就会抛出CCE异常。
然而如果使用 /data get block  获取这个潜影盒的实体数据,就会发现这个方块并非潜影盒,而是其他方块。
这里以TecoCraft全物品旁的CCE物品分身为例。

如图即为一个可以正常使用的CCE强转抑制器,我们获取这个潜影盒的方块数据,会发现其实它是个讲台。


也就是说,这是个套着潜影盒皮子的讲台。
然而实现强转抑制,并不是讲台多厉害,只是因为书架上翻书时可以发出2gt红石信号,而真正厉害的是潜影盒,这个盒子也是打不开的,Void0称其为“魔法盒”。

如何替换讲台为潜影盒?
这一步很关键!
首先,讲台上是可以放一本书的,而书的翻动则会使讲台启动并输出信号。而这个信号的时长是2gt,若能在讲台启动的时候将讲台破坏掉,它就会更新下方的毗邻方块。
想要做到这一点,首先要有一台更新抑制器,1.19之前的可以选择栈溢出更新抑制器,1.19之后可以选择内存溢出更新抑制器。
2023年4月29日,NicNac在Discord上公布了极简更新抑制器(同样只适用于1.19以下版本)。

因此,我们可以利用这个超迷你的更新抑制器制作出体积更小的CCE更新抑制器。
准备好更新抑制器后,将讲台的输出与更新抑制器的启动装置相连,使得讲台上书翻动的时候讲台启动并输出信号,启动更新抑制器,从而实现更新抑制,让讲台保持启动状态,此时破坏讲台,并在讲台的原位置上放上潜影盒,即可得到一个有着讲台数据的潜影盒。


就像清华联盟工坊动态中说的:
一次内存溢出更新抑制可以永久地解锁类型转换更新抑制,然后我们就可以用类型转换更新抑制来在整个服务器里面建造更多的强转抑制器了。
如何使用CCE进行物品分身?
当成功获取“魔法盒后”,通过其旁边的拉杆可以控制CCE更新抑制器的开闭。
而其对格比较器周围的三个方块就处于更新抑制状态,如下图表示。

将拉杆这种必须依附在方块上的方块放在上面,再打掉下面的方块,就会出现浮空拉杆现象。

浮空铁轨、浮空压力板什么的更不在话下。

还是以TecoCraft全物品旁的CCE物品分身为例。

我们可以看到,图中比较器旁边的投掷器恰好是上面三个方块之一的3号方块,可以被CCE更新抑制。
当我们拉下拉杆,红石灯灭,代表CCE更新抑制开启,这时候投掷器的更新会被抑制。
打开投掷器,将需要分身的物品放在物品栏数字栏内,通过按动数字键向投掷器放入物品并取到其他槽位中。
退出投掷器界面,会发现这些物品已经分身到其他物品栏槽位中,但是要注意,此时的物品只是原来第一个物品的分身,本质上还是同一个物品,当使用或丢出时是一起使用和一起复制。
有人要问了,那这个有什么用呢?当然有用,如果此时你退出服务器并重新加入,物品分身就会保留成新物品,从而实现物品复制。

小结
无论在哪个版本,国际版还是网易版,“刷物品”一直是大量玩家所喜欢的,通过一些游戏特性来批量复制一些难以获取的物品(如鞘翅、附魔金苹果等),可以减少跑图,减少存档体积,同时减少游玩时间达到更高产出效率。
在一些生电玩家看来,切门双维度一直是达到高效率的巧妙方法,主世界与地狱一方生成一方处死,使得产物效率最大化。
每个版本都会有自己的漏洞,比如海豚复制、悦灵复制,这些漏洞终究还是会补上的。而基于更新抑制的刷物品和切门,是代码深层的内容,也是十年来几乎没有改动的代码内容,是能更稳定进行的。
新版本栈溢出更新抑制的修复,让大量玩家灰心丧气,纷纷表示游戏变得难玩了。然而OOM的发现给了玩家们新的思路,但也因其巨大的体积而纷纷放弃。
好在CCE的发现,让生电玩家们免于疲劳建造大型更新抑制器,达成“一次努力,终生享用”的成就。
正如Void0所述:
等到那时候,1.19 的服务器可以花几个小时的时间操作第一次内存溢出,解锁强转抑制器的科技,然后更新抑制将像以前的版本一样,满血复活。
到现在,打开Minecraft中文Wiki,还能看到Void0那句震撼人心的话:
这可不是一台更新跳略器,这是一台货真价实的更新抑制器!
感谢阅读!

资料来源:
1] 【MC|熟肉】更新抑制讲解【Xcom6000】https://www.bilibili.com/video/BV1m7411i7cy[2] [1.14.4]如何不用珍珠到达边境之地?https://www.bilibili.com/video/BV1bz4y1X7Vu[3] 【MC|熟肉】强转抑制器与更新抑制革命【Igna778】https://www.bilibili.com/video/BV1tg4y1w7J5[4] 【MCJE 1.14-1.19+】基于 ClassCastException 的更新抑制!https://www.bilibili.com/video/BV1Hu4y1o71G[5] 关于强转抑制器的笔记 https://www.bilibili.com/read/cv24323749[6] 【MC|熟肉】1.19更新抑制原理讲解【Igna778】https://www.bilibili.com/video/BV1zu411p7vy[7] 清华联盟工坊的动态 https://www.bilibili.com/opus/8245254017641350614[8] [Minecraft Wiki:沙盒/教程/更新抑制 - Minecraft Wiki9]  [[TECO出品]《红石理论进阶》 | Part I 红石·反应原理 第一章:红石更新顺序
模板来自 TecoStudio 小组
by 冷域LYOfficial

来自群组: TecoStudio

第一页 上一页 下一页 最后一页