Make FlagManager patch handle both impls of CoFH Core

This commit is contained in:
embeddedt 2023-07-30 10:21:10 -04:00
parent 2b4199c0a6
commit 92a204c253
No known key found for this signature in database
GPG Key ID: A69433EC199B5613

View File

@ -7,7 +7,9 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Coerce; import org.spongepowered.asm.mixin.injection.Coerce;
import org.spongepowered.asm.mixin.injection.Redirect; 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 * 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") @RequiresMod("cofh_core")
public class FlagManagerMixin { public class FlagManagerMixin {
@Shadow @Final @Shadow @Final
private static Object2ObjectOpenHashMap<String, BooleanSupplier> FLAGS; private static Object2ObjectOpenHashMap<String, ?> FLAGS;
@Shadow @Unique
private BooleanSupplier getOrCreateFlag(String flag) { private static final MethodHandle mfix$getOrCreateFlag;
throw new AssertionError();
static {
// use this reflection dance to avoid depending on whether it's implemented via BooleanSupplier or Supplier<Boolean>
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) @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) if(flagHandler != this)
throw new AssertionError("Redirect targeted bad getOrCreateFlag invocation"); throw new AssertionError("Redirect targeted bad getOrCreateFlag invocation");
synchronized (FLAGS) { 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);
}
} }
} }
} }