diff --git a/common/src/main/java/com/railwayteam/railways/util/MethodVarHandleUtils.java b/common/src/main/java/com/railwayteam/railways/util/MethodVarHandleUtils.java index cd080b428..786158a65 100644 --- a/common/src/main/java/com/railwayteam/railways/util/MethodVarHandleUtils.java +++ b/common/src/main/java/com/railwayteam/railways/util/MethodVarHandleUtils.java @@ -18,23 +18,66 @@ package com.railwayteam.railways.util; +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import org.jetbrains.annotations.Nullable; + import java.lang.invoke.MethodHandles; +import java.lang.invoke.VarHandle; +import java.util.concurrent.ExecutionException; @SuppressWarnings("unchecked") public class MethodVarHandleUtils { + private static final Cache varHandleCache = CacheBuilder.newBuilder().build(); + private static final MethodHandles.Lookup lookup = MethodHandles.lookup(); - + public static T getStaticField(Class clazz, String fieldName, Class type) throws NoSuchFieldException, IllegalAccessException { - return (T) lookup.findStaticVarHandle(clazz, fieldName, type).get(); + T value = null; + + try { + value = (T) varHandleCache.get( + new VarHandleInfo(clazz, fieldName, type), + () -> lookup.findStaticVarHandle(clazz, fieldName, type) + ).get(); + } catch (ExecutionException ignored) {} + + return value; } public static T getStaticField(Class clazz, String fieldName, Class type, T defaultValue) { T returnValue = defaultValue; - + try { returnValue = getStaticField(clazz, fieldName, type); } catch (NoSuchFieldException | IllegalAccessException ignored) {} - + return returnValue; } + + public static T getPrivateField(U instance, Class clazz, String fieldName, Class type, T defaultValue) { + T returnValue = defaultValue; + + VarHandle handle = findPrivateFieldVarHandle(new VarHandleInfo(clazz, fieldName, type)); + if (handle != null) { + returnValue = (T) handle.get(instance); + } + + return returnValue; + } + + @Nullable + public static VarHandle findPrivateFieldVarHandle(VarHandleInfo info) { + try { + return varHandleCache.get(info, () -> { + MethodHandles.Lookup privateLookup = MethodHandles.privateLookupIn(info.clazz(), lookup); + return privateLookup.findVarHandle(info.clazz(), info.fieldName(), info.type()); + }); + } catch (ExecutionException ignored) { + return null; + } + } + + public record VarHandleInfo(Class clazz, String fieldName, Class type) { + } } \ No newline at end of file diff --git a/forge/src/main/java/com/railwayteam/railways/forge/mixin/CRMixinPlugin.java b/forge/src/main/java/com/railwayteam/railways/forge/mixin/CRMixinPlugin.java index 28adf28d2..c15c9f2a5 100644 --- a/forge/src/main/java/com/railwayteam/railways/forge/mixin/CRMixinPlugin.java +++ b/forge/src/main/java/com/railwayteam/railways/forge/mixin/CRMixinPlugin.java @@ -21,6 +21,9 @@ import com.railwayteam.railways.forge.asm.ContainerLevelAccessASM; import com.railwayteam.railways.forge.asm.RollingModeEnumAdder; import com.railwayteam.railways.util.ConditionalMixinManager; +import com.railwayteam.railways.util.MethodVarHandleUtils; +import net.minecraftforge.fml.ModLoader; +import net.minecraftforge.fml.ModLoadingException; import org.objectweb.asm.tree.ClassNode; import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; import org.spongepowered.asm.mixin.extensibility.IMixinInfo; @@ -37,6 +40,16 @@ public void onLoad(String mixinPackage) { } // NO-OP @Override public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { + //noinspection unchecked + Class> modLoadingExceptionListClass = (Class>)(Class) List.class; + + List modLoadingExceptionList = MethodVarHandleUtils.getPrivateField( + ModLoader.get(), ModLoader.class, "loadingExceptions", modLoadingExceptionListClass, null); + + if (!modLoadingExceptionList.isEmpty()) { + return false; + } + return ConditionalMixinManager.shouldApply(mixinClassName); }