From 5c1f8d50da4e895b4e210c8f4eb18a9e33d400bd Mon Sep 17 00:00:00 2001 From: Moulberry Date: Wed, 5 Feb 2025 05:05:00 +0800 Subject: [PATCH] Fix broken classloading under certain conditions --- README.md | 2 +- build.gradle.kts | 2 +- .../FabricAbstractionsImpl.java | 4 +- .../mixinconstraints/MixinConstraints.java | 36 ++++++---- .../mixinconstraints/util/Abstractions.java | 35 ++++++---- .../mixinconstraints/util/MixinHacks.java | 70 ++++++++++--------- .../mixinconstraints/testmod/TestMod.java | 2 +- 7 files changed, 83 insertions(+), 68 deletions(-) diff --git a/README.md b/README.md index 7833906..09dd7ae 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ MixinConstraints is available through Maven Central. __Gradle__ ```groovy dependencies { - include(implementation("com.moulberry:mixinconstraints:1.0.2")) + include(implementation("com.moulberry:mixinconstraints:1.0.4")) } ``` diff --git a/build.gradle.kts b/build.gradle.kts index 32c8332..57b49e2 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -8,7 +8,7 @@ plugins { id("com.vanniktech.maven.publish") version("0.28.0") // `maven-publish` doesn't support new maven central } -version = "1.0.3" +version = "1.0.4" group = "com.moulberry.mixinconstraints" idea.module.isDownloadSources = true diff --git a/src/fabric/java/com/moulberry/mixinconstraints/FabricAbstractionsImpl.java b/src/fabric/java/com/moulberry/mixinconstraints/FabricAbstractionsImpl.java index 1cd7a4a..66b9f5a 100644 --- a/src/fabric/java/com/moulberry/mixinconstraints/FabricAbstractionsImpl.java +++ b/src/fabric/java/com/moulberry/mixinconstraints/FabricAbstractionsImpl.java @@ -5,8 +5,6 @@ import net.fabricmc.loader.api.Version; import net.fabricmc.loader.api.VersionParsingException; -import static com.moulberry.mixinconstraints.util.MixinHacks.unchecked; - public class FabricAbstractionsImpl extends Abstractions { @Override protected boolean isDevEnvironment() { @@ -36,7 +34,7 @@ protected boolean isVersionInRange(String version, String minVersion, String max return (min == null || currentVersion.compareTo(min) >= 0) && (max == null || currentVersion.compareTo(max) <= 0); } catch (VersionParsingException e) { - throw unchecked(e); + throw new RuntimeException(e); } } } diff --git a/src/main/java/com/moulberry/mixinconstraints/MixinConstraints.java b/src/main/java/com/moulberry/mixinconstraints/MixinConstraints.java index 8f01a70..8c9e434 100644 --- a/src/main/java/com/moulberry/mixinconstraints/MixinConstraints.java +++ b/src/main/java/com/moulberry/mixinconstraints/MixinConstraints.java @@ -8,15 +8,12 @@ import org.spongepowered.asm.service.MixinService; import java.io.IOException; -import java.util.Locale; - -import static com.moulberry.mixinconstraints.util.MixinHacks.unchecked; public class MixinConstraints { public static final Logger LOGGER = LoggerFactory.getLogger("mixinconstraints"); public static final boolean VERBOSE = "true".equals(System.getProperty("mixinconstraints.verbose")); - public static final Loader LOADER = getLoader(); + private static Loader loader = null; public static boolean shouldApplyMixin(String mixinClassName) { try { @@ -40,17 +37,26 @@ public static boolean shouldApplyMixin(String mixinClassName) { return true; } catch (ClassNotFoundException | IOException e) { - throw unchecked(e); + throw new RuntimeException(e); } } - private static Loader getLoader() { - if (doesClassExist("net.fabricmc.loader.api.FabricLoader")) - return Loader.FABRIC; - if (doesClassExist("net.minecraftforge.fml.loading.FMLLoader")) - return Loader.FORGE; - if (doesClassExist("net.neoforged.fml.loading.FMLLoader")) + public static Loader getLoader() { + if (loader == null) { + loader = findLoader(); + } + + return loader; + } + + private static Loader findLoader() { + if (doesClassExist("net.neoforged.fml.loading.FMLLoader")) { return Loader.NEOFORGE; + } else if (doesClassExist("net.minecraftforge.fml.loading.FMLLoader")) { + return Loader.FORGE; + } else if (doesClassExist("net.fabricmc.loader.api.FabricLoader")) { + return Loader.FABRIC; + } throw new RuntimeException("Could not determine loader"); } @@ -69,9 +75,11 @@ public enum Loader { @Override public String toString() { - return name().toLowerCase(Locale.ROOT) - .replace("n", "N") - .replace("f", "F"); + return switch (this) { + case FORGE -> "Forge"; + case NEOFORGE -> "NeoForge"; + case FABRIC -> "Fabric"; + }; } } } diff --git a/src/main/java/com/moulberry/mixinconstraints/util/Abstractions.java b/src/main/java/com/moulberry/mixinconstraints/util/Abstractions.java index 42aa1a5..6775f48 100644 --- a/src/main/java/com/moulberry/mixinconstraints/util/Abstractions.java +++ b/src/main/java/com/moulberry/mixinconstraints/util/Abstractions.java @@ -3,27 +3,34 @@ import com.moulberry.mixinconstraints.MixinConstraints; public abstract class Abstractions { - private static final Abstractions instance; - static { - try { - String name = switch(MixinConstraints.LOADER) { - case FORGE -> "com.moulberry.mixinconstraints.ForgeAbstractionsImpl"; - case NEOFORGE -> "com.moulberry.mixinconstraints.NeoForgeAbstractionsImpl"; - case FABRIC -> "com.moulberry.mixinconstraints.FabricAbstractionsImpl"; - }; - instance = (Abstractions) Class.forName(name).getDeclaredConstructor().newInstance(); - } catch (ReflectiveOperationException e) { - throw new RuntimeException(e); - } - } + private static Abstractions instance = null; + + private static Abstractions getInstance() { + if (instance == null) { + try { + String name = switch (MixinConstraints.getLoader()) { + case FORGE -> "com.moulberry.mixinconstraints.ForgeAbstractionsImpl"; + case NEOFORGE -> "com.moulberry.mixinconstraints.NeoForgeAbstractionsImpl"; + case FABRIC -> "com.moulberry.mixinconstraints.FabricAbstractionsImpl"; + }; + instance = (Abstractions) Class.forName(name).getDeclaredConstructor().newInstance(); + } catch (ReflectiveOperationException e) { + throw new RuntimeException(e); + } + } + return instance; + } public static boolean isDevelopmentEnvironment() { + Abstractions instance = getInstance(); return instance.isDevEnvironment(); } public static boolean isModLoadedWithinVersion(String modId, String minVersion, String maxVersion) { + Abstractions instance = getInstance(); + String version = instance.getModVersion(modId); - if(version == null) { + if (version == null) { return false; } diff --git a/src/main/java/com/moulberry/mixinconstraints/util/MixinHacks.java b/src/main/java/com/moulberry/mixinconstraints/util/MixinHacks.java index f97ad73..b63ae65 100644 --- a/src/main/java/com/moulberry/mixinconstraints/util/MixinHacks.java +++ b/src/main/java/com/moulberry/mixinconstraints/util/MixinHacks.java @@ -24,41 +24,49 @@ */ @SuppressWarnings("unchecked") public final class MixinHacks { - private static final MethodHandle TARGET_CLASS_CONTEXT_MIXINS; - private static final MethodHandle MIXIN_INFO_GET_STATE; - private static final MethodHandle STATE_CLASS_NODE; + private static MethodHandle TARGET_CLASS_CONTEXT_MIXINS; + private static MethodHandle MIXIN_INFO_GET_STATE; + private static MethodHandle STATE_CLASS_NODE; - private static final MethodHandle EXTENSIONS_EXTENSIONS; - private static final MethodHandle EXTENSIONS_ACTIVE_EXTENSIONS_GET; - private static final MethodHandle EXTENSIONS_ACTIVE_EXTENSIONS_SET; + private static MethodHandle EXTENSIONS_EXTENSIONS; + private static MethodHandle EXTENSIONS_ACTIVE_EXTENSIONS_GET; + private static MethodHandle EXTENSIONS_ACTIVE_EXTENSIONS_SET; - static { - try { - Class TargetClassContext = Class.forName("org.spongepowered.asm.mixin.transformer.TargetClassContext"); - MethodHandles.Lookup lookup = MethodHandles.privateLookupIn(TargetClassContext, MethodHandles.lookup()); - TARGET_CLASS_CONTEXT_MIXINS = lookup.findGetter(TargetClassContext, "mixins", SortedSet.class); + private static boolean initialized = false; - Class MixinInfo = Class.forName("org.spongepowered.asm.mixin.transformer.MixinInfo"); - Class MixinInfo$State = Class.forName("org.spongepowered.asm.mixin.transformer.MixinInfo$State"); + private static void tryInit() { + if (initialized) { + return; + } + initialized = true; - lookup = MethodHandles.privateLookupIn(MixinInfo, MethodHandles.lookup()); - MIXIN_INFO_GET_STATE = lookup.findVirtual(MixinInfo, "getState", MethodType.methodType(MixinInfo$State)); + try { + Class TargetClassContext = Class.forName("org.spongepowered.asm.mixin.transformer.TargetClassContext"); + MethodHandles.Lookup lookup = MethodHandles.privateLookupIn(TargetClassContext, MethodHandles.lookup()); + TARGET_CLASS_CONTEXT_MIXINS = lookup.findGetter(TargetClassContext, "mixins", SortedSet.class); - lookup = MethodHandles.privateLookupIn(MixinInfo$State, MethodHandles.lookup()); - STATE_CLASS_NODE = lookup.findGetter(MixinInfo$State, "classNode", ClassNode.class); + Class MixinInfo = Class.forName("org.spongepowered.asm.mixin.transformer.MixinInfo"); + Class MixinInfo$State = Class.forName("org.spongepowered.asm.mixin.transformer.MixinInfo$State"); - lookup = MethodHandles.privateLookupIn(Extensions.class, MethodHandles.lookup()); + lookup = MethodHandles.privateLookupIn(MixinInfo, MethodHandles.lookup()); + MIXIN_INFO_GET_STATE = lookup.findVirtual(MixinInfo, "getState", MethodType.methodType(MixinInfo$State)); - EXTENSIONS_EXTENSIONS = lookup.findGetter(Extensions.class, "extensions", List.class); - EXTENSIONS_ACTIVE_EXTENSIONS_GET = lookup.findGetter(Extensions.class, "activeExtensions", List.class); - EXTENSIONS_ACTIVE_EXTENSIONS_SET = lookup.findSetter(Extensions.class, "activeExtensions", List.class); + lookup = MethodHandles.privateLookupIn(MixinInfo$State, MethodHandles.lookup()); + STATE_CLASS_NODE = lookup.findGetter(MixinInfo$State, "classNode", ClassNode.class); - } catch (Throwable e) { - throw unchecked(e); - } - } + lookup = MethodHandles.privateLookupIn(Extensions.class, MethodHandles.lookup()); + + EXTENSIONS_EXTENSIONS = lookup.findGetter(Extensions.class, "extensions", List.class); + EXTENSIONS_ACTIVE_EXTENSIONS_GET = lookup.findGetter(Extensions.class, "activeExtensions", List.class); + EXTENSIONS_ACTIVE_EXTENSIONS_SET = lookup.findSetter(Extensions.class, "activeExtensions", List.class); + + } catch (Throwable e) { + throw new RuntimeException(e); + } + } public static void registerMixinExtension(IExtension extension) { + tryInit(); try { Extensions extensions = (Extensions) ((IMixinTransformer) MixinEnvironment.getDefaultEnvironment().getActiveTransformer()) .getExtensions(); @@ -69,11 +77,12 @@ public static void registerMixinExtension(IExtension extension) { EXTENSIONS_ACTIVE_EXTENSIONS_SET.invokeExact(extensions, Collections.unmodifiableList(activeExtensions)); } catch (Throwable t) { - throw unchecked(t); + throw new RuntimeException(t); } } public static List> getMixinsFor(ITargetClassContext context) { + tryInit(); List> result = new ArrayList<>(); try { // note: can't use invokeExact here because TargetClassContext is not public @@ -82,7 +91,7 @@ public static List> getMixinsFor(ITargetClassContext result.add(Pair.of(mixin, classNode)); } } catch (Throwable e) { - throw unchecked(e); + throw new RuntimeException(e); } return result; } @@ -102,11 +111,4 @@ private static void addExtension(List extensions, IExtension newExte extensions.addAll(lateExtensions); } - @SuppressWarnings("unchecked") - public static RuntimeException unchecked(Throwable t) throws T { - throw (T) t; - } - - private MixinHacks() { - } } diff --git a/testmod/src/main/java/com/moulberry/mixinconstraints/testmod/TestMod.java b/testmod/src/main/java/com/moulberry/mixinconstraints/testmod/TestMod.java index cb50097..9e93a02 100644 --- a/testmod/src/main/java/com/moulberry/mixinconstraints/testmod/TestMod.java +++ b/testmod/src/main/java/com/moulberry/mixinconstraints/testmod/TestMod.java @@ -9,6 +9,6 @@ public final class TestMod { public static void init() { LOGGER.info("init() called"); - LOGGER.info("Platform: {}", MixinConstraints.LOADER); + LOGGER.info("Platform: {}", MixinConstraints.getLoader()); } }