FxMorin / MoreCulling

Stop rendering things you can't see. A mod that changes how multiple types of culling are handled in order to improve performance
https://modrinth.com/mod/moreculling
GNU General Public License v3.0
151 stars 32 forks source link

PistonMovingBlockEntity.<clinit> fails when triggered during initialization #230

Open mt1006 opened 8 months ago

mt1006 commented 8 months ago

Triggering PistonMovingBlockEntity.<clinit> during specific period of initialization (e.g. at Minecraft.<init> return) with Lithium and ModernFix dynamic resources, causes it to throw NullPointerException. This was the reason behind a crash when activating pistons with NBT Autocomplete installed on top of these three mods, which is now fixed in version 1.2 (it skips piston block entity initialization with this specific set of mods). Although it's fixed for NBTac and it's rather unlikely it occurs or will occur with any other mod, I report it here so you can fix if you think it's worth it.

Steps to recreate this issue:

  1. MC/Loader: 1.20.4 - Fabric Loader 0.15.7
  2. Mods: More Culling (0.22.1), Lithium (0.12.1), ModernFix (5.13.0), NBT Autocomplete (1.1.8, not 1.2)
  3. Dependencies: Fabric API (0.96.4), Cloth Config (13.0.121)
  4. Enable mixin.perf.dynamic_resources in config/modernfix-mixins.properties
  5. Run game and try to activate a piston.

It should most likely crash the game. There's a little chance of it not causing crash as NBTac uses another thread so in theory main thread can be faster with initialization, but through my testing it never happened.

Logs with StackDeobfuscator installed and mojang mapping:

Caused by: java.lang.ExceptionInInitializerError: Exception java.lang.NullPointerException [in thread "Thread-5"]
    at net.minecraft.client.resources.model.ModelManager.getModel(ModelManager.java:71) ~[client-intermediary.jar:?]
    at net.minecraft.client.renderer.block.BlockModelShaper.cacheBlockModel(BlockModelShaper.java:540) ~[client-intermediary.jar:?]
    at net.minecraft.client.renderer.block.BlockModelShaper.mdd75cd2$modernfix$lambda$new$0$1(BlockModelShaper.java:527) ~[client-intermediary.jar:?]
    at it.unimi.dsi.fastutil.Function.apply(Function.java:93) ~[fastutil-8.5.12.jar:?]
    at org.embeddedt.modernfix.dynamicresources.DynamicModelCache.cacheModel(DynamicModelCache.java:52) ~[modernfix-fabric-5.13.0+mc1.20.4.jar:?]
    at org.embeddedt.modernfix.dynamicresources.DynamicModelCache.get(DynamicModelCache.java:74) ~[modernfix-fabric-5.13.0+mc1.20.4.jar:?]
    at net.minecraft.client.renderer.block.BlockModelShaper.getBlockModel(BlockModelShaper.java:554) ~[client-intermediary.jar:?]
    at net.minecraft.client.renderer.block.BlockRenderDispatcher.getBlockModel(BlockRenderDispatcher.java:90) ~[client-intermediary.jar:?]
    at net.minecraft.world.level.block.state.BlockBehaviour$BlockStateBase$BlockStateBase$Cache.redirect$bji000$moreculling$shouldDoShapeCache(BlockBehaviour.java:1988) ~[client-intermediary.jar:?]
    at net.minecraft.world.level.block.state.BlockBehaviour$BlockStateBase$BlockStateBase$Cache.<init>(BlockBehaviour.java:1381) ~[client-intermediary.jar:?]
    at net.minecraft.world.level.block.state.BlockBehaviour$BlockStateBase.initCache(BlockBehaviour.java:929) ~[client-intermediary.jar:?]
    at net.minecraft.world.level.block.state.BlockBehaviour$BlockStateBase.mfix$generateCache(BlockBehaviour.java:2968) ~[client-intermediary.jar:?]
    at net.minecraft.world.level.block.state.BlockBehaviour$BlockStateBase.redirect$bfi000$modernfix$dynamicCacheGen(BlockBehaviour.java:2987) ~[client-intermediary.jar:?]
    at net.minecraft.world.level.block.state.BlockBehaviour$BlockStateBase.getCollisionShape(BlockBehaviour.java:1122) ~[client-intermediary.jar:?]
    at net.minecraft.world.level.block.piston.PistonMovingBlockEntity.precomputePistonBaseWithMovingHeadShapes(PistonMovingBlockEntity.java:604) ~[client-intermediary.jar:?]
    at net.minecraft.world.level.block.piston.PistonMovingBlockEntity.<clinit>(PistonMovingBlockEntity.java:41) ~[client-intermediary.jar:?]
    at net.minecraft.world.level.block.entity.BlockEntityType.create(BlockEntityType.java:97) ~[client-intermediary.jar:?]
    at com.mt1006.nbt_ac.autocomplete.loader.typeloader.TypeLoader.loadBlockEntityTypes(TypeLoader.java:82) ~[NBTac-FABRIC-1.20.4-1.1.8.jar:?]
    at com.mt1006.nbt_ac.autocomplete.loader.Loader.load(Loader.java:37) ~[NBTac-FABRIC-1.20.4-1.1.8.jar:?]

