diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/config/ConfigFixer.java b/forge/src/main/java/org/embeddedt/modernfix/forge/config/ConfigFixer.java index fe4cba78..2b5823ea 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/config/ConfigFixer.java +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/config/ConfigFixer.java @@ -50,7 +50,8 @@ public class ConfigFixer { this.actualHandler.accept(modConfigEvent); } } else { - ModernFix.LOGGER.warn("Unable to sync on a {} config object", modConfigEvent.getConfig().getConfigData().getClass().getName()); + if(modConfigEvent.getConfig().getConfigData() != null) + ModernFix.LOGGER.warn("Unable to sync on a {} config object", modConfigEvent.getConfig().getConfigData().getClass().getName()); this.actualHandler.accept(modConfigEvent); } } diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/config/NightConfigFixer.java b/forge/src/main/java/org/embeddedt/modernfix/forge/config/NightConfigFixer.java index acf7eeb6..b0879cdd 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/config/NightConfigFixer.java +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/config/NightConfigFixer.java @@ -85,6 +85,8 @@ public class NightConfigFixer { private static final Set> UNKNOWN_FILE_CONFIG_CLASSES = Collections.synchronizedSet(new ReferenceOpenHashSet<>()); public static Object toWriteSyncConfig(Object config) { + if(config == null) + return null; try { if(WRITE_SYNC_CONFIG.isAssignableFrom(config.getClass())) { return config; diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/dynresources/ModelBakeEventHelper.java b/forge/src/main/java/org/embeddedt/modernfix/forge/dynresources/ModelBakeEventHelper.java index 0e81d4ae..ffe4cc87 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/dynresources/ModelBakeEventHelper.java +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/dynresources/ModelBakeEventHelper.java @@ -17,10 +17,7 @@ import net.minecraftforge.registries.ForgeRegistries; import org.embeddedt.modernfix.dynamicresources.ModelLocationCache; import org.jetbrains.annotations.Nullable; -import java.util.HashSet; -import java.util.Map; -import java.util.Optional; -import java.util.Set; +import java.util.*; /** * Stores a list of all known default block/item models in the game, and provides a namespaced version @@ -54,7 +51,9 @@ public class ModelBakeEventHelper { Optional mContainer = ModList.get().getModContainerById(id); if(mContainer.isPresent()) { for(IModInfo.ModVersion version : mContainer.get().getModInfo().getDependencies()) { - this.dependencyGraph.putEdge(id, version.getModId()); + // avoid self-loops + if(!Objects.equals(id, version.getModId())) + this.dependencyGraph.putEdge(id, version.getModId()); } } } 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); + } + } +}