diff options
-rw-r--r-- | README.md | 2 | ||||
-rw-r--r-- | build.gradle.kts | 26 | ||||
-rw-r--r-- | changelogs/2.0.0.md | 7 | ||||
-rw-r--r-- | gradle.properties | 5 | ||||
-rw-r--r-- | src/client/java/dev/isxander/yacl/api/Binding.java (renamed from src/main/java/dev/isxander/yacl/api/Binding.java) | 2 | ||||
-rw-r--r-- | src/client/java/dev/isxander/yacl/api/ButtonOption.java (renamed from src/main/java/dev/isxander/yacl/api/ButtonOption.java) | 0 | ||||
-rw-r--r-- | src/client/java/dev/isxander/yacl/api/ConfigCategory.java (renamed from src/main/java/dev/isxander/yacl/api/ConfigCategory.java) | 1 | ||||
-rw-r--r-- | src/client/java/dev/isxander/yacl/api/Controller.java (renamed from src/main/java/dev/isxander/yacl/api/Controller.java) | 0 | ||||
-rw-r--r-- | src/client/java/dev/isxander/yacl/api/NameableEnum.java (renamed from src/main/java/dev/isxander/yacl/api/NameableEnum.java) | 0 | ||||
-rw-r--r-- | src/client/java/dev/isxander/yacl/api/Option.java (renamed from src/main/java/dev/isxander/yacl/api/Option.java) | 0 | ||||
-rw-r--r-- | src/client/java/dev/isxander/yacl/api/OptionFlag.java (renamed from src/main/java/dev/isxander/yacl/api/OptionFlag.java) | 8 | ||||
-rw-r--r-- | src/client/java/dev/isxander/yacl/api/OptionGroup.java (renamed from src/main/java/dev/isxander/yacl/api/OptionGroup.java) | 0 | ||||
-rw-r--r-- | src/client/java/dev/isxander/yacl/api/PlaceholderCategory.java (renamed from src/main/java/dev/isxander/yacl/api/PlaceholderCategory.java) | 0 | ||||
-rw-r--r-- | src/client/java/dev/isxander/yacl/api/YetAnotherConfigLib.java (renamed from src/main/java/dev/isxander/yacl/api/YetAnotherConfigLib.java) | 15 | ||||
-rw-r--r-- | src/client/java/dev/isxander/yacl/api/utils/OptionUtils.java (renamed from src/main/java/dev/isxander/yacl/api/utils/OptionUtils.java) | 0 | ||||
-rw-r--r-- | src/client/java/dev/isxander/yacl/gui/AbstractWidget.java (renamed from src/main/java/dev/isxander/yacl/gui/AbstractWidget.java) | 10 | ||||
-rw-r--r-- | src/client/java/dev/isxander/yacl/gui/CategoryListWidget.java (renamed from src/main/java/dev/isxander/yacl/gui/CategoryListWidget.java) | 22 | ||||
-rw-r--r-- | src/client/java/dev/isxander/yacl/gui/CategoryWidget.java (renamed from src/main/java/dev/isxander/yacl/gui/CategoryWidget.java) | 0 | ||||
-rw-r--r-- | src/client/java/dev/isxander/yacl/gui/ElementListWidgetExt.java | 152 | ||||
-rw-r--r-- | src/client/java/dev/isxander/yacl/gui/LowProfileButtonWidget.java (renamed from src/main/java/dev/isxander/yacl/gui/LowProfileButtonWidget.java) | 10 | ||||
-rw-r--r-- | src/client/java/dev/isxander/yacl/gui/OptionListWidget.java (renamed from src/main/java/dev/isxander/yacl/gui/OptionListWidget.java) | 133 | ||||
-rw-r--r-- | src/client/java/dev/isxander/yacl/gui/RequireRestartScreen.java (renamed from src/main/java/dev/isxander/yacl/gui/RequireRestartScreen.java) | 0 | ||||
-rw-r--r-- | src/client/java/dev/isxander/yacl/gui/SearchFieldWidget.java (renamed from src/main/java/dev/isxander/yacl/gui/SearchFieldWidget.java) | 2 | ||||
-rw-r--r-- | src/client/java/dev/isxander/yacl/gui/TextScaledButtonWidget.java (renamed from src/main/java/dev/isxander/yacl/gui/TextScaledButtonWidget.java) | 11 | ||||
-rw-r--r-- | src/client/java/dev/isxander/yacl/gui/TooltipButtonWidget.java (renamed from src/main/java/dev/isxander/yacl/gui/TooltipButtonWidget.java) | 4 | ||||
-rw-r--r-- | src/client/java/dev/isxander/yacl/gui/YACLScreen.java (renamed from src/main/java/dev/isxander/yacl/gui/YACLScreen.java) | 39 | ||||
-rw-r--r-- | src/client/java/dev/isxander/yacl/gui/controllers/ActionController.java (renamed from src/main/java/dev/isxander/yacl/gui/controllers/ActionController.java) | 4 | ||||
-rw-r--r-- | src/client/java/dev/isxander/yacl/gui/controllers/BooleanController.java (renamed from src/main/java/dev/isxander/yacl/gui/controllers/BooleanController.java) | 14 | ||||
-rw-r--r-- | src/client/java/dev/isxander/yacl/gui/controllers/ColorController.java (renamed from src/main/java/dev/isxander/yacl/gui/controllers/ColorController.java) | 27 | ||||
-rw-r--r-- | src/client/java/dev/isxander/yacl/gui/controllers/ControllerWidget.java (renamed from src/main/java/dev/isxander/yacl/gui/controllers/ControllerWidget.java) | 4 | ||||
-rw-r--r-- | src/client/java/dev/isxander/yacl/gui/controllers/LabelController.java (renamed from src/main/java/dev/isxander/yacl/gui/controllers/LabelController.java) | 0 | ||||
-rw-r--r-- | src/client/java/dev/isxander/yacl/gui/controllers/TickBoxController.java (renamed from src/main/java/dev/isxander/yacl/gui/controllers/TickBoxController.java) | 11 | ||||
-rw-r--r-- | src/client/java/dev/isxander/yacl/gui/controllers/cycling/CyclingControllerElement.java (renamed from src/main/java/dev/isxander/yacl/gui/controllers/cycling/CyclingControllerElement.java) | 8 | ||||
-rw-r--r-- | src/client/java/dev/isxander/yacl/gui/controllers/cycling/CyclingListController.java (renamed from src/main/java/dev/isxander/yacl/gui/controllers/cycling/CyclingListController.java) | 0 | ||||
-rw-r--r-- | src/client/java/dev/isxander/yacl/gui/controllers/cycling/EnumController.java (renamed from src/main/java/dev/isxander/yacl/gui/controllers/cycling/EnumController.java) | 0 | ||||
-rw-r--r-- | src/client/java/dev/isxander/yacl/gui/controllers/cycling/ICyclingController.java (renamed from src/main/java/dev/isxander/yacl/gui/controllers/cycling/ICyclingController.java) | 0 | ||||
-rw-r--r-- | src/client/java/dev/isxander/yacl/gui/controllers/package-info.java (renamed from src/main/java/dev/isxander/yacl/gui/controllers/package-info.java) | 0 | ||||
-rw-r--r-- | src/client/java/dev/isxander/yacl/gui/controllers/slider/DoubleSliderController.java (renamed from src/main/java/dev/isxander/yacl/gui/controllers/slider/DoubleSliderController.java) | 2 | ||||
-rw-r--r-- | src/client/java/dev/isxander/yacl/gui/controllers/slider/FloatSliderController.java (renamed from src/main/java/dev/isxander/yacl/gui/controllers/slider/FloatSliderController.java) | 2 | ||||
-rw-r--r-- | src/client/java/dev/isxander/yacl/gui/controllers/slider/ISliderController.java (renamed from src/main/java/dev/isxander/yacl/gui/controllers/slider/ISliderController.java) | 0 | ||||
-rw-r--r-- | src/client/java/dev/isxander/yacl/gui/controllers/slider/IntegerSliderController.java (renamed from src/main/java/dev/isxander/yacl/gui/controllers/slider/IntegerSliderController.java) | 2 | ||||
-rw-r--r-- | src/client/java/dev/isxander/yacl/gui/controllers/slider/LongSliderController.java (renamed from src/main/java/dev/isxander/yacl/gui/controllers/slider/LongSliderController.java) | 2 | ||||
-rw-r--r-- | src/client/java/dev/isxander/yacl/gui/controllers/slider/SliderControllerElement.java (renamed from src/main/java/dev/isxander/yacl/gui/controllers/slider/SliderControllerElement.java) | 6 | ||||
-rw-r--r-- | src/client/java/dev/isxander/yacl/gui/controllers/slider/package-info.java (renamed from src/main/java/dev/isxander/yacl/gui/controllers/slider/package-info.java) | 0 | ||||
-rw-r--r-- | src/client/java/dev/isxander/yacl/gui/controllers/string/IStringController.java (renamed from src/main/java/dev/isxander/yacl/gui/controllers/string/IStringController.java) | 12 | ||||
-rw-r--r-- | src/client/java/dev/isxander/yacl/gui/controllers/string/StringController.java (renamed from src/main/java/dev/isxander/yacl/gui/controllers/string/StringController.java) | 5 | ||||
-rw-r--r-- | src/client/java/dev/isxander/yacl/gui/controllers/string/StringControllerElement.java (renamed from src/main/java/dev/isxander/yacl/gui/controllers/string/StringControllerElement.java) | 117 | ||||
-rw-r--r-- | src/client/java/dev/isxander/yacl/gui/controllers/string/number/DoubleFieldController.java | 105 | ||||
-rw-r--r-- | src/client/java/dev/isxander/yacl/gui/controllers/string/number/FloatFieldController.java | 105 | ||||
-rw-r--r-- | src/client/java/dev/isxander/yacl/gui/controllers/string/number/IntegerFieldController.java | 109 | ||||
-rw-r--r-- | src/client/java/dev/isxander/yacl/gui/controllers/string/number/LongFieldController.java | 109 | ||||
-rw-r--r-- | src/client/java/dev/isxander/yacl/gui/controllers/string/number/NumberFieldController.java | 69 | ||||
-rw-r--r-- | src/client/java/dev/isxander/yacl/gui/controllers/string/number/package-info.java | 10 | ||||
-rw-r--r-- | src/client/java/dev/isxander/yacl/impl/ButtonOptionImpl.java (renamed from src/main/java/dev/isxander/yacl/impl/ButtonOptionImpl.java) | 0 | ||||
-rw-r--r-- | src/client/java/dev/isxander/yacl/impl/ConfigCategoryImpl.java (renamed from src/main/java/dev/isxander/yacl/impl/ConfigCategoryImpl.java) | 0 | ||||
-rw-r--r-- | src/client/java/dev/isxander/yacl/impl/GenericBindingImpl.java (renamed from src/main/java/dev/isxander/yacl/impl/GenericBindingImpl.java) | 0 | ||||
-rw-r--r-- | src/client/java/dev/isxander/yacl/impl/OptionGroupImpl.java (renamed from src/main/java/dev/isxander/yacl/impl/OptionGroupImpl.java) | 0 | ||||
-rw-r--r-- | src/client/java/dev/isxander/yacl/impl/OptionImpl.java (renamed from src/main/java/dev/isxander/yacl/impl/OptionImpl.java) | 1 | ||||
-rw-r--r-- | src/client/java/dev/isxander/yacl/impl/PlaceholderCategoryImpl.java (renamed from src/main/java/dev/isxander/yacl/impl/PlaceholderCategoryImpl.java) | 0 | ||||
-rw-r--r-- | src/client/java/dev/isxander/yacl/impl/YetAnotherConfigLibImpl.java (renamed from src/main/java/dev/isxander/yacl/impl/YetAnotherConfigLibImpl.java) | 0 | ||||
-rw-r--r-- | src/client/java/dev/isxander/yacl/mixin/client/SimpleOptionAccessor.java (renamed from src/main/java/dev/isxander/yacl/mixin/SimpleOptionAccessor.java) | 2 | ||||
-rw-r--r-- | src/client/resources/yet-another-config-lib.client.mixins.json (renamed from src/main/resources/yet-another-config-lib.mixins.json) | 2 | ||||
-rw-r--r-- | src/main/java/dev/isxander/yacl/config/ConfigInstance.java | 14 | ||||
-rw-r--r-- | src/main/java/dev/isxander/yacl/gui/controllers/EnumController.java | 35 | ||||
-rw-r--r-- | src/main/resources/fabric.mod.json | 12 | ||||
-rw-r--r-- | src/testmod/java/dev/isxander/yacl/test/GuiTest.java (renamed from src/testmod/java/dev/isxander/yacl/test/ModMenuIntegration.java) | 191 | ||||
-rw-r--r-- | src/testmod/java/dev/isxander/yacl/test/config/ConfigData.java | 4 | ||||
-rw-r--r-- | src/testmod/java/dev/isxander/yacl/test/config/Entrypoint.java | 3 | ||||
-rw-r--r-- | src/testmod/java/dev/isxander/yacl/test/mixins/TitleScreenMixin.java | 26 | ||||
-rw-r--r-- | src/testmod/resources/fabric.mod.json | 13 | ||||
-rw-r--r-- | src/testmod/resources/yet-another-config-lib.test.mixins.json | 11 |
71 files changed, 1085 insertions, 401 deletions
@@ -23,7 +23,7 @@ Yet Another Config Lib, like, what were you expecting? This mod was made to fill a hole in this area of Fabric modding. The existing main config libraries don't achieve what I want from them: -- **[Cloth Config API](https://modrinth.com/mod/cloth-config)**:<br/>**It's stale.** The developer of cloth has clarified that they are likely not going to add any more features. They don't want to touch it. +- **[Cloth Config API](https://modrinth.com/mod/cloth-config)**:<br/>**It's stale.** The developer of cloth has clarified that they are likely not going to add any more features. They don't want to touch it. ([citation](https://user-images.githubusercontent.com/43245524/206530322-3ae46008-5356-468e-9a73-63b859364d4e.png)) - **[SpruceUI](https://github.com/LambdAurora/SpruceUI)**:<br/>**It isn't designed for configuration.** In this essence the design feels cluttered. Further details available in [this issue](https://github.com/isXander/Zoomify/issues/85). - **[MidnightLib](https://modrinth.com/mod/midnightlib)**:<br/>**It has cosmetics among other utilities.** It may not be large but some players (including me) wouldn't want cosmetics out of nowhere. - **[OwoLib](https://modrinth.com/mod/owo-lib)**:<br/>**It's content focused.** It does a lot of other things as well as config, adding to the size. diff --git a/build.gradle.kts b/build.gradle.kts index 6655cbb..7fa93c3 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -2,7 +2,7 @@ plugins { java id("fabric-loom") version "1.0.+" - id("io.github.juuxel.loom-quiltflower") version "1.7.+" + id("io.github.juuxel.loom-quiltflower") version "1.8.+" id("com.modrinth.minotaur") version "2.4.+" id("me.hypherionmc.cursegradle") version "2.+" @@ -16,14 +16,27 @@ plugins { val ciRun = System.getenv().containsKey("GITHUB_ACTIONS") group = "dev.isxander" -version = "1.7.1" +version = "2.0.0" if (ciRun) version = "$version+${grgit.branch.current().name}-SNAPSHOT" +loom { + splitEnvironmentSourceSets() + + mods { + register("yet-another-config-lib") { + sourceSet(sourceSets["main"]) + sourceSet(sourceSets["client"]) + } + } +} + val testmod by sourceSets.registering { compileClasspath += sourceSets.main.get().compileClasspath runtimeClasspath += sourceSets.main.get().runtimeClasspath + compileClasspath += sourceSets["client"].compileClasspath + runtimeClasspath += sourceSets["client"].runtimeClasspath } loom { @@ -48,18 +61,17 @@ repositories { val minecraftVersion: String by project val fabricLoaderVersion: String by project +val yarnBuild: String by project dependencies { minecraft("com.mojang:minecraft:$minecraftVersion") - mappings("net.fabricmc:yarn:$minecraftVersion+build.+:v2") + mappings("net.fabricmc:yarn:$minecraftVersion+build.$yarnBuild:v2") modImplementation("net.fabricmc:fabric-loader:$fabricLoaderVersion") - modImplementation(fabricApi.module("fabric-resource-loader-v0", "0.66.0+1.19.2")) + "modClientImplementation"(fabricApi.module("fabric-resource-loader-v0", "0.68.1+1.19.3")) "testmodImplementation"(sourceSets.main.get().output) - "modTestmodImplementation"("com.terraformersmc:modmenu:4.0.6") { - exclude(module = "fabric-loader") - } + "testmodImplementation"(sourceSets["client"].output) } java { diff --git a/changelogs/2.0.0.md b/changelogs/2.0.0.md new file mode 100644 index 0000000..b56d0b1 --- /dev/null +++ b/changelogs/2.0.0.md @@ -0,0 +1,7 @@ +- Update to 1.19.3 +- Colour field controllers +- Better carot positioning when clicking in text fields +- Better text selection for text fields +- Smooth scrolling for category list +- Fix category list scrollbar appearing under option list background in-game +- Fix tick box name text length limiting diff --git a/gradle.properties b/gradle.properties index 0f0b15f..292f0c1 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,8 @@ org.gradle.jvmargs=-Xmx3G -minecraftVersion=1.19.2 -fabricLoaderVersion=0.14.10 +minecraftVersion=1.19.3 +fabricLoaderVersion=0.14.11 +yarnBuild=1 modId=yet-another-config-lib modName=YetAnotherConfigLib diff --git a/src/main/java/dev/isxander/yacl/api/Binding.java b/src/client/java/dev/isxander/yacl/api/Binding.java index 395beb2..91158d3 100644 --- a/src/main/java/dev/isxander/yacl/api/Binding.java +++ b/src/client/java/dev/isxander/yacl/api/Binding.java @@ -1,7 +1,7 @@ package dev.isxander.yacl.api; import dev.isxander.yacl.impl.GenericBindingImpl; -import dev.isxander.yacl.mixin.SimpleOptionAccessor; +import dev.isxander.yacl.mixin.client.SimpleOptionAccessor; import net.minecraft.client.option.SimpleOption; import org.apache.commons.lang3.Validate; diff --git a/src/main/java/dev/isxander/yacl/api/ButtonOption.java b/src/client/java/dev/isxander/yacl/api/ButtonOption.java index 1124a9a..1124a9a 100644 --- a/src/main/java/dev/isxander/yacl/api/ButtonOption.java +++ b/src/client/java/dev/isxander/yacl/api/ButtonOption.java diff --git a/src/main/java/dev/isxander/yacl/api/ConfigCategory.java b/src/client/java/dev/isxander/yacl/api/ConfigCategory.java index 27c3e95..e9755dd 100644 --- a/src/main/java/dev/isxander/yacl/api/ConfigCategory.java +++ b/src/client/java/dev/isxander/yacl/api/ConfigCategory.java @@ -11,7 +11,6 @@ import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.Collection; import java.util.List; -import java.util.function.Function; /** * Separates {@link Option}s or {@link OptionGroup}s into multiple distinct sections. diff --git a/src/main/java/dev/isxander/yacl/api/Controller.java b/src/client/java/dev/isxander/yacl/api/Controller.java index 7bf7e7f..7bf7e7f 100644 --- a/src/main/java/dev/isxander/yacl/api/Controller.java +++ b/src/client/java/dev/isxander/yacl/api/Controller.java diff --git a/src/main/java/dev/isxander/yacl/api/NameableEnum.java b/src/client/java/dev/isxander/yacl/api/NameableEnum.java index 793b230..793b230 100644 --- a/src/main/java/dev/isxander/yacl/api/NameableEnum.java +++ b/src/client/java/dev/isxander/yacl/api/NameableEnum.java diff --git a/src/main/java/dev/isxander/yacl/api/Option.java b/src/client/java/dev/isxander/yacl/api/Option.java index 772c816..772c816 100644 --- a/src/main/java/dev/isxander/yacl/api/Option.java +++ b/src/client/java/dev/isxander/yacl/api/Option.java diff --git a/src/main/java/dev/isxander/yacl/api/OptionFlag.java b/src/client/java/dev/isxander/yacl/api/OptionFlag.java index 203a674..7a5c23f 100644 --- a/src/main/java/dev/isxander/yacl/api/OptionFlag.java +++ b/src/client/java/dev/isxander/yacl/api/OptionFlag.java @@ -11,14 +11,10 @@ import java.util.function.Consumer; */ @FunctionalInterface public interface OptionFlag extends Consumer<MinecraftClient> { - /** - * Warns the user that a game restart is required for the changes to take effect - */ + /** Warns the user that a game restart is required for the changes to take effect */ OptionFlag GAME_RESTART = client -> client.setScreen(new RequireRestartScreen(client.currentScreen)); - /** - * Reloads chunks upon applying (F3+A) - */ + /** Reloads chunks upon applying (F3+A) */ OptionFlag RELOAD_CHUNKS = client -> client.worldRenderer.reload(); OptionFlag WORLD_RENDER_UPDATE = client -> client.worldRenderer.scheduleTerrainUpdate(); diff --git a/src/main/java/dev/isxander/yacl/api/OptionGroup.java b/src/client/java/dev/isxander/yacl/api/OptionGroup.java index 3364bdf..3364bdf 100644 --- a/src/main/java/dev/isxander/yacl/api/OptionGroup.java +++ b/src/client/java/dev/isxander/yacl/api/OptionGroup.java diff --git a/src/main/java/dev/isxander/yacl/api/PlaceholderCategory.java b/src/client/java/dev/isxander/yacl/api/PlaceholderCategory.java index de7441c..de7441c 100644 --- a/src/main/java/dev/isxander/yacl/api/PlaceholderCategory.java +++ b/src/client/java/dev/isxander/yacl/api/PlaceholderCategory.java diff --git a/src/main/java/dev/isxander/yacl/api/YetAnotherConfigLib.java b/src/client/java/dev/isxander/yacl/api/YetAnotherConfigLib.java index a69ae4e..ae6c060 100644 --- a/src/main/java/dev/isxander/yacl/api/YetAnotherConfigLib.java +++ b/src/client/java/dev/isxander/yacl/api/YetAnotherConfigLib.java @@ -1,6 +1,7 @@ package dev.isxander.yacl.api; import com.google.common.collect.ImmutableList; +import dev.isxander.yacl.config.ConfigInstance; import dev.isxander.yacl.gui.YACLScreen; import dev.isxander.yacl.impl.YetAnotherConfigLibImpl; import net.minecraft.client.gui.screen.Screen; @@ -12,6 +13,7 @@ import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.function.BiFunction; import java.util.function.Consumer; /** @@ -53,6 +55,14 @@ public interface YetAnotherConfigLib { return new Builder(); } + /** + * Creates an instance using a {@link ConfigInstance} which autofills the save() builder method. + * This also takes an easy functional interface that provides defaults and config to help build YACL bindings. + */ + static <T> YetAnotherConfigLib create(ConfigInstance<T> configInstance, ConfigBackedBuilder<T> builder) { + return builder.build(configInstance.getDefaults(), configInstance.getConfig(), createBuilder().save(configInstance::save)).build(); + } + class Builder { private Text title; private final List<ConfigCategory> categories = new ArrayList<>(); @@ -133,4 +143,9 @@ public interface YetAnotherConfigLib { return new YetAnotherConfigLibImpl(title, ImmutableList.copyOf(categories), saveFunction, initConsumer); } } + + @FunctionalInterface + interface ConfigBackedBuilder<T> { + YetAnotherConfigLib.Builder build(T defaults, T config, YetAnotherConfigLib.Builder builder); + } } diff --git a/src/main/java/dev/isxander/yacl/api/utils/OptionUtils.java b/src/client/java/dev/isxander/yacl/api/utils/OptionUtils.java index ab46b5b..ab46b5b 100644 --- a/src/main/java/dev/isxander/yacl/api/utils/OptionUtils.java +++ b/src/client/java/dev/isxander/yacl/api/utils/OptionUtils.java diff --git a/src/main/java/dev/isxander/yacl/gui/AbstractWidget.java b/src/client/java/dev/isxander/yacl/gui/AbstractWidget.java index 03dc9b9..529748d 100644 --- a/src/main/java/dev/isxander/yacl/gui/AbstractWidget.java +++ b/src/client/java/dev/isxander/yacl/gui/AbstractWidget.java @@ -15,7 +15,7 @@ import net.minecraft.client.sound.PositionedSoundInstance; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.sound.SoundEvents; -import java.awt.*; +import java.awt.Color; public abstract class AbstractWidget implements Element, Drawable, Selectable { protected final MinecraftClient client = MinecraftClient.getInstance(); @@ -82,7 +82,7 @@ public abstract class AbstractWidget implements Element, Drawable, Selectable { int width = x2 - x1; int height = y2 - y1; - RenderSystem.setShader(GameRenderer::getPositionTexShader); + RenderSystem.setShader(GameRenderer::getPositionTexProgram); RenderSystem.setShaderTexture(0, ClickableWidget.WIDGETS_TEXTURE); RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); int i = !enabled ? 0 : hovered ? 2 : 1; @@ -96,9 +96,9 @@ public abstract class AbstractWidget implements Element, Drawable, Selectable { protected int multiplyColor(int hex, float amount) { Color color = new Color(hex, true); - return new Color(Math.max((int)(color.getRed() *amount), 0), - Math.max((int)(color.getGreen()*amount), 0), - Math.max((int)(color.getBlue() *amount), 0), + return new Color(Math.max((int)(color.getRed() * amount), 0), + Math.max((int)(color.getGreen() * amount), 0), + Math.max((int)(color.getBlue() * amount), 0), color.getAlpha()).getRGB(); } diff --git a/src/main/java/dev/isxander/yacl/gui/CategoryListWidget.java b/src/client/java/dev/isxander/yacl/gui/CategoryListWidget.java index 2cb6bb6..4dbcb11 100644 --- a/src/main/java/dev/isxander/yacl/gui/CategoryListWidget.java +++ b/src/client/java/dev/isxander/yacl/gui/CategoryListWidget.java @@ -11,11 +11,11 @@ import net.minecraft.client.util.math.MatrixStack; import java.util.List; -public class CategoryListWidget extends ElementListWidget<CategoryListWidget.CategoryEntry> { +public class CategoryListWidget extends ElementListWidgetExt<CategoryListWidget.CategoryEntry> { private final YACLScreen yaclScreen; public CategoryListWidget(MinecraftClient client, YACLScreen yaclScreen, int screenWidth, int screenHeight) { - super(client, screenWidth / 3, yaclScreen.searchFieldWidget.y - 5, 0, yaclScreen.searchFieldWidget.y - 5, 21); + super(client, 0, 0, screenWidth / 3, yaclScreen.searchFieldWidget.getY() - 5, true); this.yaclScreen = yaclScreen; setRenderBackground(false); setRenderHorizontalShadows(false); @@ -26,10 +26,10 @@ public class CategoryListWidget extends ElementListWidget<CategoryListWidget.Cat } @Override - protected void renderList(MatrixStack matrices, int mouseX, int mouseY, float delta) { + public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) { double d = this.client.getWindow().getScaleFactor(); RenderSystem.enableScissor(0, (int)((yaclScreen.height - bottom) * d), (int)(width * d), (int)(height * d)); - super.renderList(matrices, mouseX, mouseY, delta); + super.render(matrices, mouseX, mouseY, delta); RenderSystem.disableScissor(); } @@ -54,6 +54,11 @@ public class CategoryListWidget extends ElementListWidget<CategoryListWidget.Cat return width - 2; } + @Override + protected void renderBackground(MatrixStack matrices) { + + } + public class CategoryEntry extends Entry<CategoryEntry> { private final CategoryWidget categoryButton; public final int categoryIndex; @@ -75,15 +80,20 @@ public class CategoryListWidget extends ElementListWidget<CategoryListWidget.Cat mouseY = -20; } - categoryButton.y = y; + categoryButton.setY(y); categoryButton.render(matrices, mouseX, mouseY, tickDelta); } - private void postRender(MatrixStack matrices, int mouseX, int mouseY, float tickDelta) { + public void postRender(MatrixStack matrices, int mouseX, int mouseY, float tickDelta) { categoryButton.renderHoveredTooltip(matrices); } @Override + public int getItemHeight() { + return 21; + } + + @Override public List<? extends Element> children() { return ImmutableList.of(categoryButton); } diff --git a/src/main/java/dev/isxander/yacl/gui/CategoryWidget.java b/src/client/java/dev/isxander/yacl/gui/CategoryWidget.java index 3c5d8d2..3c5d8d2 100644 --- a/src/main/java/dev/isxander/yacl/gui/CategoryWidget.java +++ b/src/client/java/dev/isxander/yacl/gui/CategoryWidget.java diff --git a/src/client/java/dev/isxander/yacl/gui/ElementListWidgetExt.java b/src/client/java/dev/isxander/yacl/gui/ElementListWidgetExt.java new file mode 100644 index 0000000..f2a19f2 --- /dev/null +++ b/src/client/java/dev/isxander/yacl/gui/ElementListWidgetExt.java @@ -0,0 +1,152 @@ +package dev.isxander.yacl.gui; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.widget.ElementListWidget; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.util.math.MathHelper; +import org.jetbrains.annotations.Nullable; + +public class ElementListWidgetExt<E extends ElementListWidgetExt.Entry<E>> extends ElementListWidget<E> { + protected final int x, y; + + private double smoothScrollAmount = getScrollAmount(); + private boolean returnSmoothAmount = false; + private final boolean doSmoothScrolling; + + public ElementListWidgetExt(MinecraftClient client, int x, int y, int width, int height, boolean smoothScrolling) { + super(client, width, height, y, y + height, 22); + this.x = x; + this.y = y; + this.left = x; + this.right = this.left + width; + this.doSmoothScrolling = smoothScrolling; + } + + @Override + public boolean mouseScrolled(double mouseX, double mouseY, double amount) { + // default implementation bases scroll step from total height of entries, this is constant + this.setScrollAmount(this.getScrollAmount() - amount * 20); + return true; + } + + @Override + protected void renderBackground(MatrixStack matrices) { + // render transparent background if in-game. + setRenderBackground(client.world == null); + if (client.world != null) + fill(matrices, left, top, right, bottom, 0x6B000000); + } + + @Override + protected int getScrollbarPositionX() { + // default implementation does not respect left/right + return this.right - 2; + } + + @Override + public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) { + smoothScrollAmount = MathHelper.lerp(MinecraftClient.getInstance().getLastFrameDuration() * 0.5, smoothScrollAmount, getScrollAmount()); + returnSmoothAmount = true; + super.render(matrices, mouseX, mouseY, delta); + returnSmoothAmount = false; + } + + /** + * awful code to only use smooth scroll state when rendering, + * not other code that needs target scroll amount + */ + @Override + public double getScrollAmount() { + if (returnSmoothAmount && doSmoothScrolling) + return smoothScrollAmount; + + return super.getScrollAmount(); + } + + protected void resetSmoothScrolling() { + this.smoothScrollAmount = getScrollAmount(); + } + + public void postRender(MatrixStack matrices, int mouseX, int mouseY, float delta) { + for (E entry : children()) { + entry.postRender(matrices, mouseX, mouseY, delta); + } + } + + /* + below code is licensed from cloth-config under LGPL3 + modified to inherit vanilla's EntryListWidget and use yarn mappings + + code is responsible for having dynamic item heights + */ + + @Nullable + @Override + protected E getEntryAtPosition(double x, double y) { + int listMiddleX = this.left + this.width / 2; + int minX = listMiddleX - this.getRowWidth() / 2; + int maxX = listMiddleX + this.getRowWidth() / 2; + int currentY = MathHelper.floor(y - (double) this.top) - this.headerHeight + (int) this.getScrollAmount() - 4; + int itemY = 0; + int itemIndex = -1; + for (int i = 0; i < children().size(); i++) { + E item = children().get(i); + itemY += item.getItemHeight(); + if (itemY > currentY) { + itemIndex = i; + break; + } + } + return x < (double) this.getScrollbarPositionX() && x >= minX && y <= maxX && itemIndex >= 0 && currentY >= 0 && itemIndex < this.getEntryCount() ? this.children().get(itemIndex) : null; + } + + @Override + protected int getMaxPosition() { + return children().stream().map(E::getItemHeight).reduce(0, Integer::sum) + headerHeight; + } + + @Override + protected void centerScrollOn(E entry) { + double d = (this.bottom - this.top) / -2d; + for (int i = 0; i < this.children().indexOf(entry) && i < this.getEntryCount(); i++) + d += children().get(i).getItemHeight(); + this.setScrollAmount(d); + } + + @Override + protected int getRowTop(int index) { + int integer = top + 4 - (int) this.getScrollAmount() + headerHeight; + for (int i = 0; i < children().size() && i < index; i++) + integer += children().get(i).getItemHeight(); + return integer; + } + + @Override + protected void renderList(MatrixStack matrices, int mouseX, int mouseY, float delta) { + int left = this.getRowLeft(); + int right = this.getRowWidth(); + int count = this.getEntryCount(); + + for(int i = 0; i < count; ++i) { + E entry = children().get(i); + int top = this.getRowTop(i); + int bottom = top + entry.getItemHeight(); + int entryHeight = entry.getItemHeight() - 4; + if (bottom >= this.top && top <= this.bottom) { + this.renderEntry(matrices, mouseX, mouseY, delta, i, left, top, right, entryHeight); + } + } + } + + /* END cloth config code */ + + public abstract static class Entry<E extends ElementListWidgetExt.Entry<E>> extends ElementListWidget.Entry<E> { + public void postRender(MatrixStack matrices, int mouseX, int mouseY, float delta) { + + } + + public int getItemHeight() { + return 22; + } + } +} diff --git a/src/main/java/dev/isxander/yacl/gui/LowProfileButtonWidget.java b/src/client/java/dev/isxander/yacl/gui/LowProfileButtonWidget.java index 240cfb2..9fa01a7 100644 --- a/src/main/java/dev/isxander/yacl/gui/LowProfileButtonWidget.java +++ b/src/client/java/dev/isxander/yacl/gui/LowProfileButtonWidget.java @@ -1,6 +1,7 @@ package dev.isxander.yacl.gui; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.tooltip.Tooltip; import net.minecraft.client.gui.widget.ButtonWidget; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.text.Text; @@ -8,18 +9,19 @@ import net.minecraft.util.math.MathHelper; public class LowProfileButtonWidget extends ButtonWidget { public LowProfileButtonWidget(int x, int y, int width, int height, Text message, PressAction onPress) { - super(x, y, width, height, message, onPress); + super(x, y, width, height, message, onPress, DEFAULT_NARRATION_SUPPLIER); } - public LowProfileButtonWidget(int x, int y, int width, int height, Text message, PressAction onPress, TooltipSupplier tooltipSupplier) { - super(x, y, width, height, message, onPress, tooltipSupplier); + public LowProfileButtonWidget(int x, int y, int width, int height, Text message, PressAction onPress, Tooltip tooltip) { + this(x, y, width, height, message, onPress); + setTooltip(tooltip); } @Override public void renderButton(MatrixStack matrices, int mouseX, int mouseY, float delta) { if (!isHovered()) { int j = this.active ? 0xFFFFFF : 0xA0A0A0; - drawCenteredText(matrices, MinecraftClient.getInstance().textRenderer, this.getMessage(), this.x + this.width / 2, this.y + (this.height - 8) / 2, j | MathHelper.ceil(this.alpha * 255.0F) << 24); + drawCenteredText(matrices, MinecraftClient.getInstance().textRenderer, this.getMessage(), this.getX() + this.width / 2, this.getY() + (this.height - 8) / 2, j | MathHelper.ceil(this.alpha * 255.0F) << 24); } else { super.renderButton(matrices, mouseX, mouseY, delta); } diff --git a/src/main/java/dev/isxander/yacl/gui/OptionListWidget.java b/src/client/java/dev/isxander/yacl/gui/OptionListWidget.java index cf50a58..7ea275b 100644 --- a/src/main/java/dev/isxander/yacl/gui/OptionListWidget.java +++ b/src/client/java/dev/isxander/yacl/gui/OptionListWidget.java @@ -22,20 +22,15 @@ import org.jetbrains.annotations.Nullable; import java.util.*; import java.util.function.Supplier; -public class OptionListWidget extends ElementListWidget<OptionListWidget.Entry> { +public class OptionListWidget extends ElementListWidgetExt<OptionListWidget.Entry> { private final YACLScreen yaclScreen; private boolean singleCategory = false; private ImmutableList<Entry> viewableChildren; - private double smoothScrollAmount = getScrollAmount(); - private boolean returnSmoothAmount = false; - public OptionListWidget(YACLScreen screen, MinecraftClient client, int width, int height) { - super(client, width / 3 * 2, height, 0, height, 22); + super(client, width / 3, 0, width / 3 * 2, height, true); this.yaclScreen = screen; - left = width - this.width; - right = width; refreshOptions(); } @@ -78,6 +73,7 @@ public class OptionListWidget extends ElementListWidget<OptionListWidget.Entry> recacheViewableChildren(); setScrollAmount(0); + resetSmoothScrolling(); } public void expandAllGroups() { @@ -88,97 +84,6 @@ public class OptionListWidget extends ElementListWidget<OptionListWidget.Entry> } } - /* - below code is licensed from cloth-config under LGPL3 - modified to inherit vanilla's EntryListWidget and use yarn mappings - */ - - @Nullable - @Override - protected Entry getEntryAtPosition(double x, double y) { - int listMiddleX = this.left + this.width / 2; - int minX = listMiddleX - this.getRowWidth() / 2; - int maxX = listMiddleX + this.getRowWidth() / 2; - int currentY = MathHelper.floor(y - (double) this.top) - this.headerHeight + (int) this.getScrollAmount() - 4; - int itemY = 0; - int itemIndex = -1; - for (int i = 0; i < children().size(); i++) { - Entry item = children().get(i); - itemY += item.getItemHeight(); - if (itemY > currentY) { - itemIndex = i; - break; - } - } - return x < (double) this.getScrollbarPositionX() && x >= minX && y <= maxX && itemIndex >= 0 && currentY >= 0 && itemIndex < this.getEntryCount() ? this.children().get(itemIndex) : null; - } - - @Override - protected int getMaxPosition() { - return children().stream().map(Entry::getItemHeight).reduce(0, Integer::sum) + headerHeight; - } - - @Override - protected void centerScrollOn(Entry entry) { - double d = (this.bottom - this.top) / -2d; - for (int i = 0; i < this.children().indexOf(entry) && i < this.getEntryCount(); i++) - d += children().get(i).getItemHeight(); - this.setScrollAmount(d); - } - - @Override - protected int getRowTop(int index) { - int integer = top + 4 - (int) this.getScrollAmount() + headerHeight; - for (int i = 0; i < children().size() && i < index; i++) - integer += children().get(i).getItemHeight(); - return integer; - } - - @Override - protected void renderList(MatrixStack matrices, int mouseX, int mouseY, float delta) { - int left = this.getRowLeft(); - int right = this.getRowWidth(); - int count = this.getEntryCount(); - - for(int i = 0; i < count; ++i) { - Entry entry = children().get(i); - int top = this.getRowTop(i); - int bottom = top + entry.getItemHeight(); - int entryHeight = entry.getItemHeight() - 4; - if (bottom >= this.top && top <= this.bottom) { - this.renderEntry(matrices, mouseX, mouseY, delta, i, left, top, right, entryHeight); - } - } - } - - /* END cloth config code */ - - @Override - public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) { - smoothScrollAmount = MathHelper.lerp(MinecraftClient.getInstance().getLastFrameDuration() * 0.5, smoothScrollAmount, getScrollAmount()); - returnSmoothAmount = true; - super.render(matrices, mouseX, mouseY, delta); - returnSmoothAmount = false; - } - - /** - * awful code to only use smooth scroll state when rendering, - * not other code that needs target scroll amount - */ - @Override - public double getScrollAmount() { - if (returnSmoothAmount) - return smoothScrollAmount; - - return super.getScrollAmount(); - } - - public void postRender(MatrixStack matrices, int mouseX, int mouseY, float delta) { - for (Entry entry : children()) { - entry.postRender(matrices, mouseX, mouseY, delta); - } - } - @Override public int getRowWidth() { return Math.min(396, (int)(width / 1.3f)); @@ -196,12 +101,13 @@ public class OptionListWidget extends ElementListWidget<OptionListWidget.Entry> @Override public boolean mouseScrolled(double mouseX, double mouseY, double amount) { + super.mouseScrolled(mouseX, mouseY, amount); + for (Entry child : children()) { if (child.mouseScrolled(mouseX, mouseY, amount)) - return true; + break; } - this.setScrollAmount(this.getScrollAmount() - amount * 20 /* * (double) (getMaxScroll() / getEntryCount()) / 2.0D */); return true; } @@ -227,14 +133,7 @@ public class OptionListWidget extends ElementListWidget<OptionListWidget.Entry> @Override protected int getScrollbarPositionX() { - return left + width - (int)(width * 0.05f); - } - - @Override - protected void renderBackground(MatrixStack matrices) { - setRenderBackground(client.world == null); - if (client.world != null) - fill(matrices, left, top, right, bottom, 0x6B000000); + return right - (int)(width * 0.05f); } public void recacheViewableChildren() { @@ -254,19 +153,11 @@ public class OptionListWidget extends ElementListWidget<OptionListWidget.Entry> return viewableChildren; } - public abstract class Entry extends ElementListWidget.Entry<Entry> { - public void postRender(MatrixStack matrices, int mouseX, int mouseY, float delta) { - - } - + public abstract class Entry extends ElementListWidgetExt.Entry<Entry> { public boolean isViewable() { return true; } - public int getItemHeight() { - return 22; - } - protected boolean isHovered() { return Objects.equals(getHoveredEntry(), this); } @@ -312,7 +203,7 @@ public class OptionListWidget extends ElementListWidget<OptionListWidget.Entry> widget.render(matrices, mouseX, mouseY, tickDelta); if (resetButton != null) { - resetButton.y = y; + resetButton.setY(y); resetButton.render(matrices, mouseX, mouseY, tickDelta); } } @@ -402,8 +293,8 @@ public class OptionListWidget extends ElementListWidget<OptionListWidget.Entry> public void render(MatrixStack matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) { this.y = y; - expandMinimizeButton.x = x; - expandMinimizeButton.y = y + entryHeight / 2 - expandMinimizeButton.getHeight() / 2; + expandMinimizeButton.setX(x); + expandMinimizeButton.setY(y + entryHeight / 2 - expandMinimizeButton.getHeight() / 2); expandMinimizeButton.render(matrices, mouseX, mouseY, tickDelta); wrappedName.drawCenterWithShadow(matrices, x + entryWidth / 2, y + getYPadding()); @@ -426,7 +317,7 @@ public class OptionListWidget extends ElementListWidget<OptionListWidget.Entry> } private void updateExpandMinimizeText() { - expandMinimizeButton.setMessage(Text.of(isExpanded() ? "\u25BC" : "\u25B6")); + expandMinimizeButton.setMessage(Text.of(isExpanded() ? "â–¼" : "â–¶")); } public void setOptionEntries(List<OptionEntry> optionEntries) { diff --git a/src/main/java/dev/isxander/yacl/gui/RequireRestartScreen.java b/src/client/java/dev/isxander/yacl/gui/RequireRestartScreen.java index 3c46738..3c46738 100644 --- a/src/main/java/dev/isxander/yacl/gui/RequireRestartScreen.java +++ b/src/client/java/dev/isxander/yacl/gui/RequireRestartScreen.java diff --git a/src/main/java/dev/isxander/yacl/gui/SearchFieldWidget.java b/src/client/java/dev/isxander/yacl/gui/SearchFieldWidget.java index 6184405..5b7c9dc 100644 --- a/src/main/java/dev/isxander/yacl/gui/SearchFieldWidget.java +++ b/src/client/java/dev/isxander/yacl/gui/SearchFieldWidget.java @@ -25,7 +25,7 @@ public class SearchFieldWidget extends TextFieldWidget { public void renderButton(MatrixStack matrices, int mouseX, int mouseY, float delta) { super.renderButton(matrices, mouseX, mouseY, delta); if (isVisible() && isEmpty()) { - textRenderer.drawWithShadow(matrices, emptyText, x + 4, this.y + (this.height - 8) / 2f, 0x707070); + textRenderer.drawWithShadow(matrices, emptyText, getX() + 4, this.getY() + (this.height - 8) / 2f, 0x707070); } } diff --git a/src/main/java/dev/isxander/yacl/gui/TextScaledButtonWidget.java b/src/client/java/dev/isxander/yacl/gui/TextScaledButtonWidget.java index d588d52..2d0a99c 100644 --- a/src/main/java/dev/isxander/yacl/gui/TextScaledButtonWidget.java +++ b/src/client/java/dev/isxander/yacl/gui/TextScaledButtonWidget.java @@ -2,6 +2,7 @@ package dev.isxander.yacl.gui; import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gui.tooltip.Tooltip; import net.minecraft.client.gui.widget.ButtonWidget; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.text.OrderedText; @@ -12,13 +13,13 @@ public class TextScaledButtonWidget extends ButtonWidget { public float textScale; public TextScaledButtonWidget(int x, int y, int width, int height, float textScale, Text message, PressAction onPress) { - super(x, y, width, height, message, onPress); + super(x, y, width, height, message, onPress, DEFAULT_NARRATION_SUPPLIER); this.textScale = textScale; } - public TextScaledButtonWidget(int x, int y, int width, int height, float textScale, Text message, PressAction onPress, TooltipSupplier tooltipSupplier) { - super(x, y, width, height, message, onPress, tooltipSupplier); - this.textScale = textScale; + public TextScaledButtonWidget(int x, int y, int width, int height, float textScale, Text message, PressAction onPress, Tooltip tooltip) { + this(x, y, width, height, textScale, message, onPress); + setTooltip(tooltip); } @Override @@ -35,7 +36,7 @@ public class TextScaledButtonWidget extends ButtonWidget { TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer; matrices.push(); - matrices.translate(((this.x + this.width / 2f) - textRenderer.getWidth(orderedText) * textScale / 2), (float)this.y + (this.height - 8 * textScale) / 2f / textScale, 0); + matrices.translate(((this.getX() + this.width / 2f) - textRenderer.getWidth(orderedText) * textScale / 2), (float)this.getY() + (this.height - 8 * textScale) / 2f / textScale, 0); matrices.scale(textScale, textScale, 1); textRenderer.drawWithShadow(matrices, orderedText, 0, 0, j | MathHelper.ceil(this.alpha * 255.0F) << 24); matrices.pop(); diff --git a/src/main/java/dev/isxander/yacl/gui/TooltipButtonWidget.java b/src/client/java/dev/isxander/yacl/gui/TooltipButtonWidget.java index d105f7b..b034f4b 100644 --- a/src/main/java/dev/isxander/yacl/gui/TooltipButtonWidget.java +++ b/src/client/java/dev/isxander/yacl/gui/TooltipButtonWidget.java @@ -13,14 +13,14 @@ public class TooltipButtonWidget extends ButtonWidget { protected MultilineText wrappedDescription; public TooltipButtonWidget(Screen screen, int x, int y, int width, int height, Text message, Text tooltip, PressAction onPress) { - super(x, y, width, height, message, onPress); + super(x, y, width, height, message, onPress, DEFAULT_NARRATION_SUPPLIER); this.screen = screen; setTooltip(tooltip); } public void renderHoveredTooltip(MatrixStack matrices) { if (isHovered()) { - YACLScreen.renderMultilineTooltip(matrices, MinecraftClient.getInstance().textRenderer, wrappedDescription, x + width / 2, y - 4, y + height + 4, screen.width, screen.height); + YACLScreen.renderMultilineTooltip(matrices, MinecraftClient.getInstance().textRenderer, wrappedDescription, getX() + width / 2, getY() - 4, getY() + height + 4, screen.width, screen.height); } } diff --git a/src/main/java/dev/isxander/yacl/gui/YACLScreen.java b/src/client/java/dev/isxander/yacl/gui/YACLScreen.java index 629fd4c..1fbc769 100644 --- a/src/main/java/dev/isxander/yacl/gui/YACLScreen.java +++ b/src/client/java/dev/isxander/yacl/gui/YACLScreen.java @@ -7,14 +7,16 @@ import dev.isxander.yacl.api.utils.MutableDimension; import dev.isxander.yacl.api.utils.OptionUtils; import net.minecraft.client.font.MultilineText; import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gui.DrawableHelper; import net.minecraft.client.gui.Element; import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.tooltip.TooltipBackgroundRenderer; import net.minecraft.client.render.*; import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.screen.ScreenTexts; import net.minecraft.text.Text; import net.minecraft.util.Formatting; -import net.minecraft.util.math.MathHelper; -import net.minecraft.util.math.Matrix4f; +import org.joml.Matrix4f; import java.util.HashSet; import java.util.Set; @@ -72,10 +74,10 @@ public class YACLScreen extends Screen { }); actionDim.expand(-actionDim.width() / 2 - 2, 0).move(-actionDim.width() / 2 - 2, -22); cancelResetButton = new TooltipButtonWidget(this, actionDim.x() - actionDim.width() / 2, actionDim.y(), actionDim.width(), actionDim.height(), Text.empty(), Text.empty(), (btn) -> { - if (pendingChanges()) { + if (pendingChanges()) { // if pending changes, button acts as a cancel button OptionUtils.forEachOptions(config, Option::forgetPendingValue); close(); - } else { + } else { // if not, button acts as a reset button OptionUtils.forEachOptions(config, Option::requestSetDefault); } @@ -85,7 +87,7 @@ public class YACLScreen extends Screen { OptionUtils.forEachOptions(config, Option::forgetPendingValue); }); - searchFieldWidget = new SearchFieldWidget(this, textRenderer, width / 3 / 2 - paddedWidth / 2 + 1, undoButton.y - 22, paddedWidth - 2, 18, Text.translatable("gui.recipebook.search_hint"), Text.translatable("gui.recipebook.search_hint")); + searchFieldWidget = new SearchFieldWidget(this, textRenderer, width / 3 / 2 - paddedWidth / 2 + 1, undoButton.getY() - 22, paddedWidth - 2, 18, Text.translatable("gui.recipebook.search_hint"), Text.translatable("gui.recipebook.search_hint")); categoryList = new CategoryListWidget(client, this, width, height); addSelectableChild(categoryList); @@ -159,9 +161,9 @@ public class YACLScreen extends Screen { boolean pendingChanges = pendingChanges(); undoButton.active = pendingChanges; - finishedSaveButton.setMessage(pendingChanges ? Text.translatable("yacl.gui.save") : Text.translatable("gui.done")); + finishedSaveButton.setMessage(pendingChanges ? Text.translatable("yacl.gui.save") : ScreenTexts.DONE); finishedSaveButton.setTooltip(pendingChanges ? Text.translatable("yacl.gui.save.tooltip") : Text.translatable("yacl.gui.finished.tooltip")); - cancelResetButton.setMessage(pendingChanges ? Text.translatable("gui.cancel") : Text.translatable("controls.reset")); + cancelResetButton.setMessage(pendingChanges ? ScreenTexts.CANCEL : Text.translatable("controls.reset")); cancelResetButton.setTooltip(pendingChanges ? Text.translatable("yacl.gui.cancel.tooltip") : Text.translatable("yacl.gui.reset.tooltip")); } @@ -241,23 +243,24 @@ public class YACLScreen extends Screen { matrices.push(); Tessellator tessellator = Tessellator.getInstance(); BufferBuilder bufferBuilder = tessellator.getBuffer(); - RenderSystem.setShader(GameRenderer::getPositionColorShader); + RenderSystem.setShader(GameRenderer::getPositionColorProgram); bufferBuilder.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_COLOR); Matrix4f matrix4f = matrices.peek().getPositionMatrix(); - fillGradient(matrix4f, bufferBuilder, drawX - 3, drawY - 4, drawX + maxWidth + 3, drawY - 3, 400, -267386864, -267386864); - fillGradient(matrix4f, bufferBuilder, drawX - 3, drawY + height + 3, drawX + maxWidth + 3, drawY + height + 4, 400, -267386864, -267386864); - fillGradient(matrix4f, bufferBuilder, drawX - 3, drawY - 3, drawX + maxWidth + 3, drawY + height + 3, 400, -267386864, -267386864); - fillGradient(matrix4f, bufferBuilder, drawX - 4, drawY - 3, drawX - 3, drawY + height + 3, 400, -267386864, -267386864); - fillGradient(matrix4f, bufferBuilder, drawX + maxWidth + 3, drawY - 3, drawX + maxWidth + 4, drawY + height + 3, 400, -267386864, -267386864); - fillGradient(matrix4f, bufferBuilder, drawX - 3, drawY - 3 + 1, drawX - 3 + 1, drawY + height + 3 - 1, 400, 1347420415, 1344798847); - fillGradient(matrix4f, bufferBuilder, drawX + maxWidth + 2, drawY - 3 + 1, drawX + maxWidth + 3, drawY + height + 3 - 1, 400, 1347420415, 1344798847); - fillGradient(matrix4f, bufferBuilder, drawX - 3, drawY - 3, drawX + maxWidth + 3, drawY - 3 + 1, 400, 1347420415, 1347420415); - fillGradient(matrix4f, bufferBuilder, drawX - 3, drawY + height + 2, drawX + maxWidth + 3, drawY + height + 3, 400, 1344798847, 1344798847); + TooltipBackgroundRenderer.render( + DrawableHelper::fillGradient, + matrix4f, + bufferBuilder, + drawX, + drawY, + maxWidth, + height, + 400 + ); RenderSystem.enableDepthTest(); RenderSystem.disableTexture(); RenderSystem.enableBlend(); RenderSystem.defaultBlendFunc(); - BufferRenderer.drawWithShader(bufferBuilder.end()); + BufferRenderer.drawWithGlobalProgram(bufferBuilder.end()); RenderSystem.disableBlend(); RenderSystem.enableTexture(); matrices.translate(0.0, 0.0, 400.0); diff --git a/src/main/java/dev/isxander/yacl/gui/controllers/ActionController.java b/src/client/java/dev/isxander/yacl/gui/controllers/ActionController.java index b8e2cd1..7666dff 100644 --- a/src/main/java/dev/isxander/yacl/gui/controllers/ActionController.java +++ b/src/client/java/dev/isxander/yacl/gui/controllers/ActionController.java @@ -5,8 +5,8 @@ import dev.isxander.yacl.api.Controller; import dev.isxander.yacl.api.utils.Dimension; import dev.isxander.yacl.gui.AbstractWidget; import dev.isxander.yacl.gui.YACLScreen; +import net.minecraft.client.util.InputUtil; import net.minecraft.text.Text; -import org.lwjgl.glfw.GLFW; import java.util.function.BiConsumer; @@ -94,7 +94,7 @@ public class ActionController implements Controller<BiConsumer<YACLScreen, Butto return false; } - if (keyCode == GLFW.GLFW_KEY_ENTER || keyCode == GLFW.GLFW_KEY_SPACE || keyCode == GLFW.GLFW_KEY_KP_ENTER) { + if (keyCode == InputUtil.GLFW_KEY_ENTER || keyCode == InputUtil.GLFW_KEY_SPACE || keyCode == InputUtil.GLFW_KEY_KP_ENTER) { executeAction(); return true; } diff --git a/src/main/java/dev/isxander/yacl/gui/controllers/BooleanController.java b/src/client/java/dev/isxander/yacl/gui/controllers/BooleanController.java index b7a77dd..3a8e5c3 100644 --- a/src/main/java/dev/isxander/yacl/gui/controllers/BooleanController.java +++ b/src/client/java/dev/isxander/yacl/gui/controllers/BooleanController.java @@ -5,7 +5,9 @@ import dev.isxander.yacl.api.Option; import dev.isxander.yacl.api.utils.Dimension; import dev.isxander.yacl.gui.AbstractWidget; import dev.isxander.yacl.gui.YACLScreen; +import net.minecraft.client.util.InputUtil; import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.screen.ScreenTexts; import net.minecraft.text.Text; import net.minecraft.util.Formatting; import org.lwjgl.glfw.GLFW; @@ -19,8 +21,8 @@ public class BooleanController implements Controller<Boolean> { public static final Function<Boolean, Text> ON_OFF_FORMATTER = (state) -> state - ? Text.translatable("options.on") - : Text.translatable("options.off"); + ? ScreenTexts.ON + : ScreenTexts.OFF; public static final Function<Boolean, Text> TRUE_FALSE_FORMATTER = (state) -> state @@ -29,8 +31,8 @@ public class BooleanController implements Controller<Boolean> { public static final Function<Boolean, Text> YES_NO_FORMATTER = (state) -> state - ? Text.translatable("gui.yes") - : Text.translatable("gui.no"); + ? ScreenTexts.YES + : ScreenTexts.NO; private final Option<Boolean> option; private final Function<Boolean, Text> valueFormatter; @@ -102,7 +104,7 @@ public class BooleanController implements Controller<Boolean> { } public static class BooleanControllerElement extends ControllerWidget<BooleanController> { - private BooleanControllerElement(BooleanController control, YACLScreen screen, Dimension<Integer> dim) { + public BooleanControllerElement(BooleanController control, YACLScreen screen, Dimension<Integer> dim) { super(control, screen, dim); } @@ -145,7 +147,7 @@ public class BooleanController implements Controller<Boolean> { return false; } - if (keyCode == GLFW.GLFW_KEY_ENTER || keyCode == GLFW.GLFW_KEY_SPACE || keyCode == GLFW.GLFW_KEY_KP_ENTER) { + if (keyCode == InputUtil.GLFW_KEY_ENTER || keyCode == InputUtil.GLFW_KEY_SPACE || keyCode == InputUtil.GLFW_KEY_KP_ENTER) { toggleSetting(); return true; } diff --git a/src/main/java/dev/isxander/yacl/gui/controllers/ColorController.java b/src/client/java/dev/isxander/yacl/gui/controllers/ColorController.java index 0a83fbe..b8e1942 100644 --- a/src/main/java/dev/isxander/yacl/gui/controllers/ColorController.java +++ b/src/client/java/dev/isxander/yacl/gui/controllers/ColorController.java @@ -14,7 +14,7 @@ import net.minecraft.text.MutableText; import net.minecraft.text.Text; import net.minecraft.util.Formatting; -import java.awt.*; +import java.awt.Color; import java.util.List; /** @@ -108,7 +108,7 @@ public class ColorController implements IStringController<Color> { private final List<Character> allowedChars; public ColorControllerElement(ColorController control, YACLScreen screen, Dimension<Integer> dim) { - super(control, screen, dim); + super(control, screen, dim, true); this.colorController = control; this.allowedChars = ImmutableList.of('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'); } @@ -135,21 +135,22 @@ public class ColorController implements IStringController<Color> { if (caretPos == 0) return; - string = string.substring(0, Math.min(inputField.length() - caretPos, string.length())); + String trimmed = string.substring(0, Math.min(inputField.length() - caretPos, string.length())); - inputField.replace(caretPos, caretPos + string.length(), string); - caretPos += string.length(); - setSelectionLength(); - - updateControl(); + if (modifyInput(builder -> builder.replace(caretPos, caretPos + trimmed.length(), trimmed))) { + caretPos += trimmed.length(); + setSelectionLength(); + updateControl(); + } } @Override protected void doBackspace() { if (caretPos > 1) { - inputField.setCharAt(caretPos - 1, '0'); - caretPos--; - updateControl(); + if (modifyInput(builder -> builder.setCharAt(caretPos - 1, '0'))) { + caretPos--; + updateControl(); + } } } @@ -182,11 +183,13 @@ public class ColorController implements IStringController<Color> { @Override public boolean keyPressed(int keyCode, int scanCode, int modifiers) { + int prevSelectionLength = selectionLength; + selectionLength = 0; if (super.keyPressed(keyCode, scanCode, modifiers)) { caretPos = Math.max(1, caretPos); setSelectionLength(); return true; - } + } else selectionLength = prevSelectionLength; return false; } diff --git a/src/main/java/dev/isxander/yacl/gui/controllers/ControllerWidget.java b/src/client/java/dev/isxander/yacl/gui/controllers/ControllerWidget.java index c7f9e97..cebaba7 100644 --- a/src/main/java/dev/isxander/yacl/gui/controllers/ControllerWidget.java +++ b/src/client/java/dev/isxander/yacl/gui/controllers/ControllerWidget.java @@ -4,6 +4,7 @@ import dev.isxander.yacl.api.Controller; import dev.isxander.yacl.api.utils.Dimension; import dev.isxander.yacl.gui.AbstractWidget; import dev.isxander.yacl.gui.YACLScreen; +import dev.isxander.yacl.impl.utils.YACLConstants; import net.minecraft.client.font.MultilineText; import net.minecraft.client.gui.DrawableHelper; import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder; @@ -44,6 +45,9 @@ public abstract class ControllerWidget<T extends Controller<?>> extends Abstract nameString = nameString.substring(0, Math.max(nameString.length() - (firstIter ? 2 : 5), 0)).trim(); nameString += "..."; + if (nameString.equals("...")) + break; + firstIter = false; } diff --git a/src/main/java/dev/isxander/yacl/gui/controllers/LabelController.java b/src/client/java/dev/isxander/yacl/gui/controllers/LabelController.java index 8369680..8369680 100644 --- a/src/main/java/dev/isxander/yacl/gui/controllers/LabelController.java +++ b/src/client/java/dev/isxander/yacl/gui/controllers/LabelController.java diff --git a/src/main/java/dev/isxander/yacl/gui/controllers/TickBoxController.java b/src/client/java/dev/isxander/yacl/gui/controllers/TickBoxController.java index ff693a9..b0ae449 100644 --- a/src/main/java/dev/isxander/yacl/gui/controllers/TickBoxController.java +++ b/src/client/java/dev/isxander/yacl/gui/controllers/TickBoxController.java @@ -6,9 +6,9 @@ import dev.isxander.yacl.api.utils.Dimension; import dev.isxander.yacl.gui.AbstractWidget; import dev.isxander.yacl.gui.YACLScreen; import net.minecraft.client.gui.DrawableHelper; +import net.minecraft.client.util.InputUtil; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.text.Text; -import org.lwjgl.glfw.GLFW; /** * This controller renders a tickbox @@ -50,7 +50,7 @@ public class TickBoxController implements Controller<Boolean> { } public static class TickBoxControllerElement extends ControllerWidget<TickBoxController> { - private TickBoxControllerElement(TickBoxController control, YACLScreen screen, Dimension<Integer> dim) { + public TickBoxControllerElement(TickBoxController control, YACLScreen screen, Dimension<Integer> dim) { super(control, screen, dim); } @@ -93,6 +93,11 @@ public class TickBoxController implements Controller<Boolean> { return 10; } + @Override + protected int getUnhoveredControlWidth() { + return 10; + } + public void toggleSetting() { control.option().requestSet(!control.option().pendingValue()); playDownSound(); @@ -104,7 +109,7 @@ public class TickBoxController implements Controller<Boolean> { return false; } - if (keyCode == GLFW.GLFW_KEY_ENTER || keyCode == GLFW.GLFW_KEY_SPACE || keyCode == GLFW.GLFW_KEY_KP_ENTER) { + if (keyCode == InputUtil.GLFW_KEY_ENTER || keyCode == InputUtil.GLFW_KEY_SPACE || keyCode == InputUtil.GLFW_KEY_KP_ENTER) { toggleSetting(); return true; } diff --git a/src/main/java/dev/isxander/yacl/gui/controllers/cycling/CyclingControllerElement.java b/src/client/java/dev/isxander/yacl/gui/controllers/cycling/CyclingControllerElement.java index ab0a9c3..246fbec 100644 --- a/src/main/java/dev/isxander/yacl/gui/controllers/cycling/CyclingControllerElement.java +++ b/src/client/java/dev/isxander/yacl/gui/controllers/cycling/CyclingControllerElement.java @@ -4,7 +4,7 @@ import dev.isxander.yacl.api.utils.Dimension; import dev.isxander.yacl.gui.YACLScreen; import dev.isxander.yacl.gui.controllers.ControllerWidget; import net.minecraft.client.gui.screen.Screen; -import org.lwjgl.glfw.GLFW; +import net.minecraft.client.util.InputUtil; public class CyclingControllerElement extends ControllerWidget<ICyclingController<?>> { @@ -39,11 +39,11 @@ public class CyclingControllerElement extends ControllerWidget<ICyclingControlle return false; switch (keyCode) { - case GLFW.GLFW_KEY_LEFT, GLFW.GLFW_KEY_DOWN -> + case InputUtil.GLFW_KEY_LEFT, InputUtil.GLFW_KEY_DOWN -> cycleValue(-1); - case GLFW.GLFW_KEY_RIGHT, GLFW.GLFW_KEY_UP -> + case InputUtil.GLFW_KEY_RIGHT, InputUtil.GLFW_KEY_UP -> cycleValue(1); - case GLFW.GLFW_KEY_ENTER, GLFW.GLFW_KEY_SPACE, GLFW.GLFW_KEY_KP_ENTER -> + case InputUtil.GLFW_KEY_ENTER, InputUtil.GLFW_KEY_SPACE, InputUtil.GLFW_KEY_KP_ENTER -> cycleValue(Screen.hasControlDown() || Screen.hasShiftDown() ? -1 : 1); default -> { return false; diff --git a/src/main/java/dev/isxander/yacl/gui/controllers/cycling/CyclingListController.java b/src/client/java/dev/isxander/yacl/gui/controllers/cycling/CyclingListController.java index 3b14066..3b14066 100644 --- a/src/main/java/dev/isxander/yacl/gui/controllers/cycling/CyclingListController.java +++ b/src/client/java/dev/isxander/yacl/gui/controllers/cycling/CyclingListController.java diff --git a/src/main/java/dev/isxander/yacl/gui/controllers/cycling/EnumController.java b/src/client/java/dev/isxander/yacl/gui/controllers/cycling/EnumController.java index bc9f46d..bc9f46d 100644 --- a/src/main/java/dev/isxander/yacl/gui/controllers/cycling/EnumController.java +++ b/src/client/java/dev/isxander/yacl/gui/controllers/cycling/EnumController.java diff --git a/src/main/java/dev/isxander/yacl/gui/controllers/cycling/ICyclingController.java b/src/client/java/dev/isxander/yacl/gui/controllers/cycling/ICyclingController.java index 081b572..081b572 100644 --- a/src/main/java/dev/isxander/yacl/gui/controllers/cycling/ICyclingController.java +++ b/src/client/java/dev/isxander/yacl/gui/controllers/cycling/ICyclingController.java diff --git a/src/main/java/dev/isxander/yacl/gui/controllers/package-info.java b/src/client/java/dev/isxander/yacl/gui/controllers/package-info.java index 12ce86b..12ce86b 100644 --- a/src/main/java/dev/isxander/yacl/gui/controllers/package-info.java +++ b/src/client/java/dev/isxander/yacl/gui/controllers/package-info.java diff --git a/src/main/java/dev/isxander/yacl/gui/controllers/slider/DoubleSliderController.java b/src/client/java/dev/isxander/yacl/gui/controllers/slider/DoubleSliderController.java index b530e8c..54c7476 100644 --- a/src/main/java/dev/isxander/yacl/gui/controllers/slider/DoubleSliderController.java +++ b/src/client/java/dev/isxander/yacl/gui/controllers/slider/DoubleSliderController.java @@ -13,7 +13,7 @@ public class DoubleSliderController implements ISliderController<Double> { /** * Formats doubles to two decimal places */ - public static final Function<Double, Text> DEFAULT_FORMATTER = value -> Text.of(String.format("%,.2f", value)); + public static final Function<Double, Text> DEFAULT_FORMATTER = value -> Text.of(String.format("%,.2f", value).replaceAll("[\u00a0\u202F]", " ")); private final Option<Double> option; diff --git a/src/main/java/dev/isxander/yacl/gui/controllers/slider/FloatSliderController.java b/src/client/java/dev/isxander/yacl/gui/controllers/slider/FloatSliderController.java index d7c203e..84ca9a2 100644 --- a/src/main/java/dev/isxander/yacl/gui/controllers/slider/FloatSliderController.java +++ b/src/client/java/dev/isxander/yacl/gui/controllers/slider/FloatSliderController.java @@ -13,7 +13,7 @@ public class FloatSliderController implements ISliderController<Float> { /** * Formats floats to one decimal place */ - public static final Function<Float, Text> DEFAULT_FORMATTER = value -> Text.of(String.format("%,.1f", value)); + public static final Function<Float, Text> DEFAULT_FORMATTER = value -> Text.of(String.format("%,.1f", value).replaceAll("[\u00a0\u202F]", " ")); private final Option<Float> option; diff --git a/src/main/java/dev/isxander/yacl/gui/controllers/slider/ISliderController.java b/src/client/java/dev/isxander/yacl/gui/controllers/slider/ISliderController.java index aa3c18f..aa3c18f 100644 --- a/src/main/java/dev/isxander/yacl/gui/controllers/slider/ISliderController.java +++ b/src/client/java/dev/isxander/yacl/gui/controllers/slider/ISliderController.java diff --git a/src/main/java/dev/isxander/yacl/gui/controllers/slider/IntegerSliderController.java b/src/client/java/dev/isxander/yacl/gui/controllers/slider/IntegerSliderController.java index a8bca7c..50ec9d2 100644 --- a/src/main/java/dev/isxander/yacl/gui/controllers/slider/IntegerSliderController.java +++ b/src/client/java/dev/isxander/yacl/gui/controllers/slider/IntegerSliderController.java @@ -10,7 +10,7 @@ import java.util.function.Function; * {@link ISliderController} for integers. */ public class IntegerSliderController implements ISliderController<Integer> { - public static final Function<Integer, Text> DEFAULT_FORMATTER = value -> Text.of(String.format("%,d", value)); + public static final Function<Integer, Text> DEFAULT_FORMATTER = value -> Text.of(String.format("%,d", value).replaceAll("[\u00a0\u202F]", " ")); private final Option<Integer> option; diff --git a/src/main/java/dev/isxander/yacl/gui/controllers/slider/LongSliderController.java b/src/client/java/dev/isxander/yacl/gui/controllers/slider/LongSliderController.java index 50559d5..3038402 100644 --- a/src/main/java/dev/isxander/yacl/gui/controllers/slider/LongSliderController.java +++ b/src/client/java/dev/isxander/yacl/gui/controllers/slider/LongSliderController.java @@ -10,7 +10,7 @@ import java.util.function.Function; * {@link ISliderController} for longs. */ public class LongSliderController implements ISliderController<Long> { - public static final Function<Long, Text> DEFAULT_FORMATTER = value -> Text.of(String.format("%,d", value)); + public static final Function<Long, Text> DEFAULT_FORMATTER = value -> Text.of(String.format("%,d", value).replaceAll("[\u00a0\u202F]", " ")); private final Option<Long> option; diff --git a/src/main/java/dev/isxander/yacl/gui/controllers/slider/SliderControllerElement.java b/src/client/java/dev/isxander/yacl/gui/controllers/slider/SliderControllerElement.java index 913cc00..c78e0eb 100644 --- a/src/main/java/dev/isxander/yacl/gui/controllers/slider/SliderControllerElement.java +++ b/src/client/java/dev/isxander/yacl/gui/controllers/slider/SliderControllerElement.java @@ -5,9 +5,9 @@ import dev.isxander.yacl.gui.YACLScreen; import dev.isxander.yacl.gui.controllers.ControllerWidget; import net.minecraft.client.gui.DrawableHelper; import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.util.InputUtil; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.util.math.MathHelper; -import org.lwjgl.glfw.GLFW; public class SliderControllerElement extends ControllerWidget<ISliderController<?>> { private final double min, max, interval; @@ -104,8 +104,8 @@ public class SliderControllerElement extends ControllerWidget<ISliderController< return false; switch (keyCode) { - case GLFW.GLFW_KEY_LEFT, GLFW.GLFW_KEY_DOWN -> incrementValue(-1); - case GLFW.GLFW_KEY_RIGHT, GLFW.GLFW_KEY_UP -> incrementValue(1); + case InputUtil.GLFW_KEY_LEFT, InputUtil.GLFW_KEY_DOWN -> incrementValue(-1); + case InputUtil.GLFW_KEY_RIGHT, InputUtil.GLFW_KEY_UP -> incrementValue(1); default -> { return false; } diff --git a/src/main/java/dev/isxander/yacl/gui/controllers/slider/package-info.java b/src/client/java/dev/isxander/yacl/gui/controllers/slider/package-info.java index bff0d57..bff0d57 100644 --- a/src/main/java/dev/isxander/yacl/gui/controllers/slider/package-info.java +++ b/src/client/java/dev/isxander/yacl/gui/controllers/slider/package-info.java diff --git a/src/main/java/dev/isxander/yacl/gui/controllers/string/IStringController.java b/src/client/java/dev/isxander/yacl/gui/controllers/string/IStringController.java index 41843b8..553e278 100644 --- a/src/main/java/dev/isxander/yacl/gui/controllers/string/IStringController.java +++ b/src/client/java/dev/isxander/yacl/gui/controllers/string/IStringController.java @@ -2,6 +2,9 @@ package dev.isxander.yacl.gui.controllers.string; import dev.isxander.yacl.api.Controller; import dev.isxander.yacl.api.Option; +import dev.isxander.yacl.api.utils.Dimension; +import dev.isxander.yacl.gui.AbstractWidget; +import dev.isxander.yacl.gui.YACLScreen; import net.minecraft.text.Text; /** @@ -29,4 +32,13 @@ public interface IStringController<T> extends Controller<T> { default Text formatValue() { return Text.of(getString()); } + + default boolean isInputValid(String input) { + return true; + } + + @Override + default AbstractWidget provideWidget(YACLScreen screen, Dimension<Integer> widgetDimension) { + return new StringControllerElement(this, screen, widgetDimension, true); + } } diff --git a/src/main/java/dev/isxander/yacl/gui/controllers/string/StringController.java b/src/client/java/dev/isxander/yacl/gui/controllers/string/StringController.java index 0caaa93..3a07641 100644 --- a/src/main/java/dev/isxander/yacl/gui/controllers/string/StringController.java +++ b/src/client/java/dev/isxander/yacl/gui/controllers/string/StringController.java @@ -37,9 +37,4 @@ public class StringController implements IStringController<String> { public void setFromString(String value) { option().requestSet(value); } - - @Override - public AbstractWidget provideWidget(YACLScreen screen, Dimension<Integer> widgetDimension) { - return new StringControllerElement(this, screen, widgetDimension); - } } diff --git a/src/main/java/dev/isxander/yacl/gui/controllers/string/StringControllerElement.java b/src/client/java/dev/isxander/yacl/gui/controllers/string/StringControllerElement.java index 0c3b7c9..47a4c96 100644 --- a/src/main/java/dev/isxander/yacl/gui/controllers/string/StringControllerElement.java +++ b/src/client/java/dev/isxander/yacl/gui/controllers/string/StringControllerElement.java @@ -5,13 +5,17 @@ import dev.isxander.yacl.gui.YACLScreen; import dev.isxander.yacl.gui.controllers.ControllerWidget; import net.minecraft.client.gui.DrawableHelper; import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.util.InputUtil; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.text.Text; import net.minecraft.util.Formatting; -import org.lwjgl.glfw.GLFW; + +import java.util.function.Consumer; public class StringControllerElement extends ControllerWidget<IStringController<?>> { - protected StringBuilder inputField; + protected final boolean instantApply; + + protected String inputField; protected Dimension<Integer> inputFieldBounds; protected boolean inputFieldFocused; @@ -22,12 +26,14 @@ public class StringControllerElement extends ControllerWidget<IStringController< private final Text emptyText; - public StringControllerElement(IStringController<?> control, YACLScreen screen, Dimension<Integer> dim) { + public StringControllerElement(IStringController<?> control, YACLScreen screen, Dimension<Integer> dim, boolean instantApply) { super(control, screen, dim); - inputField = new StringBuilder(control.getString()); + this.instantApply = instantApply; + inputField = control.getString(); inputFieldFocused = false; selectionLength = 0; emptyText = Text.literal("Click to type...").formatted(Formatting.GRAY); + control.option().addListener((opt, val) -> inputField = control.getString()); setDimension(dim); } @@ -35,12 +41,14 @@ public class StringControllerElement extends ControllerWidget<IStringController< protected void drawHoveredControl(MatrixStack matrices, int mouseX, int mouseY, float delta) { ticks += delta; + String text = getValueText().getString(); + DrawableHelper.fill(matrices, inputFieldBounds.x(), inputFieldBounds.yLimit(), inputFieldBounds.xLimit(), inputFieldBounds.yLimit() + 1, -1); DrawableHelper.fill(matrices, inputFieldBounds.x() + 1, inputFieldBounds.yLimit() + 1, inputFieldBounds.xLimit() + 1, inputFieldBounds.yLimit() + 2, 0xFF404040); if (inputFieldFocused || focused) { - int caretX = inputFieldBounds.x() + textRenderer.getWidth(control.getString().substring(0, caretPos)) - 1; - if (inputField.isEmpty()) + int caretX = inputFieldBounds.x() + textRenderer.getWidth(text.substring(0, caretPos)) - 1; + if (text.isEmpty()) caretX += inputFieldBounds.width() / 2; if (ticks % 20 <= 10) { @@ -48,7 +56,7 @@ public class StringControllerElement extends ControllerWidget<IStringController< } if (selectionLength != 0) { - int selectionX = inputFieldBounds.x() + textRenderer.getWidth(control.getString().substring(0, caretPos + selectionLength)); + int selectionX = inputFieldBounds.x() + textRenderer.getWidth(text.substring(0, caretPos + selectionLength)); DrawableHelper.fill(matrices, caretX, inputFieldBounds.y() - 1, selectionX, inputFieldBounds.yLimit(), 0x803030FF); } } @@ -56,13 +64,29 @@ public class StringControllerElement extends ControllerWidget<IStringController< @Override public boolean mouseClicked(double mouseX, double mouseY, int button) { - if (isAvailable() && inputFieldBounds.isPointInside((int) mouseX, (int) mouseY)) { - if (!inputFieldFocused) { - inputFieldFocused = true; + if (isAvailable() && getDimension().isPointInside((int) mouseX, (int) mouseY)) { + inputFieldFocused = true; + + if (!inputFieldBounds.isPointInside((int) mouseX, (int) mouseY)) { caretPos = getDefaultCarotPos(); } else { - int textWidth = (int) mouseX - inputFieldBounds.x(); - caretPos = textRenderer.trimToWidth(control.getString(), textWidth).length(); + // gets the appropriate carot position for where you click + int textX = (int) mouseX - inputFieldBounds.x(); + int pos = -1; + int currentWidth = 0; + for (char ch : inputField.toCharArray()) { + pos++; + int charLength = textRenderer.getWidth(String.valueOf(ch)); + if (currentWidth + charLength / 2 > textX) { // if more than half way past the characters select in front of that char + caretPos = pos; + break; + } else if (pos == inputField.length() - 1) { + // if we have reached the end and no matches, it must be the second half of the char so the last position + caretPos = pos + 1; + } + currentWidth += charLength; + } + selectionLength = 0; } return true; @@ -83,11 +107,11 @@ public class StringControllerElement extends ControllerWidget<IStringController< return false; switch (keyCode) { - case GLFW.GLFW_KEY_ESCAPE -> { - inputFieldFocused = false; + case InputUtil.GLFW_KEY_ESCAPE, InputUtil.GLFW_KEY_ENTER -> { + unfocus(); return true; } - case GLFW.GLFW_KEY_LEFT -> { + case InputUtil.GLFW_KEY_LEFT -> { if (Screen.hasShiftDown()) { if (Screen.hasControlDown()) { int spaceChar = findSpaceIndex(true); @@ -98,14 +122,18 @@ public class StringControllerElement extends ControllerWidget<IStringController< selectionLength += 1; } } else { - if (caretPos > 0) - caretPos--; + if (caretPos > 0) { + if (selectionLength != 0) + caretPos += Math.min(selectionLength, 0); + else + caretPos--; + } selectionLength = 0; } return true; } - case GLFW.GLFW_KEY_RIGHT -> { + case InputUtil.GLFW_KEY_RIGHT -> { if (Screen.hasShiftDown()) { if (Screen.hasControlDown()) { int spaceChar = findSpaceIndex(false); @@ -116,18 +144,22 @@ public class StringControllerElement extends ControllerWidget<IStringController< selectionLength -= 1; } } else { - if (caretPos < inputField.length()) - caretPos++; + if (caretPos < inputField.length()) { + if (selectionLength != 0) + caretPos += Math.max(selectionLength, 0); + else + caretPos++; + } selectionLength = 0; } return true; } - case GLFW.GLFW_KEY_BACKSPACE -> { + case InputUtil.GLFW_KEY_BACKSPACE -> { doBackspace(); return true; } - case GLFW.GLFW_KEY_DELETE -> { + case InputUtil.GLFW_KEY_DELETE -> { doDelete(); return true; } @@ -172,36 +204,46 @@ public class StringControllerElement extends ControllerWidget<IStringController< if (selectionLength != 0) { write(""); } else if (caretPos > 0) { - inputField.deleteCharAt(caretPos - 1); - caretPos--; - updateControl(); + if (modifyInput(builder -> builder.deleteCharAt(caretPos - 1))) + caretPos--; } } protected void doDelete() { if (caretPos < inputField.length()) { - inputField.deleteCharAt(caretPos); - updateControl(); + modifyInput(builder -> builder.deleteCharAt(caretPos)); } } public void write(String string) { if (selectionLength == 0) { - string = textRenderer.trimToWidth(string, getMaxLength() - textRenderer.getWidth(inputField.toString())); + String trimmed = textRenderer.trimToWidth(string, getMaxLength() - textRenderer.getWidth(inputField)); - inputField.insert(caretPos, string); - caretPos += string.length(); + if (modifyInput(builder -> builder.insert(caretPos, trimmed))) { + caretPos += trimmed.length(); + } } else { int start = getSelectionStart(); int end = getSelectionEnd(); - string = textRenderer.trimToWidth(string, getMaxLength() - textRenderer.getWidth(inputField.toString()) + textRenderer.getWidth(inputField.substring(start, end))); + String trimmed = textRenderer.trimToWidth(string, getMaxLength() - textRenderer.getWidth(inputField) + textRenderer.getWidth(inputField.substring(start, end))); - inputField.replace(start, end, string); - caretPos = start + string.length(); - selectionLength = 0; + if (modifyInput(builder -> builder.replace(start, end, trimmed))) { + caretPos = start + trimmed.length(); + selectionLength = 0; + } } - updateControl(); + } + + public boolean modifyInput(Consumer<StringBuilder> consumer) { + StringBuilder temp = new StringBuilder(inputField); + consumer.accept(temp); + if (!control.isInputValid(temp.toString())) + return false; + inputField = temp.toString(); + if (instantApply) + updateControl(); + return true; } public int getMaxLength() { @@ -249,6 +291,7 @@ public class StringControllerElement extends ControllerWidget<IStringController< public void unfocus() { super.unfocus(); inputFieldFocused = false; + if (!instantApply) updateControl(); } @Override @@ -265,7 +308,7 @@ public class StringControllerElement extends ControllerWidget<IStringController< } protected void updateControl() { - control.setFromString(inputField.toString()); + control.setFromString(inputField); } @Override @@ -278,6 +321,6 @@ public class StringControllerElement extends ControllerWidget<IStringController< if (!inputFieldFocused && inputField.isEmpty()) return emptyText; - return super.getValueText(); + return instantApply || !inputFieldFocused ? control.formatValue() : Text.of(inputField); } } diff --git a/src/client/java/dev/isxander/yacl/gui/controllers/string/number/DoubleFieldController.java b/src/client/java/dev/isxander/yacl/gui/controllers/string/number/DoubleFieldController.java new file mode 100644 index 0000000..8933df3 --- /dev/null +++ b/src/client/java/dev/isxander/yacl/gui/controllers/string/number/DoubleFieldController.java @@ -0,0 +1,105 @@ +package dev.isxander.yacl.gui.controllers.string.number; + +import dev.isxander.yacl.api.Option; +import dev.isxander.yacl.gui.controllers.slider.DoubleSliderController; +import net.minecraft.text.Text; + +import java.math.BigDecimal; +import java.util.function.Function; + +/** + * {@inheritDoc} + */ +public class DoubleFieldController extends NumberFieldController<Double> { + private final double min, max; + + /** + * Constructs a double field controller + * + * @param option option to bind controller to + * @param min minimum allowed value (clamped on apply) + * @param max maximum allowed value (clamped on apply) + * @param formatter display text, not used whilst editing + */ + public DoubleFieldController(Option<Double> option, double min, double max, Function<Double, Text> formatter) { + super(option, formatter); + this.min = min; + this.max = max; + } + + /** + * Constructs a double field controller. + * Uses {@link DoubleSliderController#DEFAULT_FORMATTER} as display text, + * not used whilst editing. + * + * @param option option to bind controller to + * @param min minimum allowed value (clamped on apply) + * @param max maximum allowed value (clamped on apply) + */ + public DoubleFieldController(Option<Double> option, double min, double max) { + this(option, min, max, DoubleSliderController.DEFAULT_FORMATTER); + } + + /** + * Constructs a double field controller. + * Does not have a minimum or a maximum range. + * + * @param option option to bind controller to + * @param formatter display text, not used whilst editing + */ + public DoubleFieldController(Option<Double> option, Function<Double, Text> formatter) { + this(option, -Double.MAX_VALUE, Double.MAX_VALUE, formatter); + } + + /** + * Constructs a double field controller. + * Uses {@link DoubleSliderController#DEFAULT_FORMATTER} as display text, + * not used whilst editing. + * Does not have a minimum or a maximum range. + * + * @param option option to bind controller to + */ + public DoubleFieldController(Option<Double> option) { + this(option, -Double.MAX_VALUE, Double.MAX_VALUE, DoubleSliderController.DEFAULT_FORMATTER); + } + + /** + * {@inheritDoc} + */ + @Override + public double min() { + return this.min; + } + + /** + * {@inheritDoc} + */ + @Override + public double max() { + return this.max; + } + + /** + * {@inheritDoc} + */ + @Override + public String getString() { + return String.valueOf(option().pendingValue()); + } + + /** + * {@inheritDoc} + */ + @Override + public void setPendingValue(double value) { + option().requestSet(value); + } + + /** + * {@inheritDoc} + */ + @Override + public double pendingValue() { + return option().pendingValue(); + } +} diff --git a/src/client/java/dev/isxander/yacl/gui/controllers/string/number/FloatFieldController.java b/src/client/java/dev/isxander/yacl/gui/controllers/string/number/FloatFieldController.java new file mode 100644 index 0000000..b1eb3a2 --- /dev/null +++ b/src/client/java/dev/isxander/yacl/gui/controllers/string/number/FloatFieldController.java @@ -0,0 +1,105 @@ +package dev.isxander.yacl.gui.controllers.string.number; + +import dev.isxander.yacl.api.Option; +import dev.isxander.yacl.gui.controllers.slider.FloatSliderController; +import net.minecraft.text.Text; + +import java.math.BigDecimal; +import java.util.function.Function; + +/** + * {@inheritDoc} + */ +public class FloatFieldController extends NumberFieldController<Float> { + private final float min, max; + + /** + * Constructs a double field controller + * + * @param option option to bind controller to + * @param min minimum allowed value (clamped on apply) + * @param max maximum allowed value (clamped on apply) + * @param formatter display text, not used whilst editing + */ + public FloatFieldController(Option<Float> option, float min, float max, Function<Float, Text> formatter) { + super(option, formatter); + this.min = min; + this.max = max; + } + + /** + * Constructs a double field controller. + * Uses {@link FloatSliderController#DEFAULT_FORMATTER} as display text, + * not used whilst editing. + * + * @param option option to bind controller to + * @param min minimum allowed value (clamped on apply) + * @param max maximum allowed value (clamped on apply) + */ + public FloatFieldController(Option<Float> option, float min, float max) { + this(option, min, max, FloatSliderController.DEFAULT_FORMATTER); + } + + /** + * Constructs a double field controller. + * Does not have a minimum or a maximum range. + * + * @param option option to bind controller to + * @param formatter display text, not used whilst editing + */ + public FloatFieldController(Option<Float> option, Function<Float, Text> formatter) { + this(option, -Float.MAX_VALUE, Float.MAX_VALUE, formatter); + } + + /** + * Constructs a double field controller. + * Uses {@link FloatSliderController#DEFAULT_FORMATTER} as display text, + * not used whilst editing. + * Does not have a minimum or a maximum range. + * + * @param option option to bind controller to + */ + public FloatFieldController(Option<Float> option) { + this(option, -Float.MAX_VALUE, Float.MAX_VALUE, FloatSliderController.DEFAULT_FORMATTER); + } + + /** + * {@inheritDoc} + */ + @Override + public double min() { + return this.min; + } + + /** + * {@inheritDoc} + */ + @Override + public double max() { + return this.max; + } + + /** + * {@inheritDoc} + */ + @Override + public String getString() { + return String.valueOf(option().pendingValue()); + } + + /** + * {@inheritDoc} + */ + @Override + public void setPendingValue(double value) { + option().requestSet((float) value); + } + + /** + * {@inheritDoc} + */ + @Override + public double pendingValue() { + return option().pendingValue(); + } +} diff --git a/src/client/java/dev/isxander/yacl/gui/controllers/string/number/IntegerFieldController.java b/src/client/java/dev/isxander/yacl/gui/controllers/string/number/IntegerFieldController.java new file mode 100644 index 0000000..50eecec --- /dev/null +++ b/src/client/java/dev/isxander/yacl/gui/controllers/string/number/IntegerFieldController.java @@ -0,0 +1,109 @@ +package dev.isxander.yacl.gui.controllers.string.number; + +import dev.isxander.yacl.api.Option; +import dev.isxander.yacl.gui.controllers.slider.IntegerSliderController; +import net.minecraft.text.Text; + +import java.util.function.Function; + +/** + * {@inheritDoc} + */ +public class IntegerFieldController extends NumberFieldController<Integer> { + private final int min, max; + + /** + * Constructs a double field controller + * + * @param option option to bind controller to + * @param min minimum allowed value (clamped on apply) + * @param max maximum allowed value (clamped on apply) + * @param formatter display text, not used whilst editing + */ + public IntegerFieldController(Option<Integer> option, int min, int max, Function<Integer, Text> formatter) { + super(option, formatter); + this.min = min; + this.max = max; + } + + /** + * Constructs a double field controller. + * Uses {@link IntegerSliderController#DEFAULT_FORMATTER} as display text, + * not used whilst editing. + * + * @param option option to bind controller to + * @param min minimum allowed value (clamped on apply) + * @param max maximum allowed value (clamped on apply) + */ + public IntegerFieldController(Option<Integer> option, int min, int max) { + this(option, min, max, IntegerSliderController.DEFAULT_FORMATTER); + } + + /** + * Constructs a double field controller. + * Does not have a minimum or a maximum range. + * + * @param option option to bind controller to + * @param formatter display text, not used whilst editing + */ + public IntegerFieldController(Option<Integer> option, Function<Integer, Text> formatter) { + this(option, -Integer.MAX_VALUE, Integer.MAX_VALUE, formatter); + } + + /** + * Constructs a double field controller. + * Uses {@link IntegerSliderController#DEFAULT_FORMATTER} as display text, + * not used whilst editing. + * Does not have a minimum or a maximum range. + * + * @param option option to bind controller to + */ + public IntegerFieldController(Option<Integer> option) { + this(option, -Integer.MAX_VALUE, Integer.MAX_VALUE, IntegerSliderController.DEFAULT_FORMATTER); + } + + @Override + public boolean isInputValid(String input) { + return input.matches("\\d+|-|"); + } + + /** + * {@inheritDoc} + */ + @Override + public double min() { + return this.min; + } + + /** + * {@inheritDoc} + */ + @Override + public double max() { + return this.max; + } + + /** + * {@inheritDoc} + */ + @Override + public String getString() { + return String.valueOf(option().pendingValue()); + } + + /** + * {@inheritDoc} + */ + @Override + public void setPendingValue(double value) { + option().requestSet((int) value); + } + + /** + * {@inheritDoc} + */ + @Override + public double pendingValue() { + return option().pendingValue(); + } +} diff --git a/src/client/java/dev/isxander/yacl/gui/controllers/string/number/LongFieldController.java b/src/client/java/dev/isxander/yacl/gui/controllers/string/number/LongFieldController.java new file mode 100644 index 0000000..516de74 --- /dev/null +++ b/src/client/java/dev/isxander/yacl/gui/controllers/string/number/LongFieldController.java @@ -0,0 +1,109 @@ +package dev.isxander.yacl.gui.controllers.string.number; + +import dev.isxander.yacl.api.Option; +import dev.isxander.yacl.gui.controllers.slider.LongSliderController; +import net.minecraft.text.Text; + +import java.util.function.Function; + +/** + * {@inheritDoc} + */ +public class LongFieldController extends NumberFieldController<Long> { + private final long min, max; + + /** + * Constructs a double field controller + * + * @param option option to bind controller to + * @param min minimum allowed value (clamped on apply) + * @param max maximum allowed value (clamped on apply) + * @param formatter display text, not used whilst editing + */ + public LongFieldController(Option<Long> option, long min, long max, Function<Long, Text> formatter) { + super(option, formatter); + this.min = min; + this.max = max; + } + + /** + * Constructs a double field controller. + * Uses {@link LongSliderController#DEFAULT_FORMATTER} as display text, + * not used whilst editing. + * + * @param option option to bind controller to + * @param min minimum allowed value (clamped on apply) + * @param max maximum allowed value (clamped on apply) + */ + public LongFieldController(Option<Long> option, long min, long max) { + this(option, min, max, LongSliderController.DEFAULT_FORMATTER); + } + + /** + * Constructs a double field controller. + * Does not have a minimum or a maximum range. + * + * @param option option to bind controller to + * @param formatter display text, not used whilst editing + */ + public LongFieldController(Option<Long> option, Function<Long, Text> formatter) { + this(option, -Long.MAX_VALUE, Long.MAX_VALUE, formatter); + } + + /** + * Constructs a double field controller. + * Uses {@link LongSliderController#DEFAULT_FORMATTER} as display text, + * not used whilst editing. + * Does not have a minimum or a maximum range. + * + * @param option option to bind controller to + */ + public LongFieldController(Option<Long> option) { + this(option, -Long.MAX_VALUE, Long.MAX_VALUE, LongSliderController.DEFAULT_FORMATTER); + } + + @Override + public boolean isInputValid(String input) { + return input.matches("\\d+|-|"); + } + + /** + * {@inheritDoc} + */ + @Override + public double min() { + return this.min; + } + + /** + * {@inheritDoc} + */ + @Override + public double max() { + return this.max; + } + + /** + * {@inheritDoc} + */ + @Override + public String getString() { + return String.valueOf(option().pendingValue()); + } + + /** + * {@inheritDoc} + */ + @Override + public void setPendingValue(double value) { + option().requestSet((long) value); + } + + /** + * {@inheritDoc} + */ + @Override + public double pendingValue() { + return option().pendingValue(); + } +} diff --git a/src/client/java/dev/isxander/yacl/gui/controllers/string/number/NumberFieldController.java b/src/client/java/dev/isxander/yacl/gui/controllers/string/number/NumberFieldController.java new file mode 100644 index 0000000..bf0354a --- /dev/null +++ b/src/client/java/dev/isxander/yacl/gui/controllers/string/number/NumberFieldController.java @@ -0,0 +1,69 @@ +package dev.isxander.yacl.gui.controllers.string.number; + +import dev.isxander.yacl.api.Option; +import dev.isxander.yacl.api.utils.Dimension; +import dev.isxander.yacl.gui.AbstractWidget; +import dev.isxander.yacl.gui.YACLScreen; +import dev.isxander.yacl.gui.controllers.slider.ISliderController; +import dev.isxander.yacl.gui.controllers.string.IStringController; +import dev.isxander.yacl.gui.controllers.string.StringControllerElement; +import net.minecraft.text.Text; +import net.minecraft.util.math.MathHelper; + +import java.text.DecimalFormatSymbols; +import java.util.function.Function; + +/** + * Controller that allows you to enter in numbers using a text field. + * + * @param <T> number type + */ +public abstract class NumberFieldController<T extends Number> implements ISliderController<T>, IStringController<T> { + private final Option<T> option; + private final Function<T, Text> displayFormatter; + + public NumberFieldController(Option<T> option, Function<T, Text> displayFormatter) { + this.option = option; + this.displayFormatter = displayFormatter; + } + + @Override + public Option<T> option() { + return this.option; + } + + @Override + public void setFromString(String value) { + if (value.isEmpty() || value.equals(".") || value.equals("-")) value = "0"; + setPendingValue(MathHelper.clamp(Double.parseDouble(cleanupNumberString(value)), min(), max())); + } + + @Override + public double pendingValue() { + return option().pendingValue().doubleValue(); + } + + @Override + public boolean isInputValid(String input) { + return input.matches("[+-]?([0-9]+([.][0-9]*)?|[.][0-9]+)|[.]||-"); + } + + @Override + public Text formatValue() { + return displayFormatter.apply(option().pendingValue()); + } + + @Override + public AbstractWidget provideWidget(YACLScreen screen, Dimension<Integer> widgetDimension) { + return new StringControllerElement(this, screen, widgetDimension, false); + } + + protected String cleanupNumberString(String number) { + return number.replace(String.valueOf(DecimalFormatSymbols.getInstance().getGroupingSeparator()), ""); + } + + @Override + public double interval() { + return -1; + } +} diff --git a/src/client/java/dev/isxander/yacl/gui/controllers/string/number/package-info.java b/src/client/java/dev/isxander/yacl/gui/controllers/string/number/package-info.java new file mode 100644 index 0000000..86b9314 --- /dev/null +++ b/src/client/java/dev/isxander/yacl/gui/controllers/string/number/package-info.java @@ -0,0 +1,10 @@ +/** + * This package contains implementations of input fields for different number types + * <ul> + * <li>For doubles: {@link dev.isxander.yacl.gui.controllers.string.number.DoubleFieldController}</li> + * <li>For floats: {@link dev.isxander.yacl.gui.controllers.string.number.FloatFieldController}</li> + * <li>For integers: {@link dev.isxander.yacl.gui.controllers.string.number.IntegerFieldController}</li> + * <li>For longs: {@link dev.isxander.yacl.gui.controllers.string.number.LongFieldController}</li> + * </ul> + */ +package dev.isxander.yacl.gui.controllers.string.number; diff --git a/src/main/java/dev/isxander/yacl/impl/ButtonOptionImpl.java b/src/client/java/dev/isxander/yacl/impl/ButtonOptionImpl.java index dcb9c7a..dcb9c7a 100644 --- a/src/main/java/dev/isxander/yacl/impl/ButtonOptionImpl.java +++ b/src/client/java/dev/isxander/yacl/impl/ButtonOptionImpl.java diff --git a/src/main/java/dev/isxander/yacl/impl/ConfigCategoryImpl.java b/src/client/java/dev/isxander/yacl/impl/ConfigCategoryImpl.java index 971fecf..971fecf 100644 --- a/src/main/java/dev/isxander/yacl/impl/ConfigCategoryImpl.java +++ b/src/client/java/dev/isxander/yacl/impl/ConfigCategoryImpl.java diff --git a/src/main/java/dev/isxander/yacl/impl/GenericBindingImpl.java b/src/client/java/dev/isxander/yacl/impl/GenericBindingImpl.java index 1867bb6..1867bb6 100644 --- a/src/main/java/dev/isxander/yacl/impl/GenericBindingImpl.java +++ b/src/client/java/dev/isxander/yacl/impl/GenericBindingImpl.java diff --git a/src/main/java/dev/isxander/yacl/impl/OptionGroupImpl.java b/src/client/java/dev/isxander/yacl/impl/OptionGroupImpl.java index 58bc96b..58bc96b 100644 --- a/src/main/java/dev/isxander/yacl/impl/OptionGroupImpl.java +++ b/src/client/java/dev/isxander/yacl/impl/OptionGroupImpl.java diff --git a/src/main/java/dev/isxander/yacl/impl/OptionImpl.java b/src/client/java/dev/isxander/yacl/impl/OptionImpl.java index c76f115..90158c7 100644 --- a/src/main/java/dev/isxander/yacl/impl/OptionImpl.java +++ b/src/client/java/dev/isxander/yacl/impl/OptionImpl.java @@ -6,7 +6,6 @@ import dev.isxander.yacl.api.Controller; import dev.isxander.yacl.api.Option; import dev.isxander.yacl.api.OptionFlag; import net.minecraft.text.Text; -import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/src/main/java/dev/isxander/yacl/impl/PlaceholderCategoryImpl.java b/src/client/java/dev/isxander/yacl/impl/PlaceholderCategoryImpl.java index a5180ad..a5180ad 100644 --- a/src/main/java/dev/isxander/yacl/impl/PlaceholderCategoryImpl.java +++ b/src/client/java/dev/isxander/yacl/impl/PlaceholderCategoryImpl.java diff --git a/src/main/java/dev/isxander/yacl/impl/YetAnotherConfigLibImpl.java b/src/client/java/dev/isxander/yacl/impl/YetAnotherConfigLibImpl.java index eb23eac..eb23eac 100644 --- a/src/main/java/dev/isxander/yacl/impl/YetAnotherConfigLibImpl.java +++ b/src/client/java/dev/isxander/yacl/impl/YetAnotherConfigLibImpl.java diff --git a/src/main/java/dev/isxander/yacl/mixin/SimpleOptionAccessor.java b/src/client/java/dev/isxander/yacl/mixin/client/SimpleOptionAccessor.java index 9207225..a48c808 100644 --- a/src/main/java/dev/isxander/yacl/mixin/SimpleOptionAccessor.java +++ b/src/client/java/dev/isxander/yacl/mixin/client/SimpleOptionAccessor.java @@ -1,4 +1,4 @@ -package dev.isxander.yacl.mixin; +package dev.isxander.yacl.mixin.client; import net.minecraft.client.option.SimpleOption; import org.spongepowered.asm.mixin.Mixin; diff --git a/src/main/resources/yet-another-config-lib.mixins.json b/src/client/resources/yet-another-config-lib.client.mixins.json index cb96c48..2367a67 100644 --- a/src/main/resources/yet-another-config-lib.mixins.json +++ b/src/client/resources/yet-another-config-lib.client.mixins.json @@ -1,6 +1,6 @@ { "required": true, - "package": "dev.isxander.yacl.mixin", + "package": "dev.isxander.yacl.mixin.client", "compatibilityLevel": "JAVA_17", "injectors": { "defaultRequire": 1 diff --git a/src/main/java/dev/isxander/yacl/config/ConfigInstance.java b/src/main/java/dev/isxander/yacl/config/ConfigInstance.java index a7c013c..aa67865 100644 --- a/src/main/java/dev/isxander/yacl/config/ConfigInstance.java +++ b/src/main/java/dev/isxander/yacl/config/ConfigInstance.java @@ -1,9 +1,9 @@ package dev.isxander.yacl.config; -import dev.isxander.yacl.api.YetAnotherConfigLib; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.lang.reflect.InvocationTargetException; -import java.util.function.BiFunction; /** * Responsible for handing the actual config data type. @@ -30,6 +30,9 @@ public abstract class ConfigInstance<T> { } } + public abstract void save(); + public abstract void load(); + public T getConfig() { return this.instance; } @@ -45,11 +48,4 @@ public abstract class ConfigInstance<T> { 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/gui/controllers/EnumController.java b/src/main/java/dev/isxander/yacl/gui/controllers/EnumController.java deleted file mode 100644 index ebad4ae..0000000 --- a/src/main/java/dev/isxander/yacl/gui/controllers/EnumController.java +++ /dev/null @@ -1,35 +0,0 @@ -package dev.isxander.yacl.gui.controllers; - -import dev.isxander.yacl.api.NameableEnum; -import dev.isxander.yacl.api.Option; -import dev.isxander.yacl.gui.controllers.cycling.CyclingListController; -import net.minecraft.text.Text; -import net.minecraft.util.TranslatableOption; - -import java.util.Arrays; -import java.util.function.Function; - -@Deprecated -public class EnumController<T extends Enum<T>> extends CyclingListController<T> { - public static <T extends Enum<T>> Function<T, Text> getDefaultFormatter() { - return value -> { - if (value instanceof NameableEnum nameableEnum) - return nameableEnum.getDisplayName(); - if (value instanceof TranslatableOption translatableOption) - return translatableOption.getText(); - return Text.of(value.toString()); - }; - } - - public EnumController(Option<T> option) { - this(option, getDefaultFormatter()); - } - - public EnumController(Option<T> option, Function<T, Text> valueFormatter) { - this(option, valueFormatter, option.typeClass().getEnumConstants()); - } - - public EnumController(Option<T> option, Function<T, Text> valueFormatter, T[] availableValues) { - super(option, Arrays.asList(availableValues), valueFormatter); - } -} diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index fc5a14f..90889a0 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -14,17 +14,21 @@ }, "icon": "yacl-128x.png", "license": "LGPL-3.0-or-later", - "environment": "client", + "environment": "*", "entrypoints": { }, "depends": { "fabricloader": ">=0.14.0", - "minecraft": "1.19.x", - "java": ">=17" + "minecraft": "~1.19.3-beta.1", + "java": ">=17", + "fabric-resource-loader-v0": "*" }, "mixins": [ - "yet-another-config-lib.mixins.json" + { + "config": "yet-another-config-lib.client.mixins.json", + "environment": "client" + } ], "accessWidener": "yacl.accesswidener", "custom": { diff --git a/src/testmod/java/dev/isxander/yacl/test/ModMenuIntegration.java b/src/testmod/java/dev/isxander/yacl/test/GuiTest.java index 596a0bf..492a573 100644 --- a/src/testmod/java/dev/isxander/yacl/test/ModMenuIntegration.java +++ b/src/testmod/java/dev/isxander/yacl/test/GuiTest.java @@ -1,7 +1,5 @@ package dev.isxander.yacl.test; -import com.terraformersmc.modmenu.api.ConfigScreenFactory; -import com.terraformersmc.modmenu.api.ModMenuApi; import dev.isxander.yacl.api.*; import dev.isxander.yacl.gui.RequireRestartScreen; import dev.isxander.yacl.gui.controllers.*; @@ -11,6 +9,10 @@ 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.gui.controllers.string.number.DoubleFieldController; +import dev.isxander.yacl.gui.controllers.string.number.FloatFieldController; +import dev.isxander.yacl.gui.controllers.string.number.IntegerFieldController; +import dev.isxander.yacl.gui.controllers.string.number.LongFieldController; import dev.isxander.yacl.test.config.ConfigData; import dev.isxander.yacl.test.config.Entrypoint; import net.minecraft.client.MinecraftClient; @@ -23,10 +25,9 @@ import net.minecraft.text.Text; import java.awt.*; -public class ModMenuIntegration implements ModMenuApi { - @Override - public ConfigScreenFactory<?> getModConfigScreenFactory() { - return (parent) -> Entrypoint.getConfig().buildConfig((config, builder) -> builder +public class GuiTest { + public static Screen getModConfigScreenFactory(Screen parent) { + return YetAnotherConfigLib.create(Entrypoint.getConfig(), (defaults, config, builder) -> builder .title(Text.of("Test Suites")) .category(ConfigCategory.createBuilder() .name(Text.of("Suites")) @@ -55,8 +56,8 @@ public class ModMenuIntegration implements ModMenuApi { .generateScreen(parent); } - private Screen getFullTestSuite(Screen parent) { - return Entrypoint.getConfig().buildConfig((config, builder) -> builder + private static Screen getFullTestSuite(Screen parent) { + return YetAnotherConfigLib.create(Entrypoint.getConfig(), (defaults, config, builder) -> builder .title(Text.of("Test GUI")) .category(ConfigCategory.createBuilder() .name(Text.of("Control Examples")) @@ -69,9 +70,9 @@ public class ModMenuIntegration implements ModMenuApi { .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 + defaults.booleanToggle, + () -> config.booleanToggle, + (value) -> config.booleanToggle = value ) .controller(BooleanController::new) .flag(OptionFlag.GAME_RESTART) @@ -81,19 +82,19 @@ public class ModMenuIntegration implements ModMenuApi { .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 + defaults.customBooleanToggle, + () -> config.customBooleanToggle, + (value) -> config.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")) + .name(Text.of("Tick Box aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")) .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 + defaults.tickbox, + () -> config.tickbox, + (value) -> config.tickbox = value ) .controller(TickBoxController::new) .build()) @@ -104,9 +105,9 @@ public class ModMenuIntegration implements ModMenuApi { .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 + defaults.intSlider, + () -> config.intSlider, + value -> config.intSlider = value ) .controller(opt -> new IntegerSliderController(opt, 0, 3, 1)) @@ -114,27 +115,27 @@ public class ModMenuIntegration implements ModMenuApi { .option(Option.createBuilder(double.class) .name(Text.of("Double Slider")) .binding( - config.getDefaults().doubleSlider, - () -> config.getConfig().doubleSlider, - (value) -> config.getConfig().doubleSlider = value + defaults.doubleSlider, + () -> config.doubleSlider, + (value) -> config.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 + defaults.floatSlider, + () -> config.floatSlider, + (value) -> config.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 + defaults.longSlider, + () -> config.longSlider, + (value) -> config.longSlider = value ) .controller(opt -> new LongSliderController(opt, 0, 1_000_000, 100)) .build()) @@ -144,30 +145,69 @@ public class ModMenuIntegration implements ModMenuApi { .option(Option.createBuilder(String.class) .name(Text.of("Text Option")) .binding( - config.getDefaults().textField, - () -> config.getConfig().textField, - value -> config.getConfig().textField = value + defaults.textField, + () -> config.textField, + value -> config.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 + defaults.colorOption, + () -> config.colorOption, + value -> config.colorOption = value ) .controller(ColorController::new) .build()) .build()) .group(OptionGroup.createBuilder() + .name(Text.of("Number Fields")) + .option(Option.createBuilder(double.class) + .name(Text.of("Double Field")) + .binding( + defaults.doubleField, + () -> config.doubleField, + value -> config.doubleField = value + ) + .controller(DoubleFieldController::new) + .build()) + .option(Option.createBuilder(float.class) + .name(Text.of("Float Field")) + .binding( + defaults.floatField, + () -> config.floatField, + value -> config.floatField = value + ) + .controller(FloatFieldController::new) + .build()) + .option(Option.createBuilder(int.class) + .name(Text.of("Integer Field")) + .binding( + defaults.intField, + () -> config.intField, + value -> config.intField = value + ) + .controller(IntegerFieldController::new) + .build()) + .option(Option.createBuilder(long.class) + .name(Text.of("Long Field")) + .binding( + defaults.longField, + () -> config.longField, + value -> config.longField = value + ) + .controller(LongFieldController::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 + defaults.enumOption, + () -> config.enumOption, + (value) -> config.enumOption = value ) .controller(EnumController::new) .build()) @@ -215,9 +255,9 @@ public class ModMenuIntegration implements ModMenuApi { .option(Option.createBuilder(boolean.class) .name(Text.of("Root Test")) .binding( - config.getDefaults().groupTestRoot, - () -> config.getConfig().groupTestRoot, - value -> config.getConfig().groupTestRoot = value + defaults.groupTestRoot, + () -> config.groupTestRoot, + value -> config.groupTestRoot = value ) .controller(TickBoxController::new) .build()) @@ -226,18 +266,18 @@ public class ModMenuIntegration implements ModMenuApi { .option(Option.createBuilder(boolean.class) .name(Text.of("First Group Test 1")) .binding( - config.getDefaults().groupTestFirstGroup, - () -> config.getConfig().groupTestFirstGroup, - value -> config.getConfig().groupTestFirstGroup = value + defaults.groupTestFirstGroup, + () -> config.groupTestFirstGroup, + value -> config.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 + defaults.groupTestFirstGroup2, + () -> config.groupTestFirstGroup2, + value -> config.groupTestFirstGroup2 = value ) .controller(TickBoxController::new) .build()) @@ -247,9 +287,9 @@ public class ModMenuIntegration implements ModMenuApi { .option(Option.createBuilder(boolean.class) .name(Text.of("Second Group Test")) .binding( - config.getDefaults().groupTestSecondGroup, - () -> config.getConfig().groupTestSecondGroup, - value -> config.getConfig().groupTestSecondGroup = value + defaults.groupTestSecondGroup, + () -> config.groupTestSecondGroup, + value -> config.groupTestSecondGroup = value ) .controller(TickBoxController::new) .build()) @@ -260,9 +300,9 @@ public class ModMenuIntegration implements ModMenuApi { .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 + defaults.scrollingSlider, + () -> config.scrollingSlider, + (value) -> config.scrollingSlider = value ) .controller(opt -> new IntegerSliderController(opt, 0, 10, 1)) .build()) @@ -334,14 +374,14 @@ public class ModMenuIntegration implements ModMenuApi { .build()) .save(() -> { MinecraftClient.getInstance().options.write(); - config.save(); + Entrypoint.getConfig().save(); }) ) .generateScreen(parent); } - private Screen getDisabledTest(Screen parent) { - return Entrypoint.getConfig().buildConfig((config, builder) -> builder + private static Screen getDisabledTest(Screen parent) { + return YetAnotherConfigLib.create(Entrypoint.getConfig(), (defaults, config, builder) -> builder .title(Text.empty()) .category(ConfigCategory.createBuilder() .name(Text.of("Disabled Test")) @@ -373,8 +413,8 @@ public class ModMenuIntegration implements ModMenuApi { .generateScreen(parent); } - private Screen getWikiBasic(Screen parent) { - return Entrypoint.getConfig().buildConfig((config, builder) -> builder + private static Screen getWikiBasic(Screen parent) { + return YetAnotherConfigLib.create(Entrypoint.getConfig(), (defaults, config, builder) -> builder .title(Text.of("Mod Name")) .category(ConfigCategory.createBuilder() .name(Text.of("My Category")) @@ -383,9 +423,9 @@ public class ModMenuIntegration implements ModMenuApi { .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 + defaults.booleanToggle, // default + () -> config.booleanToggle, // getter + newValue -> config.booleanToggle = newValue // setter ) .controller(BooleanController::new) .build()) @@ -394,8 +434,8 @@ public class ModMenuIntegration implements ModMenuApi { .generateScreen(parent); } - private Screen getWikiGroups(Screen parent) { - return Entrypoint.getConfig().buildConfig((config, builder) -> builder + private static Screen getWikiGroups(Screen parent) { + return YetAnotherConfigLib.create(Entrypoint.getConfig(), (defaults, config, builder) -> builder .title(Text.of("Mod Name")) .category(ConfigCategory.createBuilder() .name(Text.of("My Category")) @@ -406,9 +446,9 @@ public class ModMenuIntegration implements ModMenuApi { .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 + defaults.booleanToggle, // default + () -> config.booleanToggle, // getter + newValue -> config.booleanToggle = newValue // setter ) .controller(BooleanController::new) .build()) @@ -417,21 +457,4 @@ public class ModMenuIntegration implements ModMenuApi { ) .generateScreen(parent); } - - private ConfigScreenFactory<?> getWikiButton() { - 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); - } } diff --git a/src/testmod/java/dev/isxander/yacl/test/config/ConfigData.java b/src/testmod/java/dev/isxander/yacl/test/config/ConfigData.java index 35e57dd..4eedd9f 100644 --- a/src/testmod/java/dev/isxander/yacl/test/config/ConfigData.java +++ b/src/testmod/java/dev/isxander/yacl/test/config/ConfigData.java @@ -14,6 +14,10 @@ public class ConfigData { @ConfigEntry public long longSlider = 0; @ConfigEntry public String textField = "Hello"; @ConfigEntry public Color colorOption = Color.red; + @ConfigEntry public double doubleField = 0.5; + @ConfigEntry public float floatField = 0.5f; + @ConfigEntry public int intField = 5; + @ConfigEntry public long longField = 5; @ConfigEntry public Alphabet enumOption = Alphabet.A; @ConfigEntry public boolean groupTestRoot = false; diff --git a/src/testmod/java/dev/isxander/yacl/test/config/Entrypoint.java b/src/testmod/java/dev/isxander/yacl/test/config/Entrypoint.java index 39baffa..c71f592 100644 --- a/src/testmod/java/dev/isxander/yacl/test/config/Entrypoint.java +++ b/src/testmod/java/dev/isxander/yacl/test/config/Entrypoint.java @@ -1,13 +1,12 @@ package dev.isxander.yacl.test.config; -import com.google.gson.Gson; import dev.isxander.yacl.config.ConfigInstance; import dev.isxander.yacl.config.GsonConfigInstance; import net.fabricmc.api.ClientModInitializer; import net.fabricmc.loader.api.FabricLoader; public class Entrypoint implements ClientModInitializer { - private static GsonConfigInstance<ConfigData> config; + private static ConfigInstance<ConfigData> config; @Override public void onInitializeClient() { diff --git a/src/testmod/java/dev/isxander/yacl/test/mixins/TitleScreenMixin.java b/src/testmod/java/dev/isxander/yacl/test/mixins/TitleScreenMixin.java new file mode 100644 index 0000000..2635eaf --- /dev/null +++ b/src/testmod/java/dev/isxander/yacl/test/mixins/TitleScreenMixin.java @@ -0,0 +1,26 @@ +package dev.isxander.yacl.test.mixins; + +import dev.isxander.yacl.test.GuiTest; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.screen.TitleScreen; +import net.minecraft.client.gui.widget.ButtonWidget; +import net.minecraft.text.Text; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(TitleScreen.class) +public abstract class TitleScreenMixin extends Screen { + protected TitleScreenMixin(Text title) { + super(title); + } + + @Inject(method = "init", at = @At("RETURN")) + private void injectTestButton(CallbackInfo ci) { + addDrawableChild(ButtonWidget.builder(Text.of("YACL"), button -> client.setScreen(GuiTest.getModConfigScreenFactory(client.currentScreen))) + .position(0, 0) + .width(50) + .build()); + } +} diff --git a/src/testmod/resources/fabric.mod.json b/src/testmod/resources/fabric.mod.json index 1360a5e..5fe0919 100644 --- a/src/testmod/resources/fabric.mod.json +++ b/src/testmod/resources/fabric.mod.json @@ -11,15 +11,12 @@ "entrypoints": { "client": [ "dev.isxander.yacl.test.config.Entrypoint" - ], - "modmenu": [ - "dev.isxander.yacl.test.ModMenuIntegration" ] }, "depends": { - "fabricloader": ">=0.14.0", - "minecraft": "1.19.x", - "java": ">=17", - "fabric-resource-loader-v0": "*" - } + "yet-another-config-lib": "*" + }, + "mixins": [ + "yet-another-config-lib.test.mixins.json" + ] } diff --git a/src/testmod/resources/yet-another-config-lib.test.mixins.json b/src/testmod/resources/yet-another-config-lib.test.mixins.json new file mode 100644 index 0000000..9287cdd --- /dev/null +++ b/src/testmod/resources/yet-another-config-lib.test.mixins.json @@ -0,0 +1,11 @@ +{ + "required": true, + "package": "dev.isxander.yacl.test.mixins", + "compatibilityLevel": "JAVA_17", + "injectors": { + "defaultRequire": 1 + }, + "client": [ + "TitleScreenMixin" + ] +} |