Add YACL config menu

This commit is contained in:
Linnea Gräf
2024-10-13 19:53:10 +02:00
parent e6142bb936
commit 87b8513730
13 changed files with 567 additions and 306 deletions

View File

@@ -12,39 +12,40 @@ import moe.nea.firmament.util.ScreenUtil.setScreenLater
object AllConfigsGui {
val allConfigs
get() = listOf(
RepoManager.Config
) + FeatureManager.allFeatures.mapNotNull { it.config }
val allConfigs
get() = listOf(
RepoManager.Config
) + FeatureManager.allFeatures.mapNotNull { it.config }
fun <T> List<T>.toObservableList(): ObservableList<T> = ObservableList(this)
fun <T> List<T>.toObservableList(): ObservableList<T> = ObservableList(this)
class MainMapping(val allConfigs: List<ManagedConfig>) {
@get:Bind("configs")
val configs = allConfigs.map { EntryMapping(it) }.toObservableList()
class MainMapping(val allConfigs: List<ManagedConfig>) {
@get:Bind("configs")
val configs = allConfigs.map { EntryMapping(it) }.toObservableList()
class EntryMapping(val config: ManagedConfig) {
@Bind
fun name() = Text.translatable("firmament.config.${config.name}").string
class EntryMapping(val config: ManagedConfig) {
@Bind
fun name() = Text.translatable("firmament.config.${config.name}").string
@Bind
fun openEditor() {
config.showConfigEditor(MC.screen)
}
}
}
@Bind
fun openEditor() {
config.showConfigEditor(MC.screen)
}
}
}
fun makeBuiltInScreen(parent: Screen? = null): Screen {
return MoulConfigUtils.loadScreen("config/main", MainMapping(allConfigs), parent)
}
fun makeBuiltInScreen(parent: Screen? = null): Screen {
return MoulConfigUtils.loadScreen("config/main", MainMapping(allConfigs), parent)
}
fun makeScreen(parent: Screen? = null): Screen {
val provider = FirmamentConfigScreenProvider.providers.find { it.key == "builtin" }
?: FirmamentConfigScreenProvider.providers.first()
return provider.open(parent)
}
fun makeScreen(parent: Screen? = null): Screen {
val wantedKey = if (RepoManager.Config.enableYacl) "yacl" else "builtin"
val provider = FirmamentConfigScreenProvider.providers.find { it.key == wantedKey }
?: FirmamentConfigScreenProvider.providers.first()
return provider.open(parent)
}
fun showAllGuis() {
setScreenLater(makeScreen())
}
fun showAllGuis() {
setScreenLater(makeScreen())
}
}

View File

@@ -6,22 +6,29 @@ import net.minecraft.client.gui.screen.Screen
import moe.nea.firmament.Firmament
interface FirmamentConfigScreenProvider {
val key: String
val isEnabled: Boolean get() = true
val key: String
val isEnabled: Boolean get() = true
fun open(parent: Screen?): Screen
fun open(parent: Screen?): Screen
companion object {
private val loader = ServiceLoader.load(FirmamentConfigScreenProvider::class.java)
companion object {
private val loader = ServiceLoader.load(FirmamentConfigScreenProvider::class.java)
val providers by lazy {
loader.stream().asSequence().mapNotNull { service ->
kotlin.runCatching { service.get() }
.getOrElse {
Firmament.logger.warn("Could not load config provider ${service.type()}", it)
null
}
}.filter { it.isEnabled }.toList()
}
}
val providers by lazy {
loader.stream().asSequence().mapNotNull { service ->
kotlin.runCatching { service.get() }
.getOrElse {
Firmament.logger.warn("Could not load config provider ${service.type()}", it)
null
}
}.filter { it.isEnabled }
.sortedWith(Comparator.comparing(
{ it.key },
Comparator<String> { left, right ->
if (left == "builtin") return@Comparator -1
if (right == "builtin") return@Comparator 1
return@Comparator left.compareTo(right)
})).toList()
}
}
}

View File

