From dbff17a1ffd535efb9f7cbe2376f62540f7ab31e Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Thu, 3 Aug 2023 18:08:46 -0400 Subject: [PATCH] Better fix for config corruption Defer posting of all config reload events to the main thread, and don't process any until after the launch finishes. This should hopefully fix some synchronization issues --- .../forge/config/NightConfigFixer.java | 35 +++++++++++++++---- .../forge/init/ModernFixClientForge.java | 6 ++++ .../modernfix/forge/init/ModernFixForge.java | 11 ++++++ .../forge/ModernFixPlatformHooksImpl.java | 2 ++ 4 files changed, 48 insertions(+), 6 deletions(-) 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 c0cc9432..833e6eb8 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 @@ -3,17 +3,21 @@ package org.embeddedt.modernfix.forge.config; import com.electronwill.nightconfig.core.file.FileWatcher; import cpw.mods.modlauncher.api.LamdbaExceptionUtils; import net.minecraftforge.fml.common.ObfuscationReflectionHelper; +import org.embeddedt.modernfix.ModernFix; import org.embeddedt.modernfix.core.ModernFixMixinPlugin; import org.embeddedt.modernfix.util.CommonModUtil; import java.lang.reflect.Field; import java.nio.file.Path; +import java.util.ArrayList; import java.util.LinkedHashSet; +import java.util.List; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Function; public class NightConfigFixer { public static final LinkedHashSet configsToReload = new LinkedHashSet<>(); + private static int tickCounter = 0; public static void monitorFileWatcher() { if(!ModernFixMixinPlugin.instance.isOptionEnabled("bugfix.fix_config_crashes.NightConfigFixerMixin")) return; @@ -28,6 +32,30 @@ public class NightConfigFixer { }, "replacing Night Config watchedFiles map"); } + /** + * Called by the render thread on the client, and the server thread on the server. Processes all the accumulated + * file watch events. + */ + public static void runReloads() { + if((tickCounter++ % 20) != 0) + return; + List runnablesToRun; + synchronized (configsToReload) { + if(configsToReload.isEmpty()) + return; + runnablesToRun = new ArrayList<>(configsToReload); + configsToReload.clear(); + } + ModernFix.LOGGER.info("Processing {} config reloads", runnablesToRun.size()); + for(Runnable r : runnablesToRun) { + try { + r.run(); + } catch(RuntimeException e) { + e.printStackTrace(); + } + } + } + private static final Class WATCHED_FILE = LamdbaExceptionUtils.uncheck(() -> Class.forName("com.electronwill.nightconfig.core.file.FileWatcher$WatchedFile")); private static final Field CHANGE_HANDLER = ObfuscationReflectionHelper.findField(WATCHED_FILE, "changeHandler"); @@ -59,17 +87,12 @@ public class NightConfigFixer { } /** - * Add the config + * Add the config runnable to the list to be processed by the main thread. */ @Override public void run() { synchronized(configsToReload) { - int oldSize = configsToReload.size(); configsToReload.add(configTracker); - if(oldSize == 0) { - ModernFixMixinPlugin.instance.logger.info("Config file change detected on disk. The Forge feature to watch config files for changes is currently disabled due to random corruption issues."); - ModernFixMixinPlugin.instance.logger.info("This functionality will be restored in a future ModernFix update."); - } } } } diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/init/ModernFixClientForge.java b/forge/src/main/java/org/embeddedt/modernfix/forge/init/ModernFixClientForge.java index 05b901b0..bc361764 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/init/ModernFixClientForge.java +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/init/ModernFixClientForge.java @@ -4,6 +4,7 @@ import com.mojang.blaze3d.platform.InputConstants; import net.minecraft.client.KeyMapping; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.components.DebugScreenOverlay; +import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.client.event.RecipesUpdatedEvent; import net.minecraftforge.client.event.RenderGameOverlayEvent; import net.minecraftforge.client.gui.ForgeIngameGui; @@ -20,7 +21,9 @@ import net.minecraftforge.fml.common.ObfuscationReflectionHelper; import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; import net.minecraftforge.fml.event.server.FMLServerStartedEvent; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; +import net.minecraftforge.fml.loading.FMLEnvironment; import org.embeddedt.modernfix.ModernFixClient; +import org.embeddedt.modernfix.forge.config.NightConfigFixer; import org.embeddedt.modernfix.screen.ModernFixConfigScreen; import java.util.ArrayList; @@ -51,6 +54,9 @@ public class ModernFixClientForge { if(event.phase == TickEvent.Phase.START && configKey.consumeClick()) { Minecraft.getInstance().setScreen(new ModernFixConfigScreen(Minecraft.getInstance().screen)); } + if(FMLEnvironment.dist == Dist.CLIENT && event.phase == TickEvent.Phase.START && ModernFixForge.launchDone) { + NightConfigFixer.runReloads(); + } } private static final List brandingList = new ArrayList<>(); diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/init/ModernFixForge.java b/forge/src/main/java/org/embeddedt/modernfix/forge/init/ModernFixForge.java index 093158e5..72d67ede 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/init/ModernFixForge.java +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/init/ModernFixForge.java @@ -6,6 +6,7 @@ import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.OnDatapackSyncEvent; import net.minecraftforge.event.RegistryEvent; +import net.minecraftforge.event.TickEvent; import net.minecraftforge.eventbus.api.EventPriority; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.*; @@ -15,6 +16,7 @@ import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; import net.minecraftforge.fml.event.server.FMLServerStartedEvent; import net.minecraftforge.fml.event.server.FMLServerStoppedEvent; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; +import net.minecraftforge.fml.loading.FMLEnvironment; import net.minecraftforge.fml.loading.FMLLoader; import net.minecraftforge.fml.network.FMLNetworkConstants; import net.minecraftforge.fml.server.ServerLifecycleHooks; @@ -27,6 +29,7 @@ import org.embeddedt.modernfix.forge.classloading.ModFileScanDataDeduplicator; import org.embeddedt.modernfix.forge.ModernFixConfig; import org.embeddedt.modernfix.entity.EntityDataIDSyncHandler; import org.embeddedt.modernfix.forge.config.ConfigFixer; +import org.embeddedt.modernfix.forge.config.NightConfigFixer; import org.embeddedt.modernfix.forge.packet.PacketHandler; import org.embeddedt.modernfix.forge.registry.ObjectHolderClearer; import org.embeddedt.modernfix.forge.util.KubeUtil; @@ -36,6 +39,7 @@ import java.util.List; @Mod(ModernFix.MODID) public class ModernFixForge { private static ModernFix commonMod; + public static boolean launchDone = false; public ModernFixForge() { commonMod = new ModernFix(); @@ -54,6 +58,13 @@ public class ModernFixForge { ConfigFixer.replaceConfigHandlers(); } + @SubscribeEvent + public void onServerTick(TickEvent.ServerTickEvent event) { + if(FMLEnvironment.dist == Dist.DEDICATED_SERVER && event.phase == TickEvent.Phase.END && ModernFixForge.launchDone) { + NightConfigFixer.runReloads(); + } + } + @SubscribeEvent public void onDatapackSync(OnDatapackSyncEvent event) { if(event.getPlayer() != null) { diff --git a/forge/src/main/java/org/embeddedt/modernfix/platform/forge/ModernFixPlatformHooksImpl.java b/forge/src/main/java/org/embeddedt/modernfix/platform/forge/ModernFixPlatformHooksImpl.java index 44565b96..6463a58c 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/platform/forge/ModernFixPlatformHooksImpl.java +++ b/forge/src/main/java/org/embeddedt/modernfix/platform/forge/ModernFixPlatformHooksImpl.java @@ -30,6 +30,7 @@ import org.embeddedt.modernfix.api.constants.IntegrationConstants; import org.embeddedt.modernfix.forge.classloading.FastAccessTransformerList; import org.embeddedt.modernfix.forge.classloading.ModernFixResourceFinder; import org.embeddedt.modernfix.forge.config.NightConfigFixer; +import org.embeddedt.modernfix.forge.init.ModernFixForge; import org.embeddedt.modernfix.forge.packet.PacketHandler; import org.embeddedt.modernfix.forge.spark.SparkLaunchProfiler; import org.embeddedt.modernfix.platform.ModernFixPlatformHooks; @@ -270,6 +271,7 @@ public class ModernFixPlatformHooksImpl implements ModernFixPlatformHooks { if(ModernFixMixinPlugin.instance.isOptionEnabled("feature.spark_profile_launch.OnForge")) { CommonModUtil.runWithoutCrash(() -> SparkLaunchProfiler.stop("launch"), "Failed to stop profiler"); } + ModernFixForge.launchDone = true; } public String getPlatformName() {