From 65bc1f930372661745bc1b5b2d4a1f0616194ce1 Mon Sep 17 00:00:00 2001 From: TexTrue <3140846162@qq.com> Date: Sat, 17 Aug 2024 16:46:25 +0800 Subject: [PATCH] config-api --- README.md | 4 + .../resources/META-INF/neoforge.mods.toml | 4 +- config-common/build.gradle | 16 ++ .../kessoku/lib/config/KessokuConfig.java | 9 + .../lib/config/api/ModConfigHelper.java | 157 ++++++++++++ .../serializers/night/HoconSerializer.java | 148 +++++++++++ .../api/serializers/night/JsonSerializer.java | 128 ++++++++++ .../api/serializers/night/TomlSerializer.java | 157 ++++++++++++ .../api/serializers/night/YamlSerializer.java | 122 ++++++++++ .../serializers/quilt/Json5Serializer.java | 229 ++++++++++++++++++ .../lib/config/impl/ModConfigHelperImpl.java | 69 ++++++ config-common/src/main/resources/icon.png | Bin 0 -> 102075 bytes config-fabric/build.gradle | 12 + .../lib/config/KessokuConfigEntrypoint.java | 11 + .../src/main/resources/fabric.mod.json | 31 +++ config-neo/build.gradle | 12 + config-neo/gradle.properties | 1 + .../lib/config/KessokuConfigEntrypoint.java | 11 + .../resources/META-INF/neoforge.mods.toml | 29 +++ gradle/libs.versions.toml | 21 +- settings.gradle | 1 + 21 files changed, 1169 insertions(+), 3 deletions(-) create mode 100644 config-common/build.gradle create mode 100644 config-common/src/main/java/band/kessoku/lib/config/KessokuConfig.java create mode 100644 config-common/src/main/java/band/kessoku/lib/config/api/ModConfigHelper.java create mode 100644 config-common/src/main/java/band/kessoku/lib/config/api/serializers/night/HoconSerializer.java create mode 100644 config-common/src/main/java/band/kessoku/lib/config/api/serializers/night/JsonSerializer.java create mode 100644 config-common/src/main/java/band/kessoku/lib/config/api/serializers/night/TomlSerializer.java create mode 100644 config-common/src/main/java/band/kessoku/lib/config/api/serializers/night/YamlSerializer.java create mode 100644 config-common/src/main/java/band/kessoku/lib/config/api/serializers/quilt/Json5Serializer.java create mode 100644 config-common/src/main/java/band/kessoku/lib/config/impl/ModConfigHelperImpl.java create mode 100644 config-common/src/main/resources/icon.png create mode 100644 config-fabric/build.gradle create mode 100644 config-fabric/src/main/java/band/kessoku/lib/config/KessokuConfigEntrypoint.java create mode 100644 config-fabric/src/main/resources/fabric.mod.json create mode 100644 config-neo/build.gradle create mode 100644 config-neo/gradle.properties create mode 100644 config-neo/src/main/java/band/kessoku/lib/config/KessokuConfigEntrypoint.java create mode 100644 config-neo/src/main/resources/META-INF/neoforge.mods.toml diff --git a/README.md b/README.md index 5b01f3b9..6b9280e2 100644 --- a/README.md +++ b/README.md @@ -18,3 +18,7 @@ #### [HOW TO ADD MODULE](./ADD-MODULE.md) + + +## Another +- Config API part based [`quilt-config`](https://github.com/QuiltMC/quilt-config) diff --git a/command-neo/src/main/resources/META-INF/neoforge.mods.toml b/command-neo/src/main/resources/META-INF/neoforge.mods.toml index 6b937418..7d72a5ff 100644 --- a/command-neo/src/main/resources/META-INF/neoforge.mods.toml +++ b/command-neo/src/main/resources/META-INF/neoforge.mods.toml @@ -14,14 +14,14 @@ logoFile = "icon.png" authors = "Kessoku Tea Time" displayURL = "https://modrinth.com/mod/kessoku-lib" -[[dependencies.kessoku-event-base]] +[[dependencies.kessoku_command]] modId = "neoforge" type = "required" versionRange = "[21.0,)" ordering = "NONE" side = "BOTH" -[[dependencies.kessoku-event-base]] +[[dependencies.kessoku_command]] modId = "minecraft" type = "required" versionRange = "[1.21,)" diff --git a/config-common/build.gradle b/config-common/build.gradle new file mode 100644 index 00000000..5b91867e --- /dev/null +++ b/config-common/build.gradle @@ -0,0 +1,16 @@ +apply from: rootProject.file("gradle/scripts/kessokulib-common.gradle") + +group = "band.kessoku.lib.config" +base.archivesName = rootProject.name + "-config" + +repositories { + maven { url = "https://maven.quiltmc.org/repository/release/" } +} + +dependencies { + moduleImplementation(project(":base-common")) + moduleImplementation(project(":platform-common")) + + implementation(libs.bundles.night.config) + implementation(libs.bundles.quilt.config) +} \ No newline at end of file diff --git a/config-common/src/main/java/band/kessoku/lib/config/KessokuConfig.java b/config-common/src/main/java/band/kessoku/lib/config/KessokuConfig.java new file mode 100644 index 00000000..420a822b --- /dev/null +++ b/config-common/src/main/java/band/kessoku/lib/config/KessokuConfig.java @@ -0,0 +1,9 @@ +package band.kessoku.lib.config; + +import org.slf4j.Marker; +import org.slf4j.MarkerFactory; + +public class KessokuConfig { + public static final String MOD_ID = "kessoku_config"; + public static final Marker MARKER = MarkerFactory.getMarker("[KessokuConfig]"); +} diff --git a/config-common/src/main/java/band/kessoku/lib/config/api/ModConfigHelper.java b/config-common/src/main/java/band/kessoku/lib/config/api/ModConfigHelper.java new file mode 100644 index 00000000..cb8c0c94 --- /dev/null +++ b/config-common/src/main/java/band/kessoku/lib/config/api/ModConfigHelper.java @@ -0,0 +1,157 @@ +package band.kessoku.lib.config.api; + +import band.kessoku.lib.config.impl.ModConfigHelperImpl; +import org.quiltmc.config.api.Config; +import org.quiltmc.config.api.ReflectiveConfig; +import org.quiltmc.config.impl.ConfigImpl; +import org.quiltmc.config.implementor_api.ConfigFactory; + +import java.nio.file.Path; +import java.nio.file.Paths; + +public final class ModConfigHelper { + /** + * Creates and registers a config file + * + * @param family the mod owning the resulting config file + * @param id the configs id + * @param path additional path elements to include as part of this configs file, e.g. + * if the path is empty, the config file might be ".minecraft/config/example_mod/id.toml" + * if the path is "client/gui", the config file might be ".minecraft/config/example_mod/client/gui/id.toml" + * @param creators any number of {@link Config.Creator}s that can be used to configure the resulting config + */ + public static Config create(String family, String id, Path path, Config.Creator... creators) { + return ConfigImpl.create(ModConfigHelperImpl.getConfigEnvironment(), family, id, path, creators); + } + + /** + * Creates and registers a config file + * + * @param family the mod owning the resulting config file + * @param id the configs id + * @param creators any number of {@link Config.Creator}s that can be used to configure the resulting config + */ + public static Config create(String family, String id, Config.Creator... creators) { + return create(family, id, Paths.get(""), creators); + } + + /** + * Creates and registers a config with a class that contains its WrappedValues as fields. + * + * @param family the mod owning the resulting config file + * @param id the config's id + * @param path additional path elements to include as part of this configs file, e.g. + * if the path is empty, the config file might be ".minecraft/config/example_mod/id.toml" + * if the path is "client/gui", the config file might be ".minecraft/config/example_mod/client/gui/id.toml" + * @param before a {@link Config.Creator} that can be used to configure the resulting config further + * @param configCreatorClass a class as described above + * @param after a {@link Config.Creator} that can be used to configure the resulting config further + * @return a {@link ReflectiveConfig } + */ + public static C create(String family, String id, Path path, Config.Creator before, Class configCreatorClass, Config.Creator after) { + return ConfigFactory.create(ModConfigHelperImpl.getConfigEnvironment(), family, id, path, before, configCreatorClass, after); + } + + /** + * Creates and registers a config with a class that contains its WrappedValues as fields. + * + * @param family the mod owning the resulting config file + * @param id the config's id + * @param path additional path elements to include as part of this configs file, e.g. + * if the path is empty, the config file might be ".minecraft/config/example_mod/id.toml" + * if the path is "client/gui", the config file might be ".minecraft/config/example_mod/client/gui/id.toml" + * @param before a {@link Config.Creator} that can be used to configure the resulting config further + * @param configCreatorClass a class as described above + * @return a {@link ReflectiveConfig } + */ + public static C create(String family, String id, Path path, Config.Creator before, Class configCreatorClass) { + return create(family, id, path, before, configCreatorClass, builder -> {}); + } + + /** + * Creates and registers a config with a class that contains its WrappedValues as fields. + * + * @param family the mod owning the resulting config file + * @param id the configs id + * @param path additional path elements to include as part of this configs file, e.g. + * if the path is empty, the config file might be ".minecraft/config/example_mod/id.toml" + * if the path is "client/gui", the config file might be ".minecraft/config/example_mod/client/gui/id.toml" + * @param configCreatorClass a class as described above + * @param after a {@link Config.Creator} that can be used to configure the resulting config further + * @return a {@link ReflectiveConfig } + */ + public static C create(String family, String id, Path path, Class configCreatorClass, Config.Creator after) { + return create(family, id, path, builder -> {}, configCreatorClass, after); + } + + /** + * Creates and registers a config with a class that contains its WrappedValues as fields. + * + * @param family the mod owning the resulting config file + * @param id the config's id + * @param path additional path elements to include as part of this configs file, e.g. + * if the path is empty, the config file might be ".minecraft/config/example_mod/id.toml" + * if the path is "client/gui", the config file might be ".minecraft/config/example_mod/client/gui/id.toml" + * @param configCreatorClass a class as described above + * @return a {@link ReflectiveConfig } + */ + public static C create(String family, String id, Path path, Class configCreatorClass) { + return create(family, id, path, builder -> {}, configCreatorClass, builder -> {}); + } + + /** + * Creates and registers a config with a class that contains its WrappedValues as fields. + * + * @param family the mod owning the resulting config file + * @param id the config's id + * @param before a {@link Config.Creator} that can be used to configure the resulting config further + * @param configCreatorClass a class as described above + * @param after a {@link Config.Creator} that can be used to configure the resulting config further + * @return a {@link ReflectiveConfig } + */ + public static C create(String family, String id, Config.Creator before, Class configCreatorClass, Config.Creator after) { + return create(family, id, Paths.get(""), before, configCreatorClass, after); + } + + /** + * Creates and registers a config with a class that contains its WrappedValues as fields. + * + * @param family the mod owning the resulting config file + * @param id the config's id + * @param before a {@link Config.Creator} that can be used to configure the resulting config further + * @param configCreatorClass a class as described above + * @return a {@link ReflectiveConfig } + */ + public static C create(String family, String id, Config.Creator before, Class configCreatorClass) { + return create(family, id, Paths.get(""), before, configCreatorClass, builder -> {}); + } + + /** + * Creates and registers a config with a class that contains its WrappedValues as fields. + * + * @param family the mod owning the resulting config file + * @param id the config's id + * @param configCreatorClass a class as described above + * @param after a {@link Config.Creator} that can be used to configure the resulting config further + * @return a {@link ReflectiveConfig } + */ + public static C create(String family, String id, Class configCreatorClass, Config.Creator after) { + return create(family, id, Paths.get(""), builder -> {}, configCreatorClass, after); + } + + /** + * Creates and registers a config with a class that contains its WrappedValues as fields. + * + * @param family the mod owning the resulting config file + * @param id the config's id + * @param configCreatorClass a class as described above + * @return a {@link ReflectiveConfig } + */ + public static C create(String family, String id, Class configCreatorClass) { + return create(family, id, Paths.get(""), builder -> {}, configCreatorClass, builder -> {}); + } + + private ModConfigHelper() { + + } +} diff --git a/config-common/src/main/java/band/kessoku/lib/config/api/serializers/night/HoconSerializer.java b/config-common/src/main/java/band/kessoku/lib/config/api/serializers/night/HoconSerializer.java new file mode 100644 index 00000000..850443cb --- /dev/null +++ b/config-common/src/main/java/band/kessoku/lib/config/api/serializers/night/HoconSerializer.java @@ -0,0 +1,148 @@ +package band.kessoku.lib.config.api.serializers.night; + +import com.electronwill.nightconfig.core.CommentedConfig; +import com.electronwill.nightconfig.core.InMemoryCommentedFormat; +import com.electronwill.nightconfig.core.UnmodifiableCommentedConfig; +import com.electronwill.nightconfig.core.io.ConfigParser; +import com.electronwill.nightconfig.core.io.ConfigWriter; +import com.electronwill.nightconfig.hocon.HoconParser; +import com.electronwill.nightconfig.hocon.HoconWriter; +import org.quiltmc.config.api.Config; +import org.quiltmc.config.api.Constraint; +import org.quiltmc.config.api.MarshallingUtils; +import org.quiltmc.config.api.Serializer; +import org.quiltmc.config.api.annotations.Comment; +import org.quiltmc.config.api.values.*; +import org.quiltmc.config.impl.util.SerializerUtils; + +import java.io.InputStream; +import java.io.OutputStream; +import java.util.*; + +/** + * A default serializer that writes in the HOCON format. + * + * @implNote When passing entries to {@link com.electronwill.nightconfig.core.Config#add(String, Object)}, the string key is automatically split at each dot ({@code .}). + * This completely breaks TOML serialization, since we allow dots in keys, using either {@link org.quiltmc.config.api.annotations.SerializedName} or {@link ValueMap}, whose keys are not validated for certain characters. + * To get around this, use {@link com.electronwill.nightconfig.core.Config#add(List, Object)} via passing your key into {@link #toNightConfigSerializable(ValueKey)}. + */ +public final class HoconSerializer implements Serializer { + public static final HoconSerializer INSTANCE = new HoconSerializer(); + private final ConfigParser parser = new HoconParser(); + private final ConfigWriter writer = new HoconWriter(); + + private HoconSerializer() { + + } + + @Override + public String getFileExtension() { + return "hocon"; + } + + @Override + public void serialize(Config config, OutputStream to) { + this.writer.write(write(config, createCommentedConfig(), config.nodes()), to); + } + + @SuppressWarnings({"unchecked", "rawtypes"}) + @Override + public void deserialize(Config config, InputStream from) { + CommentedConfig read = this.parser.parse(from); + + for (TrackedValue trackedValue : config.values()) { + List keyOptions = SerializerUtils.getPossibleKeys(config, trackedValue); + + for (ValueKey key : keyOptions) { + String stringKey = key.toString(); + + if (read.contains(stringKey)) { + ((TrackedValue) trackedValue).setValue(MarshallingUtils.coerce(read.get(stringKey), trackedValue.getDefaultValue(), (CommentedConfig c, MarshallingUtils.MapEntryConsumer entryConsumer) -> + c.entrySet().forEach(e -> entryConsumer.put(e.getKey(), e.getValue()))), false); + } + } + } + } + + private static List convertList(List list) { + List result = new ArrayList<>(list.size()); + + for (Object value : list) { + result.add(convertAny(value)); + } + + return result; + } + + private static UnmodifiableCommentedConfig convertMap(ValueMap map) { + CommentedConfig result = createCommentedConfig(); + + for (Map.Entry entry : map.entrySet()) { + List key = new ArrayList<>(); + key.add(entry.getKey()); + result.add(key, convertAny(entry.getValue())); + } + + return result; + } + + private static Object convertAny(Object value) { + if (value instanceof ValueMap) { + return convertMap((ValueMap) value); + } else if (value instanceof ValueList) { + return convertList((ValueList) value); + } else if (value instanceof ConfigSerializableObject) { + return convertAny(((ConfigSerializableObject) value).getRepresentation()); + } else { + return value; + } + } + + private static CommentedConfig write(Config config, CommentedConfig commentedConfig, Iterable nodes) { + for (ValueTreeNode node : nodes) { + List comments = new ArrayList<>(); + + if (node.hasMetadata(Comment.TYPE)) { + for (String string : node.metadata(Comment.TYPE)) { + comments.add(string); + } + } + + ValueKey key = SerializerUtils.getSerializedKey(config, node); + + if (node instanceof TrackedValue) { + TrackedValue value = (TrackedValue) node; + Object defaultValue = value.getDefaultValue(); + + SerializerUtils.createEnumOptionsComment(defaultValue).ifPresent(comments::add); + + for (Constraint constraint : value.constraints()) { + comments.add(constraint.getRepresentation()); + } + + Optional defaultValueComment = SerializerUtils.getDefaultValueString(defaultValue); + defaultValueComment.ifPresent(s -> comments.add("default: " + s)); + + commentedConfig.add(toNightConfigSerializable(key), convertAny(value.getRealValue())); + } else { + write(config, commentedConfig, ((ValueTreeNode.Section) node)); + } + + if (!comments.isEmpty()) { + commentedConfig.setComment(toNightConfigSerializable(key), " " + String.join("\n ", comments)); + } + } + + return commentedConfig; + } + + private static CommentedConfig createCommentedConfig() { + return InMemoryCommentedFormat.defaultInstance().createConfig(LinkedHashMap::new); + } + + private static List toNightConfigSerializable(ValueKey key) { + List listKey = new ArrayList<>(); + key.forEach(listKey::add); + return listKey; + } +} diff --git a/config-common/src/main/java/band/kessoku/lib/config/api/serializers/night/JsonSerializer.java b/config-common/src/main/java/band/kessoku/lib/config/api/serializers/night/JsonSerializer.java new file mode 100644 index 00000000..c110ae38 --- /dev/null +++ b/config-common/src/main/java/band/kessoku/lib/config/api/serializers/night/JsonSerializer.java @@ -0,0 +1,128 @@ +package band.kessoku.lib.config.api.serializers.night; + +import com.electronwill.nightconfig.core.*; +import com.electronwill.nightconfig.core.io.ConfigParser; +import com.electronwill.nightconfig.core.io.ConfigWriter; +import com.electronwill.nightconfig.json.FancyJsonWriter; +import com.electronwill.nightconfig.json.JsonParser; +import org.quiltmc.config.api.Config; +import org.quiltmc.config.api.MarshallingUtils; +import org.quiltmc.config.api.Serializer; +import org.quiltmc.config.api.values.ConfigSerializableObject; +import org.quiltmc.config.api.values.TrackedValue; +import org.quiltmc.config.api.values.ValueKey; +import org.quiltmc.config.api.values.ValueList; +import org.quiltmc.config.api.values.ValueMap; +import org.quiltmc.config.api.values.ValueTreeNode; +import org.quiltmc.config.impl.util.SerializerUtils; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.*; + +/** + * A default serializer that writes in the JSON format. + * + * @implNote When passing entries to {@link com.electronwill.nightconfig.core.Config#add(String, Object)}, the string key is automatically split at each dot ({@code .}). + * This completely breaks TOML serialization, since we allow dots in keys, using either {@link org.quiltmc.config.api.annotations.SerializedName} or {@link ValueMap}, whose keys are not validated for certain characters. + * To get around this, use {@link com.electronwill.nightconfig.core.Config#add(List, Object)} via passing your key into {@link #toNightConfigSerializable(ValueKey)}. + */ +public final class JsonSerializer implements Serializer { + public static final JsonSerializer INSTANCE = new JsonSerializer(); + private final ConfigParser parser = new JsonParser(); + private final ConfigWriter writer = new FancyJsonWriter(); + + private JsonSerializer() { + + } + + @Override + public String getFileExtension() { + return "json"; + } + + @Override + public void serialize(Config config, OutputStream to) throws IOException { + this.writer.write(write(config, createUncommentedConfig(), config.nodes()), to); + } + + @SuppressWarnings({"unchecked", "rawtypes"}) + @Override + public void deserialize(Config config, InputStream from) { + com.electronwill.nightconfig.core.Config read = this.parser.parse(from); + + for (TrackedValue trackedValue : config.values()) { + List keyOptions = SerializerUtils.getPossibleKeys(config, trackedValue); + + for (ValueKey key : keyOptions) { + String stringKey = key.toString(); + + if (read.contains(stringKey)) { + ((TrackedValue) trackedValue).setValue(MarshallingUtils.coerce(read.get(stringKey), trackedValue.getDefaultValue(), (com.electronwill.nightconfig.core.Config c, MarshallingUtils.MapEntryConsumer entryConsumer) -> + c.entrySet().forEach(e -> entryConsumer.put(e.getKey(), e.getValue()))), false); + } + } + } + } + + private static List convertList(List list) { + List result = new ArrayList<>(list.size()); + + for (Object value : list) { + result.add(convertAny(value)); + } + + return result; + } + + private static UnmodifiableConfig convertMap(ValueMap map) { + com.electronwill.nightconfig.core.Config result = createUncommentedConfig(); + + for (Map.Entry entry : map.entrySet()) { + List key = new ArrayList<>(); + key.add(entry.getKey()); + result.add(key, convertAny(entry.getValue())); + } + + return result; + } + + private static Object convertAny(Object value) { + if (value instanceof ValueMap) { + return convertMap((ValueMap) value); + } else if (value instanceof ValueList) { + return convertList((ValueList) value); + } else if (value instanceof ConfigSerializableObject) { + return convertAny(((ConfigSerializableObject) value).getRepresentation()); + } else { + return value; + } + } + + private static com.electronwill.nightconfig.core.Config write(Config config, com.electronwill.nightconfig.core.Config uncommentedConfig, Iterable nodes) { + for (ValueTreeNode node : nodes) { + ValueKey key = SerializerUtils.getSerializedKey(config, node); + + if (node instanceof TrackedValue) { + TrackedValue value = (TrackedValue) node; + + uncommentedConfig.add(toNightConfigSerializable(key), convertAny(value.getRealValue())); + } else { + write(config, uncommentedConfig, ((ValueTreeNode.Section) node)); + } + } + + return uncommentedConfig; + } + + private static com.electronwill.nightconfig.core.Config createUncommentedConfig() { + return InMemoryFormat.defaultInstance().createConfig(LinkedHashMap::new); + } + + private static List toNightConfigSerializable(ValueKey key) { + List listKey = new ArrayList<>(); + key.forEach(listKey::add); + return listKey; + } +} diff --git a/config-common/src/main/java/band/kessoku/lib/config/api/serializers/night/TomlSerializer.java b/config-common/src/main/java/band/kessoku/lib/config/api/serializers/night/TomlSerializer.java new file mode 100644 index 00000000..e6df27d8 --- /dev/null +++ b/config-common/src/main/java/band/kessoku/lib/config/api/serializers/night/TomlSerializer.java @@ -0,0 +1,157 @@ +package band.kessoku.lib.config.api.serializers.night; + +import com.electronwill.nightconfig.core.CommentedConfig; +import com.electronwill.nightconfig.core.InMemoryCommentedFormat; +import com.electronwill.nightconfig.core.UnmodifiableCommentedConfig; +import com.electronwill.nightconfig.core.io.ConfigParser; +import com.electronwill.nightconfig.core.io.ConfigWriter; +import com.electronwill.nightconfig.toml.TomlParser; +import com.electronwill.nightconfig.toml.TomlWriter; +import org.quiltmc.config.api.Config; +import org.quiltmc.config.api.Constraint; +import org.quiltmc.config.api.MarshallingUtils; +import org.quiltmc.config.api.Serializer; +import org.quiltmc.config.api.annotations.Comment; +import org.quiltmc.config.api.values.ConfigSerializableObject; +import org.quiltmc.config.api.values.TrackedValue; +import org.quiltmc.config.api.values.ValueKey; +import org.quiltmc.config.api.values.ValueList; +import org.quiltmc.config.api.values.ValueMap; +import org.quiltmc.config.api.values.ValueTreeNode; +import org.quiltmc.config.impl.util.SerializerUtils; + +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +/** + * A default serializer that writes in the TOML format. + * + * @implNote When passing entries to {@link com.electronwill.nightconfig.core.Config#add(String, Object)}, the string key is automatically split at each dot ({@code .}). + * This completely breaks TOML serialization, since we allow dots in keys, using either {@link org.quiltmc.config.api.annotations.SerializedName} or {@link ValueMap}, whose keys are not validated for certain characters. + * To get around this, use {@link com.electronwill.nightconfig.core.Config#add(List, Object)} via passing your key into {@link #toNightConfigSerializable(ValueKey)}. + */ +public final class TomlSerializer implements Serializer { + public static final TomlSerializer INSTANCE = new TomlSerializer(); + private final ConfigParser parser = new TomlParser(); + private final ConfigWriter writer = new TomlWriter(); + + private TomlSerializer() { + + } + + @Override + public String getFileExtension() { + return "toml"; + } + + @Override + public void serialize(Config config, OutputStream to) { + this.writer.write(write(config, createCommentedConfig(), config.nodes()), to); + } + + @SuppressWarnings({"unchecked", "rawtypes"}) + @Override + public void deserialize(Config config, InputStream from) { + CommentedConfig read = this.parser.parse(from); + + for (TrackedValue trackedValue : config.values()) { + List keyOptions = SerializerUtils.getPossibleKeys(config, trackedValue); + + for (ValueKey key : keyOptions) { + String stringKey = key.toString(); + + if (read.contains(stringKey)) { + ((TrackedValue) trackedValue).setValue(MarshallingUtils.coerce(read.get(stringKey), trackedValue.getDefaultValue(), (CommentedConfig c, MarshallingUtils.MapEntryConsumer entryConsumer) -> + c.entrySet().forEach(e -> entryConsumer.put(e.getKey(), e.getValue()))), false); + } + } + } + } + + private static List convertList(List list) { + List result = new ArrayList<>(list.size()); + + for (Object value : list) { + result.add(convertAny(value)); + } + + return result; + } + + private static UnmodifiableCommentedConfig convertMap(ValueMap map) { + CommentedConfig result = createCommentedConfig(); + + for (Map.Entry entry : map.entrySet()) { + List key = new ArrayList<>(); + key.add(entry.getKey()); + result.add(key, convertAny(entry.getValue())); + } + + return result; + } + + private static Object convertAny(Object value) { + if (value instanceof ValueMap) { + return convertMap((ValueMap) value); + } else if (value instanceof ValueList) { + return convertList((ValueList) value); + } else if (value instanceof ConfigSerializableObject) { + return convertAny(((ConfigSerializableObject) value).getRepresentation()); + } else { + return value; + } + } + + private static CommentedConfig write(Config config, CommentedConfig commentedConfig, Iterable nodes) { + for (ValueTreeNode node : nodes) { + List comments = new ArrayList<>(); + + if (node.hasMetadata(Comment.TYPE)) { + for (String string : node.metadata(Comment.TYPE)) { + comments.add(string); + } + } + + ValueKey key = SerializerUtils.getSerializedKey(config, node); + + if (node instanceof TrackedValue) { + TrackedValue value = (TrackedValue) node; + Object defaultValue = value.getDefaultValue(); + + SerializerUtils.createEnumOptionsComment(defaultValue).ifPresent(comments::add); + + for (Constraint constraint : value.constraints()) { + comments.add(constraint.getRepresentation()); + } + + Optional defaultValueComment = SerializerUtils.getDefaultValueString(defaultValue); + defaultValueComment.ifPresent(s -> comments.add("default: " + s)); + + commentedConfig.add(toNightConfigSerializable(key), convertAny(value.getRealValue())); + } else { + write(config, commentedConfig, ((ValueTreeNode.Section) node)); + } + + if (!comments.isEmpty()) { + commentedConfig.setComment(toNightConfigSerializable(key), " " + String.join("\n ", comments)); + } + } + + return commentedConfig; + } + + private static CommentedConfig createCommentedConfig() { + return InMemoryCommentedFormat.defaultInstance().createConfig(LinkedHashMap::new); + } + + private static List toNightConfigSerializable(ValueKey key) { + List listKey = new ArrayList<>(); + key.forEach(listKey::add); + return listKey; + } +} diff --git a/config-common/src/main/java/band/kessoku/lib/config/api/serializers/night/YamlSerializer.java b/config-common/src/main/java/band/kessoku/lib/config/api/serializers/night/YamlSerializer.java new file mode 100644 index 00000000..d2a41915 --- /dev/null +++ b/config-common/src/main/java/band/kessoku/lib/config/api/serializers/night/YamlSerializer.java @@ -0,0 +1,122 @@ +package band.kessoku.lib.config.api.serializers.night; + +import com.electronwill.nightconfig.core.*; +import com.electronwill.nightconfig.core.io.ConfigParser; +import com.electronwill.nightconfig.core.io.ConfigWriter; +import com.electronwill.nightconfig.yaml.YamlParser; +import com.electronwill.nightconfig.yaml.YamlWriter; +import org.quiltmc.config.api.Config; +import org.quiltmc.config.api.MarshallingUtils; +import org.quiltmc.config.api.Serializer; +import org.quiltmc.config.api.values.*; +import org.quiltmc.config.impl.util.SerializerUtils; + +import java.io.InputStream; +import java.io.OutputStream; +import java.util.*; + +/** + * A default serializer that writes in the YAML format. + * + * @implNote When passing entries to {@link com.electronwill.nightconfig.core.Config#add(String, Object)}, the string key is automatically split at each dot ({@code .}). + * This completely breaks TOML serialization, since we allow dots in keys, using either {@link org.quiltmc.config.api.annotations.SerializedName} or {@link ValueMap}, whose keys are not validated for certain characters. + * To get around this, use {@link com.electronwill.nightconfig.core.Config#add(List, Object)} via passing your key into {@link #toNightConfigSerializable(ValueKey)}. + */ +public final class YamlSerializer implements Serializer { + public static final YamlSerializer INSTANCE = new YamlSerializer(); + private final ConfigParser parser = new YamlParser(); + private final ConfigWriter writer = new YamlWriter(); + + private YamlSerializer() { + + } + + @Override + public String getFileExtension() { + return "toml"; + } + + @Override + public void serialize(Config config, OutputStream to) { + this.writer.write(write(config, createUncommentedConfig(), config.nodes()), to); + } + + @SuppressWarnings({"unchecked", "rawtypes"}) + @Override + public void deserialize(Config config, InputStream from) { + com.electronwill.nightconfig.core.Config read = this.parser.parse(from); + + for (TrackedValue trackedValue : config.values()) { + List keyOptions = SerializerUtils.getPossibleKeys(config, trackedValue); + + for (ValueKey key : keyOptions) { + String stringKey = key.toString(); + + if (read.contains(stringKey)) { + ((TrackedValue) trackedValue).setValue(MarshallingUtils.coerce(read.get(stringKey), trackedValue.getDefaultValue(), (com.electronwill.nightconfig.core.Config c, MarshallingUtils.MapEntryConsumer entryConsumer) -> + c.entrySet().forEach(e -> entryConsumer.put(e.getKey(), e.getValue()))), false); + } + } + } + } + + private static List convertList(List list) { + List result = new ArrayList<>(list.size()); + + for (Object value : list) { + result.add(convertAny(value)); + } + + return result; + } + + private static UnmodifiableConfig convertMap(ValueMap map) { + com.electronwill.nightconfig.core.Config result = createUncommentedConfig(); + + for (Map.Entry entry : map.entrySet()) { + List key = new ArrayList<>(); + key.add(entry.getKey()); + result.add(key, convertAny(entry.getValue())); + } + + return result; + } + + private static Object convertAny(Object value) { + if (value instanceof ValueMap) { + return convertMap((ValueMap) value); + } else if (value instanceof ValueList) { + return convertList((ValueList) value); + } else if (value instanceof ConfigSerializableObject) { + return convertAny(((ConfigSerializableObject) value).getRepresentation()); + } else { + return value; + } + } + + private static com.electronwill.nightconfig.core.Config write(Config config, com.electronwill.nightconfig.core.Config uncommentedConfig, Iterable nodes) { + for (ValueTreeNode node : nodes) { + ValueKey key = SerializerUtils.getSerializedKey(config, node); + + if (node instanceof TrackedValue) { + TrackedValue value = (TrackedValue) node; + + uncommentedConfig.add(toNightConfigSerializable(key), convertAny(value.getRealValue())); + } else { + write(config, uncommentedConfig, ((ValueTreeNode.Section) node)); + } + } + + return uncommentedConfig; + } + + private static com.electronwill.nightconfig.core.Config createUncommentedConfig() { + return InMemoryFormat.defaultInstance().createConfig(LinkedHashMap::new); + } + + private static List toNightConfigSerializable(ValueKey key) { + List listKey = new ArrayList<>(); + key.forEach(listKey::add); + return listKey; + } +} diff --git a/config-common/src/main/java/band/kessoku/lib/config/api/serializers/quilt/Json5Serializer.java b/config-common/src/main/java/band/kessoku/lib/config/api/serializers/quilt/Json5Serializer.java new file mode 100644 index 00000000..4f09d111 --- /dev/null +++ b/config-common/src/main/java/band/kessoku/lib/config/api/serializers/quilt/Json5Serializer.java @@ -0,0 +1,229 @@ +package band.kessoku.lib.config.api.serializers.quilt; + +import org.quiltmc.config.api.Config; +import org.quiltmc.config.api.Constraint; +import org.quiltmc.config.api.MarshallingUtils; +import org.quiltmc.config.api.Serializer; +import org.quiltmc.config.api.annotations.Comment; +import org.quiltmc.config.api.exceptions.ConfigParseException; +import org.quiltmc.config.api.values.ConfigSerializableObject; +import org.quiltmc.config.api.values.TrackedValue; +import org.quiltmc.config.api.values.ValueKey; +import org.quiltmc.config.api.values.ValueList; +import org.quiltmc.config.api.values.ValueMap; +import org.quiltmc.config.api.values.ValueTreeNode; +import org.quiltmc.config.impl.tree.TrackedValueImpl; +import org.quiltmc.config.impl.util.SerializerUtils; +import org.quiltmc.parsers.json.JsonReader; +import org.quiltmc.parsers.json.JsonToken; +import org.quiltmc.parsers.json.JsonWriter; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +/** + * A default serializer that writes in the JSON5 format. + */ +public final class Json5Serializer implements Serializer { + public static final Json5Serializer INSTANCE = new Json5Serializer(); + + private Json5Serializer() { + + } + + @Override + public String getFileExtension() { + return "json5"; + } + + private void serialize(JsonWriter writer, Object value) throws IOException { + if (value instanceof Integer) { + writer.value((Integer) value); + } else if (value instanceof Long) { + writer.value((Long) value); + } else if (value instanceof Float) { + writer.value((Float) value); + } else if (value instanceof Double) { + writer.value((Double) value); + } else if (value instanceof Boolean) { + writer.value((Boolean) value); + } else if (value instanceof String) { + writer.value((String) value); + } else if (value instanceof ValueList) { + writer.beginArray(); + + for (Object v : (ValueList) value) { + serialize(writer, v); + } + + writer.endArray(); + } else if (value instanceof ValueMap) { + writer.beginObject(); + + for (Map.Entry entry : (ValueMap) value) { + writer.name(entry.getKey()); + serialize(writer, entry.getValue()); + } + + writer.endObject(); + } else if (value instanceof ConfigSerializableObject) { + serialize(writer, ((ConfigSerializableObject) value).getRepresentation()); + } else if (value == null) { + writer.nullValue(); + } else if (value.getClass().isEnum()) { + writer.value(((Enum) value).name()); + } else { + throw new ConfigParseException(); + } + } + + private void serialize(JsonWriter writer, ValueTreeNode node) throws IOException { + for (String comment : node.metadata(Comment.TYPE)) { + writer.comment(comment); + } + + if (node instanceof ValueTreeNode.Section) { + writer.name(node.key().getLastComponent()); + writer.beginObject(); + + for (ValueTreeNode child : ((ValueTreeNode.Section) node)) { + serialize(writer, child); + } + + writer.endObject(); + } else { + TrackedValue trackedValue = ((TrackedValue) node); + Object defaultValue = trackedValue.getDefaultValue(); + + Optional enumOptionsComment = SerializerUtils.createEnumOptionsComment(defaultValue); + if (enumOptionsComment.isPresent()) { + writer.comment(enumOptionsComment.get()); + } + + for (Constraint constraint : trackedValue.constraints()) { + writer.comment(constraint.getRepresentation()); + } + + Optional defaultComment = SerializerUtils.getDefaultValueString(defaultValue); + if (defaultComment.isPresent()) { + writer.comment("default: " + defaultComment.get()); + } + + String name = SerializerUtils.getSerializedName(trackedValue); + writer.name(name); + + serialize(writer, trackedValue.getRealValue()); + } + } + + @Override + public void serialize(Config config, OutputStream to) throws IOException { + JsonWriter writer = JsonWriter.json5(new OutputStreamWriter(to)); + + for (String comment : config.metadata(Comment.TYPE)) { + writer.comment(comment); + } + + writer.beginObject(); + + for (ValueTreeNode node : config.nodes()) { + this.serialize(writer, node); + } + + writer.endObject(); + writer.close(); + } + + @Override + @SuppressWarnings({"unchecked", "rawtypes"}) + public void deserialize(Config config, InputStream from) { + try { + JsonReader reader = JsonReader.json5(new InputStreamReader(from)); + + Map values = parseObject(reader); + + for (TrackedValue value : config.values()) { + Map m = values; + List keyOptions = SerializerUtils.getPossibleKeys(config, value); + + for (ValueKey key : keyOptions) { + for (int i = 0; i < key.length(); i++) { + String name = key.getKeyComponent(i); + if (m.containsKey(name) && i != key.length() - 1) { + m = (Map) m.get(name); + } else if (m.containsKey(name)) { + ((TrackedValueImpl) value).setValue(MarshallingUtils.coerce(m.get(name), value.getDefaultValue(), (Map map, MarshallingUtils.MapEntryConsumer entryConsumer) -> + map.forEach(entryConsumer::put)), false); + } + } + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + private static Map parseObject(JsonReader reader) throws IOException { + reader.beginObject(); + + Map object = new LinkedHashMap<>(); + + while (reader.hasNext() && reader.peek() == JsonToken.NAME) { + object.put(reader.nextName(), parseElement(reader)); + } + + reader.endObject(); + + return object; + } + + public static List parseArray(JsonReader reader) throws IOException { + reader.beginArray(); + + List array = new ArrayList<>(); + + while (reader.hasNext() && reader.peek() != JsonToken.END_ARRAY) { + array.add(parseElement(reader)); + } + + reader.endArray(); + + return array; + } + + private static Object parseElement(JsonReader reader) throws IOException { + switch (reader.peek()) { + case END_ARRAY: + throw new ConfigParseException("Unexpected end of array"); + case BEGIN_OBJECT: + return parseObject(reader); + case BEGIN_ARRAY: + return parseArray(reader); + case END_OBJECT: + throw new ConfigParseException("Unexpected end of object"); + case NAME: + throw new ConfigParseException("Unexpected name"); + case STRING: + return reader.nextString(); + case NUMBER: + return reader.nextNumber(); + case BOOLEAN: + return reader.nextBoolean(); + case NULL: + reader.nextNull(); + return null; + case END_DOCUMENT: + throw new ConfigParseException("Unexpected end of file"); + } + + throw new ConfigParseException("Encountered unknown JSON token"); + } +} diff --git a/config-common/src/main/java/band/kessoku/lib/config/impl/ModConfigHelperImpl.java b/config-common/src/main/java/band/kessoku/lib/config/impl/ModConfigHelperImpl.java new file mode 100644 index 00000000..6d2da8f0 --- /dev/null +++ b/config-common/src/main/java/band/kessoku/lib/config/impl/ModConfigHelperImpl.java @@ -0,0 +1,69 @@ +package band.kessoku.lib.config.impl; + +import band.kessoku.lib.base.ModUtils; +import band.kessoku.lib.config.api.serializers.night.HoconSerializer; +import band.kessoku.lib.config.api.serializers.night.JsonSerializer; +import band.kessoku.lib.config.api.serializers.night.YamlSerializer; +import band.kessoku.lib.config.api.serializers.quilt.Json5Serializer; +import band.kessoku.lib.config.api.serializers.night.TomlSerializer; +import band.kessoku.lib.platform.api.ModLoader; + +import org.quiltmc.config.api.Serializer; +import org.quiltmc.config.implementor_api.ConfigEnvironment; +import org.slf4j.Logger; + +import java.nio.file.Path; +import java.util.LinkedHashMap; +import java.util.Map; + +public final class ModConfigHelperImpl { + private static ConfigEnvironment ENV; + private static final Path CONFIG_DIR = ModLoader.getInstance().getConfigFolder(); + private static final Logger LOGGER = ModUtils.getLogger(); + + public static void init() { + Map serializerMap = new LinkedHashMap<>(); + + serializerMap.put("json5", Json5Serializer.INSTANCE); + + serializerMap.put("toml", TomlSerializer.INSTANCE); + serializerMap.put("json", JsonSerializer.INSTANCE); + serializerMap.put("yaml", YamlSerializer.INSTANCE); + serializerMap.put("hocon", HoconSerializer.INSTANCE); + + String globalConfigExtension = System.getProperty("kessoku.config.globalConfigExtension"); + String defaultConfigExtension = System.getProperty("kessoku.config.defaultConfigExtension"); + + Serializer[] serializers = serializerMap.values().toArray(new Serializer[0]); + + if (globalConfigExtension != null && !serializerMap.containsKey(globalConfigExtension)) { + throw new RuntimeException("Cannot use file extension " + globalConfigExtension + " globally: no matching serializer found"); + } + + if (defaultConfigExtension != null && !serializerMap.containsKey(defaultConfigExtension)) { + throw new RuntimeException("Cannot use file extension " + defaultConfigExtension + " by default: no matching serializer found"); + } + + if (defaultConfigExtension == null) { + ENV = new ConfigEnvironment(CONFIG_DIR, globalConfigExtension, serializers[0]); + + for (int i = 1; i < serializers.length; ++i) { + ENV.registerSerializer(serializers[i]); + } + } else { + ENV = new ConfigEnvironment(CONFIG_DIR, globalConfigExtension, serializerMap.get(defaultConfigExtension)); + + for (Serializer serializer : serializers) { + ENV.registerSerializer(serializer); + } + } + } + + public static ConfigEnvironment getConfigEnvironment() { + return ENV; + } + + private ModConfigHelperImpl() { + + } +} diff --git a/config-common/src/main/resources/icon.png b/config-common/src/main/resources/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..226df8cffab7310e05ba2797d4c04a7fac8d70f9 GIT binary patch literal 102075 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 z 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 GO!^=0.16.0", + "minecraft": "1.21", + "java": ">=21", + "fabric-api": "*" + }, + "custom": { + "modmenu": { + "badges": [ + "library" + ] + } + } +} \ No newline at end of file diff --git a/config-neo/build.gradle b/config-neo/build.gradle new file mode 100644 index 00000000..3a2af6af --- /dev/null +++ b/config-neo/build.gradle @@ -0,0 +1,12 @@ +apply from: rootProject.file("gradle/scripts/kessokulib-neo.gradle") + +group = "band.kessoku.lib.config" +base.archivesName = rootProject.name + "-config" + +dependencies { + moduleImplementation(project(":base-common")) + moduleImplementation(project(":platform-common")) + + common(project(path: ':config-common', configuration: 'namedElements')) { transitive false } + shadowBundle project(path: ':config-common', configuration: 'transformProductionNeoForge') +} \ No newline at end of file diff --git a/config-neo/gradle.properties b/config-neo/gradle.properties new file mode 100644 index 00000000..2914393d --- /dev/null +++ b/config-neo/gradle.properties @@ -0,0 +1 @@ +loom.platform=neoforge \ No newline at end of file diff --git a/config-neo/src/main/java/band/kessoku/lib/config/KessokuConfigEntrypoint.java b/config-neo/src/main/java/band/kessoku/lib/config/KessokuConfigEntrypoint.java new file mode 100644 index 00000000..e68e7367 --- /dev/null +++ b/config-neo/src/main/java/band/kessoku/lib/config/KessokuConfigEntrypoint.java @@ -0,0 +1,11 @@ +package band.kessoku.lib.config; + +import band.kessoku.lib.config.impl.ModConfigHelperImpl; +import net.neoforged.fml.common.Mod; + +@Mod(KessokuConfig.MOD_ID) +public class KessokuConfigEntrypoint { + public KessokuConfigEntrypoint() { + ModConfigHelperImpl.init(); + } +} diff --git a/config-neo/src/main/resources/META-INF/neoforge.mods.toml b/config-neo/src/main/resources/META-INF/neoforge.mods.toml new file mode 100644 index 00000000..1d988e2a --- /dev/null +++ b/config-neo/src/main/resources/META-INF/neoforge.mods.toml @@ -0,0 +1,29 @@ +modLoader = "javafml" +loaderVersion = "[4,)" +license = "LGPL-3.0-only" +issueTrackerURL = "https://github.com/KessokuTeaTime/KessokuLib/issues" + +[[mods]] +modId = "kessoku_config" +version = "${version}" +displayName = "Kessoku Config API" +description = ''' +A simple config api. Based quilt-config. +''' +logoFile = "icon.png" +authors = "Kessoku Tea Time" +displayURL = "https://modrinth.com/mod/kessoku-lib" + +[[dependencies.kessoku_config]] +modId = "neoforge" +type = "required" +versionRange = "[21.0,)" +ordering = "NONE" +side = "BOTH" + +[[dependencies.kessoku_config]] +modId = "minecraft" +type = "required" +versionRange = "[1.21,)" +ordering = "NONE" +side = "BOTH" \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 0be10e08..008d802e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -17,6 +17,11 @@ architectury = "3.4-SNAPSHOT" shadow = "8.1.1" spotless = "6.25.0" +# Config libraries +night-config = "3.8.1" +quilt-config = "1.3.1" +quilt-json-parsers = "0.2.0" + [libraries] minecraft = { group = "com.mojang", name = "minecraft", version.ref = "minecraft" } yarn = { group = "net.fabricmc", name = "yarn", version.ref = "yarn" } @@ -29,8 +34,22 @@ fabric-loader = { group = "net.fabricmc", name = "fabric-loader", version.ref = # Mods fabric-api = { group = "net.fabricmc.fabric-api", name = "fabric-api", version.ref = "fabric-api" } +# Config libraries +night-config-core = { group = "com.electronwill.night-config", name = "core", version.ref = "night-config" } +night-config-toml = { group = "com.electronwill.night-config", name = "toml", version.ref = "night-config" } +night-config-json = { group = "com.electronwill.night-config", name = "json", version.ref = "night-config" } +night-config-yaml = { group = "com.electronwill.night-config", name = "yaml", version.ref = "night-config" } +night-config-hocon = { group = "com.electronwill.night-config", name = "hocon", version.ref = "night-config" } + +quilt-config = { group = "org.quiltmc", name = "quilt-config", version.ref = "quilt-config" } +quilt-json-parsers = { group = "org.quiltmc.parsers", name = "json", version.ref = "quilt-json-parsers" } + [plugins] loom = { id = "dev.architectury.loom", version.ref = "loom" } architectury = { id = "architectury-plugin", version.ref = "architectury" } shadow = { id = "com.github.johnrengelman.shadow", version.ref = "shadow" } -spotless = { id = "com.diffplug.spotless", version.ref = "spotless" } \ No newline at end of file +spotless = { id = "com.diffplug.spotless", version.ref = "spotless" } + +[bundles] +night-config = ["night-config-core", "night-config-toml", "night-config-json", "night-config-yaml", "night-config-hocon"] +quilt-config = ["quilt-config", "quilt-json-parsers"] \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 8a0f20a0..36f7ece0 100644 --- a/settings.gradle +++ b/settings.gradle @@ -17,4 +17,5 @@ include("registry-common", "registry-fabric", "registry-neo") // Registry include("lifecycle-events-common", "lifecycle-events-fabric", "lifecycle-events-neo") // Lifecycle Events include("command-common", "command-fabric", "command-neo") // Command API include("keybind-common", "keybind-fabric", "keybind-neo") // Keybind API +include("config-common", "config-fabric", "config-neo") // Config API