介绍
目前为 1.17+ 版本结构变体的前置,同时也修复了一个 Minecraft 原版的错误。
注意:1.18.2 修复了空处理器,因此该 MC 版本及更新版本不再需要此模组!
问题
您是否一直在尝试使用预生成器模组预生成世界的大部分区块,并不断随机崩溃并出现此错误?
Caused by: java.lang.NullPointerException: Cannot invoke "net.minecraft.structure.processor.StructureProcessorList.getList()" because the return value of "java.util.function.Supplier.get()" is null
at net.minecraft.structure.pool.SinglePoolElement.createPlacementData(SinglePoolElement:148) ~[?:?]
at net.minecraft.structure.pool.SinglePoolElement.generate(SinglePoolElement:124) ~[?:?]
Caused by: java.lang.NullPointerException: Cannot invoke "net.minecraft.class_5497.method_31027()" because the return value of "java.util.function.Supplier.get()" is null
at net.minecraft.structure.pool.SinglePoolElement.createPlacementData(SinglePoolElement:148) ~[?:?]
at net.minecraft.structure.pool.SinglePoolElement.generate(SinglePoolElement:124) ~[?:?]
描述
如果是这样,恭喜!你在 1.17.1 Minecraft 中发现了一个非常古怪的 Bug!这个模组旨在解决这个问题。
该 Bug 很难解释,但基本上都会触发它,您需要一个包含由创建世界 json 文件创建的处理器列表的 Mod 或数据包,使用区块预生成器 Mod 或其他东西加载大量区块,然后加载所有包含使用 json 处理器列表的结构的区块。随机地,这可能会由于空处理器列表而崩溃。
这到底是怎么回事呢?好吧,Minecraft 内部有一个处理器列表注册表,应该在世界启动时创建。然后,当游戏需要它时,它会从注册表中获取它,但它不应该在运行时重写该注册表。因为那会很糟糕吧?
在创建世界期间生成结构布局时,游戏会保存该布局以及将哪些部分添加到区块本身中。然后,随着区块的构建,它会从区块中加载以在世界中生成。除了从区块中读取该结构部分时,它还需要读取附加到该部分的处理器列表,以了解应该为该部分运行哪些处理器。正是在这里,Bug 出现了。读取处理器列表的代码不正确,将获取它读取的处理器并将其再次注册到注册表,将自身替换为自身,然后使用它。
并且这个注册表替换为自身对线程是不安全的。而且由于 Minecraft 以多线程方式创建区块......存在一个点,即使用同一处理器的两个结构块可以尝试读取/写入注册表中的相同确切条目。当这种罕见的碰撞发生时,其中一个结构部分最终可能会有一个空处理器,然后导致游戏崩溃,因为游戏无法处理生成空处理器的问题,因为它不存在!
很古怪吧?调试起来超级奇怪和痛苦,但多亏了另一个模组制作者,我们能够解决这个问题并创建此修复程序。据我们所知,1.16.5 没有这个问题。问题从 1.17+ 开始,并持续到 1.18.1。但是,1.18.2 修复了此 Bug。这个 Mod 所做的修复是它缓存用于每个处理器列表的注册名,因此它只将自身写入注册表一次并永久重新使用,从而避免了对同一特定注册表项进行多次读/写的问题。(理论上)
希望这对你有帮助!