Update NF, remove config hacks as config system is rewritten
This commit is contained in:
parent
783627f4c5
commit
c3b17b2927
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 + "}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user