此漏洞未必对所有版本有效。该漏洞被修复后,下文所述的信息将不再适用。
请慎重对待。
更新抑制(Update Suppression)是强制游戏跳过方块更新的做法,更新抑制器(Update Suppressor)是用于完成更新抑制的机器。更新抑制可用于切门、复制方块、物品分身、可控崩溃、方块实体替换,或将方块放置在其它不可能的位置,例如漂浮在空中的告示牌或火把以及不在泥土等方块上的花。
内存溢出更新抑制
内存溢出(Out of Memory,简称OOM)更新抑制是通过填满内存,让游戏抛出内存溢出异常的更新抑制方式。
原理
为了进行更新抑制,我们需要恰到好处地填充游戏内存,这样当我们需要时,内存就能不够用。我们可以使用放在未加载的区块中的乱码书和方块事件列表来填满内存。
填充方块事件列表有几种方式:使用活塞阵列填充和使用飞行器填充。如果使用活塞阵列,我们就需要约37万个活塞。使用飞行器则省去了大量活塞,但需要挂机一会。
强转抑制
强转抑制(Cast Suppression或CCE Suppression)是通过让游戏在玩家更新时抛出ClassCastException类型转换异常的更新抑制方式。
该更新抑制方法一般需要先将讲台进行方块实体替换,替换为潜影盒,需要使用更新抑制进行。因为这个潜影盒是打不开的,又具有更新抑制的能力,有时我们也称这个潜影盒为魔法盒。
原理
类型转换异常(ClassCastException,简称CCE),是Java的一个运行时异常,当一个对象被强制类型转换到一个它不符合的类型的时候被抛出。因此,如果我们可以通过玩家操作抛出一个CCE,也可以用来实现更新抑制。一般而言,我们并不会有这样的机会。但是方块实体替换给了我们这样的希望。
比如说,如果将一个箱子的方块实体换到一个发射器上,当发射器执行发射动作的时候,它会获取自己位置的方块实体,然后不加判断地将其强制转换为一个发射器方块实体。但是我们换了一个箱子的方块实体上去,就抛出了ClassCastException,会导致游戏崩溃甚至是存档损坏。
这个CCE的位置太危险了,但是也给了我们新的希望——也许代码里面有别的类似地不加判断的强制类型转换,可以让我们通过玩家操作瞬时地抛出一个CCE?
当一个潜影盒计算自己的比较器输出的时候,它会获得自己的方块实体,强制类型转换为一个物品栏,然后丢进calculateComparatorOutput()这个函数。实际上,函数calculateComparatorOutput()里面已经包括了安全的类型转换的逻辑,Mojang写在这里的这一处不加判断的类型转换是完全没有必要的,也是危险的。甚至潜影盒之外的别的容器,比如箱子计算自己的比较器输出的时候都没有这个转换。
但是这一处强制类型转换是可以利用的——我们如果能够让一个潜影盒拥有一个非物品栏的方块实体,那么每当比较器想要计算它的输出的时候,就会抛出CCE。那么如果我们将一个比较器从这样的潜影盒里面输出,那么每次更新这个比较器,比较器就会重新计算一次自己该输出的能量以判断是否应该更新自己的状态,于是就会计算这个潜影盒的输出,然后就抛异常了!这个潜影盒加上这个比较器,就构成了一个没有状态、不需要重置的更新抑制器。
制作
为了实现方块实体替换,我们要找到合适的带有方块实体的方块,它被破坏的时候,在删除自己的方块实体之前会发出一次更新,方便我们用别的更新抑制方法打断逻辑,跳过删除方块实体这一步。同时,为了潜影盒可以发出CCE,我们需要换上去的方块实体不能有物品栏。讲台(1.14及以上)和唱片机(1.11-1.13)可以满足我们的要求。
当讲台上面的书被翻页的时候,会发出一个2gt长的红石信号,这个时候讲台处于启动状态。当启动状态的讲台被破坏的时候,会更新自己下方的毗邻。
我们翻书的时候,下面的动力铁轨亮起,触发了更新抑制。这是早于讲台启动状态解除的计划刻被计划的,那么这个计划刻就不再有了,讲台变成了一个常亮的状态,这个时候我们等抑制器复位,然后直接拆掉讲台就可以了。这种方法适合1.18以下的版本。因为此时栈溢出更新抑制仍然适用,我们可以承担一次额外的更新抑制。
在1.15和1.18之间的某个版本
1.18中直接拆掉对着更新抑制器的浮空比较器边上的有书的讲台也可以
现在,我们在保留方块实体地拆掉讲台之后,在那个位置放一个潜影盒上去,就可以得到一个有讲台方块实体的潜影盒了。这就是我们的强转抑制器的核心,更新一个从它这里取输出的比较器,就会触发基于CCE的更新抑制。
应用
当物品被放进投掷器,投掷器物品栏发生变化,发出比较器更新,抑制器中的那个比较器重新计算自己的能量,更新抑制触发。我们就完成了一次物品分身。连续这样操作,我们就可以以极为快速的方式制作物品分身,这是目前已知的最好的物品分身制作的方法。
强转抑制器是无状态的,更新到比较器就抛异常,但是这也不绝对。异常的触发是在计算潜影盒输出的时候发生的,那么如果比较器受到更新可以不计算这个输出,就不会抛出异常了。我们可以对比较器后面的红石导体充能到15信号强度,这样的话,比较器看到15信号强度就不再会检测容器,就不会抛异常了,强转抑制器就被关闭了。
如图所示,灯亮,抑制器启动;灯灭,抑制器关闭。另外,强转抑制器的工作是需要用比较器从潜影盒取输出的,所以说如果把比较器拆了,只有潜影盒在那里,也是安全的,不会触发更新抑制。
栈溢出更新抑制
栈溢出(Stack Overflow)更新抑制是通过填满栈,让游戏抛出栈溢出异常的更新抑制方式。
原理
这种更新抑制器会在一个游戏刻中引起足够的方块更新来导致栈溢出,此时游戏会抛出栈溢出异常。如果更新是由玩家直接引起的,则不会使游戏崩溃,并成功更新抑制。但如果通过其他方式完成,它将使游戏崩溃。
极简更新抑制器
该更新抑制/跳略器最初起源于一个Discord上的截图。
在木活板门上要放置红石线。
使用这个机器前建议打开游戏声音。使用机器需要先打开活板门,之后敲击音符盒B。若敲击音符盒时机器未发出活板门声,则可关闭活板门,进行更新抑制。
历史
在22w11a中,更新的存储从栈更改为队列了,更新顺序不再颠倒,因此栈溢出更新抑制被修复,这在MC-249082中被认为是按预期工作。然而,这个更新已在22w12a中修复,并在一个单独但相关的漏洞报告MC-249181中说这个“漏洞”已经在这个快照中修复了,取而代之的是更新跳略。我们现在常使用内存溢出更新抑制或强转抑制的方法进行更新抑制。
视频
参见
参考
- ↑ BV1zu411p7vy(00:31)
- ↑ 部分视频中两个内容都有讲解
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||