Refactor source layout
Introduce compat source sets and move all kotlin sources to the main directory [no changelog]
This commit is contained in:
46
src/main/kotlin/gui/config/AllConfigsGui.kt
Normal file
46
src/main/kotlin/gui/config/AllConfigsGui.kt
Normal file
@@ -0,0 +1,46 @@
|
||||
|
||||
|
||||
package moe.nea.firmament.gui.config
|
||||
|
||||
import io.github.notenoughupdates.moulconfig.observer.ObservableList
|
||||
import io.github.notenoughupdates.moulconfig.xml.Bind
|
||||
import net.minecraft.client.gui.screen.Screen
|
||||
import net.minecraft.text.Text
|
||||
import moe.nea.firmament.features.FeatureManager
|
||||
import moe.nea.firmament.repo.RepoManager
|
||||
import moe.nea.firmament.util.MC
|
||||
import moe.nea.firmament.util.MoulConfigUtils
|
||||
import moe.nea.firmament.util.ScreenUtil.setScreenLater
|
||||
|
||||
object AllConfigsGui {
|
||||
|
||||
val allConfigs
|
||||
get() = listOf(
|
||||
RepoManager.Config
|
||||
) + FeatureManager.allFeatures.mapNotNull { it.config }
|
||||
|
||||
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 EntryMapping(val config: ManagedConfig) {
|
||||
@Bind
|
||||
fun name() = Text.translatable("firmament.config.${config.name}").string
|
||||
|
||||
@Bind
|
||||
fun openEditor() {
|
||||
config.showConfigEditor(MC.screen)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun makeScreen(parent: Screen? = null): Screen {
|
||||
return MoulConfigUtils.loadScreen("config/main", MainMapping(allConfigs), parent)
|
||||
}
|
||||
|
||||
fun showAllGuis() {
|
||||
setScreenLater(makeScreen())
|
||||
}
|
||||
}
|
||||
37
src/main/kotlin/gui/config/BooleanHandler.kt
Normal file
37
src/main/kotlin/gui/config/BooleanHandler.kt
Normal file
@@ -0,0 +1,37 @@
|
||||
|
||||
|
||||
package moe.nea.firmament.gui.config
|
||||
|
||||
import io.github.notenoughupdates.moulconfig.gui.component.CenterComponent
|
||||
import io.github.notenoughupdates.moulconfig.gui.component.SwitchComponent
|
||||
import io.github.notenoughupdates.moulconfig.observer.GetSetter
|
||||
import kotlinx.serialization.json.JsonElement
|
||||
import kotlinx.serialization.json.JsonPrimitive
|
||||
import kotlinx.serialization.json.boolean
|
||||
import kotlinx.serialization.json.jsonPrimitive
|
||||
|
||||
class BooleanHandler(val config: ManagedConfig) : ManagedConfig.OptionHandler<Boolean> {
|
||||
override fun toJson(element: Boolean): JsonElement? {
|
||||
return JsonPrimitive(element)
|
||||
}
|
||||
|
||||
override fun fromJson(element: JsonElement): Boolean {
|
||||
return element.jsonPrimitive.boolean
|
||||
}
|
||||
|
||||
override fun emitGuiElements(opt: ManagedOption<Boolean>, guiAppender: GuiAppender) {
|
||||
guiAppender.appendLabeledRow(
|
||||
opt.labelText,
|
||||
CenterComponent(SwitchComponent(object : GetSetter<Boolean> {
|
||||
override fun get(): Boolean {
|
||||
return opt.get()
|
||||
}
|
||||
|
||||
override fun set(newValue: Boolean) {
|
||||
opt.set(newValue)
|
||||
config.save()
|
||||
}
|
||||
}, 200)
|
||||
))
|
||||
}
|
||||
}
|
||||
24
src/main/kotlin/gui/config/ClickHandler.kt
Normal file
24
src/main/kotlin/gui/config/ClickHandler.kt
Normal file
@@ -0,0 +1,24 @@
|
||||
|
||||
|
||||
package moe.nea.firmament.gui.config
|
||||
|
||||
import io.github.notenoughupdates.moulconfig.gui.component.TextComponent
|
||||
import kotlinx.serialization.json.JsonElement
|
||||
import moe.nea.firmament.gui.FirmButtonComponent
|
||||
|
||||
class ClickHandler(val config: ManagedConfig, val runnable: () -> Unit) : ManagedConfig.OptionHandler<Unit> {
|
||||
override fun toJson(element: Unit): JsonElement? {
|
||||
return null
|
||||
}
|
||||
|
||||
override fun fromJson(element: JsonElement) {}
|
||||
|
||||
override fun emitGuiElements(opt: ManagedOption<Unit>, guiAppender: GuiAppender) {
|
||||
guiAppender.appendLabeledRow(
|
||||
opt.labelText,
|
||||
FirmButtonComponent(
|
||||
TextComponent(opt.labelText.string),
|
||||
action = runnable),
|
||||
)
|
||||
}
|
||||
}
|
||||
58
src/main/kotlin/gui/config/DurationHandler.kt
Normal file
58
src/main/kotlin/gui/config/DurationHandler.kt
Normal file
@@ -0,0 +1,58 @@
|
||||
|
||||
|
||||
package moe.nea.firmament.gui.config
|
||||
|
||||
import io.github.notenoughupdates.moulconfig.common.IMinecraft
|
||||
import io.github.notenoughupdates.moulconfig.gui.component.RowComponent
|
||||
import io.github.notenoughupdates.moulconfig.gui.component.SliderComponent
|
||||
import io.github.notenoughupdates.moulconfig.gui.component.TextComponent
|
||||
import io.github.notenoughupdates.moulconfig.observer.GetSetter
|
||||
import kotlinx.serialization.json.JsonElement
|
||||
import kotlinx.serialization.json.JsonPrimitive
|
||||
import kotlinx.serialization.json.jsonPrimitive
|
||||
import kotlinx.serialization.json.long
|
||||
import kotlin.time.Duration
|
||||
import kotlin.time.DurationUnit
|
||||
import kotlin.time.toDuration
|
||||
import net.minecraft.text.Text
|
||||
import moe.nea.firmament.util.FirmFormatters
|
||||
|
||||
class DurationHandler(val config: ManagedConfig, val min: Duration, val max: Duration) :
|
||||
ManagedConfig.OptionHandler<Duration> {
|
||||
override fun toJson(element: Duration): JsonElement? {
|
||||
return JsonPrimitive(element.inWholeMilliseconds)
|
||||
}
|
||||
|
||||
override fun fromJson(element: JsonElement): Duration {
|
||||
return element.jsonPrimitive.long.toDuration(DurationUnit.MILLISECONDS)
|
||||
}
|
||||
|
||||
override fun emitGuiElements(opt: ManagedOption<Duration>, guiAppender: GuiAppender) {
|
||||
guiAppender.appendLabeledRow(
|
||||
opt.labelText,
|
||||
RowComponent(
|
||||
TextComponent(IMinecraft.instance.defaultFontRenderer,
|
||||
{ FirmFormatters.formatTimespan(opt.value) },
|
||||
40,
|
||||
TextComponent.TextAlignment.CENTER,
|
||||
true,
|
||||
false),
|
||||
SliderComponent(
|
||||
object : GetSetter<Float> {
|
||||
override fun get(): Float {
|
||||
return opt.value.toDouble(DurationUnit.SECONDS).toFloat()
|
||||
}
|
||||
|
||||
override fun set(newValue: Float) {
|
||||
opt.value = newValue.toDouble().toDuration(DurationUnit.SECONDS)
|
||||
}
|
||||
},
|
||||
min.toDouble(DurationUnit.SECONDS).toFloat(),
|
||||
max.toDouble(DurationUnit.SECONDS).toFloat(),
|
||||
0.1F,
|
||||
130
|
||||
)
|
||||
))
|
||||
}
|
||||
|
||||
}
|
||||
40
src/main/kotlin/gui/config/GuiAppender.kt
Normal file
40
src/main/kotlin/gui/config/GuiAppender.kt
Normal file
@@ -0,0 +1,40 @@
|
||||
|
||||
|
||||
package moe.nea.firmament.gui.config
|
||||
|
||||
import io.github.notenoughupdates.moulconfig.gui.GuiComponent
|
||||
import io.github.notenoughupdates.moulconfig.gui.component.RowComponent
|
||||
import io.github.notenoughupdates.moulconfig.gui.component.TextComponent
|
||||
import io.github.notenoughupdates.moulconfig.observer.GetSetter
|
||||
import net.minecraft.client.gui.screen.Screen
|
||||
import net.minecraft.text.Text
|
||||
import moe.nea.firmament.gui.FixedComponent
|
||||
|
||||
class GuiAppender(val width: Int, val screenAccessor: () -> Screen) {
|
||||
val panel = mutableListOf<GuiComponent>()
|
||||
internal val reloadables = mutableListOf<(() -> Unit)>()
|
||||
|
||||
fun onReload(reloadable: () -> Unit) {
|
||||
reloadables.add(reloadable)
|
||||
}
|
||||
|
||||
fun appendLabeledRow(label: Text, right: GuiComponent) {
|
||||
appendSplitRow(
|
||||
TextComponent(label.string),
|
||||
right
|
||||
)
|
||||
}
|
||||
|
||||
fun appendSplitRow(left: GuiComponent, right: GuiComponent) {
|
||||
// TODO: make this more dynamic
|
||||
// i could just make a component that allows for using half the available size
|
||||
appendFullRow(RowComponent(
|
||||
FixedComponent(GetSetter.constant(width / 2), null, left),
|
||||
FixedComponent(GetSetter.constant(width / 2), null, right),
|
||||
))
|
||||
}
|
||||
|
||||
fun appendFullRow(widget: GuiComponent) {
|
||||
panel.add(widget)
|
||||
}
|
||||
}
|
||||
39
src/main/kotlin/gui/config/HudMetaHandler.kt
Normal file
39
src/main/kotlin/gui/config/HudMetaHandler.kt
Normal file
@@ -0,0 +1,39 @@
|
||||
|
||||
|
||||
package moe.nea.firmament.gui.config
|
||||
|
||||
import io.github.notenoughupdates.moulconfig.gui.component.TextComponent
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.JsonElement
|
||||
import kotlinx.serialization.json.decodeFromJsonElement
|
||||
import kotlinx.serialization.json.encodeToJsonElement
|
||||
import net.minecraft.text.MutableText
|
||||
import net.minecraft.text.Text
|
||||
import moe.nea.firmament.gui.FirmButtonComponent
|
||||
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)
|
||||
}
|
||||
|
||||
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)
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
54
src/main/kotlin/gui/config/IntegerHandler.kt
Normal file
54
src/main/kotlin/gui/config/IntegerHandler.kt
Normal file
@@ -0,0 +1,54 @@
|
||||
|
||||
|
||||
package moe.nea.firmament.gui.config
|
||||
|
||||
import io.github.notenoughupdates.moulconfig.common.IMinecraft
|
||||
import io.github.notenoughupdates.moulconfig.gui.component.RowComponent
|
||||
import io.github.notenoughupdates.moulconfig.gui.component.SliderComponent
|
||||
import io.github.notenoughupdates.moulconfig.gui.component.TextComponent
|
||||
import io.github.notenoughupdates.moulconfig.observer.GetSetter
|
||||
import kotlinx.serialization.json.JsonElement
|
||||
import kotlinx.serialization.json.JsonPrimitive
|
||||
import kotlinx.serialization.json.int
|
||||
import kotlinx.serialization.json.jsonPrimitive
|
||||
import moe.nea.firmament.util.FirmFormatters
|
||||
|
||||
class IntegerHandler(val config: ManagedConfig, val min: Int, val max: Int) : ManagedConfig.OptionHandler<Int> {
|
||||
override fun toJson(element: Int): JsonElement? {
|
||||
return JsonPrimitive(element)
|
||||
}
|
||||
|
||||
override fun fromJson(element: JsonElement): Int {
|
||||
return element.jsonPrimitive.int
|
||||
}
|
||||
|
||||
override fun emitGuiElements(opt: ManagedOption<Int>, guiAppender: GuiAppender) {
|
||||
guiAppender.appendLabeledRow(
|
||||
opt.labelText,
|
||||
RowComponent(
|
||||
TextComponent(IMinecraft.instance.defaultFontRenderer,
|
||||
{ FirmFormatters.formatCommas(opt.value, 0) },
|
||||
40,
|
||||
TextComponent.TextAlignment.CENTER,
|
||||
true,
|
||||
false),
|
||||
SliderComponent(
|
||||
object : GetSetter<Float> {
|
||||
override fun get(): Float {
|
||||
return opt.value.toFloat()
|
||||
}
|
||||
|
||||
override fun set(newValue: Float) {
|
||||
opt.value = newValue.toInt()
|
||||
}
|
||||
},
|
||||
min.toFloat(),
|
||||
max.toFloat(),
|
||||
0.1F,
|
||||
130
|
||||
)
|
||||
))
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
48
src/main/kotlin/gui/config/JAnyHud.kt
Normal file
48
src/main/kotlin/gui/config/JAnyHud.kt
Normal file
@@ -0,0 +1,48 @@
|
||||
|
||||
|
||||
package moe.nea.firmament.gui.config
|
||||
|
||||
import moe.nea.jarvis.api.JarvisHud
|
||||
import moe.nea.jarvis.api.JarvisScalable
|
||||
import kotlinx.serialization.Serializable
|
||||
import net.minecraft.text.Text
|
||||
|
||||
@Serializable
|
||||
data class HudPosition(
|
||||
var x: Double,
|
||||
var y: Double,
|
||||
var scale: Float,
|
||||
)
|
||||
|
||||
|
||||
data class HudMeta(
|
||||
val position: HudPosition,
|
||||
private val label: Text,
|
||||
private val width: Int,
|
||||
private val height: Int,
|
||||
) : JarvisScalable, JarvisHud {
|
||||
override fun getX(): Double = position.x
|
||||
|
||||
override fun setX(newX: Double) {
|
||||
position.x = newX
|
||||
}
|
||||
|
||||
override fun getY(): Double = position.y
|
||||
|
||||
override fun setY(newY: Double) {
|
||||
position.y = newY
|
||||
}
|
||||
|
||||
override fun getLabel(): Text = label
|
||||
|
||||
override fun getWidth(): Int = width
|
||||
|
||||
override fun getHeight(): Int = height
|
||||
|
||||
override fun getScale(): Float = position.scale
|
||||
|
||||
override fun setScale(newScale: Float) {
|
||||
position.scale = newScale
|
||||
}
|
||||
|
||||
}
|
||||
149
src/main/kotlin/gui/config/KeyBindingHandler.kt
Normal file
149
src/main/kotlin/gui/config/KeyBindingHandler.kt
Normal file
@@ -0,0 +1,149 @@
|
||||
|
||||
|
||||
package moe.nea.firmament.gui.config
|
||||
|
||||
import io.github.notenoughupdates.moulconfig.common.IMinecraft
|
||||
import io.github.notenoughupdates.moulconfig.common.MyResourceLocation
|
||||
import io.github.notenoughupdates.moulconfig.deps.libninepatch.NinePatch
|
||||
import io.github.notenoughupdates.moulconfig.gui.GuiImmediateContext
|
||||
import io.github.notenoughupdates.moulconfig.gui.KeyboardEvent
|
||||
import io.github.notenoughupdates.moulconfig.gui.component.TextComponent
|
||||
import org.lwjgl.glfw.GLFW
|
||||
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> {
|
||||
|
||||
override fun initOption(opt: ManagedOption<SavedKeyBinding>) {
|
||||
FirmamentKeyBindings.registerKeyBinding(name, opt)
|
||||
}
|
||||
|
||||
override fun toJson(element: SavedKeyBinding): JsonElement? {
|
||||
return Json.encodeToJsonElement(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 getBackground(context: GuiImmediateContext): NinePatch<MyResourceLocation> {
|
||||
if (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)
|
||||
}
|
||||
|
||||
}
|
||||
181
src/main/kotlin/gui/config/ManagedConfig.kt
Normal file
181
src/main/kotlin/gui/config/ManagedConfig.kt
Normal file
@@ -0,0 +1,181 @@
|
||||
|
||||
|
||||
package moe.nea.firmament.gui.config
|
||||
|
||||
import io.github.notenoughupdates.moulconfig.gui.CloseEventListener
|
||||
import io.github.notenoughupdates.moulconfig.gui.GuiComponentWrapper
|
||||
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.RowComponent
|
||||
import io.github.notenoughupdates.moulconfig.gui.component.ScrollPanelComponent
|
||||
import io.github.notenoughupdates.moulconfig.gui.component.TextComponent
|
||||
import moe.nea.jarvis.api.Point
|
||||
import org.lwjgl.glfw.GLFW
|
||||
import kotlinx.serialization.encodeToString
|
||||
import kotlinx.serialization.json.JsonElement
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
import kotlin.io.path.createDirectories
|
||||
import kotlin.io.path.readText
|
||||
import kotlin.io.path.writeText
|
||||
import kotlin.time.Duration
|
||||
import net.minecraft.client.gui.screen.Screen
|
||||
import net.minecraft.text.Text
|
||||
import moe.nea.firmament.Firmament
|
||||
import moe.nea.firmament.gui.FirmButtonComponent
|
||||
import moe.nea.firmament.keybindings.SavedKeyBinding
|
||||
import moe.nea.firmament.util.ScreenUtil.setScreenLater
|
||||
|
||||
abstract class ManagedConfig(override val name: String) : ManagedConfigElement() {
|
||||
|
||||
interface OptionHandler<T : Any> {
|
||||
fun initOption(opt: ManagedOption<T>) {}
|
||||
fun toJson(element: T): JsonElement?
|
||||
fun fromJson(element: JsonElement): T
|
||||
fun emitGuiElements(opt: ManagedOption<T>, guiAppender: GuiAppender)
|
||||
}
|
||||
|
||||
val file = Firmament.CONFIG_DIR.resolve("$name.json")
|
||||
val data: JsonObject by lazy {
|
||||
try {
|
||||
Firmament.json.decodeFromString(
|
||||
file.readText()
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
Firmament.logger.info("Could not read config $name. Loading empty config.")
|
||||
JsonObject(mutableMapOf())
|
||||
}
|
||||
}
|
||||
|
||||
fun save() {
|
||||
val data = JsonObject(allOptions.mapNotNull { (key, value) ->
|
||||
value.toJson()?.let {
|
||||
key to it
|
||||
}
|
||||
}.toMap())
|
||||
file.parent.createDirectories()
|
||||
file.writeText(Firmament.json.encodeToString(data))
|
||||
}
|
||||
|
||||
|
||||
val allOptions = mutableMapOf<String, ManagedOption<*>>()
|
||||
val sortedOptions = mutableListOf<ManagedOption<*>>()
|
||||
|
||||
private var latestGuiAppender: GuiAppender? = null
|
||||
|
||||
protected fun <T : Any> option(
|
||||
propertyName: String,
|
||||
default: () -> T,
|
||||
handler: OptionHandler<T>
|
||||
): ManagedOption<T> {
|
||||
if (propertyName in allOptions) error("Cannot register the same name twice")
|
||||
return ManagedOption(this, propertyName, default, handler).also {
|
||||
it.handler.initOption(it)
|
||||
it.load(data)
|
||||
allOptions[propertyName] = it
|
||||
sortedOptions.add(it)
|
||||
}
|
||||
}
|
||||
|
||||
protected fun toggle(propertyName: String, default: () -> Boolean): ManagedOption<Boolean> {
|
||||
return option(propertyName, default, BooleanHandler(this))
|
||||
}
|
||||
|
||||
protected fun duration(
|
||||
propertyName: String,
|
||||
min: Duration,
|
||||
max: Duration,
|
||||
default: () -> Duration,
|
||||
): ManagedOption<Duration> {
|
||||
return option(propertyName, default, DurationHandler(this, min, max))
|
||||
}
|
||||
|
||||
|
||||
protected fun position(
|
||||
propertyName: String,
|
||||
width: Int,
|
||||
height: Int,
|
||||
default: () -> Point,
|
||||
): ManagedOption<HudMeta> {
|
||||
val label = Text.translatable("firmament.config.${name}.${propertyName}")
|
||||
return option(propertyName, {
|
||||
val p = default()
|
||||
HudMeta(HudPosition(p.x, p.y, 1F), label, width, height)
|
||||
}, HudMetaHandler(this, label, width, height))
|
||||
}
|
||||
|
||||
protected fun keyBinding(
|
||||
propertyName: String,
|
||||
default: () -> Int,
|
||||
): ManagedOption<SavedKeyBinding> = keyBindingWithOutDefaultModifiers(propertyName) { SavedKeyBinding(default()) }
|
||||
|
||||
protected fun keyBindingWithOutDefaultModifiers(
|
||||
propertyName: String,
|
||||
default: () -> SavedKeyBinding,
|
||||
): ManagedOption<SavedKeyBinding> {
|
||||
return option(propertyName, default, KeyBindingHandler("firmament.config.${name}.${propertyName}", this))
|
||||
}
|
||||
|
||||
protected fun keyBindingWithDefaultUnbound(
|
||||
propertyName: String,
|
||||
): ManagedOption<SavedKeyBinding> {
|
||||
return keyBindingWithOutDefaultModifiers(propertyName) { SavedKeyBinding(GLFW.GLFW_KEY_UNKNOWN) }
|
||||
}
|
||||
|
||||
protected fun integer(
|
||||
propertyName: String,
|
||||
min: Int,
|
||||
max: Int,
|
||||
default: () -> Int,
|
||||
): ManagedOption<Int> {
|
||||
return option(propertyName, default, IntegerHandler(this, min, max))
|
||||
}
|
||||
|
||||
protected fun button(propertyName: String, runnable: () -> Unit): ManagedOption<Unit> {
|
||||
return option(propertyName, { }, ClickHandler(this, runnable))
|
||||
}
|
||||
|
||||
protected fun string(propertyName: String, default: () -> String): ManagedOption<String> {
|
||||
return option(propertyName, default, StringHandler(this))
|
||||
}
|
||||
|
||||
|
||||
fun reloadGui() {
|
||||
latestGuiAppender?.reloadables?.forEach { it() }
|
||||
}
|
||||
|
||||
val labelText = Text.translatable("firmament.config.${name}")
|
||||
|
||||
fun getConfigEditor(parent: Screen? = null): Screen {
|
||||
var screen: Screen? = null
|
||||
val guiapp = GuiAppender(400) { requireNotNull(screen) { "Screen Accessor called too early" } }
|
||||
latestGuiAppender = guiapp
|
||||
guiapp.appendFullRow(RowComponent(
|
||||
FirmButtonComponent(TextComponent("←")) {
|
||||
if (parent != null) {
|
||||
save()
|
||||
setScreenLater(parent)
|
||||
} else {
|
||||
AllConfigsGui.showAllGuis()
|
||||
}
|
||||
}
|
||||
))
|
||||
sortedOptions.forEach { it.appendToGui(guiapp) }
|
||||
guiapp.reloadables.forEach { it() }
|
||||
val component = CenterComponent(PanelComponent(ScrollPanelComponent(400, 300, ColumnComponent(guiapp.panel)), 10, PanelComponent.DefaultBackgroundRenderer.VANILLA))
|
||||
screen = object : GuiComponentWrapper(GuiContext(component)) {
|
||||
override fun close() {
|
||||
if (context.onBeforeClose() == CloseEventListener.CloseAction.NO_OBJECTIONS_TO_CLOSE) {
|
||||
client!!.setScreen(parent)
|
||||
}
|
||||
}
|
||||
}
|
||||
return screen
|
||||
}
|
||||
|
||||
fun showConfigEditor(parent: Screen? = null) {
|
||||
setScreenLater(getConfigEditor(parent))
|
||||
}
|
||||
|
||||
}
|
||||
8
src/main/kotlin/gui/config/ManagedConfigElement.kt
Normal file
8
src/main/kotlin/gui/config/ManagedConfigElement.kt
Normal file
@@ -0,0 +1,8 @@
|
||||
|
||||
|
||||
package moe.nea.firmament.gui.config
|
||||
|
||||
abstract class ManagedConfigElement {
|
||||
abstract val name: String
|
||||
|
||||
}
|
||||
62
src/main/kotlin/gui/config/ManagedOption.kt
Normal file
62
src/main/kotlin/gui/config/ManagedOption.kt
Normal file
@@ -0,0 +1,62 @@
|
||||
|
||||
|
||||
package moe.nea.firmament.gui.config
|
||||
|
||||
import io.github.notenoughupdates.moulconfig.observer.GetSetter
|
||||
import kotlinx.serialization.json.JsonElement
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
import kotlin.properties.ReadWriteProperty
|
||||
import kotlin.reflect.KProperty
|
||||
import net.minecraft.text.Text
|
||||
import moe.nea.firmament.Firmament
|
||||
|
||||
class ManagedOption<T : Any>(
|
||||
val element: ManagedConfigElement,
|
||||
val propertyName: String,
|
||||
val default: () -> T,
|
||||
val handler: ManagedConfig.OptionHandler<T>
|
||||
) : ReadWriteProperty<Any?, T>, GetSetter<T> {
|
||||
override fun set(newValue: T) {
|
||||
this.value = newValue
|
||||
}
|
||||
|
||||
override fun get(): T {
|
||||
return this.value
|
||||
}
|
||||
|
||||
val rawLabelText = "firmament.config.${element.name}.${propertyName}"
|
||||
val labelText = Text.translatable(rawLabelText)
|
||||
|
||||
lateinit var value: T
|
||||
|
||||
override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
|
||||
this.value = value
|
||||
}
|
||||
|
||||
override fun getValue(thisRef: Any?, property: KProperty<*>): T {
|
||||
return value
|
||||
}
|
||||
|
||||
fun load(root: JsonElement) {
|
||||
if (root is JsonObject && root.containsKey(propertyName)) {
|
||||
try {
|
||||
value = handler.fromJson(root[propertyName]!!)
|
||||
return
|
||||
} catch (e: Exception) {
|
||||
Firmament.logger.error(
|
||||
"Exception during loading of config file ${element.name}. This will reset this config.",
|
||||
e
|
||||
)
|
||||
}
|
||||
}
|
||||
value = default()
|
||||
}
|
||||
|
||||
fun toJson(): JsonElement? {
|
||||
return handler.toJson(value)
|
||||
}
|
||||
|
||||
fun appendToGui(guiapp: GuiAppender) {
|
||||
handler.emitGuiElements(this, guiapp)
|
||||
}
|
||||
}
|
||||
36
src/main/kotlin/gui/config/StringHandler.kt
Normal file
36
src/main/kotlin/gui/config/StringHandler.kt
Normal file
@@ -0,0 +1,36 @@
|
||||
|
||||
|
||||
package moe.nea.firmament.gui.config
|
||||
|
||||
import io.github.notenoughupdates.moulconfig.gui.component.TextFieldComponent
|
||||
import io.github.notenoughupdates.moulconfig.observer.GetSetter
|
||||
import kotlinx.serialization.json.JsonElement
|
||||
import kotlinx.serialization.json.JsonPrimitive
|
||||
import kotlinx.serialization.json.jsonPrimitive
|
||||
import net.minecraft.text.Text
|
||||
|
||||
class StringHandler(val config: ManagedConfig) : ManagedConfig.OptionHandler<String> {
|
||||
override fun toJson(element: String): JsonElement? {
|
||||
return JsonPrimitive(element)
|
||||
}
|
||||
|
||||
override fun fromJson(element: JsonElement): String {
|
||||
return element.jsonPrimitive.content
|
||||
}
|
||||
|
||||
override fun emitGuiElements(opt: ManagedOption<String>, guiAppender: GuiAppender) {
|
||||
guiAppender.appendLabeledRow(
|
||||
opt.labelText,
|
||||
TextFieldComponent(
|
||||
object : GetSetter<String> by opt {
|
||||
override fun set(newValue: String) {
|
||||
opt.set(newValue)
|
||||
config.save()
|
||||
}
|
||||
},
|
||||
130,
|
||||
suggestion = Text.translatableWithFallback(opt.rawLabelText + ".hint", "").string
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user