aboutsummaryrefslogtreecommitdiff
path: root/src/compat/yacl/java/YaclIntegration.kt
blob: 6c9354a231072b60356c4c1a60b7f2238136e87a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
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)
	}

}