From 92a204c2537560377f4da231a3dc1c9aa7475c20 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Sun, 30 Jul 2023 10:21:10 -0400 Subject: [PATCH] Make FlagManager patch handle both impls of CoFH Core --- .../cofh_core_crash/FlagManagerMixin.java | 33 +++++++++++++++---- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/bugfix/cofh_core_crash/FlagManagerMixin.java b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/bugfix/cofh_core_crash/FlagManagerMixin.java index f39e12e1..c73ef328 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/bugfix/cofh_core_crash/FlagManagerMixin.java +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/bugfix/cofh_core_crash/FlagManagerMixin.java @@ -7,7 +7,9 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Coerce; import org.spongepowered.asm.mixin.injection.Redirect; -import java.util.function.BooleanSupplier; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.reflect.Method; /** * Fix getOrCreateFlag accessing the FLAGS map without synchronization by wrapping all calls to it @@ -18,19 +20,36 @@ import java.util.function.BooleanSupplier; @RequiresMod("cofh_core") public class FlagManagerMixin { @Shadow @Final - private static Object2ObjectOpenHashMap FLAGS; + private static Object2ObjectOpenHashMap FLAGS; - @Shadow - private BooleanSupplier getOrCreateFlag(String flag) { - throw new AssertionError(); + @Unique + private static final MethodHandle mfix$getOrCreateFlag; + + static { + // use this reflection dance to avoid depending on whether it's implemented via BooleanSupplier or Supplier + try { + Method m = MethodHandles.lookup().lookupClass().getDeclaredMethod("getOrCreateFlag", String.class); + m.setAccessible(true); + mfix$getOrCreateFlag = MethodHandles.lookup().unreflect(m); + } catch(ReflectiveOperationException e) { + throw new AssertionError(e); + } } @Redirect(method = "*", at = @At(value = "INVOKE", target = "getOrCreateFlag"), require = 0) - private BooleanSupplier getFlag(@Coerce Object flagHandler, String flag) { + @Coerce + private Object getFlag(@Coerce Object flagHandler, String flag) { if(flagHandler != this) throw new AssertionError("Redirect targeted bad getOrCreateFlag invocation"); synchronized (FLAGS) { - return this.getOrCreateFlag(flag); + try { + return mfix$getOrCreateFlag.invoke((Object)this, flag); + } catch(Throwable e) { + if(e instanceof RuntimeException) + throw (RuntimeException)e; + else + throw new RuntimeException(e); + } } } }