diff --git a/gradle.properties b/gradle.properties index 9307eb0b..2648772c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -7,8 +7,8 @@ mixinextras_version=0.3.2 mod_id=modernfix minecraft_version=1.21 enabled_platforms=fabric,neoforge -forge_version=21.0.42-beta -# parchment_version=2023.07.09 +forge_version=21.0.83-beta +parchment_version=2024.07.07 refined_storage_version=4392788 jei_version=19.0.0.9 rei_version=13.0.678 diff --git a/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/config/ConfigFixer.java b/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/config/ConfigFixer.java deleted file mode 100644 index 7f310484..00000000 --- a/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/config/ConfigFixer.java +++ /dev/null @@ -1,69 +0,0 @@ -package org.embeddedt.modernfix.neoforge.config; - -import net.neoforged.fml.ModContainer; -import net.neoforged.fml.ModList; -import net.neoforged.fml.config.IConfigEvent; -import net.neoforged.fml.util.ObfuscationReflectionHelper; -import org.embeddedt.modernfix.ModernFix; -import org.embeddedt.modernfix.core.ModernFixMixinPlugin; - -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; -import java.util.function.Consumer; - -public class ConfigFixer { - /** - * To prevent mods from crashing if their ModConfigEvent is invoked by Night Config's watch thread and Forge - * at the same time, wrap their config handler so that it only executes the event in serial for that mod. - * - * Should have no noticeable performance impact as config handlers are virtually instant. - */ - public static void replaceConfigHandlers() { - if(!ModernFixMixinPlugin.instance.isOptionEnabled("bugfix.fix_config_crashes.ConfigFixerMixin")) - return; - ModList.get().forEachModContainer((id, container) -> { - try { - Optional> configOpt = ObfuscationReflectionHelper.getPrivateValue(ModContainer.class, container, "configHandler"); - if(configOpt.isPresent()) { - ObfuscationReflectionHelper.setPrivateValue(ModContainer.class, container, Optional.of(new LockingConfigHandler(id, configOpt.get())), "configHandler"); - } - } catch(RuntimeException e) { - ModernFix.LOGGER.error("Error replacing config handler", e); - } - }); - } - - private static class LockingConfigHandler implements Consumer { - private final Consumer actualHandler; - private final String modId; - private final Lock lock = new ReentrantLock(); - - LockingConfigHandler(String id, Consumer actualHandler) { - this.modId = id; - this.actualHandler = actualHandler; - } - - @Override - public void accept(IConfigEvent modConfigEvent) { - try { - if(lock.tryLock(2, TimeUnit.SECONDS)) { - try { - this.actualHandler.accept(modConfigEvent); - } finally { - lock.unlock(); - } - } else - ModernFix.LOGGER.error("Failed to post config event for {}, someone else is holding the lock", modId); - } catch(InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - - @Override - public String toString() { - return "LockingConfigHandler{id=" + modId + "}"; - } - } -} diff --git a/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/config/NightConfigFixer.java b/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/config/NightConfigFixer.java deleted file mode 100644 index 64587d03..00000000 --- a/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/config/NightConfigFixer.java +++ /dev/null @@ -1,113 +0,0 @@ -package org.embeddedt.modernfix.neoforge.config; - -import com.electronwill.nightconfig.core.file.FileWatcher; -import cpw.mods.modlauncher.api.LambdaExceptionUtils; -import net.neoforged.fml.loading.FMLLoader; -import net.neoforged.fml.util.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<>(); - - public static void monitorFileWatcher() { - if(!ModernFixMixinPlugin.instance.isOptionEnabled("bugfix.fix_config_crashes.NightConfigFixerMixin")) - return; - CommonModUtil.runWithoutCrash(() -> { - FileWatcher watcher = FileWatcher.defaultInstance(); - Field field = FileWatcher.class.getDeclaredField("watchedFiles"); - field.setAccessible(true); - ConcurrentHashMap theMap = (ConcurrentHashMap)field.get(watcher); - // replace the backing map of watched files with one we control - field.set(watcher, new MonitoringMap(theMap)); - ModernFixMixinPlugin.instance.logger.info("Applied Forge config corruption patch"); - }, "replacing Night Config watchedFiles map"); - } - - public static void runReloads() { - List runnablesToRun; - synchronized (configsToReload) { - runnablesToRun = new ArrayList<>(configsToReload); - configsToReload.clear(); - } - for(Runnable r : runnablesToRun) { - try { - r.run(); - } catch(RuntimeException e) { - e.printStackTrace(); - } - } - ModernFix.LOGGER.info("Processed {} config reloads", runnablesToRun.size()); - couldShowMessage = true; - } - - static class MonitoringMap extends ConcurrentHashMap { - private static final Class WATCHED_FILE = LambdaExceptionUtils.uncheck(() -> Class.forName("com.electronwill.nightconfig.core.file.FileWatcher$WatchedFile")); - private static final Field CHANGE_HANDLER = ObfuscationReflectionHelper.findField(WATCHED_FILE, "changeHandler"); - - public MonitoringMap(ConcurrentHashMap oldMap) { - super(oldMap); - } - - @Override - public Object computeIfAbsent(Path key, Function mappingFunction) { - return super.computeIfAbsent(key, path -> { - Object watchedFile = mappingFunction.apply(path); - try { - Runnable changeHandler = (Runnable)CHANGE_HANDLER.get(watchedFile); - CHANGE_HANDLER.set(watchedFile, new MonitoringConfigTracker(changeHandler)); - } catch(ReflectiveOperationException e) { - e.printStackTrace(); - } - return watchedFile; - }); - } - } - - private static boolean couldShowMessage = true; - - private static void triggerConfigMessage() { - /* - if(false && couldShowMessage && Minecraft.getInstance().level != null && ModernFixClient.recipesUpdated && ModernFixClient.tagsUpdated) { - Minecraft.getInstance().execute(() -> { - if(Minecraft.getInstance().level != null) { - couldShowMessage = false; - Minecraft.getInstance().gui.getChat().addMessage(Component.translatable("modernfix.message.reload_config")); - } - }); - } - */ - } - - static class MonitoringConfigTracker implements Runnable { - private final Runnable configTracker; - - MonitoringConfigTracker(Runnable r) { - this.configTracker = r; - } - - /** - * Add the config runnable to the list to be processed by the main thread. - */ - @Override - public void run() { - synchronized(configsToReload) { - if(FMLLoader.getDist().isClient()) - triggerConfigMessage(); - if(configsToReload.size() == 0) { - ModernFixMixinPlugin.instance.logger.info("Please use /{} to reload any changed mod config files", FMLLoader.getDist().isDedicatedServer() ? "mfsrc" : "mfrc"); - } - configsToReload.add(configTracker); - } - } - } -} diff --git a/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/config/NightConfigWatchThrottler.java b/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/config/NightConfigWatchThrottler.java deleted file mode 100644 index 049575da..00000000 --- a/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/config/NightConfigWatchThrottler.java +++ /dev/null @@ -1,56 +0,0 @@ -package org.embeddedt.modernfix.neoforge.config; - -import com.electronwill.nightconfig.core.file.FileWatcher; -import com.google.common.collect.ForwardingCollection; -import com.google.common.collect.ForwardingMap; -import net.neoforged.fml.util.ObfuscationReflectionHelper; - -import java.util.Collection; -import java.util.Iterator; -import java.util.Map; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.locks.LockSupport; - -/** - * Throttle NightConfig's file watching. There are reports of this consuming excessive CPU time - * (example) and the spammed iterator calls - * end up being 10% of allocations when testing in a dev environment. - */ -public class NightConfigWatchThrottler { - private static final long DELAY = TimeUnit.MILLISECONDS.toNanos(1000); - - @SuppressWarnings("rawtypes") - public static void throttle() { - Map watchedDirs = ObfuscationReflectionHelper.getPrivateValue(FileWatcher.class, FileWatcher.defaultInstance(), "watchedDirs"); - ObfuscationReflectionHelper.setPrivateValue(FileWatcher.class, FileWatcher.defaultInstance(), new ForwardingMap() { - @Override - protected Map delegate() { - return watchedDirs; - } - - private Collection cachedValues; - - @Override - public Collection values() { - if(cachedValues == null) { - Collection values = super.values(); - cachedValues = new ForwardingCollection() { - @Override - protected Collection delegate() { - return values; - } - - @Override - public Iterator iterator() { - // iterator() is called at the beginning of each iteration of the watch loop, - // so it is a good spot to inject the delay. - LockSupport.parkNanos(DELAY); - return super.iterator(); - } - }; - } - return cachedValues; - } - }, "watchedDirs"); - } -} diff --git a/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/init/ModernFixClientForge.java b/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/init/ModernFixClientForge.java index c39dbbe4..9c2a5b4a 100644 --- a/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/init/ModernFixClientForge.java +++ b/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/init/ModernFixClientForge.java @@ -1,11 +1,9 @@ package org.embeddedt.modernfix.neoforge.init; import com.mojang.blaze3d.platform.InputConstants; -import com.mojang.brigadier.builder.LiteralArgumentBuilder; import net.minecraft.client.KeyMapping; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.components.DebugScreenOverlay; -import net.minecraft.commands.CommandSourceStack; import net.neoforged.bus.api.EventPriority; import net.neoforged.bus.api.IEventBus; import net.neoforged.bus.api.SubscribeEvent; @@ -16,7 +14,6 @@ import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent; import net.neoforged.neoforge.client.event.ClientTickEvent; import net.neoforged.neoforge.client.event.CustomizeGuiOverlayEvent; import net.neoforged.neoforge.client.event.RecipesUpdatedEvent; -import net.neoforged.neoforge.client.event.RegisterClientCommandsEvent; import net.neoforged.neoforge.client.event.RegisterKeyMappingsEvent; import net.neoforged.neoforge.client.event.RenderFrameEvent; import net.neoforged.neoforge.client.gui.IConfigScreenFactory; @@ -25,7 +22,6 @@ import net.neoforged.neoforge.event.TagsUpdatedEvent; import net.neoforged.neoforge.event.level.LevelEvent; import net.neoforged.neoforge.event.server.ServerStartedEvent; import org.embeddedt.modernfix.ModernFixClient; -import org.embeddedt.modernfix.neoforge.config.NightConfigFixer; import org.embeddedt.modernfix.screen.ModernFixConfigScreen; import java.util.ArrayList; @@ -63,15 +59,6 @@ public class ModernFixClientForge { } } - @SubscribeEvent(priority = EventPriority.LOW) - public void onClientChat(RegisterClientCommandsEvent event) { - event.getDispatcher().register(LiteralArgumentBuilder.literal("mfrc") - .executes(context -> { - NightConfigFixer.runReloads(); - return 1; - })); - } - private static final List brandingList = new ArrayList<>(); @SubscribeEvent(priority = EventPriority.HIGHEST) diff --git a/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/init/ModernFixForge.java b/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/init/ModernFixForge.java index a99fe7c5..e74b95ae 100644 --- a/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/init/ModernFixForge.java +++ b/neoforge/src/main/java/org/embeddedt/modernfix/neoforge/init/ModernFixForge.java @@ -1,8 +1,6 @@ package org.embeddedt.modernfix.neoforge.init; import com.google.common.collect.ImmutableList; -import com.mojang.brigadier.builder.LiteralArgumentBuilder; -import net.minecraft.commands.CommandSourceStack; import net.minecraft.core.registries.Registries; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.Item; @@ -17,7 +15,6 @@ import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent; import net.neoforged.fml.loading.FMLEnvironment; import net.neoforged.fml.loading.FMLLoader; import net.neoforged.neoforge.common.NeoForge; -import net.neoforged.neoforge.event.RegisterCommandsEvent; import net.neoforged.neoforge.event.server.ServerStartedEvent; import net.neoforged.neoforge.event.server.ServerStoppedEvent; import net.neoforged.neoforge.registries.RegisterEvent; @@ -26,7 +23,6 @@ import org.embeddedt.modernfix.ModernFix; import org.embeddedt.modernfix.core.ModernFixMixinPlugin; import org.embeddedt.modernfix.neoforge.ModernFixConfig; import org.embeddedt.modernfix.neoforge.classloading.ModFileScanDataDeduplicator; -import org.embeddedt.modernfix.neoforge.config.NightConfigFixer; import java.util.List; @@ -46,19 +42,6 @@ public class ModernFixForge { } modContainer.registerConfig(ModConfig.Type.COMMON, ModernFixConfig.COMMON_CONFIG); ModFileScanDataDeduplicator.deduplicate(); - //ConfigFixer.replaceConfigHandlers(); - } - - @SubscribeEvent - public void onCommandRegister(RegisterCommandsEvent event) { - for(String name : new String[] { "mfsrc"}) { - event.getDispatcher().register(LiteralArgumentBuilder.literal(name) - .requires(source -> source.hasPermission(3)) - .executes(context -> { - NightConfigFixer.runReloads(); - return 1; - })); - } } private void registerItems(RegisterEvent event) { diff --git a/neoforge/src/main/java/org/embeddedt/modernfix/platform/neoforge/ModernFixPlatformHooksImpl.java b/neoforge/src/main/java/org/embeddedt/modernfix/platform/neoforge/ModernFixPlatformHooksImpl.java index 4a030ec2..3d717c7c 100644 --- a/neoforge/src/main/java/org/embeddedt/modernfix/platform/neoforge/ModernFixPlatformHooksImpl.java +++ b/neoforge/src/main/java/org/embeddedt/modernfix/platform/neoforge/ModernFixPlatformHooksImpl.java @@ -20,17 +20,12 @@ import net.neoforged.neoforge.network.PacketDistributor; import net.neoforged.neoforge.server.ServerLifecycleHooks; import org.embeddedt.modernfix.api.constants.IntegrationConstants; import org.embeddedt.modernfix.core.ModernFixMixinPlugin; -import org.embeddedt.modernfix.neoforge.config.NightConfigFixer; -import org.embeddedt.modernfix.neoforge.config.NightConfigWatchThrottler; import org.embeddedt.modernfix.neoforge.init.ModernFixForge; import org.embeddedt.modernfix.platform.ModernFixPlatformHooks; import org.embeddedt.modernfix.spark.SparkLaunchProfiler; import org.embeddedt.modernfix.util.CommonModUtil; -import org.embeddedt.modernfix.util.DummyList; import org.objectweb.asm.tree.ClassNode; -import org.spongepowered.asm.mixin.injection.struct.InjectorGroupInfo; -import java.lang.reflect.Field; import java.nio.file.Path; import java.util.Map; import java.util.Optional; @@ -87,26 +82,10 @@ public class ModernFixPlatformHooksImpl implements ModernFixPlatformHooks { public void injectPlatformSpecificHacks() { - /* https://github.com/FabricMC/Mixin/pull/99 */ - try { - Field groupMembersField = InjectorGroupInfo.class.getDeclaredField("members"); - groupMembersField.setAccessible(true); - Field noGroupField = InjectorGroupInfo.Map.class.getDeclaredField("NO_GROUP"); - noGroupField.setAccessible(true); - InjectorGroupInfo noGroup = (InjectorGroupInfo)noGroupField.get(null); - groupMembersField.set(noGroup, new DummyList<>()); - } catch(NoSuchFieldException ignored) { - // Connector will replace FML's mixin with one which already has the fix, don't bother logging - } catch(RuntimeException | ReflectiveOperationException e) { - ModernFixMixinPlugin.instance.logger.error("Failed to patch mixin memory leak", e); - } - if(ModernFixMixinPlugin.instance.isOptionEnabled("feature.spark_profile_launch.OnForge")) { CommonModUtil.runWithoutCrash(() -> SparkLaunchProfiler.start("launch"), "Failed to start profiler"); } - NightConfigFixer.monitorFileWatcher(); - NightConfigWatchThrottler.throttle(); } public void applyASMTransformers(String mixinClassName, ClassNode targetClass) {