DragonAPI icon indicating copy to clipboard operation
DragonAPI copied to clipboard

Fix compatibility with SpongePowered Mixins

Open FalsePattern opened this issue 3 years ago • 0 comments

SpongePowered Mixins runs getClassBytes during the coremod setup in the LaunchWrapper to detect mixin injection targets, before Minecraft or FML gets properly initialized. This causes the cpw.mods.fml.common.Loader.isModLoaded(modName) method to throw a NullPointerException, because it's not properly set up yet when a DragonAPI-based mod tries to call ModList.MOD.isLoaded() inside an ASMEnum apply() call. (One example: Creating a mixin targeting net.minecraft.world.gen.ChunkProviderEnd, and then trying to launch a mod containing that mixin with ChromatiCraft installed causes the following exception:

Click to expand
java.lang.ClassNotFoundException: net.minecraft.client.main.Main
	at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:191) ~[launchwrapper-1.12.jar:?]
	at java.lang.ClassLoader.loadClass(ClassLoader.java:418) ~[?:1.8.0_332]
	at java.lang.ClassLoader.loadClass(ClassLoader.java:351) ~[?:1.8.0_332]
	at java.lang.Class.forName0(Native Method) ~[?:1.8.0_332]
	at java.lang.Class.forName(Class.java:348) ~[?:1.8.0_332]
	at net.minecraft.launchwrapper.Launch.launch(Launch.java:131) [launchwrapper-1.12.jar:?]
	at net.minecraft.launchwrapper.Launch.main(Launch.java:28) [launchwrapper-1.12.jar:?]
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_332]
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_332]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_332]
	at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_332]
	at org.multimc.impl.OneSixLauncher.invokeMain(OneSixLauncher.java:104) [NewLaunch.jar:?]
	at org.multimc.impl.OneSixLauncher.launchWithMainClass(OneSixLauncher.java:175) [NewLaunch.jar:?]
	at org.multimc.impl.OneSixLauncher.launch(OneSixLauncher.java:185) [NewLaunch.jar:?]
	at org.multimc.EntryPoint.listen(EntryPoint.java:127) [NewLaunch.jar:?]
	at org.multimc.EntryPoint.main(EntryPoint.java:57) [NewLaunch.jar:?]
Caused by: java.lang.ExceptionInInitializerError
	at Reika.ChromatiCraft.Auxiliary.ChromaASMHandler$ASMExecutor$ClassPatch.apply(ChromaASMHandler.java:121) ~[ChromatiCraft+1.7.10+V31b.jar:?]
	at Reika.ChromatiCraft.Auxiliary.ChromaASMHandler$ASMExecutor.transform(ChromaASMHandler.java:507) ~[ChromatiCraft+1.7.10+V31b.jar:?]
	at org.spongepowered.asm.service.mojang.LegacyTransformerHandle.transformClassBytes(LegacyTransformerHandle.java:71) ~[SpongeMixins-1.2.0.jar:?]
	at org.spongepowered.asm.service.mojang.MixinServiceLaunchWrapper.applyTransformers(MixinServiceLaunchWrapper.java:388) ~[SpongeMixins-1.2.0.jar:?]
	at org.spongepowered.asm.service.mojang.MixinServiceLaunchWrapper.getClassBytes(MixinServiceLaunchWrapper.java:352) ~[SpongeMixins-1.2.0.jar:?]
	at org.spongepowered.asm.service.mojang.MixinServiceLaunchWrapper.getClassNode(MixinServiceLaunchWrapper.java:432) ~[SpongeMixins-1.2.0.jar:?]
	at org.spongepowered.asm.mixin.transformer.ClassInfo.forName(ClassInfo.java:1676) ~[SpongeMixins-1.2.0.jar:?]
	at org.spongepowered.asm.mixin.transformer.MixinInfo.getTarget(MixinInfo.java:908) ~[SpongeMixins-1.2.0.jar:?]
	at org.spongepowered.asm.mixin.transformer.MixinInfo.readTargets(MixinInfo.java:891) ~[SpongeMixins-1.2.0.jar:?]
	at org.spongepowered.asm.mixin.transformer.MixinInfo.readTargetClasses(MixinInfo.java:856) ~[SpongeMixins-1.2.0.jar:?]
	at org.spongepowered.asm.mixin.transformer.MixinInfo.<init>(MixinInfo.java:809) ~[SpongeMixins-1.2.0.jar:?]
	at org.spongepowered.asm.mixin.transformer.MixinConfig.prepareMixins(MixinConfig.java:569) ~[SpongeMixins-1.2.0.jar:?]
	at org.spongepowered.asm.mixin.transformer.MixinConfig.postInitialise(MixinConfig.java:522) ~[SpongeMixins-1.2.0.jar:?]
	at org.spongepowered.asm.mixin.transformer.MixinTransformer.prepareConfigs(MixinTransformer.java:675) ~[SpongeMixins-1.2.0.jar:?]
	at org.spongepowered.asm.mixin.transformer.MixinTransformer.select(MixinTransformer.java:572) ~[SpongeMixins-1.2.0.jar:?]
	at org.spongepowered.asm.mixin.transformer.MixinTransformer.checkSelect(MixinTransformer.java:548) ~[SpongeMixins-1.2.0.jar:?]
	at org.spongepowered.asm.mixin.transformer.MixinTransformer.transformClassBytes(MixinTransformer.java:451) ~[SpongeMixins-1.2.0.jar:?]
	at org.spongepowered.asm.mixin.transformer.Proxy.transform(Proxy.java:72) ~[SpongeMixins-1.2.0.jar:?]
	at net.minecraft.launchwrapper.LaunchClassLoader.runTransformers(LaunchClassLoader.java:279) ~[launchwrapper-1.12.jar:?]
	at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:176) ~[launchwrapper-1.12.jar:?]
	... 15 more