Logs without StackDeobfuscator:

Caused by: java.lang.ExceptionInInitializerError: Exception java.lang.NullPointerException [in thread "Thread-5"]
    at net.minecraft.class_1092.method_4742(class_1092.java:71)
    at net.minecraft.class_773.cacheBlockModel(class_773.java:540)
    at net.minecraft.class_773.md43553c$modernfix$lambda$new$0$1(class_773.java:527)
    at it.unimi.dsi.fastutil.Function.apply(Function.java:93)
    at org.embeddedt.modernfix.dynamicresources.DynamicModelCache.cacheModel(DynamicModelCache.java:52)
    at org.embeddedt.modernfix.dynamicresources.DynamicModelCache.get(DynamicModelCache.java:74)
    at net.minecraft.class_773.method_3335(class_773.java:554)
    at net.minecraft.class_776.method_3349(class_776.java:90)
    at net.minecraft.class_4970$class_4971$class_3752.redirect$bji000$moreculling$shouldDoShapeCache(class_4970.java:1988)
    at net.minecraft.class_4970$class_4971$class_3752.<init>(class_4970.java:1381)
    at net.minecraft.class_4970$class_4971.method_26200(class_4970.java:929)
    at net.minecraft.class_4970$class_4971.mfix$generateCache(class_4970.java:2968)
    at net.minecraft.class_4970$class_4971.redirect$bfi000$modernfix$dynamicCacheGen(class_4970.java:2987)
    at net.minecraft.class_4970$class_4971.method_26220(class_4970.java:1122)
    at net.minecraft.class_2669.precomputePistonBaseWithMovingHeadShapes(class_2669.java:604)
    at net.minecraft.class_2669.<clinit>(class_2669.java:41)
    at net.minecraft.class_2591.method_11032(class_2591.java:97)
    at com.mt1006.nbt_ac.autocomplete.loader.typeloader.TypeLoader.loadBlockEntityTypes(TypeLoader.java:82)
    at com.mt1006.nbt_ac.autocomplete.loader.Loader.load(Loader.java:37)

btw. PistonMovingBlockEntity.precomputePistonBaseWithMovingHeadShapes is a Lithium mixin.

Simple code to recreate this issue without NBTac:

@Mixin(Minecraft.class)
public class MinecraftMixin
{
    @Inject(method = "<init>", at = @At("RETURN"))
    private void atConstructor(GameConfig gameConfig, CallbackInfo callbackInfo)
    {
        PistonEntityFields.getNOCLIP();

        // NBTac-like "smart" "no issue" system:
        /*try
        {
            PistonEntityFields.getNOCLIP();
        }
        catch (Throwable ignore) {}*/
    }
}
@Mixin(PistonMovingBlockEntity.class)
public interface PistonEntityFields
{
    @Accessor static ThreadLocal<Direction> getNOCLIP() { return null; }
}

It's also worth noting it don't crash when doing it in onInitialize, even though it is called during Minecraft.<init>, but I didn't want to investigate this issue so much.

Related issues: https://github.com/FxMorin/MoreCulling/issues/203 (closed as resolved but it wasn't) https://github.com/embeddedt/ModernFix/issues/324 https://github.com/mt1006/mc-nbtac-mod/issues/18