diff --git a/CHANGELOG.md b/CHANGELOG.md
index b8b1312..87b4271 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,7 +1,9 @@
### Build Specific Changes
-- Configs now load immediately when registered on Fabric.
-- Added getLocalRoot method to GreenhouseInheritedConfigHolder, a shortcut for getLocal().root()
-- Removed GreenhouseConfigHolder#loadEarly from public facing API.
+- Configs now load immediately upon registration, no matter the loader.
+- Config changes on initial load now save after the client/server has initialized, rather than immediately.
+- Removed GreenhouseConfigEvents#CONFIG_LOAD_PHASE and replaced it with GreenhouseConfigEvents#CONFIG_SAVE_PHASE. Which now runs after the default phase on Fabric or at lowest priority on NeoForge.
+- Fixed a bug introduced within the previous version where data fixes were incorrectly handled when inherited configs are in play.
+- Fixed an API oversight that caused an inability to load configs after registration on NeoForge.
# Full Changelog
This is the v3.0.0 Release of Greenhouse Config, which is additionally the first release to be hosted on the Greenhouse Forgejo instead of GitHub.
diff --git a/fabric/src/main/java/lgbt/greenhouse/config/impl/fabric/client/GreenhouseConfigClientFabric.java b/fabric/src/main/java/lgbt/greenhouse/config/impl/fabric/client/GreenhouseConfigClientFabric.java
index 6a806f2..c14cf63 100644
--- a/fabric/src/main/java/lgbt/greenhouse/config/impl/fabric/client/GreenhouseConfigClientFabric.java
+++ b/fabric/src/main/java/lgbt/greenhouse/config/impl/fabric/client/GreenhouseConfigClientFabric.java
@@ -20,9 +20,9 @@ public class GreenhouseConfigClientFabric implements ClientModInitializer {
}
private static void registerEvents() {
- ClientLifecycleEvents.CLIENT_STARTED.addPhaseOrdering(GreenhouseConfigEventPhases.CONFIG_LOAD_PHASE, Event.DEFAULT_PHASE);
- ClientLifecycleEvents.CLIENT_STARTED.register(GreenhouseConfigEventPhases.CONFIG_LOAD_PHASE, server ->
- GreenhouseConfigImpl.loadConfigs());
+ ClientLifecycleEvents.CLIENT_STARTED.addPhaseOrdering(Event.DEFAULT_PHASE, GreenhouseConfigEventPhases.CONFIG_SAVE_PHASE);
+ ClientLifecycleEvents.CLIENT_STARTED.register(GreenhouseConfigEventPhases.CONFIG_SAVE_PHASE, server ->
+ GreenhouseConfigImpl.onMinecraftLoad());
ClientPlayConnectionEvents.JOIN.addPhaseOrdering(GreenhouseConfigEventPhases.CONFIG_REGISTRIES_PHASE, Event.DEFAULT_PHASE);
ClientPlayConnectionEvents.JOIN.register(GreenhouseConfigEventPhases.CONFIG_REGISTRIES_PHASE, (listener, sender, client) -> {
diff --git a/fabric/src/main/java/lgbt/greenhouse/config/impl/fabric/server/dedicated/GreenhouseConfigDedicatedFabric.java b/fabric/src/main/java/lgbt/greenhouse/config/impl/fabric/server/dedicated/GreenhouseConfigDedicatedFabric.java
index 8cee217..f8ec007 100644
--- a/fabric/src/main/java/lgbt/greenhouse/config/impl/fabric/server/dedicated/GreenhouseConfigDedicatedFabric.java
+++ b/fabric/src/main/java/lgbt/greenhouse/config/impl/fabric/server/dedicated/GreenhouseConfigDedicatedFabric.java
@@ -13,9 +13,9 @@ public class GreenhouseConfigDedicatedFabric implements DedicatedServerModInitia
}
private static void registerEvents() {
- ServerLifecycleEvents.SERVER_STARTING.addPhaseOrdering(GreenhouseConfigEventPhases.CONFIG_LOAD_PHASE, Event.DEFAULT_PHASE);
- ServerLifecycleEvents.SERVER_STARTING.register(GreenhouseConfigEventPhases.CONFIG_LOAD_PHASE, server ->
- GreenhouseConfigImpl.loadConfigs());
+ ServerLifecycleEvents.SERVER_STARTING.addPhaseOrdering(Event.DEFAULT_PHASE, GreenhouseConfigEventPhases.CONFIG_SAVE_PHASE);
+ ServerLifecycleEvents.SERVER_STARTING.register(GreenhouseConfigEventPhases.CONFIG_SAVE_PHASE, server ->
+ GreenhouseConfigImpl.onMinecraftLoad());
ServerLifecycleEvents.SERVER_STARTED.addPhaseOrdering(GreenhouseConfigEventPhases.CONFIG_REGISTRIES_PHASE, Event.DEFAULT_PHASE);
ServerLifecycleEvents.SERVER_STARTED.register(GreenhouseConfigEventPhases.CONFIG_REGISTRIES_PHASE, server ->
diff --git a/fabric/src/test/java/lgbt/greenhouse/config/test/GreenhouseConfigTestFabric.java b/fabric/src/test/java/lgbt/greenhouse/config/test/GreenhouseConfigTestFabric.java
index d61e071..01aa131 100644
--- a/fabric/src/test/java/lgbt/greenhouse/config/test/GreenhouseConfigTestFabric.java
+++ b/fabric/src/test/java/lgbt/greenhouse/config/test/GreenhouseConfigTestFabric.java
@@ -7,9 +7,9 @@ public class GreenhouseConfigTestFabric implements ModInitializer {
@Override
public void onInitialize() {
GreenhouseConfigTest.init();
+ GreenhouseConfigTest.ITEM_REGISTRY.registerContents();
GreenhouseConfigTest.SOUND_EVENT_REGISTRY.registerContents();
- CommandRegistrationCallback.EVENT.register((dispatcher, ctx, selection) -> {
- GreenhouseConfigTest.registerServerCommands(dispatcher);
- });
+ CommandRegistrationCallback.EVENT.register((dispatcher, ctx, selection) ->
+ GreenhouseConfigTest.registerServerCommands(dispatcher));
}
}
diff --git a/neoforge/src/main/java/lgbt/greenhouse/config/impl/neoforge/client/GreenhouseConfigClientNeoForge.java b/neoforge/src/main/java/lgbt/greenhouse/config/impl/neoforge/client/GreenhouseConfigClientNeoForge.java
index bc971ed..9686abd 100644
--- a/neoforge/src/main/java/lgbt/greenhouse/config/impl/neoforge/client/GreenhouseConfigClientNeoForge.java
+++ b/neoforge/src/main/java/lgbt/greenhouse/config/impl/neoforge/client/GreenhouseConfigClientNeoForge.java
@@ -20,9 +20,9 @@ public class GreenhouseConfigClientNeoForge {
event.register(SyncGreenhouseConfigClientboundPacket.TYPE, (packet, ctx) -> GreenhouseConfigClientPacketHandlers.handleConfigSync(packet));
}
- @SubscribeEvent(priority = EventPriority.HIGHEST)
+ @SubscribeEvent(priority = EventPriority.LOWEST)
public static void onFmlClientSetup(FMLClientSetupEvent event) {
- GreenhouseConfigImpl.loadConfigs();
+ event.enqueueWork(GreenhouseConfigImpl::onMinecraftLoad);
}
@SubscribeEvent(priority = EventPriority.HIGHEST)
diff --git a/neoforge/src/main/java/lgbt/greenhouse/config/impl/neoforge/server/dedicated/GreenhouseConfigDedicatedNeoForge.java b/neoforge/src/main/java/lgbt/greenhouse/config/impl/neoforge/server/dedicated/GreenhouseConfigDedicatedNeoForge.java
index 9ea9f8a..31daaf8 100644
--- a/neoforge/src/main/java/lgbt/greenhouse/config/impl/neoforge/server/dedicated/GreenhouseConfigDedicatedNeoForge.java
+++ b/neoforge/src/main/java/lgbt/greenhouse/config/impl/neoforge/server/dedicated/GreenhouseConfigDedicatedNeoForge.java
@@ -12,9 +12,9 @@ import net.neoforged.neoforge.event.server.ServerStoppedEvent;
@EventBusSubscriber(modid = GreenhouseConfigConstants.MOD_ID, value = Dist.DEDICATED_SERVER)
public class GreenhouseConfigDedicatedNeoForge {
- @SubscribeEvent(priority = EventPriority.HIGHEST)
+ @SubscribeEvent(priority = EventPriority.LOWEST)
public static void onFmlDedicatedServerSetup(FMLDedicatedServerSetupEvent event) {
- GreenhouseConfigImpl.loadConfigs();
+ event.enqueueWork(GreenhouseConfigImpl::onMinecraftLoad);
}
@SubscribeEvent(priority = EventPriority.HIGHEST)
diff --git a/neoforge/src/test/java/lgbt/greenhouse/config/test/GreenhouseConfigTestNeoForge.java b/neoforge/src/test/java/lgbt/greenhouse/config/test/GreenhouseConfigTestNeoForge.java
index a24a762..0978df2 100644
--- a/neoforge/src/test/java/lgbt/greenhouse/config/test/GreenhouseConfigTestNeoForge.java
+++ b/neoforge/src/test/java/lgbt/greenhouse/config/test/GreenhouseConfigTestNeoForge.java
@@ -5,6 +5,7 @@ import net.neoforged.bus.api.IEventBus;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.fml.common.Mod;
+import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent;
import net.neoforged.neoforge.event.RegisterCommandsEvent;
import net.neoforged.neoforge.registries.RegisterEvent;
@@ -12,6 +13,10 @@ import net.neoforged.neoforge.registries.RegisterEvent;
@EventBusSubscriber(modid = GreenhouseConfigTest.MOD_ID)
public class GreenhouseConfigTestNeoForge {
public GreenhouseConfigTestNeoForge(IEventBus bus) {
+ }
+
+ @SubscribeEvent
+ public static void onCommonSetup(FMLCommonSetupEvent event) {
GreenhouseConfigTest.init();
}
@@ -22,6 +27,9 @@ public class GreenhouseConfigTestNeoForge {
@SubscribeEvent
public static void registerContents(RegisterEvent event) {
+ if (event.getRegistryKey() == Registries.ITEM) {
+ GreenhouseConfigTest.ITEM_REGISTRY.registerContents();
+ }
if (event.getRegistryKey() == Registries.SOUND_EVENT) {
GreenhouseConfigTest.SOUND_EVENT_REGISTRY.registerContents();
}
diff --git a/neoforge/src/test/java/lgbt/greenhouse/config/test/client/GreenhouseConfigTestClientNeoForge.java b/neoforge/src/test/java/lgbt/greenhouse/config/test/client/GreenhouseConfigTestClientNeoForge.java
index 0e15ea7..1abece9 100644
--- a/neoforge/src/test/java/lgbt/greenhouse/config/test/client/GreenhouseConfigTestClientNeoForge.java
+++ b/neoforge/src/test/java/lgbt/greenhouse/config/test/client/GreenhouseConfigTestClientNeoForge.java
@@ -7,6 +7,7 @@ import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.ModContainer;
import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.fml.common.Mod;
+import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent;
import net.neoforged.neoforge.client.event.RegisterClientCommandsEvent;
import net.neoforged.neoforge.client.gui.IConfigScreenFactory;
@@ -14,10 +15,14 @@ import net.neoforged.neoforge.client.gui.IConfigScreenFactory;
@EventBusSubscriber(modid = GreenhouseConfigTest.MOD_ID, value = Dist.CLIENT)
public class GreenhouseConfigTestClientNeoForge {
public GreenhouseConfigTestClientNeoForge(ModContainer container) {
- GreenhouseConfigTestClient.init();
container.registerExtensionPoint(IConfigScreenFactory.class, (modContainer, screen) -> new GreenhouseConfigTestScreen(screen));
}
+ @SubscribeEvent
+ public static void onClientSetup(FMLClientSetupEvent event) {
+ GreenhouseConfigTestClient.init();
+ }
+
@SubscribeEvent
public static void registerClientCommands(RegisterClientCommandsEvent event) {
GreenhouseConfigTestClient.registerClientCommands(event.getDispatcher());
diff --git a/templates/v0/greenhouseconfig_test_split.json b/templates/v0/greenhouseconfig_test_split.json
index df74309..0e88889 100644
--- a/templates/v0/greenhouseconfig_test_split.json
+++ b/templates/v0/greenhouseconfig_test_split.json
@@ -9,6 +9,14 @@
"f": "f",
"g": "g"
},
+ "vanilla_item_stack": {
+ "id": "minecraft:enchanted_golden_apple",
+ "count": 1
+ },
+ "modded_item_stack": {
+ "id": "greenhouseconfig_test:test",
+ "count": 1
+ },
"play_cow_sounds_constantly": false,
"play_cat_sounds_constantly": false
}
\ No newline at end of file
diff --git a/templates/v1/greenhouseconfig_test_split.jsonc b/templates/v1/greenhouseconfig_test_split.jsonc
index a8f60c9..6a82e11 100644
--- a/templates/v1/greenhouseconfig_test_split.jsonc
+++ b/templates/v1/greenhouseconfig_test_split.jsonc
@@ -20,6 +20,18 @@
// Default Value: "g"
"g": "g"
},
+ // An item stack of an item from the vanilla game.
+ // Useful for testing static registries!
+ "vanilla_item_stack": {
+ "id": "minecraft:enchanted_golden_apple",
+ "count": 1
+ },
+ // An item stack of an item from the test mod.
+ // Useful for testing static registries!
+ "modded_item_stack": {
+ "id": "greenhouseconfig_test:test",
+ "count": 1
+ },
// Whether to play cow sounds locally at the player's position constantly
// Default Value: false
"play_cow_sounds_constantly": false,
diff --git a/xplat/src/main/java/lgbt/greenhouse/config/api/v3/GreenhouseConfigEventPhases.java b/xplat/src/main/java/lgbt/greenhouse/config/api/v3/GreenhouseConfigEventPhases.java
index cfb0b04..887d823 100644
--- a/xplat/src/main/java/lgbt/greenhouse/config/api/v3/GreenhouseConfigEventPhases.java
+++ b/xplat/src/main/java/lgbt/greenhouse/config/api/v3/GreenhouseConfigEventPhases.java
@@ -1,7 +1,6 @@
package lgbt.greenhouse.config.api.v3;
import lgbt.greenhouse.config.impl.GreenhouseConfigConstants;
-import net.minecraft.core.RegistryAccess;
import net.minecraft.resources.Identifier;
public class GreenhouseConfigEventPhases {
@@ -15,13 +14,13 @@ public class GreenhouseConfigEventPhases {
public static final Identifier LATE_REGISTRY_DEPOPULATION_PHASE = GreenhouseConfigConstants.id("late_registry_depopulation");
/**
- * An event phase used on Fabric that runs before the default event phase.
+ * An event phase used on Fabric that runs after the default event phase.
*
- * This is used when loading configs initially and when reloading configs via {@link GreenhouseConfigHolder#reload(RegistryAccess)} or {@link GreenhouseConfigHolder#save(Object, RegistryAccess)}.
+ * This is used when saving changes within configs upon client/server load.
*
- * The NeoForge equivalent instead runs at HIGHEST priority.
+ * The NeoForge equivalent instead runs at LOWEST priority.
*/
- public static final Identifier CONFIG_LOAD_PHASE = GreenhouseConfigConstants.id("config_load");
+ public static final Identifier CONFIG_SAVE_PHASE = GreenhouseConfigConstants.id("close_registration");
/**
* An event phase used on Fabric that runs before the default event phase.
diff --git a/xplat/src/main/java/lgbt/greenhouse/config/impl/GreenhouseConfigImpl.java b/xplat/src/main/java/lgbt/greenhouse/config/impl/GreenhouseConfigImpl.java
index 31a19b2..a5eb369 100644
--- a/xplat/src/main/java/lgbt/greenhouse/config/impl/GreenhouseConfigImpl.java
+++ b/xplat/src/main/java/lgbt/greenhouse/config/impl/GreenhouseConfigImpl.java
@@ -23,7 +23,6 @@ import lgbt.greenhouse.config.impl.config.AbstractGreenhouseConfigHolderImpl;
import lgbt.greenhouse.config.impl.config.builder.AbstractGreenhouseConfigHolderBuilderImpl;
import lgbt.greenhouse.config.impl.config.builder.ConfigRecordBuilderImpl;
import lgbt.greenhouse.config.impl.network.clientbound.SyncGreenhouseConfigClientboundPacket;
-import lgbt.greenhouse.config.impl.platform.Platform;
import lgbt.greenhouse.config.impl.platform.side.Side;
import lgbt.greenhouse.config.impl.util.GreenhouseConfigLangExecutor;
import lgbt.greenhouse.config.impl.util.MetaFileData;
@@ -33,6 +32,8 @@ import net.minecraft.core.Holder;
import net.minecraft.core.HolderSet;
import net.minecraft.core.RegistryAccess;
import org.jspecify.annotations.Nullable;
+import org.slf4j.event.Level;
+import org.slf4j.spi.LoggingEventBuilder;
import java.io.*;
import java.nio.ByteBuffer;
@@ -53,13 +54,14 @@ public class GreenhouseConfigImpl {
private static final Map> CONFIG_HOLDER_REGISTRATION = new HashMap<>();
private static final Map> CONFIG_HOLDERS = new HashMap<>();
+ private static final Set> CONFIGS_TO_SAVE = new HashSet<>();
+ private static final Map, ExceptionEntry> CONFIG_EXCEPTIONS = new HashMap<>();
+
private static final Map, Object> LOCAL_CONFIGS = new HashMap<>();
private static final Map, Object> NETWORKABLE_CONFIGS = new HashMap<>();
private static final Map, GreenhouseConfigLangExecutor>> EXECUTORS = new HashMap<>();
- private static final String CONFIG_LANG_ERROR = "This is not a fault of the developer implementing the config, Please report this to https://git.greenhouse.lgbt/Modding/polyamory or wherever the repository of the config language they used is instead";
-
public static > H registerConfig(H configHolder, GreenhouseConfigSide side) {
if (!registrationOpen)
throw new RuntimeException("Unable to register a new config at this point in time");
@@ -70,9 +72,7 @@ public class GreenhouseConfigImpl {
return configList;
});
- if (GreenhouseConfigConstants.getPlatformHelper().getPlatform() == Platform.FABRIC) {
- loadEarly(configHolder.getModId());
- }
+ register(configHolder.getModId());
return configHolder;
}
@@ -201,7 +201,7 @@ public class GreenhouseConfigImpl {
}
}
- public static void loadEarly(String configKey) {
+ public static void register(String configKey) {
Side side = GreenhouseConfigConstants.getPlatformHelper().getSide();
var registeredConfig = CONFIG_HOLDER_REGISTRATION.get(configKey);
@@ -241,66 +241,74 @@ public class GreenhouseConfigImpl {
}
GreenhouseConfigEvents.invokeConfigLoadedEvents(holderImpl);
-
- writeSchemaVersion(GreenhouseConfigConstants.getPlatformHelper()
- .getConfigDir()
- .resolve(holderImpl.getModId() + "." + holderImpl.getConfigLang().getFileExtension()),
- holderImpl.getSchemaVersion()
- );
});
- CONFIG_HOLDER_REGISTRATION.remove(configKey);
}
- public static void loadConfigs() {
- Side side = GreenhouseConfigConstants.getPlatformHelper().getSide();
- for (String configKey : CONFIG_HOLDER_REGISTRATION.keySet()) {
- var registeredConfig = CONFIG_HOLDER_REGISTRATION.get(configKey);
- registeredConfig.removeIf(configEntry ->
- configEntry.side == GreenhouseConfigSide.DEDICATED && side == Side.CLIENT || configEntry.side == GreenhouseConfigSide.CLIENT && side == Side.DEDICATED
- );
- Optional configEntry = registeredConfig.stream().max((entry, otherEntry) -> { // Sorted provides an easy way to compare values.
- if (entry.side == otherEntry.side) {
- throw new IllegalStateException("Config with ID '" + configKey + "' has been registered more than once for the same side: '" + side.name() + "'");
- }
+ public static void onMinecraftLoad() {
+ saveChanges();
+ logExceptions();
+ CONFIG_HOLDER_REGISTRATION.clear();
+ registrationOpen = false;
+ }
- if (!(entry.configHolder instanceof GreenhouseInheritedConfigHolder, ?>) && !(otherEntry.configHolder instanceof GreenhouseInheritedConfigHolder, ?>)) {
- throw new IllegalStateException("Config with ID '" + configKey + "' has been registered more than once");
- }
+ private static void saveChanges() {
+ for (var holder : CONFIG_HOLDERS.values()) {
+ //noinspection DuplicatedCode
+ AbstractGreenhouseConfigHolderImpl, ?, ?> impl = (AbstractGreenhouseConfigHolderImpl, ?, ?>) holder;
+ File file = GreenhouseConfigConstants.getPlatformHelper()
+ .getConfigDir()
+ .resolve(impl.getModId() + "." + impl.getConfigLang().getFileExtension())
+ .toFile();
+
+ if (!CONFIGS_TO_SAVE.contains(holder)) {
+ continue;
+ }
- if ((entry.side == GreenhouseConfigSide.CLIENT || entry.side == GreenhouseConfigSide.DEDICATED) && otherEntry.side == GreenhouseConfigSide.COMMON) {
- return 1;
- }
- if (entry.side == GreenhouseConfigSide.COMMON && (otherEntry.side == GreenhouseConfigSide.CLIENT || otherEntry.side == GreenhouseConfigSide.DEDICATED)) {
- return -1;
- }
- return 0;
- });
+ try {
+ saveNewConfig(impl, file, impl.getConfigLang());
+ writeSchemaVersion(GreenhouseConfigConstants.getPlatformHelper()
+ .getConfigDir()
+ .resolve(impl.getModId() + "." + impl.getConfigLang().getFileExtension()),
+ impl.getSchemaVersion()
+ );
+ } catch (IOException e) {
+ CONFIG_SAVE_LOG.error("Could not save config '{}'", holder.getModId(), e);
+ }
+ }
+ CONFIGS_TO_SAVE.clear();
+ }
- configEntry.ifPresent(entry -> {
- CONFIG_HOLDERS.put(configKey, entry.configHolder);
- AbstractGreenhouseConfigHolderImpl, ?, Object> holderImpl = (AbstractGreenhouseConfigHolderImpl, ?, Object>) entry.configHolder;
- var config = loadConfigInternal(holderImpl);
+ private static void logExceptions() {
+ for (var entry : CONFIG_EXCEPTIONS.entrySet()) {
+ if (!CONFIG_HOLDERS.containsValue(entry.getKey()))
+ continue;
- var localData = holderImpl.getLocalData(config);
- var networkData = holderImpl.getNetworkData(config);
+ ExceptionEntry exceptionEntry = entry.getValue();
- LOCAL_CONFIGS.put(holderImpl, localData);
- if (localData != networkData) {
- NETWORKABLE_CONFIGS.put(holderImpl, networkData);
- }
+ LoggingEventBuilder builder = CONFIG_LOAD_LOG
+ .atLevel(exceptionEntry.logLevel)
+ .setMessage(exceptionEntry.message);
- GreenhouseConfigEvents.invokeConfigLoadedEvents(holderImpl);
+ if (exceptionEntry.exception != null) {
+ builder = builder.setCause(exceptionEntry.exception);
+ }
- writeSchemaVersion(GreenhouseConfigConstants.getPlatformHelper()
- .getConfigDir()
- .resolve(holderImpl.getModId() + "." + holderImpl.getConfigLang().getFileExtension()),
- holderImpl.getSchemaVersion()
- );
- });
+ builder.log();
}
- CONFIG_HOLDER_REGISTRATION.clear();
- registrationOpen = false;
}
+
+ private static void saveNewConfig(AbstractGreenhouseConfigHolderImpl, ?, Config> impl, File file, GreenhouseConfigLang lang) throws IOException {
+ DataResult encoded;
+ if (impl.getCommentedCodec() != null) {
+ impl.getCommentedCodec().encodeDefaultComments();
+ encoded = impl.getCommentedCodec().encodeStart(lang.getOps(), new CommentedValueWithoutInternal<>(Collections.emptyList(), impl.getDefaultValue().get()));
+ } else {
+ encoded = impl.getCodec().encodeStart(lang.getOps(), impl.getDefaultValue().get());
+ }
+
+ saveConfigInternal(impl, lang, encoded.getPartialOrThrow(), file);
+ }
+
public static void lateHolderRegistryCallback(AbstractGreenhouseConfigHolderBuilder, ?, C, ?> config, Function> getter) {
AbstractGreenhouseConfigHolderBuilderImpl, ?, C, ?, ?> impl = (AbstractGreenhouseConfigHolderBuilderImpl, ?, C, ?, ?>)config;
@@ -363,7 +371,7 @@ public class GreenhouseConfigImpl {
.toFile();
File file = latestLangFile;
- int schemaVersion = readSchemaVersion(holder.getModId(), file.toPath());
+ int schemaVersion = readSchemaVersion(holder, file.toPath());
if (!latestLangFile.exists()) {
schemaVersion = 0;
for (var entry : holderImpl.getPreviousLangs().int2ObjectEntrySet()) {
@@ -371,7 +379,7 @@ public class GreenhouseConfigImpl {
.getConfigDir()
.resolve(holderImpl.getModId() + "." + entry.getValue().getFileExtension())
.toFile();
- int potentialSchemaVersion = readSchemaVersion(holder.getModId(), oldFile.toPath());
+ int potentialSchemaVersion = readSchemaVersion(holder, oldFile.toPath());
if (oldFile.exists() && schemaVersion <= entry.getIntKey()) {
file = oldFile;
schemaVersion = potentialSchemaVersion;
@@ -400,7 +408,7 @@ public class GreenhouseConfigImpl {
if (oldLang != null) {
if (oldLang == lang) {
- CONFIG_LOAD_LOG.warn("Config file '{}' has an unnecessary previous lang fix for schema version {}", configFileName, schemaVersion);
+ CONFIG_EXCEPTIONS.put(holder, new ExceptionEntry("Config file '" + configFileName + "' has an unnecessary previous lang fix for schema version " + schemaVersion, Level.ERROR));
}
OldLang oldContents;
@@ -411,10 +419,9 @@ public class GreenhouseConfigImpl {
try {
Files.deleteIfExists(file.toPath());
} catch (FileSystemException e) {
- CONFIG_LOAD_LOG.error("Failed to delete old config at path {}", holderImpl.getModId() + "." + oldLang.getFileExtension(), e);
+ CONFIG_EXCEPTIONS.put(holder, new ExceptionEntry("Failed to delete old config at path " + holderImpl.getModId() + "." + oldLang.getFileExtension(), Level.ERROR, e));
}
contents = oldLang.getOps().convertTo(lang.getOps(), oldContents);
- file = latestLangFile;
} else {
try (FileReader fileReader = new FileReader(file)) {
GreenhouseConfigLangExecutor executor = (GreenhouseConfigLangExecutor)EXECUTORS
@@ -434,25 +441,17 @@ public class GreenhouseConfigImpl {
DataResult> commentedParsed = holderImpl.getCommentedCodec()
.parse(lang.getOps(), lang.mergeComments(fixed, contents));
- holderImpl.getCommentedCodec().encodeDefaultComments();
- Lang reEncoded = holderImpl.getCommentedCodec().encodeStart(lang.getOps(), commentedParsed.getPartialOrThrow())
- .getOrThrow(s -> new IllegalStateException("Failed to re-encode broken fields in data-fixed config. " + CONFIG_LANG_ERROR + " " + s));
- saveConfigInternal(holder, lang, reEncoded, file);
-
parsed = commentedParsed.map(CommentedValue::value);
} else {
parsed = holderImpl.getCodec().parse(lang.getOps(), fixed);
-
- Lang reEncoded = holderImpl.getCodec()
- .encodeStart(lang.getOps(), parsed.getPartialOrThrow())
- .getOrThrow(s -> new IllegalStateException("Failed to re-encode broken fields in data-fixed config. " + CONFIG_LANG_ERROR + " " + s));
- saveConfigInternal(holder, lang, reEncoded, file);
}
- if (parsed.resultOrPartial(s -> CONFIG_LOAD_LOG.warn("Could not completely fix config file '{}'. {}", configFileName, s)).isEmpty()) {
+ if (parsed.resultOrPartial(error -> CONFIG_EXCEPTIONS.put(holder, new ExceptionEntry("Could not completely fix config file '" + configFileName + "' " + error, Level.WARN))).isEmpty()) {
throw new IllegalStateException("Could not fix old config file. " + parsed.error().orElseThrow().message());
}
+ CONFIGS_TO_SAVE.add(holder);
+
return parsed.resultOrPartial()
.orElse(holderImpl.getDefaultValue().get());
}
@@ -471,11 +470,7 @@ public class GreenhouseConfigImpl {
.parse(lang.getOps(), contents);
if (!commentedParsed.isSuccess()) {
- holderImpl.getCommentedCodec().encodeDefaultComments();
- Lang reEncoded = holderImpl.getCommentedCodec()
- .encodeStart(lang.getOps(), commentedParsed.getPartialOrThrow())
- .getOrThrow(s -> new IllegalStateException("Failed to re-encode broken config fields. " + CONFIG_LANG_ERROR + " " + s));
- saveConfigInternal(holder, lang, reEncoded, file);
+ CONFIGS_TO_SAVE.add(holder);
}
parsed = commentedParsed.map(CommentedValue::value);
@@ -484,10 +479,7 @@ public class GreenhouseConfigImpl {
.parse(lang.getOps(), contents);
if (!parsed.isSuccess()) {
- Lang reEncoded = holderImpl.getCodec()
- .encodeStart(lang.getOps(), parsed.getPartialOrThrow())
- .getOrThrow(s -> new IllegalStateException("Failed to re-encode broken config fields. " + CONFIG_LANG_ERROR + " " + s));
- saveConfigInternal(holder, lang, reEncoded, file);
+ CONFIGS_TO_SAVE.add(holder);
}
}
@@ -496,28 +488,14 @@ public class GreenhouseConfigImpl {
}
return parsed
- .resultOrPartial(error -> CONFIG_LOAD_LOG.warn("Could not completely load config file '{}'. {}", configFileName, error))
+ .resultOrPartial(error -> CONFIG_EXCEPTIONS.put(holder, new ExceptionEntry("Could not completely load config file '" + configFileName + "' " + error, Level.WARN)))
.orElse(holderImpl.getDefaultValue().get());
}
} catch (Exception e) {
- CONFIG_LOAD_LOG.error("Failed to load config from file '{}'. Falling back to the default values...", configFileName, e);
+ CONFIG_EXCEPTIONS.put(holder, new ExceptionEntry("Failed to load config from file '" + configFileName + "'. Falling back to the default values...", Level.ERROR, e));
}
- try {
- DataResult encoded;
- if (holderImpl.getCommentedCodec() != null) {
- holderImpl.getCommentedCodec().encodeDefaultComments();
- encoded = holderImpl.getCommentedCodec().encodeStart(lang.getOps(), new CommentedValueWithoutInternal<>(Collections.emptyList(), holderImpl.getDefaultValue().get()));
- } else {
- encoded = holderImpl.getCodec().encodeStart(lang.getOps(), holderImpl.getDefaultValue().get());
- }
-
- saveConfigInternal(holder, lang, encoded.getPartialOrThrow(), file);
-
- return holderImpl.getDefaultValue().get();
- } catch (Exception e) {
- CONFIG_LOAD_LOG.error("Failed to encode default values to file {}. {}", configFileName, CONFIG_LANG_ERROR, e);
- }
+ CONFIGS_TO_SAVE.add(holder);
return holderImpl.getDefaultValue().get();
}
@@ -542,7 +520,7 @@ public class GreenhouseConfigImpl {
}
}
- private static int readSchemaVersion(String configModId, Path path) {
+ private static int readSchemaVersion(GreenhouseConfigHolder> configHolder, Path path) {
try {
Path metaFilePath = GreenhouseConfigConstants.getPlatformHelper().getConfigDir()
.resolve(".greenhouse_config_meta/" + path.getFileName() + ".meta");
@@ -568,7 +546,7 @@ public class GreenhouseConfigImpl {
}
}
} catch (IOException e) {
- CONFIG_LOAD_LOG.warn("Failed to load schema version for config '{}', falling back to its default value.", configModId, e);
+ CONFIG_EXCEPTIONS.put(configHolder, new ExceptionEntry("Failed to load schema version for config '" + configHolder + "', falling back to its default value.", Level.ERROR, e));
}
return 0;
}
@@ -669,4 +647,10 @@ public class GreenhouseConfigImpl {
private record ConfigEntry(GreenhouseConfigHolder> configHolder, GreenhouseConfigSide side) {
}
+
+ private record ExceptionEntry(String message, Level logLevel, @Nullable Exception exception) {
+ private ExceptionEntry(String message, Level logLevel) {
+ this(message, logLevel, null);
+ }
+ }
}
diff --git a/xplat/src/test/java/lgbt/greenhouse/config/test/GreenhouseConfigTest.java b/xplat/src/test/java/lgbt/greenhouse/config/test/GreenhouseConfigTest.java
index fa3baad..778ee39 100644
--- a/xplat/src/test/java/lgbt/greenhouse/config/test/GreenhouseConfigTest.java
+++ b/xplat/src/test/java/lgbt/greenhouse/config/test/GreenhouseConfigTest.java
@@ -31,6 +31,9 @@ import net.minecraft.resources.Identifier;
import net.minecraft.resources.ResourceKey;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.tags.TagKey;
+import net.minecraft.world.item.Item;
+import net.minecraft.world.item.ItemStack;
+import net.minecraft.world.item.Items;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.block.Block;
import org.slf4j.Logger;
@@ -39,6 +42,13 @@ public class GreenhouseConfigTest {
public static final String MOD_ID = "greenhouseconfig_test";
public static final Logger LOG = GreenhouseConfigConstants.getLogger("Test");
+ public static final DeferredRegistry- ITEM_REGISTRY = DeferredRegistry.create(BuiltInRegistries.ITEM);
+ public static final DeferredValue
- TEST_ITEM = ITEM_REGISTRY.register("test", () ->
+ new Item(new Item.Properties()
+ .setId(ResourceKey.create(Registries.ITEM, Identifier.fromNamespaceAndPath(MOD_ID, "test")))
+ )
+ );
+
public static final DeferredRegistry SOUND_EVENT_REGISTRY = DeferredRegistry.create(BuiltInRegistries.SOUND_EVENT);
public static final DeferredValue SYLV_FAN = SOUND_EVENT_REGISTRY.register("sylv_fan", () -> SoundEvent.createVariableRangeEvent(id("sylv_fan")));
@@ -122,6 +132,26 @@ public class GreenhouseConfigTest {
SplitConfig.Alphabet::h,
DefaultValueCommentSettings.DISABLE
)
+ ).withValue(
+ "vanilla_item_stack",
+ """
+ An item stack of an item from the vanilla game.
+ Useful for testing static registries!
+ """,
+ ItemStack.CODEC,
+ new ItemStack(Items.ENCHANTED_GOLDEN_APPLE),
+ SplitConfig::vanillaItemStack,
+ DefaultValueCommentSettings.DISABLE
+ ).withValue(
+ "modded_item_stack",
+ """
+ An item stack of an item from the test mod.
+ Useful for testing static registries!
+ """,
+ ItemStack.CODEC,
+ new ItemStack(TEST_ITEM.get()),
+ SplitConfig::moddedItemStack,
+ DefaultValueCommentSettings.DISABLE
),
fixerBuilder -> fixerBuilder
.withPreviousLang(0, GreenhouseConfigJsonLang.INSTANCE)
diff --git a/xplat/src/test/java/lgbt/greenhouse/config/test/config/SplitConfig.java b/xplat/src/test/java/lgbt/greenhouse/config/test/config/SplitConfig.java
index a9e155b..5931bfd 100644
--- a/xplat/src/test/java/lgbt/greenhouse/config/test/config/SplitConfig.java
+++ b/xplat/src/test/java/lgbt/greenhouse/config/test/config/SplitConfig.java
@@ -1,6 +1,8 @@
package lgbt.greenhouse.config.test.config;
-public record SplitConfig(double volumeOfSylvsFan, Alphabet alphabet) {
+import net.minecraft.world.item.ItemStack;
+
+public record SplitConfig(double volumeOfSylvsFan, Alphabet alphabet, ItemStack vanillaItemStack, ItemStack moddedItemStack) {
public record Alphabet(String a, String b, String c, String d, String e, String f, String h) {
}