From 58218e9f62c192d709af22bf01d4a20aa16adabe Mon Sep 17 00:00:00 2001 From: BrokenK3yboard <63761658+BrokenK3yboard@users.noreply.github.com> Date: Wed, 11 Dec 2024 00:13:05 -0600 Subject: [PATCH] Properly disable config hackery --- src/main/java/org/violetmoon/zeta/Zeta.java | 13 ++-- .../java/org/violetmoon/zeta/mod/ZetaMod.java | 2 +- .../violetmoon/zetaimplforge/ForgeZeta.java | 16 ++++ .../config/ConfigEventDispatcher.java | 2 - .../config/ForgeBackedConfig.java | 75 ++++++++++++++++++ .../config/TerribleForgeConfigHackery.java | 76 +++++++++++++++++++ .../zetaimplforge/mod/ZetaForgeMod.java | 6 +- 7 files changed, 179 insertions(+), 11 deletions(-) create mode 100644 src/main/java/org/violetmoon/zetaimplforge/config/ForgeBackedConfig.java create mode 100644 src/main/java/org/violetmoon/zetaimplforge/config/TerribleForgeConfigHackery.java diff --git a/src/main/java/org/violetmoon/zeta/Zeta.java b/src/main/java/org/violetmoon/zeta/Zeta.java index acc42e4..a791d98 100644 --- a/src/main/java/org/violetmoon/zeta/Zeta.java +++ b/src/main/java/org/violetmoon/zeta/Zeta.java @@ -13,6 +13,7 @@ import org.violetmoon.zeta.block.ext.BlockExtensionFactory; import org.violetmoon.zeta.config.ConfigManager; import org.violetmoon.zeta.config.IZetaConfigInternals; +import org.violetmoon.zeta.config.SectionDefinition; import org.violetmoon.zeta.event.bus.*; import org.violetmoon.zeta.item.ext.ItemExtensionFactory; import org.violetmoon.zeta.module.ModuleFinder; @@ -116,7 +117,7 @@ public Zeta(String modid, Logger log, ZetaSide side) { * @param categories List of module categories in this mod, if null, will not load Modules but still load general config * @param finder Module finder instance to locate the modules this Zeta will load, if null, will not load Modules but still load general config */ - public void loadModules(@Nullable Iterable categories, @Nullable ModuleFinder finder) { + public void loadModules(@Nullable Iterable categories, @Nullable ModuleFinder finder, Object rootPojo) { if(categories != null && finder != null) { modules.initCategories(categories); modules.load(finder); @@ -127,11 +128,11 @@ public void loadModules(@Nullable Iterable categories, @Nullable M // - The platform-specific configInternals loads the actual values, from the platform-specfic config file // - Only then can ConfigManager do the initial config load - /* CONFIG REMOVE this.configManager = new ConfigManager(this, rootPojo); - this.configInternals = makeConfigInternals(configManager.getRootConfig()); - this.configManager.onReload(); - */ + if (rootPojo != null) { + this.configInternals = makeConfigInternals(configManager.getRootConfig()); + this.configManager.onReload(); + } } // modloader services @@ -145,6 +146,8 @@ public T modIntegration(String compatWith, Supplier> yes, Suppli } } + public abstract IZetaConfigInternals makeConfigInternals(SectionDefinition rootSection); + // general xplat stuff public ZetaModuleManager createModuleManager() { return new ZetaModuleManager(this); diff --git a/src/main/java/org/violetmoon/zeta/mod/ZetaMod.java b/src/main/java/org/violetmoon/zeta/mod/ZetaMod.java index 3850b4f..de56e0e 100644 --- a/src/main/java/org/violetmoon/zeta/mod/ZetaMod.java +++ b/src/main/java/org/violetmoon/zeta/mod/ZetaMod.java @@ -13,7 +13,7 @@ public static void start(Zeta zeta, ZetaModProxy proxy, IEventBus bus) { ZetaMod.proxy = proxy; ZETA.start(bus); - ZETA.loadModules(null, null); + ZETA.loadModules(null, null, null); proxy.registerEvents(zeta); } diff --git a/src/main/java/org/violetmoon/zetaimplforge/ForgeZeta.java b/src/main/java/org/violetmoon/zetaimplforge/ForgeZeta.java index 27ea957..c486860 100644 --- a/src/main/java/org/violetmoon/zetaimplforge/ForgeZeta.java +++ b/src/main/java/org/violetmoon/zetaimplforge/ForgeZeta.java @@ -15,6 +15,7 @@ import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent; import net.neoforged.fml.event.lifecycle.FMLLoadCompleteEvent; import net.neoforged.fml.loading.FMLEnvironment; +import net.neoforged.neoforge.common.ModConfigSpec; import net.neoforged.neoforge.common.NeoForge; import net.neoforged.neoforge.event.AddReloadListenerEvent; import net.neoforged.neoforge.event.AnvilUpdateEvent; @@ -36,6 +37,8 @@ import org.jetbrains.annotations.Nullable; import org.violetmoon.zeta.Zeta; import org.violetmoon.zeta.block.ext.BlockExtensionFactory; +import org.violetmoon.zeta.config.IZetaConfigInternals; +import org.violetmoon.zeta.config.SectionDefinition; import org.violetmoon.zeta.event.load.*; import org.violetmoon.zeta.event.play.*; import org.violetmoon.zeta.event.play.entity.*; @@ -54,6 +57,8 @@ import org.violetmoon.zetaimplforge.api.GatherAdvancementModifiersEvent; import org.violetmoon.zetaimplforge.block.IForgeBlockBlockExtensions; import org.violetmoon.zetaimplforge.config.ConfigEventDispatcher; +import org.violetmoon.zetaimplforge.config.ForgeBackedConfig; +import org.violetmoon.zetaimplforge.config.TerribleForgeConfigHackery; import org.violetmoon.zetaimplforge.event.load.ForgeZAddReloadListener; import org.violetmoon.zetaimplforge.event.load.ForgeZCommonSetup; import org.violetmoon.zetaimplforge.event.load.ForgeZEntityAttributeCreation; @@ -94,6 +99,17 @@ public boolean isModLoaded(String modid) { .orElse(null); } + @Override + public IZetaConfigInternals makeConfigInternals(SectionDefinition rootSection) { + ModConfigSpec.Builder bob = new ModConfigSpec.Builder(); + ForgeBackedConfig forge = new ForgeBackedConfig(rootSection, bob); + ModConfigSpec spec = bob.build(); + + TerribleForgeConfigHackery.registerAndLoadConfigEarlierThanUsual(spec); + + return forge; + } + @Override public ZetaRegistry createRegistry() { return new ForgeZetaRegistry(this); diff --git a/src/main/java/org/violetmoon/zetaimplforge/config/ConfigEventDispatcher.java b/src/main/java/org/violetmoon/zetaimplforge/config/ConfigEventDispatcher.java index 4658975..549ebff 100644 --- a/src/main/java/org/violetmoon/zetaimplforge/config/ConfigEventDispatcher.java +++ b/src/main/java/org/violetmoon/zetaimplforge/config/ConfigEventDispatcher.java @@ -22,12 +22,10 @@ public static void configChanged(ModConfigEvent event) { } } - /* Remove config public static void dispatchAllInitialLoads() { for(Zeta z : ZetaList.INSTANCE.getZetas()) handleConfigChange(z); } - */ private static void handleConfigChange(Zeta z) { z.configManager.onReload(); diff --git a/src/main/java/org/violetmoon/zetaimplforge/config/ForgeBackedConfig.java b/src/main/java/org/violetmoon/zetaimplforge/config/ForgeBackedConfig.java new file mode 100644 index 0000000..5c7c5f8 --- /dev/null +++ b/src/main/java/org/violetmoon/zetaimplforge/config/ForgeBackedConfig.java @@ -0,0 +1,75 @@ +package org.violetmoon.zetaimplforge.config; + +import net.neoforged.neoforge.common.ModConfigSpec; +import org.violetmoon.zeta.config.IZetaConfigInternals; +import org.violetmoon.zeta.config.SectionDefinition; +import org.violetmoon.zeta.config.ValueDefinition; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class ForgeBackedConfig implements IZetaConfigInternals { + private final Map, ModConfigSpec.ConfigValue> definitionsToValues = new HashMap<>(); + private long debounceTime = System.currentTimeMillis(); + + public ForgeBackedConfig(SectionDefinition rootSection, ModConfigSpec.Builder forgeBuilder) { + walkSection(rootSection, forgeBuilder, true); + } + + private void walkSection(SectionDefinition sect, ModConfigSpec.Builder builder, boolean root) { + if(!root) { + builder.comment(sect.commentToArray()); + builder.push(sect.name); + } + + for(ValueDefinition value : sect.getValues()) + addValue(value, builder); + + for(SectionDefinition subsection : sect.getSubsections()) + walkSection(subsection, builder, false); + + if(!root) + builder.pop(); + } + + private void addValue(ValueDefinition val, ModConfigSpec.Builder builder) { + builder.comment(val.commentToArray()); + + ModConfigSpec.ConfigValue forge; + if(val.defaultValue instanceof List list) + forge = builder.defineList(val.name, list, val::validate); + else + forge = builder.define(List.of(val.name), () -> val.defaultValue, val::validate, val.defaultValue.getClass()); //forge is weird + + definitionsToValues.put(val, forge); + } + + @Override + @SuppressWarnings("unchecked") + public T get(ValueDefinition definition) { + ModConfigSpec.ConfigValue forge = (ModConfigSpec.ConfigValue) definitionsToValues.get(definition); + return forge.get(); + } + + @Override + @SuppressWarnings("unchecked") + public void set(ValueDefinition definition, T value) { + ModConfigSpec.ConfigValue forge = (ModConfigSpec.ConfigValue) definitionsToValues.get(definition); + debounceTime = System.currentTimeMillis(); + forge.set(value); + } + + @Override + public void flush() { + debounceTime = 0; //force ConfigChangedEvent to not debounce this, it's important + + //just pick one; they all point to the same FileConfig anyway + definitionsToValues.values().iterator().next().save(); + } + + @Override + public long debounceTime() { + return debounceTime; + } +} \ No newline at end of file diff --git a/src/main/java/org/violetmoon/zetaimplforge/config/TerribleForgeConfigHackery.java b/src/main/java/org/violetmoon/zetaimplforge/config/TerribleForgeConfigHackery.java new file mode 100644 index 0000000..2793550 --- /dev/null +++ b/src/main/java/org/violetmoon/zetaimplforge/config/TerribleForgeConfigHackery.java @@ -0,0 +1,76 @@ +package org.violetmoon.zetaimplforge.config; + +import com.electronwill.nightconfig.core.file.CommentedFileConfig; +import com.electronwill.nightconfig.core.io.WritingMode; +import net.neoforged.fml.ModContainer; +import net.neoforged.fml.ModLoadingContext; +import net.neoforged.fml.config.ConfigTracker; +import net.neoforged.fml.config.ModConfig; +import net.neoforged.fml.util.ObfuscationReflectionHelper; +import net.neoforged.neoforge.common.ModConfigSpec; + +import java.io.Serial; +import java.lang.reflect.Method; +import java.nio.file.Path; + +public class TerribleForgeConfigHackery { + + // private static final Method SET_CONFIG_DATA = ObfuscationReflectionHelper.findMethod(ModConfig.class, "setConfig", LoadedConfig.class, FunctionalInterface.class); + private static final Method SETUP_CONFIG_FILE = ObfuscationReflectionHelper.findMethod(ConfigTracker.class, "setupConfigFile", ModConfig.class, Path.class); + + // TODO: Replace the name string + not 100% sure about this + public static void registerAndLoadConfigEarlierThanUsual(ModConfigSpec spec) { + ModContainer container = ModLoadingContext.get().getActiveContainer(); + ModConfig modConfig = ConfigTracker.INSTANCE.registerConfig(ModConfig.Type.COMMON, spec, container, "zeta-common.toml"); + + ConfigTracker.INSTANCE.loadConfigs(ModConfig.Type.COMMON, Path.of(modConfig.getFileName())); + + //same stuff that forge config tracker does + //read config without setting file watcher which could cause resets. forge will load it later + //CommentedFileConfig configData = readConfig(ConfigTracker.INSTANCE, FMLPaths.CONFIGDIR.get(), modConfig); + //CommentedFileConfig configData = handler.reader(FMLPaths.CONFIGDIR.get()).apply( modConfig); + + /* + SET_CONFIG_DATA.setAccessible(true); + try { + SET_CONFIG_DATA.invoke(modConfig, new LoadedConfig(configData, modConfig.getFullPath(), modConfig), ModConfigEvent.Loading::new); + } catch (Exception ignored) {} + //container.dispatchConfigEvent(IConfigEvent.loading(this.config)); + + configData.save(); + */ + } + + //we need this so we dont add a second file watcher. Same as handler::reader + private static CommentedFileConfig readConfig(ConfigTracker handler, Path configBasePath, ModConfig c) { + Path configPath = configBasePath.resolve(c.getFileName()); + CommentedFileConfig configData = CommentedFileConfig.builder(configPath).sync(). + preserveInsertionOrder(). + autosave(). + onFileNotFound((newfile, configFormat)->{ + try { + return (Boolean) SETUP_CONFIG_FILE.invoke(handler, c, newfile, configFormat); + } catch (Exception e) { + throw new ConfigLoadingException(c, e); + } + }). + writingMode(WritingMode.REPLACE). + build(); + try { + configData.load(); + } + catch (Exception ex) { + throw new ConfigLoadingException(c, ex); + } + return configData; + } + + private static class ConfigLoadingException extends RuntimeException { + @Serial + private static final long serialVersionUID = 1554369973578001612L; + + public ConfigLoadingException(ModConfig config, Exception cause) { + super("Failed loading config file " + config.getFileName() + " of type " + config.getType() + " for modid " + config.getModId(), cause); + } + } +} \ No newline at end of file diff --git a/src/main/java/org/violetmoon/zetaimplforge/mod/ZetaForgeMod.java b/src/main/java/org/violetmoon/zetaimplforge/mod/ZetaForgeMod.java index 0a6ad35..bef7233 100644 --- a/src/main/java/org/violetmoon/zetaimplforge/mod/ZetaForgeMod.java +++ b/src/main/java/org/violetmoon/zetaimplforge/mod/ZetaForgeMod.java @@ -2,6 +2,7 @@ import net.neoforged.bus.api.IEventBus; import net.neoforged.fml.common.Mod; +import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent; import org.apache.logging.log4j.LogManager; import org.violetmoon.zeta.Zeta; import org.violetmoon.zeta.mod.ZetaClientProxy; @@ -10,6 +11,7 @@ import org.violetmoon.zeta.multiloader.Env; import org.violetmoon.zetaimplforge.ForgeZeta; import org.violetmoon.zetaimplforge.client.ForgeZetaClient; +import org.violetmoon.zetaimplforge.config.ConfigEventDispatcher; import org.violetmoon.zetaimplforge.world.ZetaBiomeModifier; @Mod("zeta") @@ -25,12 +27,10 @@ public ZetaForgeMod(IEventBus bus) { ZetaMod.proxy.setClientZeta(zetaClient); ZetaBiomeModifier.registerBiomeModifier(bus); - // bus.addListener(this::setup); Remove config + bus.addListener(this::setup); } - /* public void setup(FMLCommonSetupEvent event) { event.enqueueWork(ConfigEventDispatcher::dispatchAllInitialLoads); } - */ } \ No newline at end of file