Update NF, remove config hacks as config system is rewritten

This commit is contained in:
embeddedt 2024-07-11 08:00:59 -04:00
parent 783627f4c5
commit c3b17b2927
No known key found for this signature in database
GPG Key ID: A69433EC199B5613
7 changed files with 2 additions and 291 deletions

View File

@ -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

View File

@ -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<Consumer<IConfigEvent>> 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<IConfigEvent> {
private final Consumer<IConfigEvent> actualHandler;
private final String modId;
private final Lock lock = new ReentrantLock();
LockingConfigHandler(String id, Consumer<IConfigEvent> 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 + "}";
}
}
}

View File

@ -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<Runnable> 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<Path, ?> theMap = (ConcurrentHashMap<Path, ?>)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<Runnable> 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<Path, Object> {
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<Path, ?> oldMap) {
super(oldMap);
}
@Override
public Object computeIfAbsent(Path key, Function<? super Path, ?> 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);
}
}
}
}

View File

@ -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
* (<a href="https://github.com/TheElectronWill/night-config/pull/144">example</a>) 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");
}
}

View File

@ -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.<CommandSourceStack>literal("mfrc")
.executes(context -> {
NightConfigFixer.runReloads();
return 1;
}));
}
private static final List<String> brandingList = new ArrayList<>();
@SubscribeEvent(priority = EventPriority.HIGHEST)

View File

@ -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.<CommandSourceStack>literal(name)
.requires(source -> source.hasPermission(3))
.executes(context -> {
NightConfigFixer.runReloads();
return 1;
}));
}
}
private void registerItems(RegisterEvent event) {

View File

@ -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) {