@@ -1,5 +1,3 @@
package moe.nea.firmament.gui.config
import io.github.notenoughupdates.moulconfig.gui.component.TextComponent
@@ -7,6 +5,7 @@ import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.decodeFromJsonElement
import kotlinx.serialization.json.encodeToJsonElement
import net.minecraft.client.gui.screen.Screen
import net.minecraft.text.MutableText
import net.minecraft.text.Text
import moe.nea.firmament.gui.FirmButtonComponent
@@ -14,26 +13,30 @@ import moe.nea.firmament.jarvis.JarvisIntegration
import moe.nea.firmament.util.MC
class HudMetaHandler(val config: ManagedConfig, val label: MutableText, val width: Int, val height: Int) :
ManagedConfig.OptionHandler<HudMeta> {
override fun toJson(element: HudMeta): JsonElement? {
return Json.encodeToJsonElement(element.position)
}
ManagedConfig.OptionHandler<HudMeta> {
override fun toJson(element: HudMeta): JsonElement? {
return Json.encodeToJsonElement(element.position)
}
override fun fromJson(element: JsonElement): HudMeta {
return HudMeta(Json.decodeFromJsonElement(element), label, width, height)
}
override fun fromJson(element: JsonElement): HudMeta {
return HudMeta(Json.decodeFromJsonElement(element), label, width, height)
}
override fun emitGuiElements(opt: ManagedOption<HudMeta>, guiAppender: GuiAppender) {
guiAppender.appendLabeledRow(
opt.labelText,
FirmButtonComponent(
TextComponent(
Text.stringifiedTranslatable("firmament.hud.edit", label).string),
) {
MC.screen = JarvisIntegration.jarvis.getHudEditor(
guiAppender.screenAccessor.invoke(),
listOf(opt.value)
)
})
}
fun openEditor(option: ManagedOption<HudMeta>, oldScreen: Screen) {
MC.screen = JarvisIntegration.jarvis.getHudEditor(
oldScreen,
listOf(option.value)
)
}
override fun emitGuiElements(opt: ManagedOption<HudMeta>, guiAppender: GuiAppender) {
guiAppender.appendLabeledRow(
opt.labelText,
FirmButtonComponent(
TextComponent(
Text.stringifiedTranslatable("firmament.hud.edit", label).string),
) {
openEditor(opt, guiAppender.screenAccessor())
})
}
}

View File

@@ -1,5 +1,3 @@
package moe.nea.firmament.gui.config
import io.github.notenoughupdates.moulconfig.common.IMinecraft
@@ -13,137 +11,63 @@ import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.decodeFromJsonElement
import kotlinx.serialization.json.encodeToJsonElement
import net.minecraft.text.Text
import net.minecraft.util.Formatting
import moe.nea.firmament.gui.FirmButtonComponent
import moe.nea.firmament.keybindings.FirmamentKeyBindings
import moe.nea.firmament.keybindings.SavedKeyBinding
class KeyBindingHandler(val name: String, val managedConfig: ManagedConfig) :
ManagedConfig.OptionHandler<SavedKeyBinding> {
ManagedConfig.OptionHandler<SavedKeyBinding> {
override fun initOption(opt: ManagedOption<SavedKeyBinding>) {
FirmamentKeyBindings.registerKeyBinding(name, opt)
}
override fun initOption(opt: ManagedOption<SavedKeyBinding>) {
FirmamentKeyBindings.registerKeyBinding(name, opt)
}
override fun toJson(element: SavedKeyBinding): JsonElement? {
return Json.encodeToJsonElement(element)
}
override fun toJson(element: SavedKeyBinding): JsonElement? {
return Json.encodeToJsonElement(element)
}
override fun fromJson(element: JsonElement): SavedKeyBinding {
return Json.decodeFromJsonElement(element)
}
override fun fromJson(element: JsonElement): SavedKeyBinding {
return Json.decodeFromJsonElement(element)
}
override fun emitGuiElements(opt: ManagedOption<SavedKeyBinding>, guiAppender: GuiAppender) {
var editing = false
var lastPressed = 0
var lastPressedNonModifier = 0
var label: String = ""
var button: FirmButtonComponent? = null
fun updateLabel() {
var stroke = opt.value.format()
if (editing) {
stroke = Text.literal("")
val (shift, alt, ctrl) = SavedKeyBinding.getMods(SavedKeyBinding.getModInt())
if (shift) {
stroke.append("SHIFT + ")
}
if (alt) {
stroke.append("ALT + ")
}
if (ctrl) {
stroke.append("CTRL + ")
}
stroke.append("???")
stroke.styled { it.withColor(Formatting.YELLOW) }
}
label = (stroke).string
managedConfig.save()
}
button = object : FirmButtonComponent(
TextComponent(
IMinecraft.instance.defaultFontRenderer,
{ label },
130,
TextComponent.TextAlignment.LEFT,
false,
false
), action = {
if (editing) {
button!!.blur()
} else {
editing = true
button!!.requestFocus()
updateLabel()
}
}) {
override fun keyboardEvent(event: KeyboardEvent, context: GuiImmediateContext): Boolean {
if (event is KeyboardEvent.KeyPressed) {
return if (event.pressed) onKeyPressed(event.keycode, SavedKeyBinding.getModInt())
else onKeyReleased(event.keycode, SavedKeyBinding.getModInt())
}
return super.keyboardEvent(event, context)
}
override fun emitGuiElements(opt: ManagedOption<SavedKeyBinding>, guiAppender: GuiAppender) {
lateinit var button: FirmButtonComponent
val sm = KeyBindingStateManager(
{ opt.value },
{ opt.value = it },
{ button.blur() },
{ button.requestFocus() }
)
button = object : FirmButtonComponent(
TextComponent(
IMinecraft.instance.defaultFontRenderer,
{ sm.label.string },
130,
TextComponent.TextAlignment.LEFT,
false,
false
), action = {
sm.onClick()
}) {
override fun keyboardEvent(event: KeyboardEvent, context: GuiImmediateContext): Boolean {
if (event is KeyboardEvent.KeyPressed) {
return sm.keyboardEvent(event.keycode, event.pressed)
}
return super.keyboardEvent(event, context)
}
override fun getBackground(context: GuiImmediateContext): NinePatch<MyResourceLocation> {
if (editing) return activeBg
return super.getBackground(context)
}
override fun getBackground(context: GuiImmediateContext): NinePatch<MyResourceLocation> {
if (sm.editing) return activeBg
return super.getBackground(context)
}
fun onKeyPressed(ch: Int, modifiers: Int): Boolean {
if (!editing) {
return false
}
if (ch == GLFW.GLFW_KEY_ESCAPE) {
lastPressedNonModifier = 0
editing = false
lastPressed = 0
opt.value = SavedKeyBinding(GLFW.GLFW_KEY_UNKNOWN)
updateLabel()
blur()
return true
}
if (ch == GLFW.GLFW_KEY_LEFT_SHIFT || ch == GLFW.GLFW_KEY_RIGHT_SHIFT
|| ch == GLFW.GLFW_KEY_LEFT_ALT || ch == GLFW.GLFW_KEY_RIGHT_ALT
|| ch == GLFW.GLFW_KEY_LEFT_CONTROL || ch == GLFW.GLFW_KEY_RIGHT_CONTROL
) {
lastPressed = ch
} else {
opt.value = SavedKeyBinding(
ch, modifiers
)
editing = false
blur()
lastPressed = 0
lastPressedNonModifier = 0
}
updateLabel()
return true
}
override fun onLostFocus() {
lastPressedNonModifier = 0
editing = false
lastPressed = 0
updateLabel()
}
fun onKeyReleased(ch: Int, modifiers: Int): Boolean {
if (!editing)
return false
if (lastPressedNonModifier == ch || (lastPressedNonModifier == 0 && ch == lastPressed)) {
opt.value = SavedKeyBinding(ch, modifiers)
editing = false
blur()
lastPressed = 0
lastPressedNonModifier = 0
}
updateLabel()
return true
}
}
updateLabel()
guiAppender.appendLabeledRow(opt.labelText, button)
}
override fun onLostFocus() {
sm.onLostFocus()
}
}
sm.updateLabel()
guiAppender.appendLabeledRow(opt.labelText, button)
}
}

View File

@@ -0,0 +1,108 @@
package moe.nea.firmament.gui.config
import org.lwjgl.glfw.GLFW
import net.minecraft.text.Text
import net.minecraft.util.Formatting
import moe.nea.firmament.keybindings.SavedKeyBinding
class KeyBindingStateManager(
val value: () -> SavedKeyBinding,
val setValue: (key: SavedKeyBinding) -> Unit,
val blur: () -> Unit,
val requestFocus: () -> Unit,
) {
var editing = false
var lastPressed = 0
var lastPressedNonModifier = 0
var label: Text = Text.literal("")
fun onClick() {
if (editing) {
editing = false
blur()
} else {
editing = true
requestFocus()
}
updateLabel()
}
fun keyboardEvent(keyCode: Int, pressed: Boolean): Boolean {
return if (pressed) onKeyPressed(keyCode, SavedKeyBinding.getModInt())
else onKeyReleased(keyCode, SavedKeyBinding.getModInt())
}
fun onKeyPressed(ch: Int, modifiers: Int): Boolean {
if (!editing) {
return false
}
if (ch == GLFW.GLFW_KEY_ESCAPE) {
lastPressedNonModifier = 0
editing = false
lastPressed = 0
setValue(SavedKeyBinding(GLFW.GLFW_KEY_UNKNOWN))
updateLabel()
blur()
return true
}
if (ch == GLFW.GLFW_KEY_LEFT_SHIFT || ch == GLFW.GLFW_KEY_RIGHT_SHIFT
|| ch == GLFW.GLFW_KEY_LEFT_ALT || ch == GLFW.GLFW_KEY_RIGHT_ALT
|| ch == GLFW.GLFW_KEY_LEFT_CONTROL || ch == GLFW.GLFW_KEY_RIGHT_CONTROL
) {
lastPressed = ch
} else {
setValue(SavedKeyBinding(
ch, modifiers
))
editing = false
blur()
lastPressed = 0
lastPressedNonModifier = 0
}
updateLabel()
return true
}
fun onLostFocus() {
lastPressedNonModifier = 0
editing = false
lastPressed = 0
updateLabel()
}
fun onKeyReleased(ch: Int, modifiers: Int): Boolean {
if (!editing)
return false
if (lastPressedNonModifier == ch || (lastPressedNonModifier == 0 && ch == lastPressed)) {
setValue(SavedKeyBinding(ch, modifiers))
editing = false
blur()
lastPressed = 0
lastPressedNonModifier = 0
}
updateLabel()
return true
}
fun updateLabel() {
var stroke = value().format()
if (editing) {
stroke = Text.literal("")
val (shift, ctrl, alt) = SavedKeyBinding.getMods(SavedKeyBinding.getModInt())
if (shift) {
stroke.append("SHIFT + ")
}
if (alt) {
stroke.append("ALT + ")
}
if (ctrl) {
stroke.append("CTRL + ")
}
stroke.append("???")
stroke.styled { it.withColor(Formatting.YELLOW) }
}
label = stroke
}
}