diff --git a/docs/libjf-config-v0.md b/docs/libjf-config-v0.md index c84c302..1995483 100644 --- a/docs/libjf-config-v0.md +++ b/docs/libjf-config-v0.md @@ -47,7 +47,7 @@ Enum keys are translated as follows: `.jfconfig.enum..< ## Categories Categories can be added by creating public static subclasses in your config class and annotating them with @Category. -Entries will be read as before, however translations for fields will use `jfconfig..` instead of `jfconfig.` +Entries will be read as before, however the translation prefix will be `jfconfig..` instead of `jfconfig.` ## Presets libjf-config-v0 provides a preset system to automatically fill in certain values based on a function. diff --git a/libjf-base/src/main/java/io/gitlab/jfronny/libjf/LibJf.java b/libjf-base/src/main/java/io/gitlab/jfronny/libjf/LibJf.java index 935c64e..1674464 100644 --- a/libjf-base/src/main/java/io/gitlab/jfronny/libjf/LibJf.java +++ b/libjf-base/src/main/java/io/gitlab/jfronny/libjf/LibJf.java @@ -15,6 +15,7 @@ public class LibJf { static { GsonHolder.modifyBuilder((final GsonBuilder builder) -> { + builder.setOmitQuotes(); for (GsonAdapter adapter : FabricLoader.getInstance().getEntrypoints(MOD_ID + ":gson_adapter", GsonAdapter.class)) { adapter.apply(builder); } diff --git a/libjf-config-v0/src/main/java/io/gitlab/jfronny/libjf/config/api/ConfigInstance.java b/libjf-config-v0/src/main/java/io/gitlab/jfronny/libjf/config/api/ConfigInstance.java index 16fcc12..7813220 100644 --- a/libjf-config-v0/src/main/java/io/gitlab/jfronny/libjf/config/api/ConfigInstance.java +++ b/libjf-config-v0/src/main/java/io/gitlab/jfronny/libjf/config/api/ConfigInstance.java @@ -1,10 +1,5 @@ package io.gitlab.jfronny.libjf.config.api; -import io.gitlab.jfronny.gson.JsonObject; -import io.gitlab.jfronny.gson.stream.JsonWriter; -import org.jetbrains.annotations.ApiStatus; - -import java.io.IOException; import java.util.List; import java.util.Map; @@ -17,15 +12,20 @@ public interface ConfigInstance { } void load(); void write(); - String getModId(); + String getId(); + String getCategoryPath(); + default String getTranslationPrefix() { + return getId() + ".jfconfig." + getCategoryPath(); + } List> getEntries(); Map getPresets(); - List getReferencedConfigs(); + default List getReferencedConfigs() { + return List.of(); + } Map getCategories(); - - @ApiStatus.Internal void verify(); - @ApiStatus.Internal boolean matchesConfigClass(Class candidate); - @ApiStatus.Internal void loadFrom(JsonObject source); - @ApiStatus.Internal void writeTo(JsonWriter writer) throws IOException; - @ApiStatus.Internal String getCategoryPath(); + default void fix() { + for (EntryInfo entry : getEntries()) { + entry.fix(); + } + } } diff --git a/libjf-config-v0/src/main/java/io/gitlab/jfronny/libjf/config/api/EntryInfo.java b/libjf-config-v0/src/main/java/io/gitlab/jfronny/libjf/config/api/EntryInfo.java index 922cdbf..853cae3 100644 --- a/libjf-config-v0/src/main/java/io/gitlab/jfronny/libjf/config/api/EntryInfo.java +++ b/libjf-config-v0/src/main/java/io/gitlab/jfronny/libjf/config/api/EntryInfo.java @@ -2,26 +2,10 @@ package io.gitlab.jfronny.libjf.config.api; import io.gitlab.jfronny.gson.JsonElement; import io.gitlab.jfronny.gson.stream.JsonWriter; -import io.gitlab.jfronny.libjf.config.impl.EntryInfoImpl; -import org.jetbrains.annotations.Nullable; import java.io.IOException; -import java.lang.reflect.Field; public interface EntryInfo { - static @Nullable EntryInfo fromField(Field field) { - if (!field.isAnnotationPresent(Entry.class)) { - return null; - } - EntryInfoImpl info = new EntryInfoImpl<>(); - info.field = field; - info.entry = field.getAnnotation(Entry.class); - try { - info.defaultValue = (T) field.get(null); - } catch (IllegalAccessException ignored) {} - return info; - } - /** * @return Get the default value of this entry */ diff --git a/libjf-config-v0/src/main/java/io/gitlab/jfronny/libjf/config/impl/ConfigHolderImpl.java b/libjf-config-v0/src/main/java/io/gitlab/jfronny/libjf/config/impl/ConfigHolderImpl.java index 248f70b..0f9d830 100644 --- a/libjf-config-v0/src/main/java/io/gitlab/jfronny/libjf/config/impl/ConfigHolderImpl.java +++ b/libjf-config-v0/src/main/java/io/gitlab/jfronny/libjf/config/impl/ConfigHolderImpl.java @@ -24,7 +24,7 @@ public class ConfigHolderImpl implements ConfigHolder { @Override public void register(String modId, Class config) { if (isRegistered(modId)) { - if (get(modId).matchesConfigClass(config)) { + if (get(modId) instanceof ConfigInstanceAbstract instance && instance.matchesConfigClass(config)) { SafeLog.warn("Attempted to set config of " + modId + " twice, skipping"); return; } @@ -61,7 +61,7 @@ public class ConfigHolderImpl implements ConfigHolder { @Override public ConfigInstance get(Class configClass) { for (ConfigInstance value : configs.values()) { - if (value.matchesConfigClass(configClass)) + if (value instanceof ConfigInstanceAbstract instance && instance.matchesConfigClass(configClass)) return value; } return null; @@ -80,7 +80,7 @@ public class ConfigHolderImpl implements ConfigHolder { @Override public boolean isRegistered(Class config) { for (ConfigInstance value : configs.values()) { - if (value.matchesConfigClass(config)) + if (value instanceof ConfigInstanceAbstract instance && instance.matchesConfigClass(config)) return true; } return false; diff --git a/libjf-config-v0/src/main/java/io/gitlab/jfronny/libjf/config/impl/ConfigInstanceAbstract.java b/libjf-config-v0/src/main/java/io/gitlab/jfronny/libjf/config/impl/ConfigInstanceAbstract.java index 5a9968b..1c375f5 100644 --- a/libjf-config-v0/src/main/java/io/gitlab/jfronny/libjf/config/impl/ConfigInstanceAbstract.java +++ b/libjf-config-v0/src/main/java/io/gitlab/jfronny/libjf/config/impl/ConfigInstanceAbstract.java @@ -29,8 +29,8 @@ public abstract class ConfigInstanceAbstract implements ConfigInstance { this.configClass = configClass; this.referencedConfigs = List.copyOf(meta.referencedConfigs); for (Field field : configClass.getFields()) { - EntryInfo newInfo = EntryInfo.fromField(field); - if (newInfo != null) entries.add(newInfo); + if (field.isAnnotationPresent(Entry.class)) + entries.add(new EntryInfoImpl<>(field)); } presets.put(CONFIG_PRESET_DEFAULT, () -> { for (EntryInfo entry : entries) { @@ -62,11 +62,6 @@ public abstract class ConfigInstanceAbstract implements ConfigInstance { }); } } - verifiers.add(() -> { - for (EntryInfo entry : entries) { - entry.fix(); - } - }); for (Class categoryClass : configClass.getClasses()) { if (categoryClass.isAnnotationPresent(Category.class)) { @@ -88,7 +83,6 @@ public abstract class ConfigInstanceAbstract implements ConfigInstance { return Character.toLowerCase(source.charAt(0)) + source.substring(1); } - @Override public void loadFrom(JsonObject source) { for (EntryInfo entry : entries) { if (source.has(entry.getName())) { @@ -100,17 +94,16 @@ public abstract class ConfigInstanceAbstract implements ConfigInstance { } else SafeLog.error("Config does not contain entry for " + entry.getName()); } for (Map.Entry entry : subcategories.entrySet()) { - if (source.has(entry.getKey())) { + if (entry.getValue() instanceof ConfigInstanceAbstract instance && source.has(entry.getKey())) { JsonElement el = source.get(entry.getKey()); - if (el.isJsonObject()) entry.getValue().loadFrom(el.getAsJsonObject()); + if (el.isJsonObject()) instance.loadFrom(el.getAsJsonObject()); else SafeLog.error("Config category is not a JSON object, skipping"); } else SafeLog.error("Config does not contain entry for subcategory " + entry.getKey()); } } - @Override public void writeTo(JsonWriter writer) throws IOException { - verify(); + fix(); writer.beginObject(); String val; for (EntryInfo entry : entries) { @@ -121,26 +114,27 @@ public abstract class ConfigInstanceAbstract implements ConfigInstance { } } for (Map.Entry entry : subcategories.entrySet()) { + if (!(entry.getValue() instanceof ConfigInstanceAbstract instance)) continue; if ((val = JfConfigSafe.TRANSLATION_SUPPLIER.apply(modId + ".jfconfig." + categoryPath + entry.getKey() + ".title")) != null) writer.comment(val); writer.name(entry.getKey()); - entry.getValue().writeTo(writer); + instance.writeTo(writer); } writer.endObject(); } @Override - public void verify() { + public void fix() { for (Runnable verifier : verifiers) verifier.run(); + for (EntryInfo entry : entries) entry.fix(); } - @Override public boolean matchesConfigClass(Class candidate) { return candidate != null && candidate.isAssignableFrom(configClass); } @Override - public String getModId() { + public String getId() { return modId; } @@ -160,8 +154,13 @@ public abstract class ConfigInstanceAbstract implements ConfigInstance { } @Override - public List getReferencedConfigs() { - return referencedConfigs; + public List getReferencedConfigs() { + List result = new LinkedList<>(); + for (String referencedConfig : referencedConfigs) { + ConfigInstance ci = ConfigHolder.getInstance().get(referencedConfig); + if (ci != null) result.add(ci); + } + return result; } @Override diff --git a/libjf-config-v0/src/main/java/io/gitlab/jfronny/libjf/config/impl/EntryInfoImpl.java b/libjf-config-v0/src/main/java/io/gitlab/jfronny/libjf/config/impl/EntryInfoImpl.java index 60d4276..543aa67 100644 --- a/libjf-config-v0/src/main/java/io/gitlab/jfronny/libjf/config/impl/EntryInfoImpl.java +++ b/libjf-config-v0/src/main/java/io/gitlab/jfronny/libjf/config/impl/EntryInfoImpl.java @@ -18,7 +18,12 @@ public class EntryInfoImpl implements EntryInfo { public T defaultValue; public Entry entry; - public EntryInfoImpl() { + public EntryInfoImpl(Field field) { + this.field = field; + this.entry = field.getAnnotation(Entry.class); + try { + this.defaultValue = (T) field.get(null); + } catch (IllegalAccessException ignored) {} } @Override diff --git a/libjf-config-v0/src/main/java/io/gitlab/jfronny/libjf/config/impl/client/JfConfigClient.java b/libjf-config-v0/src/main/java/io/gitlab/jfronny/libjf/config/impl/client/JfConfigClient.java index 74e0f76..f8f18b9 100644 --- a/libjf-config-v0/src/main/java/io/gitlab/jfronny/libjf/config/impl/client/JfConfigClient.java +++ b/libjf-config-v0/src/main/java/io/gitlab/jfronny/libjf/config/impl/client/JfConfigClient.java @@ -3,14 +3,13 @@ package io.gitlab.jfronny.libjf.config.impl.client; import io.gitlab.jfronny.libjf.LibJf; import io.gitlab.jfronny.libjf.config.api.ConfigHolder; import io.gitlab.jfronny.libjf.config.api.ConfigInstance; -import io.gitlab.jfronny.libjf.config.impl.client.gui.EntryInfoWidgetBuilder; import net.fabricmc.api.ClientModInitializer; public class JfConfigClient implements ClientModInitializer { @Override public void onInitializeClient() { for (ConfigInstance config : ConfigHolder.getInstance().getRegistered().values()) { - LibJf.LOGGER.info("Registering config UI for " + config.getModId()); + LibJf.LOGGER.info("Registering config UI for " + config.getId()); } } } diff --git a/libjf-config-v0/src/main/java/io/gitlab/jfronny/libjf/config/impl/client/gui/EntryInfoWidgetBuilder.java b/libjf-config-v0/src/main/java/io/gitlab/jfronny/libjf/config/impl/client/gui/EntryInfoWidgetBuilder.java index 7e1c0cc..ccf9e81 100644 --- a/libjf-config-v0/src/main/java/io/gitlab/jfronny/libjf/config/impl/client/gui/EntryInfoWidgetBuilder.java +++ b/libjf-config-v0/src/main/java/io/gitlab/jfronny/libjf/config/impl/client/gui/EntryInfoWidgetBuilder.java @@ -53,7 +53,7 @@ public class EntryInfoWidgetBuilder { factory = toggle(info, state, value -> { int index = values.indexOf(value) + 1; return values.get(index >= values.size() ? 0 : index); - }, value -> Text.translatable(config.getModId() + ".jfconfig.enum." + type.getSimpleName() + "." + state.cachedValue)); + }, value -> Text.translatable(config.getTranslationPrefix() + "enum." + type.getSimpleName() + "." + state.cachedValue)); } else { LibJf.LOGGER.error("Invalid entry type in " + info.getName() + ": " + type.getName()); factory = ((screenWidth, textRenderer, done) -> new WidgetFactory.Widget(() -> {}, new ButtonWidget(-10, 0, 0, 0, Text.of(""), null))); diff --git a/libjf-config-v0/src/main/java/io/gitlab/jfronny/libjf/config/impl/client/gui/TinyConfigScreen.java b/libjf-config-v0/src/main/java/io/gitlab/jfronny/libjf/config/impl/client/gui/TinyConfigScreen.java index d7dd987..e8b75e5 100644 --- a/libjf-config-v0/src/main/java/io/gitlab/jfronny/libjf/config/impl/client/gui/TinyConfigScreen.java +++ b/libjf-config-v0/src/main/java/io/gitlab/jfronny/libjf/config/impl/client/gui/TinyConfigScreen.java @@ -1,7 +1,6 @@ package io.gitlab.jfronny.libjf.config.impl.client.gui; import io.gitlab.jfronny.commons.throwable.Try; -import io.gitlab.jfronny.libjf.config.api.ConfigHolder; import io.gitlab.jfronny.libjf.config.api.ConfigInstance; import io.gitlab.jfronny.libjf.config.api.WidgetFactory; import io.gitlab.jfronny.libjf.config.impl.client.gui.presets.PresetsScreen; @@ -21,11 +20,11 @@ import java.util.*; @Environment(EnvType.CLIENT) public class TinyConfigScreen extends Screen { public TinyConfigScreen(ConfigInstance config, Screen parent) { - super(Text.translatable(config.getModId() + ".jfconfig." + config.getCategoryPath() + "title")); + super(Text.translatable(config.getTranslationPrefix() + "title")); this.parent = parent; this.config = config; this.widgets = EntryInfoWidgetBuilder.buildWidgets(config); - this.translationPrefix = config.getModId() + ".jfconfig." + config.getCategoryPath(); + this.translationPrefix = config.getTranslationPrefix(); } private final String translationPrefix; private final Screen parent; @@ -37,7 +36,7 @@ public class TinyConfigScreen extends Screen { protected void init() { super.init(); - config.verify(); + config.fix(); this.addDrawableChild(new ButtonWidget(4, 6, 80, 20, Text.translatable("libjf-config-v0.presets"), button -> { MinecraftClient.getInstance().setScreen(new PresetsScreen(this, config)); @@ -60,7 +59,7 @@ public class TinyConfigScreen extends Screen { this.addSelectableChild(this.list); for (Map.Entry entry : config.getCategories().entrySet()) { this.list.addReference(width / 2, - Text.translatable(entry.getValue().getModId() + ".jfconfig." + entry.getValue().getCategoryPath() + "title"), + Text.translatable(entry.getValue().getTranslationPrefix() + "title"), () -> new TinyConfigScreen(entry.getValue(), this)); } for (WidgetState info : widgets) { @@ -76,11 +75,10 @@ public class TinyConfigScreen extends Screen { return visible; }, name); } - for (String referencedConfig : config.getReferencedConfigs()) { - ConfigInstance ci = ConfigHolder.getInstance().get(referencedConfig); + for (ConfigInstance ci : config.getReferencedConfigs()) { if (ci != null) { this.list.addReference(width / 2, - Text.translatable("libjf-config-v0.see-also", Text.translatable(ci.getModId() + ".jfconfig." + ci.getCategoryPath() + "title")), + Text.translatable("libjf-config-v0.see-also", Text.translatable(ci.getTranslationPrefix() + "title")), () -> new TinyConfigScreen(ci, this)); } } diff --git a/libjf-config-v0/src/main/java/io/gitlab/jfronny/libjf/config/impl/client/gui/presets/PresetsScreen.java b/libjf-config-v0/src/main/java/io/gitlab/jfronny/libjf/config/impl/client/gui/presets/PresetsScreen.java index 33abf55..908f5fd 100644 --- a/libjf-config-v0/src/main/java/io/gitlab/jfronny/libjf/config/impl/client/gui/presets/PresetsScreen.java +++ b/libjf-config-v0/src/main/java/io/gitlab/jfronny/libjf/config/impl/client/gui/presets/PresetsScreen.java @@ -34,7 +34,7 @@ public class PresetsScreen extends Screen { button -> { LibJf.LOGGER.info("Preset selected: " + entry.getKey()); entry.getValue().run(); - config.verify(); + config.fix(); MinecraftClient.getInstance().setScreen(parent); })); }