Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix for NPE crash when sourceMap is empty #420

Closed

Conversation

kstvr32
Copy link

@kstvr32 kstvr32 commented Sep 12, 2024

Fixes GTNewHorizons/GT-New-Horizons-Modpack#17190
Fixes GTNewHorizons/GT-New-Horizons-Modpack#17190
Fixes GTNewHorizons/GT-New-Horizons-Modpack#16281
Maybe Fixes GTNewHorizons/GT-New-Horizons-Modpack#12848 (might be another issue, but this should prevent the crash)
Fixes #406
by adding a null check before querying the HashMap.

First time using mixins, so please add comments if there is something I can improve.

Stacktrace of relevant NPE

---- Minecraft Crash Report ----
// This doesn't make any sense!

Time: 2024-09-11 17:54:09 EDT
Description: Unexpected error

java.lang.NullPointerException: Cannot invoke "java.util.HashMap.get(Object)" because the return value of "paulscode.sound.Library.getSources()" is null
    at net.minecraft.client.audio.SoundManager$SoundSystemStarterThread.playing(SoundManager.java:499)
    at net.minecraft.client.audio.SoundManager.updateAllSounds(SoundManager.java:218)
    at net.minecraft.client.audio.SoundHandler.update(SourceFile:179)
    at net.minecraft.client.Minecraft.runTick(Minecraft.java:2013)
    at net.minecraft.client.Minecraft.runGameLoop(Minecraft.java:973)
    at net.minecraft.client.Minecraft.run(Minecraft.java:5110)
    at net.minecraft.client.main.Main.main(SourceFile:148)
    at jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
    at java.lang.reflect.Method.invoke(Method.java:580)
    at net.minecraft.launchwrapper.Launch.rfb$realLaunch(Launch.java:250)
    at net.minecraft.launchwrapper.Launch.launch(Launch.java:35)
    at net.minecraft.launchwrapper.Launch.main(Launch.java:60)
    at jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
    at java.lang.reflect.Method.invoke(Method.java:580)
    at com.gtnewhorizons.retrofuturabootstrap.Main.main(Main.java:219)
    at org.prismlauncher.launcher.impl.StandardLauncher.launch(StandardLauncher.java:100)
    at org.prismlauncher.EntryPoint.listen(EntryPoint.java:129)
    at org.prismlauncher.EntryPoint.main(EntryPoint.java:70)

Before Mixin

    @SideOnly(Side.CLIENT)
    class SoundSystemStarterThread extends SoundSystem
    {
        private static final String __OBFID = "CL_00001145";

        private SoundSystemStarterThread() {}

        public boolean playing(String p_playing_1_)
        {
            Object object = SoundSystemConfig.THREAD_SYNC;

            synchronized (SoundSystemConfig.THREAD_SYNC)
            {
                if (this.soundLibrary == null)
                {
                    return false;
                }
                else
                {
                    Source source = (Source)this.soundLibrary.getSources().get(p_playing_1_); // crashes here when getSources returns null
                    return source == null ? false : source.playing() || source.paused() || source.preLoad;
                }
            }
        }

        SoundSystemStarterThread(Object p_i45118_2_)
        {
            this();
        }
    }

With Mixin

class SoundManager$SoundSystemStarterThread extends SoundSystem {
    private static final String __OBFID = "CL_00001145";
    // $FF: synthetic field
    final SoundManager this$0;

    private SoundManager$SoundSystemStarterThread(SoundManager this$0) {
        this.this$0 = this$0;
    }

    public boolean playing(String p_playing_1_) {
        Object object = SoundSystemConfig.THREAD_SYNC;
        synchronized(SoundSystemConfig.THREAD_SYNC) {
            if (this.soundLibrary == null) {
                return false;
            } else {
                Library var10000 = this.soundLibrary;
                CallbackInfoReturnable callbackInfo6 = new CallbackInfoReturnable("playing", true);
                this.handler$zcj000$hodgepodge$playingPatch(callbackInfo6); // if getSources() is null, short-circuits return false
                if (callbackInfo6.isCancelled()) {
                    return callbackInfo6.getReturnValueZ();
                } else {
                    Source source = (Source)var10000.getSources().get(p_playing_1_);
                    return source == null ? false : source.playing() || source.paused() || source.preLoad;
                }
            }
        }
    }

    SoundManager$SoundSystemStarterThread(SoundManager this$0, Object p_i45118_2_) {
        this(this$0);
    }

    @MixinMerged(
        mixin = "com.mitchej123.hodgepodge.mixins.early.minecraft.MixinSoundSystemStarterThread",
        priority = 1000,
        sessionId = "7d8ea081-07c1-4dc2-a5a0-2b9544df73c8"
    )
    private void handler$zcj000$hodgepodge$playingPatch(CallbackInfoReturnable<Boolean> cir) {
        if (this.soundLibrary.getSources() == null) {
            cir.setReturnValue(false);
        }

    }
}

@kstvr32
Copy link
Author

kstvr32 commented Sep 13, 2024

Looking at this more, this may just be a bandaid. It does look like sourceMap should not be null. Something funky is happening in the sound Library.

@Edgars-Cirulis
Copy link

Seems the issue is fixed from my side.

@kstvr32
Copy link
Author

kstvr32 commented Sep 13, 2024

Closing this PR, fixing the underlying issue in GTNewHorizons/lwjgl3ify#173

@kstvr32 kstvr32 closed this Sep 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants