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 new file mode 100644 index 00000000..f39e12e1 --- /dev/null +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/bugfix/cofh_core_crash/FlagManagerMixin.java @@ -0,0 +1,36 @@ +package org.embeddedt.modernfix.forge.mixin.bugfix.cofh_core_crash; + +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import org.embeddedt.modernfix.annotation.RequiresMod; +import org.spongepowered.asm.mixin.*; +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; + +/** + * Fix getOrCreateFlag accessing the FLAGS map without synchronization by wrapping all calls to it + * in a synchronized block. + */ +@Pseudo +@Mixin(targets = { "cofh/lib/util/flags/FlagManager" }, remap = false) +@RequiresMod("cofh_core") +public class FlagManagerMixin { + @Shadow @Final + private static Object2ObjectOpenHashMap FLAGS; + + @Shadow + private BooleanSupplier getOrCreateFlag(String flag) { + throw new AssertionError(); + } + + @Redirect(method = "*", at = @At(value = "INVOKE", target = "getOrCreateFlag"), require = 0) + private BooleanSupplier getFlag(@Coerce Object flagHandler, String flag) { + if(flagHandler != this) + throw new AssertionError("Redirect targeted bad getOrCreateFlag invocation"); + synchronized (FLAGS) { + return this.getOrCreateFlag(flag); + } + } +}