diff options
Diffstat (limited to 'common/src/main/java/dev/isxander/yacl')
74 files changed, 7769 insertions, 0 deletions
diff --git a/common/src/main/java/dev/isxander/yacl/api/Binding.java b/common/src/main/java/dev/isxander/yacl/api/Binding.java new file mode 100644 index 0000000..b4cd2d0 --- /dev/null +++ b/common/src/main/java/dev/isxander/yacl/api/Binding.java @@ -0,0 +1,64 @@ +package dev.isxander.yacl.api; + +import dev.isxander.yacl.impl.GenericBindingImpl; +import dev.isxander.yacl.mixin.OptionInstanceAccessor; +import net.minecraft.client.OptionInstance; +import org.apache.commons.lang3.Validate; + +import java.util.function.Consumer; +import java.util.function.Supplier; + +/** + * Controls modifying the bound option. + * Provides the default value, a setter and a getter. + */ +public interface Binding<T> { + void setValue(T value); + + T getValue(); + + T defaultValue(); + + /** + * Creates a generic binding. + * + * @param def default value of the option, used to reset + * @param getter should return the current value of the option + * @param setter should set the option to the supplied value + */ + static <T> Binding<T> generic(T def, Supplier<T> getter, Consumer<T> setter) { + Validate.notNull(def, "`def` must not be null"); + Validate.notNull(getter, "`getter` must not be null"); + Validate.notNull(setter, "`setter` must not be null"); + + return new GenericBindingImpl<>(def, getter, setter); + } + + /** + * Creates a {@link Binding} for Minecraft's {@link OptionInstance} + */ + static <T> Binding<T> minecraft(OptionInstance<T> minecraftOption) { + Validate.notNull(minecraftOption, "`minecraftOption` must not be null"); + + return new GenericBindingImpl<>( + ((OptionInstanceAccessor<T>) (Object) minecraftOption).getInitialValue(), + minecraftOption::get, + minecraftOption::set + ); + } + + /** + * Creates an immutable binding that has no default and cannot be modified. + * + * @param value the value for the binding + */ + static <T> Binding<T> immutable(T value) { + Validate.notNull(value, "`value` must not be null"); + + return new GenericBindingImpl<>( + value, + () -> value, + changed -> {} + ); + } +} diff --git a/common/src/main/java/dev/isxander/yacl/api/ButtonOption.java b/common/src/main/java/dev/isxander/yacl/api/ButtonOption.java new file mode 100644 index 0000000..88e1c4b --- /dev/null +++ b/common/src/main/java/dev/isxander/yacl/api/ButtonOption.java @@ -0,0 +1,66 @@ +package dev.isxander.yacl.api; + +import dev.isxander.yacl.gui.YACLScreen; +import dev.isxander.yacl.impl.ButtonOptionImpl; +import net.minecraft.network.chat.Component; +import org.jetbrains.annotations.NotNull; + +import java.util.function.BiConsumer; +import java.util.function.Consumer; +import java.util.function.Function; + +public interface ButtonOption extends Option<BiConsumer<YACLScreen, ButtonOption>> { + /** + * Action to be executed upon button press + */ + BiConsumer<YACLScreen, ButtonOption> action(); + + static dev.isxander.yacl.api.ButtonOption.Builder createBuilder() { + return new ButtonOptionImpl.BuilderImpl(); + } + + interface Builder { + /** + * Sets the name to be used by the option. + * + * @see Option#name() + */ + dev.isxander.yacl.api.ButtonOption.Builder name(@NotNull Component name); + + /** + * Sets the tooltip to be used by the option. + * Can be invoked twice to append more lines. + * No need to wrap the text yourself, the gui does this itself. + * + * @param tooltips text lines - merged with a new-line on {@link Option.Builder#build()}. + */ + dev.isxander.yacl.api.ButtonOption.Builder tooltip(@NotNull Component... tooltips); + + dev.isxander.yacl.api.ButtonOption.Builder action(@NotNull BiConsumer<YACLScreen, ButtonOption> action); + + /** + * Action to be executed upon button press + * + * @see ButtonOption#action() + */ + @Deprecated + dev.isxander.yacl.api.ButtonOption.Builder action(@NotNull Consumer<YACLScreen> action); + + /** + * Sets if the option can be configured + * + * @see Option#available() + */ + dev.isxander.yacl.api.ButtonOption.Builder available(boolean available); + + /** + * Sets the controller for the option. + * This is how you interact and change the options. + * + * @see dev.isxander.yacl.gui.controllers + */ + dev.isxander.yacl.api.ButtonOption.Builder controller(@NotNull Function<ButtonOption, Controller<BiConsumer<YACLScreen, ButtonOption>>> control); + + ButtonOption build(); + } +} diff --git a/common/src/main/java/dev/isxander/yacl/api/ConfigCategory.java b/common/src/main/java/dev/isxander/yacl/api/ConfigCategory.java new file mode 100644 index 0000000..7764479 --- /dev/null +++ b/common/src/main/java/dev/isxander/yacl/api/ConfigCategory.java @@ -0,0 +1,94 @@ +package dev.isxander.yacl.api; + +import com.google.common.collect.ImmutableList; +import dev.isxander.yacl.impl.ConfigCategoryImpl; +import net.minecraft.network.chat.Component; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; + +/** + * Separates {@link Option}s or {@link OptionGroup}s into multiple distinct sections. + * Served to a user as a button in the left column, + * upon pressing, the options list is filled with options contained within this category. + */ +public interface ConfigCategory { + /** + * Name of category, displayed as a button on the left column. + */ + @NotNull Component name(); + + /** + * Gets every {@link OptionGroup} in this category. + */ + @NotNull ImmutableList<OptionGroup> groups(); + + /** + * Tooltip (or description) of the category. + * Rendered on hover. + */ + @NotNull Component tooltip(); + + /** + * Creates a builder to construct a {@link ConfigCategory} + */ + static Builder createBuilder() { + return new ConfigCategoryImpl.BuilderImpl(); + } + + interface Builder extends OptionAddable { + /** + * Sets name of the category + * + * @see ConfigCategory#name() + */ + Builder name(@NotNull Component name); + + /** + * Adds an option to the root group of the category. + * To add to another group, use {@link Builder#group(OptionGroup)}. + * To construct an option, use {@link Option#createBuilder(Class)} + * + * @see ConfigCategory#groups() + * @see OptionGroup#isRoot() + */ + @Override + Builder option(@NotNull Option<?> option); + + /** + * Adds multiple options to the root group of the category. + * To add to another group, use {@link Builder#groups(Collection)}. + * To construct an option, use {@link Option#createBuilder(Class)} + * + * @see ConfigCategory#groups() + * @see OptionGroup#isRoot() + */ + @Override + Builder options(@NotNull Collection<? extends Option<?>> options); + + /** + * Adds an option group. + * To add an option to the root group, use {@link Builder#option(Option)} + * To construct a group, use {@link OptionGroup#createBuilder()} + */ + Builder group(@NotNull OptionGroup group); + + /** + * Adds multiple option groups. + * To add multiple options to the root group, use {@link Builder#options(Collection)} + * To construct a group, use {@link OptionGroup#createBuilder()} + */ + Builder groups(@NotNull Collection<OptionGroup> groups); + + /** + * Sets the tooltip to be used by the category. + * Can be invoked twice to append more lines. + * No need to wrap the text yourself, the gui does this itself. + * + * @param tooltips text lines - merged with a new-line on {@link Builder#build()}. + */ + Builder tooltip(@NotNull Component... tooltips); + + ConfigCategory build(); + } +} diff --git a/common/src/main/java/dev/isxander/yacl/api/Controller.java b/common/src/main/java/dev/isxander/yacl/api/Controller.java new file mode 100644 index 0000000..0b8e2ed --- /dev/null +++ b/common/src/main/java/dev/isxander/yacl/api/Controller.java @@ -0,0 +1,28 @@ +package dev.isxander.yacl.api; + +import dev.isxander.yacl.api.utils.Dimension; +import dev.isxander.yacl.gui.AbstractWidget; +import dev.isxander.yacl.gui.YACLScreen; +import net.minecraft.network.chat.Component; + +/** + * Provides a widget to control the option. + */ +public interface Controller<T> { + /** + * Gets the dedicated {@link Option} for this controller + */ + Option<T> option(); + + /** + * Gets the formatted value based on {@link Option#pendingValue()} + */ + Component formatValue(); + + /** + * Provides a widget to display + * + * @param screen parent screen + */ + AbstractWidget provideWidget(YACLScreen screen, Dimension<Integer> widgetDimension); +} diff --git a/common/src/main/java/dev/isxander/yacl/api/LabelOption.java b/common/src/main/java/dev/isxander/yacl/api/LabelOption.java new file mode 100644 index 0000000..05c7214 --- /dev/null +++ b/common/src/main/java/dev/isxander/yacl/api/LabelOption.java @@ -0,0 +1,41 @@ +package dev.isxander.yacl.api; + +import dev.isxander.yacl.impl.LabelOptionImpl; +import net.minecraft.network.chat.Component; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; + +/** + * A label option is an easier way of creating a label with a {@link dev.isxander.yacl.gui.controllers.LabelController}. + * This option is immutable and cannot be disabled. Tooltips are supported through + * {@link Component} styling. + */ +public interface LabelOption extends Option<Component> { + @NotNull Component label(); + + /** + * Creates a new label option with the given label, skipping a builder for ease. + */ + static LabelOption create(@NotNull Component label) { + return new LabelOptionImpl(label); + } + + static dev.isxander.yacl.api.LabelOption.Builder createBuilder() { + return new LabelOptionImpl.BuilderImpl(); + } + + interface Builder { + /** + * Appends a line to the label + */ + dev.isxander.yacl.api.LabelOption.Builder line(@NotNull Component line); + + /** + * Appends multiple lines to the label + */ + dev.isxander.yacl.api.LabelOption.Builder lines(@NotNull Collection<? extends Component> lines); + + LabelOption build(); + } +} diff --git a/common/src/main/java/dev/isxander/yacl/api/ListOption.java b/common/src/main/java/dev/isxander/yacl/api/ListOption.java new file mode 100644 index 0000000..afba8ee --- /dev/null +++ b/common/src/main/java/dev/isxander/yacl/api/ListOption.java @@ -0,0 +1,152 @@ +package dev.isxander.yacl.api; + +import com.google.common.collect.ImmutableList; +import dev.isxander.yacl.impl.ListOptionImpl; +import net.minecraft.network.chat.Component; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; + +import java.util.*; +import java.util.function.BiConsumer; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Supplier; + +/** + * A list option that takes form as an option group for UX. + * You add this option through {@link ConfigCategory.Builder#group(OptionGroup)}. Do NOT add as an option. + * Users can add remove and reshuffle a list type. You can use any controller you wish, there are no dedicated + * controllers for list types. List options do not manipulate your list but get and set the list with a + * regular binding for simplicity. + * + * You may apply option flags like a normal option and collapse like a normal group, it is a merge of them both. + * Methods in this interface marked with {@link ApiStatus.Internal} should not be used, and could be subject to + * change at any time + * @param <T> |
