aboutsummaryrefslogtreecommitdiff
path: root/src/compat
diff options
context:
space:
mode:
authorLinnea Gräf <nea@nea.moe>2024-10-13 19:53:10 +0200
committerLinnea Gräf <nea@nea.moe>2024-10-13 19:53:10 +0200
commit87b851373071490bb371ba1160f85f0341579cb2 (patch)
tree45d267d83baad2e3cb6caad6127f6a4d40e7fcbf /src/compat
parente6142bb93619dee768fc18b87ffdd28558d4bcab (diff)
downloadFirmament-87b851373071490bb371ba1160f85f0341579cb2.tar.gz
Firmament-87b851373071490bb371ba1160f85f0341579cb2.tar.bz2
Firmament-87b851373071490bb371ba1160f85f0341579cb2.zip
Add YACL config menu
Diffstat (limited to 'src/compat')
-rw-r--r--src/compat/yacl/java/KeybindingBuilder.kt16
-rw-r--r--src/compat/yacl/java/KeybindingController.kt71
-rw-r--r--src/compat/yacl/java/YaclIntegration.kt119
3 files changed, 206 insertions, 0 deletions
diff --git a/src/compat/yacl/java/KeybindingBuilder.kt b/src/compat/yacl/java/KeybindingBuilder.kt
new file mode 100644
index 0000000..322ddff
--- /dev/null
+++ b/src/compat/yacl/java/KeybindingBuilder.kt
@@ -0,0 +1,16 @@
+package moe.nea.firmament.compat.yacl
+
+import dev.isxander.yacl3.api.Controller
+import dev.isxander.yacl3.api.Option
+import dev.isxander.yacl3.api.controller.ControllerBuilder
+import moe.nea.firmament.gui.config.ManagedOption
+import moe.nea.firmament.keybindings.SavedKeyBinding
+
+class KeybindingBuilder(
+ val option: Option<SavedKeyBinding>,
+ val managedOption: ManagedOption<SavedKeyBinding>
+) : ControllerBuilder<SavedKeyBinding> {
+ override fun build(): Controller<SavedKeyBinding> {
+ return KeybindingController(option, managedOption)
+ }
+}
diff --git a/src/compat/yacl/java/KeybindingController.kt b/src/compat/yacl/java/KeybindingController.kt
new file mode 100644
index 0000000..6be9dd1
--- /dev/null
+++ b/src/compat/yacl/java/KeybindingController.kt
@@ -0,0 +1,71 @@
+package moe.nea.firmament.compat.yacl
+
+import dev.isxander.yacl3.api.Controller
+import dev.isxander.yacl3.api.Option
+import dev.isxander.yacl3.api.utils.Dimension
+import dev.isxander.yacl3.gui.AbstractWidget
+import dev.isxander.yacl3.gui.YACLScreen
+import dev.isxander.yacl3.gui.controllers.ControllerWidget
+import net.minecraft.text.Text
+import moe.nea.firmament.gui.config.KeyBindingHandler
+import moe.nea.firmament.gui.config.KeyBindingStateManager
+import moe.nea.firmament.gui.config.ManagedOption
+import moe.nea.firmament.keybindings.SavedKeyBinding
+
+class KeybindingController(
+ val option: Option<SavedKeyBinding>,
+ val managedOption: ManagedOption<SavedKeyBinding>,
+) : Controller<SavedKeyBinding> {
+ val handler = managedOption.handler as KeyBindingHandler
+ override fun option(): Option<SavedKeyBinding> {
+ return option
+ }
+
+ override fun formatValue(): Text {
+ return option.pendingValue().format()
+ }
+
+ override fun provideWidget(screen: YACLScreen, widgetDimension: Dimension<Int>): AbstractWidget {
+ lateinit var button: ControllerWidget<KeybindingController>
+ val sm = KeyBindingStateManager(
+ { option.pendingValue() },
+ { option.requestSet(it) },
+ { screen.focused = null },
+ { screen.focused = button }
+ )
+ button = object : ControllerWidget<KeybindingController>(this, screen, widgetDimension) {
+ override fun getHoveredControlWidth(): Int {
+ return 130
+ }
+
+ override fun getValueText(): Text {
+ return sm.label
+ }
+
+ override fun keyPressed(keyCode: Int, scanCode: Int, modifiers: Int): Boolean {
+ return sm.keyboardEvent(keyCode, true)
+ }
+
+ override fun keyReleased(keyCode: Int, scanCode: Int, modifiers: Int): Boolean {
+ return sm.keyboardEvent(keyCode, false)
+ }
+
+ override fun unfocus() {
+ sm.onLostFocus()
+ }
+
+ override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
+ if (button == 0 && isHovered) {
+ sm.onClick()
+ return true
+ }
+ return super.mouseClicked(mouseX, mouseY, button)
+ }
+ }
+ option.addListener { t, u ->
+ sm.updateLabel()
+ }
+ sm.updateLabel()
+ return button
+ }
+}
diff --git a/src/compat/yacl/java/YaclIntegration.kt b/src/compat/yacl/java/YaclIntegration.kt
new file mode 100644
index 0000000..6c9354a
--- /dev/null
+++ b/src/compat/yacl/java/YaclIntegration.kt
@@ -0,0 +1,119 @@
+package moe.nea.firmament.compat.yacl
+
+import com.google.auto.service.AutoService
+import dev.isxander.yacl3.api.Binding
+import dev.isxander.yacl3.api.ButtonOption
+import dev.isxander.yacl3.api.ConfigCategory
+import dev.isxander.yacl3.api.LabelOption
+import dev.isxander.yacl3.api.Option
+import dev.isxander.yacl3.api.YetAnotherConfigLib
+import dev.isxander.yacl3.api.controller.ControllerBuilder
+import dev.isxander.yacl3.api.controller.DoubleSliderControllerBuilder
+import dev.isxander.yacl3.api.controller.IntegerSliderControllerBuilder
+import dev.isxander.yacl3.api.controller.StringControllerBuilder
+import dev.isxander.yacl3.api.controller.TickBoxControllerBuilder
+import kotlin.time.Duration
+import kotlin.time.Duration.Companion.seconds
+import kotlin.time.DurationUnit
+import net.minecraft.client.gui.screen.Screen
+import net.minecraft.text.Text
+import moe.nea.firmament.gui.config.AllConfigsGui
+import moe.nea.firmament.gui.config.BooleanHandler
+import moe.nea.firmament.gui.config.ClickHandler
+import moe.nea.firmament.gui.config.DurationHandler
+import moe.nea.firmament.gui.config.FirmamentConfigScreenProvider
+import moe.nea.firmament.gui.config.HudMeta
+import moe.nea.firmament.gui.config.HudMetaHandler
+import moe.nea.firmament.gui.config.IntegerHandler
+import moe.nea.firmament.gui.config.KeyBindingHandler
+import moe.nea.firmament.gui.config.ManagedConfig
+import moe.nea.firmament.gui.config.ManagedOption
+import moe.nea.firmament.gui.config.StringHandler
+import moe.nea.firmament.keybindings.SavedKeyBinding
+import moe.nea.firmament.util.FirmFormatters
+
+
+@AutoService(FirmamentConfigScreenProvider::class)
+class YaclIntegration : FirmamentConfigScreenProvider {
+ fun buildCategories() =
+ AllConfigsGui.allConfigs
+ .map(::buildCategory)
+
+ private fun buildCategory(managedConfig: ManagedConfig): ConfigCategory {
+ return ConfigCategory.createBuilder()
+ .name(managedConfig.labelText)
+ .also {
+ it.rootGroupBuilder()
+ .options(buildOptions(managedConfig.sortedOptions))
+ }
+ .build()
+ }
+
+ fun buildOptions(options: List<ManagedOption<*>>): Collection<Option<*>> =
+ options.map { buildOption(it) }
+
+ private fun <T : Any> buildOption(managedOption: ManagedOption<T>): Option<*> {
+ val handler = managedOption.handler
+ val binding = Binding.generic(managedOption.default(), managedOption::value, managedOption::value.setter)
+ fun <T> createDefaultBinding(function: (Option<T>) -> ControllerBuilder<T>): Option.Builder<T> {
+ return Option.createBuilder<T>()
+ .name(managedOption.labelText)
+ .binding(binding as Binding<T>)
+ .controller { function(it) }
+ }
+ when (handler) {
+ is ClickHandler -> return ButtonOption.createBuilder()
+ .name(managedOption.labelText)
+ .action { t, u ->
+ handler.runnable()
+ }
+ .build()
+
+ is HudMetaHandler -> return ButtonOption.createBuilder()
+ .name(managedOption.labelText)
+ .action { t, u ->
+ handler.openEditor(managedOption as ManagedOption<HudMeta>, t)
+ }
+ .build()
+
+ is BooleanHandler -> return createDefaultBinding(TickBoxControllerBuilder::create).build()
+ is StringHandler -> return createDefaultBinding(StringControllerBuilder::create).build()
+ is IntegerHandler -> return createDefaultBinding {
+ IntegerSliderControllerBuilder.create(it).range(handler.min, handler.max).step(1)
+ }.build()
+
+ is DurationHandler -> return Option.createBuilder<Double>()
+ .name(managedOption.labelText)
+ .binding((binding as Binding<Duration>).xmap({ it.toDouble(DurationUnit.SECONDS) }, { it.seconds }))
+ .controller {
+ DoubleSliderControllerBuilder.create(it)
+ .formatValue { Text.literal(FirmFormatters.formatTimespan(it.seconds)) }
+ .step(0.1)
+ .range(handler.min.toDouble(DurationUnit.SECONDS), handler.max.toDouble(DurationUnit.SECONDS))
+ }
+ .build()
+
+ is KeyBindingHandler -> return createDefaultBinding {
+ KeybindingBuilder(it, managedOption as ManagedOption<SavedKeyBinding>)
+ }.build()
+
+ else -> return LabelOption.create(Text.literal("This option is currently unhandled for this config menu. Please report this as a bug."))
+ }
+ }
+
+
+ fun buildConfig(): YetAnotherConfigLib {
+ return YetAnotherConfigLib.createBuilder()
+ .title(Text.literal("Firmament"))
+ .categories(buildCategories())
+ .build()
+ }
+
+ override val key: String
+ get() = "yacl"
+
+ override fun open(parent: Screen?): Screen {
+ return buildConfig().generateScreen(parent)
+ }
+
+}