diff options
26 files changed, 362 insertions, 15 deletions
diff --git a/common/src/main/java/dev/isxander/yacl3/config/v2/api/ReadOnlyFieldAccess.java b/common/src/main/java/dev/isxander/yacl3/config/v2/api/ReadOnlyFieldAccess.java index 5b71e58..1146e68 100644 --- a/common/src/main/java/dev/isxander/yacl3/config/v2/api/ReadOnlyFieldAccess.java +++ b/common/src/main/java/dev/isxander/yacl3/config/v2/api/ReadOnlyFieldAccess.java @@ -8,4 +8,6 @@ public interface ReadOnlyFieldAccess<T> { String name(); Type type(); + + Class<T> typeClass(); } diff --git a/common/src/main/java/dev/isxander/yacl3/config/v2/api/autogen/ColorRGBA.java b/common/src/main/java/dev/isxander/yacl3/config/v2/api/autogen/ColorRGBA.java new file mode 100644 index 0000000..dc5b8ff --- /dev/null +++ b/common/src/main/java/dev/isxander/yacl3/config/v2/api/autogen/ColorRGBA.java @@ -0,0 +1,12 @@ +package dev.isxander.yacl3.config.v2.api.autogen; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface ColorRGBA { + boolean allowAlpha() default false; +} diff --git a/common/src/main/java/dev/isxander/yacl3/config/v2/api/autogen/EnumCycler.java b/common/src/main/java/dev/isxander/yacl3/config/v2/api/autogen/EnumCycler.java new file mode 100644 index 0000000..5545c13 --- /dev/null +++ b/common/src/main/java/dev/isxander/yacl3/config/v2/api/autogen/EnumCycler.java @@ -0,0 +1,16 @@ +package dev.isxander.yacl3.config.v2.api.autogen; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface EnumCycler { + int[] allowedOrdinals() default {}; + + interface CyclableEnum<T extends Enum<T>> { + T[] allowedValues(); + } +} diff --git a/common/src/main/java/dev/isxander/yacl3/config/v2/api/autogen/ListGroup.java b/common/src/main/java/dev/isxander/yacl3/config/v2/api/autogen/ListGroup.java new file mode 100644 index 0000000..0853ba4 --- /dev/null +++ b/common/src/main/java/dev/isxander/yacl3/config/v2/api/autogen/ListGroup.java @@ -0,0 +1,30 @@ +package dev.isxander.yacl3.config.v2.api.autogen; + +import dev.isxander.yacl3.api.Option; +import dev.isxander.yacl3.api.controller.ControllerBuilder; +import dev.isxander.yacl3.config.v2.api.ConfigField; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.util.List; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface ListGroup { + Class<? extends ValueFactory<?>> valueFactory(); + + Class<? extends ControllerFactory<?>> controllerFactory(); + + int maxEntries() default 0; + int minEntries() default 0; + + interface ValueFactory<T> { + T provideNewValue(); + } + + interface ControllerFactory<T> { + ControllerBuilder<T> createController(ListGroup annotation, ConfigField<List<T>> field, OptionStorage storage, Option<T> option); + } +} diff --git a/common/src/main/java/dev/isxander/yacl3/config/v2/api/autogen/LongSlider.java b/common/src/main/java/dev/isxander/yacl3/config/v2/api/autogen/LongSlider.java new file mode 100644 index 0000000..c77b3d3 --- /dev/null +++ b/common/src/main/java/dev/isxander/yacl3/config/v2/api/autogen/LongSlider.java @@ -0,0 +1,16 @@ +package dev.isxander.yacl3.config.v2.api.autogen; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface LongSlider { + long min(); + + long max(); + + long step(); +} diff --git a/common/src/main/java/dev/isxander/yacl3/config/v2/api/OptionFactory.java b/common/src/main/java/dev/isxander/yacl3/config/v2/api/autogen/OptionFactory.java index 9d53e79..2e3a537 100644 --- a/common/src/main/java/dev/isxander/yacl3/config/v2/api/OptionFactory.java +++ b/common/src/main/java/dev/isxander/yacl3/config/v2/api/autogen/OptionFactory.java @@ -1,7 +1,7 @@ -package dev.isxander.yacl3.config.v2.api; +package dev.isxander.yacl3.config.v2.api.autogen; import dev.isxander.yacl3.api.Option; -import dev.isxander.yacl3.config.v2.api.autogen.OptionStorage; +import dev.isxander.yacl3.config.v2.api.ConfigField; import dev.isxander.yacl3.config.v2.impl.autogen.OptionFactoryRegistry; import java.lang.annotation.Annotation; diff --git a/common/src/main/java/dev/isxander/yacl3/config/v2/api/SimpleOptionFactory.java b/common/src/main/java/dev/isxander/yacl3/config/v2/api/autogen/SimpleOptionFactory.java index 67b1d87..c532f29 100644 --- a/common/src/main/java/dev/isxander/yacl3/config/v2/api/SimpleOptionFactory.java +++ b/common/src/main/java/dev/isxander/yacl3/config/v2/api/autogen/SimpleOptionFactory.java @@ -1,10 +1,10 @@ -package dev.isxander.yacl3.config.v2.api; +package dev.isxander.yacl3.config.v2.api.autogen; import dev.isxander.yacl3.api.Option; import dev.isxander.yacl3.api.OptionDescription; import dev.isxander.yacl3.api.OptionFlag; import dev.isxander.yacl3.api.controller.ControllerBuilder; -import dev.isxander.yacl3.config.v2.api.autogen.OptionStorage; +import dev.isxander.yacl3.config.v2.api.ConfigField; import dev.isxander.yacl3.config.v2.impl.FieldBackedBinding; import net.minecraft.client.Minecraft; import net.minecraft.locale.Language; diff --git a/common/src/main/java/dev/isxander/yacl3/config/v2/api/autogen/StringField.java b/common/src/main/java/dev/isxander/yacl3/config/v2/api/autogen/StringField.java new file mode 100644 index 0000000..c30a75e --- /dev/null +++ b/common/src/main/java/dev/isxander/yacl3/config/v2/api/autogen/StringField.java @@ -0,0 +1,11 @@ +package dev.isxander.yacl3.config.v2.api.autogen; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface StringField { +} diff --git a/common/src/main/java/dev/isxander/yacl3/config/v2/impl/ConfigClassHandlerImpl.java b/common/src/main/java/dev/isxander/yacl3/config/v2/impl/ConfigClassHandlerImpl.java index b9274e9..7c0c2a9 100644 --- a/common/src/main/java/dev/isxander/yacl3/config/v2/impl/ConfigClassHandlerImpl.java +++ b/common/src/main/java/dev/isxander/yacl3/config/v2/impl/ConfigClassHandlerImpl.java @@ -5,6 +5,7 @@ import dev.isxander.yacl3.config.v2.api.*; import dev.isxander.yacl3.config.v2.api.autogen.AutoGen; import dev.isxander.yacl3.config.v2.api.autogen.OptionStorage; import dev.isxander.yacl3.config.v2.impl.autogen.OptionFactoryRegistry; +import dev.isxander.yacl3.config.v2.impl.autogen.OptionStorageImpl; import dev.isxander.yacl3.platform.YACLPlatform; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; diff --git a/common/src/main/java/dev/isxander/yacl3/config/v2/impl/ReflectionFieldAccess.java b/common/src/main/java/dev/isxander/yacl3/config/v2/impl/ReflectionFieldAccess.java index 114137f..7bba083 100644 --- a/common/src/main/java/dev/isxander/yacl3/config/v2/impl/ReflectionFieldAccess.java +++ b/common/src/main/java/dev/isxander/yacl3/config/v2/impl/ReflectionFieldAccess.java @@ -33,4 +33,9 @@ public record ReflectionFieldAccess<T>(Field field, Object instance) implements public Type type() { return field.getGenericType(); } + + @Override + public Class<T> typeClass() { + return (Class<T>) field.getType(); + } } diff --git a/common/src/main/java/dev/isxander/yacl3/config/v2/impl/autogen/BooleanImpl.java b/common/src/main/java/dev/isxander/yacl3/config/v2/impl/autogen/BooleanImpl.java index 0a24cf5..74eab90 100644 --- a/common/src/main/java/dev/isxander/yacl3/config/v2/impl/autogen/BooleanImpl.java +++ b/common/src/main/java/dev/isxander/yacl3/config/v2/impl/autogen/BooleanImpl.java @@ -4,7 +4,7 @@ import dev.isxander.yacl3.api.Option; import dev.isxander.yacl3.api.controller.BooleanControllerBuilder; import dev.isxander.yacl3.api.controller.ControllerBuilder; import dev.isxander.yacl3.config.v2.api.ConfigField; -import dev.isxander.yacl3.config.v2.api.SimpleOptionFactory; +import dev.isxander.yacl3.config.v2.api.autogen.SimpleOptionFactory; import dev.isxander.yacl3.config.v2.api.autogen.Boolean; import dev.isxander.yacl3.config.v2.api.autogen.OptionStorage; import net.minecraft.network.chat.Component; diff --git a/common/src/main/java/dev/isxander/yacl3/config/v2/impl/autogen/ColorRGBAImpl.java b/common/src/main/java/dev/isxander/yacl3/config/v2/impl/autogen/ColorRGBAImpl.java new file mode 100644 index 0000000..4bbeca1 --- /dev/null +++ b/common/src/main/java/dev/isxander/yacl3/config/v2/impl/autogen/ColorRGBAImpl.java @@ -0,0 +1,19 @@ +package dev.isxander.yacl3.config.v2.impl.autogen; + +import dev.isxander.yacl3.api.Option; +import dev.isxander.yacl3.api.controller.ColorControllerBuilder; +import dev.isxander.yacl3.api.controller.ControllerBuilder; +import dev.isxander.yacl3.config.v2.api.ConfigField; +import dev.isxander.yacl3.config.v2.api.autogen.SimpleOptionFactory; +import dev.isxander.yacl3.config.v2.api.autogen.ColorRGBA; +import dev.isxander.yacl3.config.v2.api.autogen.OptionStorage; + +import java.awt.Color; + +public class ColorRGBAImpl extends SimpleOptionFactory<ColorRGBA, Color> { + @Override + protected ControllerBuilder<Color> createController(ColorRGBA annotation, ConfigField<Color> field, OptionStorage storage, Option<Color> option) { + return ColorControllerBuilder.create(option) + .allowAlpha(annotation.allowAlpha()); + } +} diff --git a/common/src/main/java/dev/isxander/yacl3/config/v2/impl/autogen/DoubleSliderImpl.java b/common/src/main/java/dev/isxander/yacl3/config/v2/impl/autogen/DoubleSliderImpl.java index 87db158..1a397bd 100644 --- a/common/src/main/java/dev/isxander/yacl3/config/v2/impl/autogen/DoubleSliderImpl.java +++ b/common/src/main/java/dev/isxander/yacl3/config/v2/impl/autogen/DoubleSliderImpl.java @@ -4,7 +4,7 @@ import dev.isxander.yacl3.api.Option; import dev.isxander.yacl3.api.controller.ControllerBuilder; import dev.isxander.yacl3.api.controller.DoubleSliderControllerBuilder; import dev.isxander.yacl3.config.v2.api.ConfigField; -import dev.isxander.yacl3.config.v2.api.SimpleOptionFactory; +import dev.isxander.yacl3.config.v2.api.autogen.SimpleOptionFactory; import dev.isxander.yacl3.config.v2.api.autogen.DoubleSlider; import dev.isxander.yacl3.config.v2.api.autogen.OptionStorage; import net.minecraft.locale.Language; diff --git a/common/src/main/java/dev/isxander/yacl3/config/v2/impl/autogen/EnumCyclerImpl.java b/common/src/main/java/dev/isxander/yacl3/config/v2/impl/autogen/EnumCyclerImpl.java new file mode 100644 index 0000000..e42ab3f --- /dev/null +++ b/common/src/main/java/dev/isxander/yacl3/config/v2/impl/autogen/EnumCyclerImpl.java @@ -0,0 +1,42 @@ +package dev.isxander.yacl3.config.v2.impl.autogen; + +import dev.isxander.yacl3.api.NameableEnum; +import dev.isxander.yacl3.api.Option; +import dev.isxander.yacl3.api.controller.ControllerBuilder; +import dev.isxander.yacl3.api.controller.CyclingListControllerBuilder; +import dev.isxander.yacl3.config.v2.api.ConfigField; +import dev.isxander.yacl3.config.v2.api.autogen.SimpleOptionFactory; +import dev.isxander.yacl3.config.v2.api.autogen.EnumCycler; +import dev.isxander.yacl3.config.v2.api.autogen.OptionStorage; +import net.minecraft.network.chat.Component; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.IntStream; + +public class EnumCyclerImpl extends SimpleOptionFactory<EnumCycler, Enum<?>> { + @Override + protected ControllerBuilder<Enum<?>> createController(EnumCycler annotation, ConfigField<Enum<?>> field, OptionStorage storage, Option<Enum<?>> option) { + List<? extends Enum<?>> values; + + if (option.pendingValue() instanceof EnumCycler.CyclableEnum<?> cyclableEnum) { + values = Arrays.asList(cyclableEnum.allowedValues()); + } else { + Enum<?>[] constants = field.access().typeClass().getEnumConstants(); + values = IntStream.range(0, constants.length) + .filter(ordinal -> annotation.allowedOrdinals().length == 0 || Arrays.stream(annotation.allowedOrdinals()).noneMatch(allowed -> allowed == ordinal)) + .mapToObj(ordinal -> constants[ordinal]) + .toList(); + } + + // EnumController doesn't support filtering + var builder = CyclingListControllerBuilder.create(option) + .values(values); + if (NameableEnum.class.isAssignableFrom(field.access().typeClass())) { + builder.valueFormatter(v -> ((NameableEnum) v).getDisplayName()); + } else { + builder.valueFormatter(v -> Component.translatable(getTranslationKey(field, "fmt." + v.name().toLowerCase()))); + } + return builder; + } +} diff --git a/common/src/main/java/dev/isxander/yacl3/config/v2/impl/autogen/FloatSliderImpl.java b/common/src/main/java/dev/isxander/yacl3/config/v2/impl/autogen/FloatSliderImpl.java index b856a7a..7a098e1 100644 --- a/common/src/main/java/dev/isxander/yacl3/config/v2/impl/autogen/FloatSliderImpl.java +++ b/common/src/main/java/dev/isxander/yacl3/config/v2/impl/autogen/FloatSliderImpl.java @@ -4,7 +4,7 @@ import dev.isxander.yacl3.api.Option; import dev.isxander.yacl3.api.controller.ControllerBuilder; import dev.isxander.yacl3.api.controller.FloatSliderControllerBuilder; import dev.isxander.yacl3.config.v2.api.ConfigField; -import dev.isxander.yacl3.config.v2.api.SimpleOptionFactory; +import dev.isxander.yacl3.config.v2.api.autogen.SimpleOptionFactory; import dev.isxander.yacl3.config.v2.api.autogen.FloatSlider; import dev.isxander.yacl3.config.v2.api.autogen.OptionStorage; import net.minecraft.locale.Language; diff --git a/common/src/main/java/dev/isxander/yacl3/config/v2/impl/autogen/IntSliderImpl.java b/common/src/main/java/dev/isxander/yacl3/config/v2/impl/autogen/IntSliderImpl.java index c03d370..5f6e88e 100644 --- a/common/src/main/java/dev/isxander/yacl3/config/v2/impl/autogen/IntSliderImpl.java +++ b/common/src/main/java/dev/isxander/yacl3/config/v2/impl/autogen/IntSliderImpl.java @@ -4,7 +4,7 @@ import dev.isxander.yacl3.api.Option; import dev.isxander.yacl3.api.controller.ControllerBuilder; import dev.isxander.yacl3.api.controller.IntegerSliderControllerBuilder; import dev.isxander.yacl3.config.v2.api.ConfigField; -import dev.isxander.yacl3.config.v2.api.SimpleOptionFactory; +import dev.isxander.yacl3.config.v2.api.autogen.SimpleOptionFactory; import dev.isxander.yacl3.config.v2.api.autogen.IntSlider; import dev.isxander.yacl3.config.v2.api.autogen.OptionStorage; import net.minecraft.locale.Language; diff --git a/common/src/main/java/dev/isxander/yacl3/config/v2/impl/autogen/LabelImpl.java b/common/src/main/java/dev/isxander/yacl3/config/v2/impl/autogen/LabelImpl.java index c36c8b7..6585652 100644 --- a/common/src/main/java/dev/isxander/yacl3/config/v2/impl/autogen/LabelImpl.java +++ b/common/src/main/java/dev/isxander/yacl3/config/v2/impl/autogen/LabelImpl.java @@ -3,7 +3,7 @@ package dev.isxander.yacl3.config.v2.impl.autogen; import dev.isxander.yacl3.api.LabelOption; import dev.isxander.yacl3.api.Option; import dev.isxander.yacl3.config.v2.api.ConfigField; -import dev.isxander.yacl3.config.v2.api.OptionFactory; +import dev.isxander.yacl3.config.v2.api.autogen.OptionFactory; import dev.isxander.yacl3.config.v2.api.autogen.Label; import dev.isxander.yacl3.config.v2.api.autogen.OptionStorage; import net.minecraft.network.chat.Component; diff --git a/common/src/main/java/dev/isxander/yacl3/config/v2/impl/autogen/ListGroupImpl.java b/common/src/main/java/dev/isxander/yacl3/config/v2/impl/autogen/ListGroupImpl.java new file mode 100644 index 0000000..c94be2e --- /dev/null +++ b/common/src/main/java/dev/isxander/yacl3/config/v2/impl/autogen/ListGroupImpl.java @@ -0,0 +1,95 @@ +package dev.isxander.yacl3.config.v2.impl.autogen; + +import dev.isxander.yacl3.api.ListOption; +import dev.isxander.yacl3.api.Option; +import dev.isxander.yacl3.api.OptionDescription; +import dev.isxander.yacl3.config.v2.api.ConfigField; +import dev.isxander.yacl3.config.v2.api.autogen.ListGroup; +import dev.isxander.yacl3.config.v2.api.autogen.OptionFactory; +import dev.isxander.yacl3.config.v2.api.autogen.OptionStorage; +import dev.isxander.yacl3.config.v2.impl.FieldBackedBinding; +import net.minecraft.client.Minecraft; +import net.minecraft.locale.Language; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import org.jetbrains.annotations.Nullable; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.List; + +public class ListGroupImpl<T> implements OptionFactory<ListGroup, List<T>> { + @Override + public Option<List<T>> createOption(ListGroup annotation, ConfigField<List<T>> field, OptionStorage storage) { + ListGroup.ValueFactory<T> valueFactory = createValueFactory((Class<? extends ListGroup.ValueFactory<T>>) annotation.valueFactory()); + ListGroup.ControllerFactory<T> controllerFactory = createControllerFactory((Class<? extends ListGroup.ControllerFactory<T>>) annotation.controllerFactory()); + + return ListOption.<T>createBuilder() + .name(Component.translatable(this.getTranslationKey(field, null))) + .description(this.description(field)) + .initial(valueFactory::provideNewValue) + .controller(opt -> controllerFactory.createController(annotation, field, storage, opt)) + .binding(new FieldBackedBinding<>(field.access(), field.defaultAccess())) + .build(); + } + + private OptionDescription description(ConfigField<List<T>> field) { + OptionDescription.Builder builder = OptionDescription.createBuilder(); + + String key = this.getTranslationKey(field, "desc"); + if (Language.getInstance().has(key)) { + builder.text(Component.translatable(key)); + } else { + key += "."; + int i = 0; + while (Language.getInstance().has(key + i++)) { + builder.text(Component.translatable(key + i)); + } + } + + String imagePath = "textures/yacl3/" + field.parent().id().getPath() + "/" + field.access().name() + ".webp"; + imagePath = imagePath.toLowerCase().replaceAll("[^a-z0-9/._:-]", "_"); + ResourceLocation imageLocation = new ResourceLocation(field.parent().id().getNamespace(), imagePath); + if (Minecraft.getInstance().getResourceManager().getResource(imageLocation).isPresent()) { + builder.webpImage(imageLocation); + } + + return builder.build(); + } + + private ListGroup.ValueFactory<T> createValueFactory(Class<? extends ListGroup.ValueFactory<T>> clazz) { + Constructor<? extends ListGroup.ValueFactory<T>> constructor; + try { + constructor = clazz.getConstructor(); + } catch (NoSuchMethodException e) { + throw new YACLAutoGenException("Could not find no-args constructor for `valueFactory` on '%s' for @ListGroup field.".formatted(clazz.getName()), e); + } + + try { + return constructor.newInstance(); + } catch (InvocationTargetException | InstantiationException | IllegalAccessException e) { + throw new YACLAutoGenException("Couldn't invoke no-args constructor for `valueFactory` on '%s' for @ListGroup field.".formatted(clazz.getName()), e); + } + } + + private ListGroup.ControllerFactory<T> createControllerFactory(Class<? extends ListGroup.ControllerFactory<T>> clazz) { + Constructor<? extends ListGroup.ControllerFactory<T>> constructor; + try { + constructor = clazz.getConstructor(); + } catch (NoSuchMethodException e) { + throw new YACLAutoGenException("Could not find no-args constructor on `controllerFactory`, '%s' for @ListGroup field.".formatted(clazz.getName()), e); + } + + try { + return constructor.newInstance(); + } catch (InvocationTargetException | InstantiationException | IllegalAccessException e) { + throw new YACLAutoGenException("Couldn't invoke no-args constructor on `controllerFactory`, '%s' for @ListGroup field.".formatted(clazz.getName()), e); + } + } + + private String getTranslationKey(ConfigField<List<T>> field, @Nullable String suffix) { + String key = "yacl3.config.%s.%s".formatted(field.parent().id().toString(), field.access().name()); + if (suffix != null) key += "." + suffix; + return key; + } +} diff --git a/common/src/main/java/dev/isxander/yacl3/config/v2/impl/autogen/LongSliderImpl.java b/common/src/main/java/dev/isxander/yacl3/config/v2/impl/autogen/LongSliderImpl.java new file mode 100644 index 0000000..5850315 --- /dev/null +++ b/common/src/main/java/dev/isxander/yacl3/config/v2/impl/autogen/LongSliderImpl.java @@ -0,0 +1,28 @@ +package dev.isxander.yacl3.config.v2.impl.autogen; + +import dev.isxander.yacl3.api.Option; +import dev.isxander.yacl3.api.controller.ControllerBuilder; +import dev.isxander.yacl3.api.controller.IntegerSliderControllerBuilder; +import dev.isxander.yacl3.api.controller.LongSliderControllerBuilder; +import dev.isxander.yacl3.config.v2.api.ConfigField; +import dev.isxander.yacl3.config.v2.api.autogen.IntSlider; +import dev.isxander.yacl3.config.v2.api.autogen.LongSlider; +import dev.isxander.yacl3.config.v2.api.autogen.OptionStorage; +import dev.isxander.yacl3.config.v2.api.autogen.SimpleOptionFactory; +import net.minecraft.locale.Language; +import net.minecraft.network.chat.Component; + +public class LongSliderImpl extends SimpleOptionFactory<LongSlider, Long> { + @Override + protected ControllerBuilder<Long> createController(LongSlider annotation, ConfigField<Long> field, OptionStorage storage, Option<Long> option) { + return LongSliderControllerBuilder.create(option) + .valueFormatter(v -> { + String key = getTranslationKey(field, "fmt." + v); + if (Language.getInstance().has(key)) + return Component.translatable(key); + return Component.literal(Long.toString(v)); + }) + .range(annotation.min(), annotation.max()) + .step(annotation.step()); + } +} diff --git a/common/src/main/java/dev/isxander/yacl3/config/v2/impl/autogen/MasterTickBoxImpl.java b/common/src/main/java/dev/isxander/yacl3/config/v2/impl/autogen/MasterTickBoxImpl.java index fa2b7b5..367b4d0 100644 --- a/common/src/main/java/dev/isxander/yacl3/config/v2/impl/autogen/MasterTickBoxImpl.java +++ b/common/src/main/java/dev/isxander/yacl3/config/v2/impl/autogen/MasterTickBoxImpl.java @@ -4,7 +4,7 @@ import dev.isxander.yacl3.api.Option; import dev.isxander.yacl3.api.controller.ControllerBuilder; import dev.isxander.yacl3.api.controller.TickBoxControllerBuilder; import dev.isxander.yacl3.config.v2.api.ConfigField; -import dev.isxander.yacl3.config.v2.api.SimpleOptionFactory; +import dev.isxander.yacl3.config.v2.api.autogen.SimpleOptionFactory; import dev.isxander.yacl3.config.v2.api.autogen.MasterTickBox; import dev.isxander.yacl3.config.v2.api.autogen.OptionStorage; diff --git a/common/src/main/java/dev/isxander/yacl3/config/v2/impl/autogen/OptionFactoryRegistry.java b/common/src/main/java/dev/isxander/yacl3/config/v2/impl/autogen/OptionFactoryRegistry.java index 1762f2d..28d8bb3 100644 --- a/common/src/main/java/dev/isxander/yacl3/config/v2/impl/autogen/OptionFactoryRegistry.java +++ b/common/src/main/java/dev/isxander/yacl3/config/v2/impl/autogen/OptionFactoryRegistry.java @@ -2,10 +2,9 @@ package dev.isxander.yacl3.config.v2.impl.autogen; import dev.isxander.yacl3.api.Option; import dev.isxander.yacl3.config.v2.api.ConfigField; -import dev.isxander.yacl3.config.v2.api.OptionFactory; +import dev.isxander.yacl3.config.v2.api.autogen.OptionFactory; import dev.isxander.yacl3.config.v2.api.autogen.*; import dev.isxander.yacl3.config.v2.api.autogen.Boolean; -import dev.isxander.yacl3.config.v2.impl.autogen.*; import dev.isxander.yacl3.impl.utils.YACLConstants; import java.lang.annotation.Annotation; @@ -22,9 +21,14 @@ public class OptionFactoryRegistry { registerOptionFactory(TickBox.class, new TickBoxImpl()); registerOptionFactory(Boolean.class, new BooleanImpl()); registerOptionFactory(IntSlider.class, new IntSliderImpl()); + registerOptionFactory(LongSlider.class, new LongSliderImpl()); registerOptionFactory(FloatSlider.class, new FloatSliderImpl()); registerOptionFactory(DoubleSlider.class, new DoubleSliderImpl()); + registerOptionFactory(EnumCycler.class, new EnumCyclerImpl()); + registerOptionFactory(StringField.class, new StringFieldImpl()); + registerOptionFactory(ColorRGBA.class, new ColorRGBAImpl()); registerOptionFactory(Label.class, new LabelImpl()); + registerOptionFactory(ListGroup.class, new ListGroupImpl<>()); registerOptionFactory(MasterTickBox.class, new MasterTickBoxImpl()); } diff --git a/common/src/main/java/dev/isxander/yacl3/config/v2/impl/OptionStorageImpl.java b/common/src/main/java/dev/isxander/yacl3/config/v2/impl/autogen/OptionStorageImpl.java index 3c75a11..80147d8 100644 --- a/common/src/main/java/dev/isxander/yacl3/config/v2/impl/OptionStorageImpl.java +++ b/common/src/main/java/dev/isxander/yacl3/config/v2/impl/autogen/OptionStorageImpl.java @@ -1,4 +1,4 @@ -package dev.isxander.yacl3.config.v2.impl; +package dev.isxander.yacl3.config.v2.impl.autogen; import dev.isxander.yacl3.api.Option; import dev.isxander.yacl3.config.v2.api.autogen.OptionStorage; diff --git a/common/src/main/java/dev/isxander/yacl3/config/v2/impl/autogen/StringFieldImpl.java b/common/src/main/java/dev/isxander/yacl3/config/v2/impl/autogen/StringFieldImpl.java new file mode 100644 index 0000000..7d6c993 --- /dev/null +++ b/common/src/main/java/dev/isxander/yacl3/config/v2/impl/autogen/StringFieldImpl.java @@ -0,0 +1,16 @@ +package dev.isxander.yacl3.config.v2.impl.autogen; + +import dev.isxander.yacl3.api.Option; +import dev.isxander.yacl3.api.controller.ControllerBuilder; +import dev.isxander.yacl3.api.controller.StringControllerBuilder; +import dev.isxander.yacl3.config.v2.api.ConfigField; +import dev.isxander.yacl3.config.v2.api.autogen.SimpleOptionFactory; +import dev.isxander.yacl3.config.v2.api.autogen.OptionStorage; +import dev.isxander.yacl3.config.v2.api.autogen.StringField; + +public class StringFieldImpl extends SimpleOptionFactory<StringField, String> { + @Override + protected ControllerBuilder<String> createController(StringField annotation, ConfigField<String> field, OptionStorage storage, Option<String> option) { + return StringControllerBuilder.create(option); + } +} diff --git a/common/src/main/java/dev/isxander/yacl3/config/v2/impl/autogen/TickBoxImpl.java b/common/src/main/java/dev/isxander/yacl3/config/v2/impl/autogen/TickBoxImpl.java index 202534e..72ef046 100644 --- a/common/src/main/java/dev/isxander/yacl3/config/v2/impl/autogen/TickBoxImpl.java +++ b/common/src/main/java/dev/isxander/yacl3/config/v2/impl/autogen/TickBoxImpl.java @@ -4,7 +4,7 @@ import dev.isxander.yacl3.api.Option; import dev.isxander.yacl3.api.controller.ControllerBuilder; import dev.isxander.yacl3.api.controller.TickBoxControllerBuilder; import dev.isxander.yacl3.config.v2.api.ConfigField; -import dev.isxander.yacl3.config.v2.api.SimpleOptionFactory; +import dev.isxander.yacl3.config.v2.api.autogen.SimpleOptionFactory; import dev.isxander.yacl3.config.v2.api.autogen.OptionStorage; import dev.isxander.yacl3.config.v2.api.autogen.TickBox; diff --git a/common/src/main/java/dev/isxander/yacl3/config/v2/impl/autogen/YACLAutoGenException.java b/common/src/main/java/dev/isxander/yacl3/config/v2/impl/autogen/YACLAutoGenException.java new file mode 100644 index 0000000..68b375d --- /dev/null +++ b/common/src/main/java/dev/isxander/yacl3/config/v2/impl/autogen/YACLAutoGenException.java @@ -0,0 +1,11 @@ +package dev.isxander.yacl3.config.v2.impl.autogen; + +public class YACLAutoGenException extends RuntimeException { + public YACLAutoGenException(String message) { + super(message); + } + + public YACLAutoGenException(String message, Throwable e) { + super(message, e); + } +} diff --git a/test-common/src/main/java/dev/isxander/yacl3/test/ConfigV2Test.java b/test-common/src/main/java/dev/isxander/yacl3/test/ConfigV2Test.java index d287604..04b7db0 100644 --- a/test-common/src/main/java/dev/isxander/yacl3/test/ConfigV2Test.java +++ b/test-common/src/main/java/dev/isxander/yacl3/test/ConfigV2Test.java @@ -1,6 +1,12 @@ package dev.isxander.yacl3.test; +import com.google.common.collect.Lists; +import dev.isxander.yacl3.api.NameableEnum; +import dev.isxander.yacl3.api.Option; +import dev.isxander.yacl3.api.controller.ControllerBuilder; +import dev.isxander.yacl3.api.controller.StringControllerBuilder; import dev.isxander.yacl3.config.v2.api.ConfigClassHandler; +import dev.isxander.yacl3.config.v2.api.ConfigField; import dev.isxander.yacl3.config.v2.api.GsonConfigSerializerBuilder; import dev.isxander.yacl3.config.v2.api.SerialEntry; import dev.isxander.yacl3.config.v2.api.autogen.*; @@ -8,6 +14,8 @@ import dev.isxander.yacl3.platform.YACLPlatform; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; +import java.util.List; + public class ConfigV2Test { public static ConfigClassHandler<ConfigV2Test> INSTANCE = ConfigClassHandler.createBuilder(ConfigV2Test.class) .id(new ResourceLocation("yacl3", "config")) @@ -19,7 +27,7 @@ public class ConfigV2Test { .build(); @AutoGen(category = "test", group = "master_test") - @MasterTickBox({ "testTickBox", "testInt" }) + @MasterTickBox({ "testTickBox", "testInt", "testEnum" }) @SerialEntry(comment = "This option does this and that which is cool because this...") public boolean masterOption = true; @@ -32,6 +40,37 @@ public class ConfigV2Test { @IntSlider(min = 0, max = 10, step = 2) @SerialEntry public int testInt = 0; + @AutoGen(category = "test", group = "master_test") + @EnumCycler + @SerialEntry public Alphabet testEnum = Alphabet.A; + @AutoGen(category = "test", group = "misc") @Label private final Component testLabel = Component.literal("Test label"); + + @AutoGen(category = "test") + @ListGroup(valueFactory = TestListValueFactory.class, controllerFactory = TestListControllerFactory.class) + @SerialEntry public List<String> testList = Lists.newArrayList("A", "B"); + + public enum Alphabet implements NameableEnum { + A, B, C; + + @Override + public Component getDisplayName() { + return Component.literal(name()); + } + } + + public static class TestListValueFactory implements ListGroup.ValueFactory<String> { + @Override + public String provideNewValue() { + return ""; + } + } + + public static class TestListControllerFactory implements ListGroup.ControllerFactory<String> { + @Override + public ControllerBuilder<String> createController(ListGroup annotation, ConfigField<List<String>> field, OptionStorage storage, Option<String> option) { + return StringControllerBuilder.create(option); + } + } } |