aboutsummaryrefslogtreecommitdiff
path: root/src/main/kotlin/features/macros
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/kotlin/features/macros')
-rw-r--r--src/main/kotlin/features/macros/ComboProcessor.kt26
-rw-r--r--src/main/kotlin/features/macros/HotkeyAction.kt7
-rw-r--r--src/main/kotlin/features/macros/KeyComboTrie.kt23
-rw-r--r--src/main/kotlin/features/macros/MacroData.kt11
-rw-r--r--src/main/kotlin/features/macros/MacroUI.kt161
5 files changed, 213 insertions, 15 deletions
diff --git a/src/main/kotlin/features/macros/ComboProcessor.kt b/src/main/kotlin/features/macros/ComboProcessor.kt
index 55b3f6e..5c5ac0e 100644
--- a/src/main/kotlin/features/macros/ComboProcessor.kt
+++ b/src/main/kotlin/features/macros/ComboProcessor.kt
@@ -10,6 +10,7 @@ import moe.nea.firmament.events.WorldKeyboardEvent
import moe.nea.firmament.keybindings.SavedKeyBinding
import moe.nea.firmament.util.MC
import moe.nea.firmament.util.TimeMark
+import moe.nea.firmament.util.tr
object ComboProcessor {
@@ -22,18 +23,13 @@ object ComboProcessor {
var isInputting = false
var lastInput = TimeMark.farPast()
val breadCrumbs = mutableListOf<SavedKeyBinding>()
- // TODO: keep breadcrumbs
-
init {
val f = SavedKeyBinding(InputUtil.GLFW_KEY_F)
val one = SavedKeyBinding(InputUtil.GLFW_KEY_1)
val two = SavedKeyBinding(InputUtil.GLFW_KEY_2)
setActions(
- listOf(
- ComboKeyAction(CommandAction("wardrobe"), listOf(f, one)),
- ComboKeyAction(CommandAction("equipment"), listOf(f, two)),
- )
+ MacroData.DConfig.data.comboActions
)
}
@@ -68,10 +64,24 @@ object ComboProcessor {
0F
)
val breadCrumbText = breadCrumbs.joinToString(" > ")
- event.context.drawText(MC.font, breadCrumbText, 0, 0, -1, true)
+ event.context.drawText(
+ MC.font,
+ tr("firmament.combo.active", "Current Combo: ").append(breadCrumbText),
+ 0,
+ 0,
+ -1,
+ true
+ )
event.context.matrices.translate(0F, MC.font.fontHeight + 2F, 0F)
for ((key, value) in activeTrie.nodes) {
- event.context.drawText(MC.font, Text.literal("$breadCrumbText > $key: ").append(value.label), 0, 0, -1, true)
+ event.context.drawText(
+ MC.font,
+ Text.literal("$breadCrumbText > $key: ").append(value.label),
+ 0,
+ 0,
+ -1,
+ true
+ )
event.context.matrices.translate(0F, MC.font.fontHeight + 1F, 0F)
}
event.context.matrices.pop()
diff --git a/src/main/kotlin/features/macros/HotkeyAction.kt b/src/main/kotlin/features/macros/HotkeyAction.kt
index 51c1baa..011f797 100644
--- a/src/main/kotlin/features/macros/HotkeyAction.kt
+++ b/src/main/kotlin/features/macros/HotkeyAction.kt
@@ -1,14 +1,19 @@
package moe.nea.firmament.features.macros
+import kotlinx.serialization.SerialName
+import kotlinx.serialization.Serializable
import net.minecraft.text.Text
import moe.nea.firmament.util.MC
-interface HotkeyAction {
+@Serializable
+sealed interface HotkeyAction {
// TODO: execute
val label: Text
fun execute()
}
+@Serializable
+@SerialName("command")
data class CommandAction(val command: String) : HotkeyAction {
override val label: Text
get() = Text.literal("/$command")
diff --git a/src/main/kotlin/features/macros/KeyComboTrie.kt b/src/main/kotlin/features/macros/KeyComboTrie.kt
index 5c14bcd..57ff289 100644
--- a/src/main/kotlin/features/macros/KeyComboTrie.kt
+++ b/src/main/kotlin/features/macros/KeyComboTrie.kt
@@ -1,7 +1,9 @@
package moe.nea.firmament.features.macros
+import kotlinx.serialization.Serializable
import net.minecraft.text.Text
import moe.nea.firmament.keybindings.SavedKeyBinding
+import moe.nea.firmament.util.ErrorUtil
sealed interface KeyComboTrie {
val label: Text
@@ -13,19 +15,27 @@ sealed interface KeyComboTrie {
val root = Branch(mutableMapOf())
for (combo in combos) {
var p = root
- require(combo.keys.isNotEmpty())
+ if (combo.keys.isEmpty()) {
+ ErrorUtil.softUserError("Key Combo for ${combo.action.label.string} is empty")
+ continue
+ }
for ((index, key) in combo.keys.withIndex()) {
val m = (p.nodes as MutableMap)
if (index == combo.keys.lastIndex) {
- if (key in m)
- error("Overlapping actions found for ${combo.keys} (another action ${m[key]} already exists).")
+ if (key in m) {
+ ErrorUtil.softUserError("Overlapping actions found for ${combo.keys.joinToString(" > ")} (another action ${m[key]} already exists).")
+ break
+ }
m[key] = Leaf(combo.action)
} else {
val c = m.getOrPut(key) { Branch(mutableMapOf()) }
- if (c !is Branch)
- error("Overlapping actions found for ${combo.keys} (final node exists at index $index) through another action already")
- p = c
+ if (c !is Branch) {
+ ErrorUtil.softUserError("Overlapping actions found for ${combo.keys} (final node exists at index $index) through another action already")
+ break
+ } else {
+ p = c
+ }
}
}
}
@@ -35,6 +45,7 @@ sealed interface KeyComboTrie {
}
+@Serializable
data class ComboKeyAction(
val action: HotkeyAction,
val keys: List<SavedKeyBinding>,
diff --git a/src/main/kotlin/features/macros/MacroData.kt b/src/main/kotlin/features/macros/MacroData.kt
new file mode 100644
index 0000000..78a5948
--- /dev/null
+++ b/src/main/kotlin/features/macros/MacroData.kt
@@ -0,0 +1,11 @@
+package moe.nea.firmament.features.macros
+
+import kotlinx.serialization.Serializable
+import moe.nea.firmament.util.data.DataHolder
+
+@Serializable
+data class MacroData(
+ var comboActions: List<ComboKeyAction> = listOf(),
+){
+ object DConfig : DataHolder<MacroData>(kotlinx.serialization.serializer(), "macros", ::MacroData)
+}
diff --git a/src/main/kotlin/features/macros/MacroUI.kt b/src/main/kotlin/features/macros/MacroUI.kt
new file mode 100644
index 0000000..17fdd0a
--- /dev/null
+++ b/src/main/kotlin/features/macros/MacroUI.kt
@@ -0,0 +1,161 @@
+package moe.nea.firmament.features.macros
+
+import io.github.notenoughupdates.moulconfig.gui.CloseEventListener
+import io.github.notenoughupdates.moulconfig.observer.ObservableList
+import io.github.notenoughupdates.moulconfig.xml.Bind
+import moe.nea.firmament.annotations.Subscribe
+import moe.nea.firmament.commands.thenExecute
+import moe.nea.firmament.events.CommandEvent
+import moe.nea.firmament.gui.config.AllConfigsGui.toObservableList
+import moe.nea.firmament.gui.config.KeyBindingStateManager
+import moe.nea.firmament.keybindings.SavedKeyBinding
+import moe.nea.firmament.util.MC
+import moe.nea.firmament.util.MoulConfigUtils
+import moe.nea.firmament.util.ScreenUtil
+
+class MacroUI {
+
+
+ companion object {
+ @Subscribe
+ fun onCommands(event: CommandEvent.SubCommand) {
+ // TODO: add button in config
+ event.subcommand("macros") {
+ thenExecute {
+ ScreenUtil.setScreenLater(MoulConfigUtils.loadScreen("config/macros/index", MacroUI(), null))
+ }
+ }
+ }
+
+ }
+
+ @field:Bind("combos")
+ val combos = Combos()
+
+ class Combos {
+ @field:Bind("actions")
+ val actions: ObservableList<ActionEditor> = ObservableList(
+ MacroData.DConfig.data.comboActions.mapTo(mutableListOf()) {
+ ActionEditor(it, this)
+ }
+ )
+
+ var dontSave = false
+
+ @Bind
+ fun beforeClose(): CloseEventListener.CloseAction {
+ if (!dontSave)
+ save()
+ return CloseEventListener.CloseAction.NO_OBJECTIONS_TO_CLOSE
+ }
+
+ @Bind
+ fun addCommand() {
+ actions.add(
+ ActionEditor(
+ ComboKeyAction(
+ CommandAction("ac Hello from a Firmament Hotkey"),
+ listOf()
+ ),
+ this
+ )
+ )
+ }
+
+ @Bind
+ fun discard() {
+ dontSave = true
+ MC.screen?.close()
+ }
+
+ @Bind
+ fun saveAndClose() {
+ save()
+ MC.screen?.close()
+ }
+
+ @Bind
+ fun save() {
+ MacroData.DConfig.data.comboActions = actions.map { it.asSaveable() }
+ MacroData.DConfig.markDirty()
+ ComboProcessor.setActions(MacroData.DConfig.data.comboActions) // TODO: automatically reload those from the config on startup
+ }
+ }
+
+ class KeyBindingEditor(var binding: SavedKeyBinding, val parent: ActionEditor) {
+ val sm = KeyBindingStateManager(
+ { binding },
+ { binding = it },
+ ::blur,
+ ::requestFocus
+ )
+
+ @field:Bind
+ val button = sm.createButton()
+
+ init {
+ sm.updateLabel()
+ }
+
+ fun blur() {
+ button.blur()
+ }
+
+ @Bind
+ fun delete() {
+ parent.combo.removeIf { it === this }
+ parent.combo.update()
+ }
+
+ fun requestFocus() {
+ button.requestFocus()
+ }
+ }
+
+ class ActionEditor(val action: ComboKeyAction, val parent: MacroUI.Combos) {
+ fun asSaveable(): ComboKeyAction {
+ return ComboKeyAction(
+ CommandAction(command),
+ combo.map { it.binding }
+ )
+ }
+
+ @field:Bind("command")
+ var command: String = (action.action as CommandAction).command
+
+ @field:Bind("combo")
+ val combo = action.keys.map { KeyBindingEditor(it, this) }.toObservableList()
+
+ @Bind
+ fun formattedCombo() =
+ combo.joinToString(" > ") { it.binding.toString() }
+
+ @Bind
+ fun addStep() {
+ combo.add(KeyBindingEditor(SavedKeyBinding.unbound(), this))
+ }
+
+ @Bind
+ fun back() {
+ MC.screen?.close()
+ }
+
+ @Bind
+ fun delete() {
+ parent.actions.removeIf { it === this }
+ parent.actions.update()
+ }
+ @Bind
+ fun edit() {
+ MC.screen = MoulConfigUtils.loadScreen("config/macros/editor", this, MC.screen)
+ }
+ }
+}
+
+private fun <T> ObservableList<T>.setAll(ts: Collection<T>) {
+ val observer = this.observer
+ this.clear()
+ this.addAll(ts)
+ this.observer = observer
+ this.update()
+}