Caused by: java.lang.NullPointerException
	at cpw.mods.fml.common.Loader.isModLoaded(Loader.java:619) ~[Loader.class:?]
	at Reika.DragonAPI.ModList.<init>(ModList.java:154) ~[ModList.class:?]
	at Reika.DragonAPI.ModList.<init>(ModList.java:181) ~[ModList.class:?]
	at Reika.DragonAPI.ModList.<clinit>(ModList.java:31) ~[ModList.class:?]
	at Reika.ChromatiCraft.Auxiliary.ChromaASMHandler$ASMExecutor$ClassPatch.apply(ChromaASMHandler.java:121) ~[ChromatiCraft+1.7.10+V31b.jar:?]
	at Reika.ChromatiCraft.Auxiliary.ChromaASMHandler$ASMExecutor.transform(ChromaASMHandler.java:507) ~[ChromatiCraft+1.7.10+V31b.jar:?]
	at org.spongepowered.asm.service.mojang.LegacyTransformerHandle.transformClassBytes(LegacyTransformerHandle.java:71) ~[SpongeMixins-1.2.0.jar:?]
	at org.spongepowered.asm.service.mojang.MixinServiceLaunchWrapper.applyTransformers(MixinServiceLaunchWrapper.java:388) ~[SpongeMixins-1.2.0.jar:?]
	at org.spongepowered.asm.service.mojang.MixinServiceLaunchWrapper.getClassBytes(MixinServiceLaunchWrapper.java:352) ~[SpongeMixins-1.2.0.jar:?]
	at org.spongepowered.asm.service.mojang.MixinServiceLaunchWrapper.getClassNode(MixinServiceLaunchWrapper.java:432) ~[SpongeMixins-1.2.0.jar:?]
	at org.spongepowered.asm.mixin.transformer.ClassInfo.forName(ClassInfo.java:1676) ~[SpongeMixins-1.2.0.jar:?]
	at org.spongepowered.asm.mixin.transformer.MixinInfo.getTarget(MixinInfo.java:908) ~[SpongeMixins-1.2.0.jar:?]
	at org.spongepowered.asm.mixin.transformer.MixinInfo.readTargets(MixinInfo.java:891) ~[SpongeMixins-1.2.0.jar:?]
	at org.spongepowered.asm.mixin.transformer.MixinInfo.readTargetClasses(MixinInfo.java:856) ~[SpongeMixins-1.2.0.jar:?]
	at org.spongepowered.asm.mixin.transformer.MixinInfo.<init>(MixinInfo.java:809) ~[SpongeMixins-1.2.0.jar:?]
	at org.spongepowered.asm.mixin.transformer.MixinConfig.prepareMixins(MixinConfig.java:569) ~[SpongeMixins-1.2.0.jar:?]
	at org.spongepowered.asm.mixin.transformer.MixinConfig.postInitialise(MixinConfig.java:522) ~[SpongeMixins-1.2.0.jar:?]
	at org.spongepowered.asm.mixin.transformer.MixinTransformer.prepareConfigs(MixinTransformer.java:675) ~[SpongeMixins-1.2.0.jar:?]
	at org.spongepowered.asm.mixin.transformer.MixinTransformer.select(MixinTransformer.java:572) ~[SpongeMixins-1.2.0.jar:?]
	at org.spongepowered.asm.mixin.transformer.MixinTransformer.checkSelect(MixinTransformer.java:548) ~[SpongeMixins-1.2.0.jar:?]
	at org.spongepowered.asm.mixin.transformer.MixinTransformer.transformClassBytes(MixinTransformer.java:451) ~[SpongeMixins-1.2.0.jar:?]
	at org.spongepowered.asm.mixin.transformer.Proxy.transform(Proxy.java:72) ~[SpongeMixins-1.2.0.jar:?]
	at net.minecraft.launchwrapper.LaunchClassLoader.runTransformers(LaunchClassLoader.java:279) ~[launchwrapper-1.12.jar:?]
	at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:176) ~[launchwrapper-1.12.jar:?]
	... 15 more

This patch fixes this issue using lazy detection, repeatedly deferring the actual detection of a mod until Loader gets properly initialized.

As long as any code that uses ASMEnum behaves properly and always applies the respective patch when getClassBytes is called multiple times, this fix shouldn't cause any new problems.

FalsePattern avatar Jul 03 '22 10:07 FalsePattern