aboutsummaryrefslogtreecommitdiff
path: root/src/main/kotlin/util/async/input.kt
blob: 2c546bad3913ab4c8bfa3f5e39733ce4afa51704 (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
package moe.nea.firmament.util.async

import io.github.notenoughupdates.moulconfig.gui.GuiContext
import io.github.notenoughupdates.moulconfig.gui.component.CenterComponent
import io.github.notenoughupdates.moulconfig.gui.component.ColumnComponent
import io.github.notenoughupdates.moulconfig.gui.component.PanelComponent
import io.github.notenoughupdates.moulconfig.gui.component.TextComponent
import io.github.notenoughupdates.moulconfig.gui.component.TextFieldComponent
import io.github.notenoughupdates.moulconfig.observer.GetSetter
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlin.coroutines.resume
import net.minecraft.client.gui.screen.Screen
import moe.nea.firmament.events.HandledScreenKeyPressedEvent
import moe.nea.firmament.gui.FirmButtonComponent
import moe.nea.firmament.keybindings.IKeyBinding
import moe.nea.firmament.util.MC
import moe.nea.firmament.util.MoulConfigUtils
import moe.nea.firmament.util.ScreenUtil

private object InputHandler {
	data class KeyInputContinuation(val keybind: IKeyBinding, val onContinue: () -> Unit)

	private val activeContinuations = mutableListOf<KeyInputContinuation>()

	fun registerContinuation(keyInputContinuation: KeyInputContinuation): () -> Unit {
		synchronized(InputHandler) {
			activeContinuations.add(keyInputContinuation)
		}
		return {
			synchronized(this) {
				activeContinuations.remove(keyInputContinuation)
			}
		}
	}

	init {
		HandledScreenKeyPressedEvent.subscribe("Input:resumeAfterInput") { event ->
			synchronized(InputHandler) {
				val toRemove = activeContinuations.filter {
					event.matches(it.keybind)
				}
				toRemove.forEach { it.onContinue() }
				activeContinuations.removeAll(toRemove)
			}
		}
	}
}

suspend fun waitForInput(keybind: IKeyBinding): Unit = suspendCancellableCoroutine { cont ->
	val unregister =
		InputHandler.registerContinuation(InputHandler.KeyInputContinuation(keybind) { cont.resume(Unit) })
	cont.invokeOnCancellation {
		unregister()
	}
}


fun createPromptScreenGuiComponent(suggestion: String, prompt: String, action: Runnable) = (run {
	val text = GetSetter.floating(suggestion)
	GuiContext(
		CenterComponent(
			PanelComponent(
				ColumnComponent(
					TextFieldComponent(text, 120),
					FirmButtonComponent(TextComponent(prompt), action = action)
				)
			)
		)
	) to text
})

suspend fun waitForTextInput(suggestion: String, prompt: String) =
	suspendCancellableCoroutine<String> { cont ->
		lateinit var screen: Screen
		lateinit var text: GetSetter<String>
		val action = {
			if (MC.screen === screen)
				MC.screen = null
			// TODO: should this exit
			cont.resume(text.get())
		}
		val (gui, text_) = createPromptScreenGuiComponent(suggestion, prompt, action)
		text = text_
		screen = MoulConfigUtils.wrapScreen(gui, null, onClose = action)
		ScreenUtil.setScreenLater(screen)
		cont.invokeOnCancellation {
			action()
		}
	}