aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main/java/dev/isxander/yacl/config/ConfigInstance.java48
-rw-r--r--src/main/java/dev/isxander/yacl/config/GsonConfigInstance.java82
-rw-r--r--src/main/java/dev/isxander/yacl/config/YACLConfigManager.java26
-rw-r--r--src/main/java/dev/isxander/yacl/impl/YetAnotherConfigLibImpl.java2
-rw-r--r--src/main/java/dev/isxander/yacl/impl/utils/YaclConstants.java8
-rw-r--r--src/testmod/java/dev/isxander/yacl/test/ModMenuIntegration.java809
-rw-r--r--src/testmod/java/dev/isxander/yacl/test/config/ConfigData.java27
-rw-r--r--src/testmod/java/dev/isxander/yacl/test/config/Entrypoint.java19
-rw-r--r--src/testmod/resources/fabric.mod.json3
9 files changed, 607 insertions, 417 deletions
diff --git a/src/main/java/dev/isxander/yacl/config/ConfigInstance.java b/src/main/java/dev/isxander/yacl/config/ConfigInstance.java
new file mode 100644
index 0000000..e85a645
--- /dev/null
+++ b/src/main/java/dev/isxander/yacl/config/ConfigInstance.java
@@ -0,0 +1,48 @@
+package dev.isxander.yacl.config;
+
+import dev.isxander.yacl.api.YetAnotherConfigLib;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.function.BiFunction;
+
+public abstract class ConfigInstance<T> {
+ private final Class<T> configClass;
+ private final T defaultInstance;
+ private T instance;
+
+ public ConfigInstance(Class<T> configClass) {
+ this.configClass = configClass;
+
+ try {
+ this.defaultInstance = this.instance = configClass.getConstructor().newInstance();
+ } catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
+ throw new IllegalStateException(String.format("Could not create default instance of config for %s. Make sure there is a default constructor!", this.configClass.getSimpleName()));
+ }
+
+ }
+
+ public T getConfig() {
+ return this.instance;
+ }
+
+ protected void setConfig(T instance) {
+ this.instance = instance;
+ }
+
+ public T getDefaults() {
+ return this.defaultInstance;
+ }
+
+ public Class<T> getConfigClass() {
+ return this.configClass;
+ }
+
+ public YetAnotherConfigLib buildConfig(BiFunction<ConfigInstance<T>, YetAnotherConfigLib.Builder, YetAnotherConfigLib.Builder> builder) {
+ return builder.apply(this, YetAnotherConfigLib.createBuilder())
+ .save(this::save)
+ .build();
+ }
+
+ public abstract void save();
+ public abstract void load();
+}
diff --git a/src/main/java/dev/isxander/yacl/config/GsonConfigInstance.java b/src/main/java/dev/isxander/yacl/config/GsonConfigInstance.java
new file mode 100644
index 0000000..732492d
--- /dev/null
+++ b/src/main/java/dev/isxander/yacl/config/GsonConfigInstance.java
@@ -0,0 +1,82 @@
+package dev.isxander.yacl.config;
+
+import com.google.gson.*;
+import dev.isxander.yacl.impl.utils.YaclConstants;
+import net.minecraft.text.Style;
+import net.minecraft.text.Text;
+
+import java.awt.*;
+import java.io.IOException;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Type;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardOpenOption;
+import java.util.function.UnaryOperator;
+
+public class GsonConfigInstance<T> extends ConfigInstance<T> {
+ private final Gson gson;
+ private final Path path;
+
+ public GsonConfigInstance(Class<T> configClass, Path path, Gson gson) {
+ this(configClass, path, gson.newBuilder());
+ }
+
+ public GsonConfigInstance(Class<T> configClass, Path path, UnaryOperator<GsonBuilder> builder) {
+ this(configClass, path, builder.apply(new GsonBuilder()));
+ }
+
+ public GsonConfigInstance(Class<T> configClass, Path path, GsonBuilder builder) {
+ super(configClass);
+ this.path = path;
+ this.gson = builder
+ .excludeFieldsWithModifiers(Modifier.TRANSIENT)
+ .registerTypeHierarchyAdapter(Text.class, new Text.Serializer())
+ .registerTypeHierarchyAdapter(Style.class, new Style.Serializer())
+ .registerTypeHierarchyAdapter(Color.class, new ColorTypeAdapter())
+ .serializeNulls()
+ .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
+ .create();
+ }
+
+ @Override
+ public void save() {
+ try {
+ YaclConstants.LOGGER.info("Saving {}...", getConfigClass().getSimpleName());
+ Files.writeString(path, gson.toJson(getConfig()), StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.CREATE);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void load() {
+ try {
+ if (Files.notExists(path)) {
+ save();
+ return;
+ }
+
+ YaclConstants.LOGGER.info("Loading {}...", getConfigClass().getSimpleName());
+ setConfig(gson.fromJson(Files.readString(path), getConfigClass()));
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public Path getPath() {
+ return this.path;
+ }
+
+ public static class ColorTypeAdapter implements JsonSerializer<Color>, JsonDeserializer<Color> {
+ @Override
+ public Color deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
+ return new Color(jsonElement.getAsInt(), true);
+ }
+
+ @Override
+ public JsonElement serialize(Color color, Type type, JsonSerializationContext jsonSerializationContext) {
+ return new JsonPrimitive(color.getRGB());
+ }
+ }
+}
diff --git a/src/main/java/dev/isxander/yacl/config/YACLConfigManager.java b/src/main/java/dev/isxander/yacl/config/YACLConfigManager.java
new file mode 100644
index 0000000..d91f3f6
--- /dev/null
+++ b/src/main/java/dev/isxander/yacl/config/YACLConfigManager.java
@@ -0,0 +1,26 @@
+package dev.isxander.yacl.config;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@SuppressWarnings("unchecked")
+public class YACLConfigManager {
+ private static final Map<Class<?>, ConfigInstance<?>> configs = new HashMap<>();
+
+ public static <T> void register(ConfigInstance<T> configInstance) {
+ configs.put(configInstance.getConfigClass(), configInstance);
+ configInstance.load();
+ }
+
+ public static <T> T getConfigData(Class<T> configClass) {
+ return ((ConfigInstance<T>) configs.get(configClass)).getConfig();
+ }
+
+ public static <T> ConfigInstance<T> getConfigInstance(Class<T> configClass) {
+ return (ConfigInstance<T>) configs.get(configClass);
+ }
+
+ public static <T, I extends ConfigInstance<T>> I getConfigInstanceType(Class<T> configClass) {
+ return (I) configs.get(configClass);
+ }
+}
diff --git a/src/main/java/dev/isxander/yacl/impl/YetAnotherConfigLibImpl.java b/src/main/java/dev/isxander/yacl/impl/YetAnotherConfigLibImpl.java
index 7e2afdb..38112f4 100644
--- a/src/main/java/dev/isxander/yacl/impl/YetAnotherConfigLibImpl.java
+++ b/src/main/java/dev/isxander/yacl/impl/YetAnotherConfigLibImpl.java
@@ -4,6 +4,7 @@ import com.google.common.collect.ImmutableList;
import dev.isxander.yacl.api.ConfigCategory;
import dev.isxander.yacl.api.YetAnotherConfigLib;
import dev.isxander.yacl.gui.YACLScreen;
+import dev.isxander.yacl.impl.utils.YaclConstants;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.text.Text;
@@ -12,6 +13,7 @@ import java.util.function.Consumer;
public record YetAnotherConfigLibImpl(Text title, ImmutableList<ConfigCategory> categories, Runnable saveFunction, Consumer<YACLScreen> initConsumer) implements YetAnotherConfigLib {
@Override
public Screen generateScreen(Screen parent) {
+ YaclConstants.LOGGER.info("Generating YACL screen");
return new YACLScreen(this, parent);
}
}
diff --git a/src/main/java/dev/isxander/yacl/impl/utils/YaclConstants.java b/src/main/java/dev/isxander/yacl/impl/utils/YaclConstants.java
new file mode 100644
index 0000000..aadeb18
--- /dev/null
+++ b/src/main/java/dev/isxander/yacl/impl/utils/YaclConstants.java
@@ -0,0 +1,8 @@
+package dev.isxander.yacl.impl.utils;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class YaclConstants {
+ public static final Logger LOGGER = LoggerFactory.getLogger("YetAnotherConfigLib");
+}
diff --git a/src/testmod/java/dev/isxander/yacl/test/ModMenuIntegration.java b/src/testmod/java/dev/isxander/yacl/test/ModMenuIntegration.java
index d1bd2c5..596a0bf 100644
--- a/src/testmod/java/dev/isxander/yacl/test/ModMenuIntegration.java
+++ b/src/testmod/java/dev/isxander/yacl/test/ModMenuIntegration.java
@@ -5,13 +5,15 @@ import com.terraformersmc.modmenu.api.ModMenuApi;
import dev.isxander.yacl.api.*;
import dev.isxander.yacl.gui.RequireRestartScreen;
import dev.isxander.yacl.gui.controllers.*;
+import dev.isxander.yacl.gui.controllers.cycling.EnumController;
import dev.isxander.yacl.gui.controllers.slider.DoubleSliderController;
import dev.isxander.yacl.gui.controllers.slider.FloatSliderController;
import dev.isxander.yacl.gui.controllers.slider.IntegerSliderController;
import dev.isxander.yacl.gui.controllers.slider.LongSliderController;
import dev.isxander.yacl.gui.controllers.string.StringController;
+import dev.isxander.yacl.test.config.ConfigData;
+import dev.isxander.yacl.test.config.Entrypoint;
import net.minecraft.client.MinecraftClient;
-import net.minecraft.client.gui.screen.MessageScreen;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.option.GraphicsMode;
import net.minecraft.client.toast.SystemToast;
@@ -24,439 +26,412 @@ import java.awt.*;
public class ModMenuIntegration implements ModMenuApi {
@Override
public ConfigScreenFactory<?> getModConfigScreenFactory() {
- return (parent) -> YetAnotherConfigLib.createBuilder()
- .title(Text.of("Test Suites"))
- .category(ConfigCategory.createBuilder()
- .name(Text.of("Suites"))
- .option(ButtonOption.createBuilder()
- .name(Text.of("Full Test Suite"))
- .controller(ActionController::new)
- .action(screen -> MinecraftClient.getInstance().setScreen(getFullTestSuite(screen)))
- .build())
- .option(ButtonOption.createBuilder()
- .name(Text.of("Basic Wiki Suite"))
- .controller(ActionController::new)
- .action(screen -> MinecraftClient.getInstance().setScreen(getWikiBasic(screen)))
- .build())
- .option(ButtonOption.createBuilder()
- .name(Text.of("Group Wiki Suite"))
- .controller(ActionController::new)
- .action(screen -> MinecraftClient.getInstance().setScreen(getWikiGroups(screen)))
- .build())
- .option(ButtonOption.createBuilder()
- .name(Text.of("Unavailable Test Suite"))
- .controller(ActionController::new)
- .action(screen -> MinecraftClient.getInstance().setScreen(getDisabledTest(screen)))
- .build())
- .build())
- .build().generateScreen(parent);
+ return (parent) -> Entrypoint.getConfig().buildConfig((config, builder) -> builder
+ .title(Text.of("Test Suites"))
+ .category(ConfigCategory.createBuilder()
+ .name(Text.of("Suites"))
+ .option(ButtonOption.createBuilder()
+ .name(Text.of("Full Test Suite"))
+ .controller(ActionController::new)
+ .action((screen, opt) -> MinecraftClient.getInstance().setScreen(getFullTestSuite(screen)))
+ .build())
+ .option(ButtonOption.createBuilder()
+ .name(Text.of("Basic Wiki Suite"))
+ .controller(ActionController::new)
+ .action((screen, opt) -> MinecraftClient.getInstance().setScreen(getWikiBasic(screen)))
+ .build())
+ .option(ButtonOption.createBuilder()
+ .name(Text.of("Group Wiki Suite"))
+ .controller(ActionController::new)
+ .action((screen, opt) -> MinecraftClient.getInstance().setScreen(getWikiGroups(screen)))
+ .build())
+ .option(ButtonOption.createBuilder()
+ .name(Text.of("Unavailable Test Suite"))
+ .controller(ActionController::new)
+ .action((screen, opt) -> MinecraftClient.getInstance().setScreen(getDisabledTest(screen)))
+ .build())
+ .build())
+ )
+ .generateScreen(parent);
}
private Screen getFullTestSuite(Screen parent) {
- return YetAnotherConfigLib.createBuilder()
- .title(Text.of("Test GUI"))
- .category(ConfigCategory.createBuilder()
- .name(Text.of("Control Examples"))
- .tooltip(Text.of("Example Category Description"))
- .group(OptionGroup.createBuilder()
- .name(Text.of("Boolean Controllers"))
- .tooltip(Text.of("Test!"))
- .collapsed(true)
- .option(Option.createBuilder(boolean.class)
- .name(Text.of("Boolean Toggle"))
- .tooltip(value -> Text.of("A simple toggle button that contains the value '" + value + "'"))
- .binding(
- false,
- () -> TestSettings.booleanToggle,
- (value) -> TestSettings.booleanToggle = value
- )
- .controller(BooleanController::new)
- .flag(OptionFlag.GAME_RESTART)
- .available(false)
- .build())
- .option(Option.createBuilder(boolean.class)
- .name(Text.of("Custom Boolean Toggle"))
- .tooltip(Text.of("You can customize these controllers like this!"))
- .binding(
- false,
- () -> TestSettings.customBooleanToggle,
- (value) -> TestSettings.customBooleanToggle = value
- )
- .controller(opt -> new BooleanController(opt, state -> state ? Text.of("Amazing") : Text.of("Not Amazing"), true))
- .build())
- .option(Option.createBuilder(boolean.class)
- .name(Text.of("Tick Box"))
- .tooltip(Text.of("There are even alternate methods of displaying the same data type!"))
- .binding(
- false,
- () -> TestSettings.tickbox,
- (value) -> TestSettings.tickbox = value
- )
- .controller(TickBoxController::new)
- .build())
- .build())
- .group(OptionGroup.createBuilder()
- .name(Text.of("Slider Controllers"))
- .option(Option.createBuilder(int.class)
- .name(Text.of("Int Slider that is cut off because the slider"))
- .instant(true)
- .binding(
- 0,
- () -> TestSettings.intSlider,
- (value) -> {
- TestSettings.intSlider = value;
- System.out.println("Set int value!");
- }
- )
- .controller(opt -> new IntegerSliderController(opt, 0, 3, 1))
- .build())
- .option(Option.createBuilder(double.class)
- .name(Text.of("Double Slider"))
- .binding(
- 0.0,
- () -> TestSettings.doubleSlider,
- (value) -> TestSettings.doubleSlider = value
- )
- .controller(opt -> new DoubleSliderController(opt, 0, 3, 0.05))
- .build())
- .option(Option.createBuilder(float.class)
- .name(Text.of("Float Slider"))
- .binding(
- 0f,
- () -> TestSettings.floatSlider,
- (value) -> TestSettings.floatSlider = value
- )
- .controller(opt -> new FloatSliderController(opt, 0, 3, 0.1f))
- .build())
- .option(Option.createBuilder(long.class)
- .name(Text.of("Long Slider"))
- .binding(
- 0L,
- () -> TestSettings.longSlider,
- (value) -> TestSettings.longSlider = value
- )
- .controller(opt -> new LongSliderController(opt, 0, 1_000_000, 100))
- .build())
- .build())
- .group(OptionGroup.createBuilder()
- .name(Text.of("Input Field Controllers"))
- .option(Option.createBuilder(String.class)
- .name(Text.of("Text Option"))
- .binding(
- "Hello",
- () -> TestSettings.textField,
- value -> TestSettings.textField = value
- )
- .controller(StringController::new)
- .build())
- .option(Option.createBuilder(Color.class)
- .name(Text.of("Color Option"))
- .binding(
- Color.red,
- () -> TestSettings.colorOption,
- value -> TestSettings.colorOption = value
- )
- .controller(ColorController::new)
- .build())
- .build())
- .group(OptionGroup.createBuilder()
- .name(Text.of("Enum Controllers"))
- .option(Option.createBuilder(TestSettings.Alphabet.class)
- .name(Text.of("Enum Cycler"))
- .binding(
- TestSettings.Alphabet.A,
- () -> TestSettings.enumOption,
- (value) -> TestSettings.enumOption = value
- )
- .controller(EnumController::new)
- .build())
- .build())
- .group(OptionGroup.createBuilder()
- .name(Text.of("Options that aren't really options"))
- .option(ButtonOption.createBuilder()
- .name(Text.of("Button \"Option\""))
- .action(screen -> SystemToast.add(MinecraftClient.getInstance().getToastManager(), SystemToast.Type.TUTORIAL_HINT, Text.of("Button Pressed"), Text.of("Button option was invoked!")))
- .controller(ActionController::new)
- .build())
- .option(Option.createBuilder(Text.class)
- .binding(Binding.immutable(Text.empty()
- .append(Text.literal("a").styled(style -> style.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Text.of("a")))))
- .append(Text.literal("b").styled(style -> style.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Text.of("b")))))
- .append(Text.literal("c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c").styled(style -> style.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Text.of("c")))))
- .append(Text.literal("e").styled(style -> style.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Text.of("e")))))
- .styled(style -> style.withClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, "https://isxander.dev")))
- ))
- .controller(LabelController::new)
- .build())
- .build())
- .group(OptionGroup.createBuilder()
- .name(Text.of("Minecraft Bindings"))
- .tooltip(Text.of("YACL can also bind Minecraft options!"))
- .option(Option.createBuilder(boolean.class)
- .name(Text.of("Minecraft AutoJump"))
- .tooltip(Text.of("You can even bind minecraft options!"))
- .binding(Binding.minecraft(MinecraftClient.getInstance().options.getAutoJump()))
- .controller(TickBoxController::new)
- .build())
- .option(Option.createBuilder(GraphicsMode.class)
- .name(Text.of("Minecraft Graphics Mode"))
- .binding(Binding.minecraft(MinecraftClient.getInstance().options.getGraphicsMode()))
- .controller(EnumController::new)
- .build())
- .build())
- .build())
- .category(PlaceholderCategory.createBuilder()
- .name(Text.of("Placeholder Category"))
- .screen((client, yaclScreen) -> new RequireRestartScreen(yaclScreen))
- .build())
- .category(ConfigCategory.createBuilder()
- .name(Text.of("Group Test"))
- .option(Option.createBuilder(boolean.class)
- .name(Text.of("Root Test"))
- .binding(
- false,
- () -> TestSettings.groupTestRoot,
- value -> TestSettings.groupTestRoot = value
- )
- .controller(TickBoxController::new)
- .build())
- .group(OptionGroup.createBuilder()
- .name(Text.of("First Group"))
- .option(Option.createBuilder(boolean.class)
- .name(Text.of("First Group Test 1"))
- .binding(
- false,
- () -> TestSettings.groupTestFirstGroup,
- value -> TestSettings.groupTestFirstGroup = value
- )
- .controller(TickBoxController::new)
- .build())
- .option(Option.createBuilder(boolean.class)
- .name(Text.of("First Group Test 2"))
- .binding(
- false,
- () -> TestSettings.groupTestFirstGroup2,
- value -> TestSettings.groupTestFirstGroup2 = value
- )
- .controller(TickBoxController::new)
- .build())
- .build())
- .group(OptionGroup.createBuilder()
- .name(Text.empty())
- .option(Option.createBuilder(boolean.class)
- .name(Text.of("Second Group Test"))
- .binding(
- false,
- () -> TestSettings.groupTestSecondGroup,
- value -> TestSettings.groupTestSecondGroup = value
- )
- .controller(TickBoxController::new)
- .build())
- .build())
- .build())
- .category(ConfigCategory.createBuilder()
- .name(Text.of("Scroll Test"))
- .option(Option.createBuilder(int.class)
- .name(Text.of("Int Slider that is cut off because the slider"))
- .binding(
- 0,
- () -> TestSettings.scrollingSlider,
- (value) -> TestSettings.scrollingSlider = value
- )
- .controller(opt -> new IntegerSliderController(opt, 0, 10, 1))
- .build())
- .option(ButtonOption.createBuilder()
- .name(Text.of("Option"))
- .action(screen -> {})
- .controller(ActionController::new)
- .build())
- .option(ButtonOption.createBuilder()
- .name(Text.of("Option"))
- .action(screen -> {})
- .controller(ActionController::new)
- .build())
- .option(ButtonOption.createBuilder()
- .name(Text.of("Option"))
- .action(screen -> {})
- .controller(ActionController::new)
- .build())
- .option(ButtonOption.createBuilder()
- .name(Text.of("Option"))
- .action(screen -> {})
- .controller(ActionController::new)
- .build())
- .option(ButtonOption.createBuilder()
- .name(Text.of("Option"))
- .action(screen -> {})
- .controller(ActionController::new)
- .build())
- .option(ButtonOption.createBuilder()
- .name(Text.of("Option"))
- .action(screen -> {})
- .controller(ActionController::new)
- .build())
- .option(ButtonOption.createBuilder()
- .name(Text.of("Option"))
- .action(screen -> {})
- .controller(ActionController::new)
- .build())
- .option(ButtonOption.createBuilder()
- .name(Text.of("Option"))
- .action(screen -> {})
- .controller(ActionController::new)
- .build())
- .option(ButtonOption.createBuilder()
- .name(Text.of("Option"))
- .action(screen -> {})
- .controller(ActionController::new)
- .build())
- .option(ButtonOption.createBuilder()
- .name(Text.of("Option"))
- .action(screen -> {})
- .controller(ActionController::new)
- .build())
- .option(ButtonOption.createBuilder()
- .name(Text.of("Option"))
- .action(screen -> {})
- .controller(ActionController::new)
- .build())
- .option(ButtonOption.createBuilder()
- .name(Text.of("Option"))
- .action(screen -> {})
- .controller(ActionController::new)
- .build())
- .option(ButtonOption.createBuilder()
- .name(Text.of("Option"))
- .action(screen -> {})
- .controller(ActionController::new)
- .build())
- .build())
- .save(() -> MinecraftClient.getInstance().options.write())
- .build().generateScreen(parent);
+ return Entrypoint.getConfig().buildConfig((config, builder) -> builder
+ .title(Text.of("Test GUI"))
+ .category(ConfigCategory.createBuilder()
+ .name(Text.of("Control Examples"))
+ .tooltip(Text.of("Example Category Description"))
+ .group(OptionGroup.createBuilder()
+ .name(Text.of("Boolean Controllers"))
+ .tooltip(Text.of("Test!"))
+ .collapsed(true)
+ .option(Option.createBuilder(boolean.class)
+ .name(Text.of("Boolean Toggle"))
+ .tooltip(value -> Text.of("A simple toggle button that contains the value '" + value + "'"))
+ .binding(
+ config.getDefaults().booleanToggle,
+ () -> config.getConfig().booleanToggle,
+ (value) -> config.getConfig().booleanToggle = value
+ )
+ .controller(BooleanController::new)
+ .flag(OptionFlag.GAME_RESTART)
+ .available(false)
+ .build())
+ .option(Option.createBuilder(boolean.class)
+ .name(Text.of("Custom Boolean Toggle"))
+ .tooltip(Text.of("You can customize these controllers like this!"))
+ .binding(
+ config.getDefaults().customBooleanToggle,
+ () -> config.getConfig().customBooleanToggle,
+ (value) -> config.getConfig().customBooleanToggle = value
+ )
+ .controller(opt -> new BooleanController(opt, state -> state ? Text.of("Amazing") : Text.of("Not Amazing"), true))
+ .build())
+ .option(Option.createBuilder(boolean.class)
+ .name(Text.of("Tick Box"))
+ .tooltip(Text.of("There are even alternate methods of displaying the same data type!"))
+ .binding(
+ config.getDefaults().tickbox,
+ () -> config.getConfig().tickbox,
+ (value) -> config.getConfig().tickbox = value
+ )
+ .controller(TickBoxController::new)
+ .build())
+ .build())
+ .group(OptionGroup.createBuilder()
+ .name(Text.of("Slider Controllers"))
+ .option(Option.createBuilder(int.class)
+ .name(Text.of("Int Slider that is cut off because the slider"))
+ .instant(true)
+ .binding(
+ config.getDefaults().intSlider,
+ () -> config.getConfig().intSlider,
+ value -> config.getConfig().intSlider = value
+
+ )
+ .controller(opt -> new IntegerSliderController(opt, 0, 3, 1))
+ .build())
+ .option(Option.createBuilder(double.class)
+ .name(Text.of("Double Slider"))
+ .binding(
+ config.getDefaults().doubleSlider,
+ () -> config.getConfig().doubleSlider,
+ (value) -> config.getConfig().doubleSlider = value
+ )
+ .controller(opt -> new DoubleSliderController(opt, 0, 3, 0.05))
+ .build())
+ .option(Option.createBuilder(float.class)
+ .name(Text.of("Float Slider"))
+ .binding(
+ config.getDefaults().floatSlider,
+ () -> config.getConfig().floatSlider,
+ (value) -> config.getConfig().floatSlider = value
+ )
+ .controller(opt -> new FloatSliderController(opt, 0, 3, 0.1f))
+ .build())
+ .option(Option.createBuilder(long.class)
+ .name(Text.of("Long Slider"))
+ .binding(
+ config.getDefaults().longSlider,
+ () -> config.getConfig().longSlider,
+ (value) -> config.getConfig().longSlider = value
+ )
+ .controller(opt -> new LongSliderController(opt, 0, 1_000_000, 100))
+ .build())
+ .build())
+ .group(OptionGroup.createBuilder()
+ .name(Text.of("Input Field Controllers"))
+ .option(Option.createBuilder(String.class)
+ .name(Text.of("Text Option"))
+ .binding(
+ config.getDefaults().textField,
+ () -> config.getConfig().textField,
+ value -> config.getConfig().textField = value
+ )
+ .controller(StringController::new)
+ .build())
+ .option(Option.createBuilder(Color.class)
+ .name(Text.of("Color Option"))
+ .binding(
+ config.getDefaults().colorOption,
+ () -> config.getConfig().colorOption,
+ value -> config.getConfig().colorOption = value
+ )
+ .controller(ColorController::new)
+ .build())
+ .build())
+ .group(OptionGroup.createBuilder()
+ .name(Text.of("Enum Controllers"))
+ .option(Option.createBuilder(ConfigData.Alphabet.class)
+ .name(Text.of("Enum Cycler"))
+ .binding(
+ config.getDefaults().enumOption,
+ () -> config.getConfig().enumOption,
+ (value) -> config.getConfig().enumOption = value
+ )
+ .controller(EnumController::new)
+ .build())
+ .build())
+ .group(OptionGroup.createBuilder()
+ .name(Text.of("Options that aren't really options"))
+ .option(ButtonOption.createBuilder()
+ .name(Text.of("Button \"Option\""))
+ .action((screen, opt) -> SystemToast.add(MinecraftClient.getInstance().getToastManager(), SystemToast.Type.TUTORIAL_HINT, Text.of("Button Pressed"), Text.of("Button option was invoked!")))
+ .controller(ActionController::new)
+ .build())
+ .option(Option.createBuilder(Text.class)
+ .binding(Binding.immutable(Text.empty()
+ .append(Text.literal("a").styled(style -> style.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Text.of("a")))))
+ .append(Text.literal("b").styled(style -> style.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Text.of("b")))))
+ .append(Text.literal("c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c").styled(style -> style.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Text.of("c")))))
+ .append(Text.literal("e").styled(style -> style.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Text.of("e")))))
+ .styled(style -> style.withClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, "https://isxander.dev")))
+ ))
+ .controller(LabelController::new)
+ .build())
+ .build())
+ .group(OptionGroup.createBuilder()
+ .name(Text.of("Minecraft Bindings"))
+ .tooltip(Text.of("YACL can also bind Minecraft options!"))
+ .option(Option.createBuilder(boolean.class)
+ .name(Text.of("Minecraft AutoJump"))
+ .tooltip(Text.of("You can even bind minecraft options!"))
+ .binding(Binding.minecraft(MinecraftClient.getInstance().options.getAutoJump()))
+ .controller(TickBoxController::new)
+ .build())
+ .option(Option.createBuilder(GraphicsMode.class)
+ .name(Text.of("Minecraft Graphics Mode"))
+ .binding(Binding.minecraft(MinecraftClient.getInstance().options.getGraphicsMode()))
+ .controller(EnumController::new)
+ .build())
+ .build())
+ .build())
+ .category(PlaceholderCategory.createBuilder()
+ .name(Text.of("Placeholder Category"))
+ .screen((client, yaclScreen) -> new RequireRestartScreen(yaclScreen))
+ .build())
+ .category(ConfigCategory.createBuilder()
+ .name(Text.of("Group Test"))
+ .option(Option.createBuilder(boolean.class)
+ .name(Text.of("Root Test"))
+ .binding(
+ config.getDefaults().groupTestRoot,
+ () -> config.getConfig().groupTestRoot,
+ value -> config.getConfig().groupTestRoot = value
+ )
+ .controller(TickBoxController::new)
+ .build())
+ .group(OptionGroup.createBuilder()
+ .name(Text.of("First Group"))
+ .option(Option.createBuilder(boolean.class)
+ .name(Text.of("First Group Test 1"))
+ .binding(
+ config.getDefaults().groupTestFirstGroup,
+ () -> config.getConfig().groupTestFirstGroup,
+ value -> config.getConfig().groupTestFirstGroup = value
+ )
+ .controller(TickBoxController::new)
+ .build())
+ .option(Option.createBuilder(boolean.class)
+ .name(Text.of("First Group Test 2"))
+ .binding(
+ config.getDefaults().groupTestFirstGroup2,
+ () -> config.getConfig().groupTestFirstGroup2,
+ value -> config.getConfig().groupTestFirstGroup2 = value
+ )
+ .controller(TickBoxController::new)
+ .build())
+ .build())
+ .group(OptionGroup.createBuilder()
+ .name(Text.empty())
+ .option(Option.createBuilder(boolean.class)
+ .name(Text.of("Second Group Test"))
+ .binding(
+ config.getDefaults().groupTestSecondGroup,
+ () -> config.getConfig().groupTestSecondGroup,
+ value -> config.getConfig().groupTestSecondGroup = value
+ )
+ .controller(TickBoxController::new)
+ .build())
+ .build())
+ .build())
+ .category(ConfigCategory.createBuilder()
+ .name(Text.of("Scroll Test"))
+ .option(Option.createBuilder(int.class)
+ .name(Text.of("Int Slider that is cut off because the slider"))
+ .binding(
+ config.getDefaults().scrollingSlider,
+ () -> config.getConfig().scrollingSlider,
+ (value) -> config.getConfig().scrollingSlider = value
+ )
+ .controller(opt -> new IntegerSliderController(opt, 0, 10, 1))
+ .build())
+ .option(ButtonOption.createBuilder()
+ .name(Text.of("Option"))
+ .action((screen, opt) -> {})
+ .controller(ActionController::new)
+ .build())
+ .option(ButtonOption.createBuilder()
+ .name(Text.of("Option"))
+ .action((screen, opt) -> {})
+ .controller(ActionController::new)
+ .build())
+ .option(ButtonOption.createBuilder()
+ .name(Text.of("Option"))
+ .action((screen, opt) -> {})
+ .controller(ActionController::new)
+ .build())
+ .option(ButtonOption.createBuilder()
+ .name(Text.of("Option"))
+ .action((screen, opt) -> {})
+ .controller(ActionController::new)
+ .build())
+ .option(ButtonOption.createBuilder()
+ .name(Text.of("Option"))
+ .action((screen, opt) -> {})
+ .controller(ActionController::new)
+ .build())
+ .option(ButtonOption.createBuilder()
+ .name(Text.of("Option"))
+ .action((screen, opt) -> {})
+ .controller(ActionController::new)
+ .build())
+ .option(ButtonOption.createBuilder()
+ .name(Text.of("Option"))
+ .action((screen, opt) -> {})
+ .controller(ActionController::new)
+ .build())
+ .option(ButtonOption.createBuilder()
+ .name(Text.of("Option"))
+ .action((screen, opt) -> {})
+ .controller(ActionController::new)
+ .build())
+ .option(ButtonOption.createBuilder()
+ .name(Text.of("Option"))
+ .action((screen, opt) -> {})
+ .controller(ActionController::new)
+ .build())
+ .option(ButtonOption.createBuilder()
+ .name(Text.of("Option"))
+ .action((screen, opt) -> {})
+ .controller(ActionController::new)
+ .build())
+ .option(ButtonOption.createBuilder()
+ .name(Text.of("Option"))
+ .action((screen, opt) -> {})
+ .controller(ActionController::new)
+ .build())
+ .option(ButtonOption.createBuilder()
+ .name(Text.of("Option"))
+ .action((screen, opt) -> {})
+ .controller(ActionController::new)
+ .build())
+ .option(ButtonOption.createBuilder()
+ .name(Text.of("Option"))
+ .action((screen, opt) -> {})
+ .controller(ActionController::new)
+ .build())
+ .build())
+ .save(() -> {
+ MinecraftClient.getInstance().options.write();
+ config.save();
+ })
+ )
+ .generateScreen(parent);
}
private Screen getDisabledTest(Screen parent) {
- return YetAnotherConfigLib.createBuilder()
- .title(Text.empty())
- .category(ConfigCategory.createBuilder()
- .name(Text.of("Disabled Test"))
- .option(Option.createBuilder(int.class)
- .name(Text.of("Slider"))
- .binding(Binding.immutable(0))
- .controller(opt -> new IntegerSliderController(opt, 0, 5, 1))
- .available(false)
- .build())
- .option(Option.createBuilder(boolean.class)
- .name(Text.of("Tick Box"))
- .binding(Binding.immutable(true))
- .controller(TickBoxController::new)
- .available(false)
- .build())
- .option(Option.createBuilder(boolean.class)
- .name(Text.of("Tick Box (Enabled)"))
- .binding(Binding.immutable(true))
- .controller(TickBoxController::new)
- .build())
- .option(Option.createBuilder(String.class)
- .name(Text.of("Text Field"))
- .binding(Binding.immutable("hi"))
- .controller(StringController::new)
- .available(false)
- .build())
- .build())
- .build().generateScreen(parent);
+ return Entrypoint.getConfig().buildConfig((config, builder) -> builder
+ .title(Text.empty())
+ .category(ConfigCategory.createBuilder()
+ .name(Text.of("Disabled Test"))
+ .option(Option.createBuilder(int.class)
+ .name(Text.of("Slider"))
+ .binding(Binding.immutable(0))
+ .controller(opt -> new IntegerSliderController(opt, 0, 5, 1))
+ .available(false)
+ .build())
+ .option(Option.createBuilder(boolean.class)
+ .name(Text.of("Tick Box"))
+ .binding(Binding.immutable(true))
+ .controller(TickBoxController::new)
+ .available(false)
+ .build())
+ .option(Option.createBuilder(boolean.class)
+ .name(Text.of("Tick Box (Enabled)"))
+ .binding(Binding.immutable(true))
+ .controller(TickBoxController::new)
+ .build())
+ .option(Option.createBuilder(String.class)
+ .name(Text.of("Text Field"))
+ .binding(Binding.immutable("hi"))
+ .controller(StringController::new)
+ .available(false)
+ .build())
+ .build())
+ )
+ .generateScreen(parent);
}
private Screen getWikiBasic(Screen parent) {
- return YetAnotherConfigLib.createBuilder()
- .title(Text.of("Mod Name"))
- .category(ConfigCategory.createBuilder()
- .name(Text.of("My Category"))
- .tooltip(Text.of("This displays when you hover over a category button")) // optional
- .option(Option.createBuilder(boolean.class)
- .name(Text.of("My Boolean Option"))
- .tooltip(Text.of("This option displays the basic capabilities of YetAnotherConfigLib")) // optional
- .binding(
- true, // default
- () -> TestSettings.booleanToggle, // getter
- newValue -> TestSettings.booleanToggle = newValue // setter
- )
- .controller(BooleanController::new)
- .build())
- .build())
- .save(TestSettings::save)
- .build()
+ return Entrypoint.getConfig().buildConfig((config, builder) -> builder
+ .title(Text.of("Mod Name"))
+ .category(ConfigCategory.createBuilder()
+ .name(Text.of("My Category"))
+ .tooltip(Text.of("This displays when you hover over a category button")) // optional
+ .option(Option.createBuilder(boolean.class)
+ .name(Text.of("My Boolean Option"))
+ .tooltip(Text.of("This option displays the basic capabilities of YetAnotherConfigLib")) // optional
+ .binding(
+ config.getDefaults().booleanToggle, // default
+ () -> config.getConfig().booleanToggle, // getter
+ newValue -> config.getConfig().booleanToggle = newValue // setter
+ )
+ .controller(BooleanController::new)
+ .build())
+ .build())
+ )
.generateScreen(parent);
}
private Screen getWikiGroups(Screen parent) {
- return YetAnotherConfigLib.createBuilder()
- .title(Text.of("Mod Name"))
- .category(ConfigCategory.createBuilder()
- .name(Text.of("My Category"))
- .tooltip(Text.of("This displays when you hover over a category button")) // optional
- .group(OptionGroup.createBuilder()
- .name(Text.of("Option Group"))
- .option(Option.createBuilder(boolean.class)
- .name(Text.of("My Boolean Option"))
- .tooltip(Text.of("This option displays the basic capabilities of YetAnotherConfigLib")) // optional
- .binding(
- true, // default
- () -> TestSettings.booleanToggle, // getter
- newValue -> TestSettings.booleanToggle = newValue // setter
- )
- .controller(BooleanController::new)
- .build())
- .build())
- .build())
- .save(TestSettings::save)
- .build()
+ return Entrypoint.getConfig().buildConfig((config, builder) -> builder
+ .title(Text.of("Mod Name"))
+ .category(ConfigCategory.createBuilder()
+ .name(Text.of("My Category"))
+ .tooltip(Text.of("This displays when you hover over a category button")) // optional
+ .group(OptionGroup.createBuilder()
+ .name(Text.of("Option Group"))
+ .option(Option.createBuilder(boolean.class)
+ .name(Text.of("My Boolean Option"))
+ .tooltip(Text.of("This option displays the basic capabilities of YetAnotherConfigLib")) // optional
+ .binding(
+ config.getDefaults().booleanToggle, // default
+ () -> config.getConfig().booleanToggle, // getter
+ newValue -> config.getConfig().booleanToggle = newValue // setter
+ )
+ .controller(BooleanController::new)
+ .build())
+ .build())
+ .build())
+ )
.generateScreen(parent);
}
private ConfigScreenFactory<?> getWikiButton() {
- return (parent) -> YetAnotherConfigLib.createBuilder()
- .title(Text.of("Mod Name"))
- .category(ConfigCategory.createBuilder()
- .name(Text.of("My Category"))
- .tooltip(Text.of("This displays when you hover over a category button")) // optional
- .option(ButtonOption.createBuilder()
- .name(Text.of("Pressable Button"))
- .tooltip(Text.of("This is so easy!")) // optional
- .action(screen -> {})
- .controller(ActionController::new)
- .build())
- .build())
- .save(TestSettings::save)
- .build()
+ return (parent) -> Entrypoint.getConfig().buildConfig((config, builder) -> builder
+ .title(Text.of("Mod Name"))
+ .category(ConfigCategory.createBuilder()
+ .name(Text.of("My Category"))
+ .tooltip(Text.of("This displays when you hover over a category button")) // optional
+ .option(ButtonOption.createBuilder()
+ .name(Text.of("Pressable Button"))
+ .tooltip(Text.of("This is so easy!")) // optional
+ .action(screen -> {})
+ .controller(ActionController::new)
+ .build())
+ .build())
+ )
.generateScreen(parent);
}
-
- private static class TestSettings {
- private static boolean booleanToggle = false;
- private static boolean customBooleanToggle = false;
- private static boolean tickbox = false;
- private static int intSlider = 0;
- private static double doubleSlider = 0;
- private static float floatSlider = 0;
- private static long longSlider = 0;
- private static String textField = "Hello";
- private static Color colorOption = Color.red;
- private static Alphabet enumOption = Alphabet.A;
-
- private static boolean groupTestRoot = false;
- private static boolean groupTestFirstGroup = false;
- private static boolean groupTestFirstGroup2 = false;
- private static boolean groupTestSecondGroup = false;
-
- private static int scrollingSlider = 0;
-
- public enum Alphabet {
- A, B, C
- }
-
- public static void save() {
-
- }
- }
}
diff --git a/src/testmod/java/dev/isxander/yacl/test/config/ConfigData.java b/src/testmod/java/dev/isxander/yacl/test/config/ConfigData.java
new file mode 100644
index 0000000..d0d47b1
--- /dev/null
+++ b/src/testmod/java/dev/isxander/yacl/test/config/ConfigData.java
@@ -0,0 +1,27 @@
+package dev.isxander.yacl.test.config;
+
+import java.awt.*;
+
+public class ConfigData {
+ public boolean booleanToggle = false;
+ public boolean customBooleanToggle = false;
+ public boolean tickbox = false;
+ public int intSlider = 0;
+ public double doubleSlider = 0;
+ public float floatSlider = 0;
+ public long longSlider = 0;
+ public String textField = "Hello";
+ public Color colorOption = Color.red;
+ public Alphabet enumOption = Alphabet.A;
+
+ public boolean groupTestRoot = false;
+ public boolean groupTestFirstGroup = false;
+ public boolean groupTestFirstGroup2 = false;
+ public boolean groupTestSecondGroup = false;
+
+ public int scrollingSlider = 0;
+
+ public enum Alphabet {
+ A, B, C
+ }
+}
diff --git a/src/testmod/java/dev/isxander/yacl/test/config/Entrypoint.java b/src/testmod/java/dev/isxander/yacl/test/config/Entrypoint.java
new file mode 100644
index 0000000..7875700
--- /dev/null
+++ b/src/testmod/java/dev/isxander/yacl/test/config/Entrypoint.java
@@ -0,0 +1,19 @@
+package dev.isxander.yacl.test.config;
+
+import com.google.gson.Gson;
+import dev.isxander.yacl.config.ConfigInstance;
+import dev.isxander.yacl.config.GsonConfigInstance;
+import dev.isxander.yacl.config.YACLConfigManager;
+import net.fabricmc.api.ClientModInitializer;
+import net.fabricmc.loader.api.FabricLoader;
+
+public class Entrypoint implements ClientModInitializer {
+ @Override
+ public void onInitializeClient() {
+ YACLConfigManager.register(new GsonConfigInstance<>(ConfigData.class, FabricLoader.getInstance().getConfigDir().resolve("yacl-test.json"), new Gson()));
+ }
+
+ public static ConfigInstance<ConfigData> getConfig() {
+ return YACLConfigManager.getConfigInstance(ConfigData.class);
+ }
+}
diff --git a/src/testmod/resources/fabric.mod.json b/src/testmod/resources/fabric.mod.json
index 333adc3..1360a5e 100644
--- a/src/testmod/resources/fabric.mod.json
+++ b/src/testmod/resources/fabric.mod.json
@@ -9,6 +9,9 @@
"license": "LGPL-3.0-or-later",
"environment": "client",
"entrypoints": {
+ "client": [
+ "dev.isxander.yacl.test.config.Entrypoint"
+ ],
"modmenu": [
"dev.isxander.yacl.test.ModMenuIntegration"
]