Common config gui
This commit is contained in:
@@ -14,10 +14,7 @@
|
|||||||
- Recipe Viewer for Forge Recipes
|
- Recipe Viewer for Forge Recipes
|
||||||
- Fishing Helper for Fishing particles (currently not working if you sneak because of 1.19 messing up positioning)
|
- Fishing Helper for Fishing particles (currently not working if you sneak because of 1.19 messing up positioning)
|
||||||
- Fairy soul highlighter
|
- Fairy soul highlighter
|
||||||
|
- Basic Config Gui (/firm config). Still needs improvement, but for the basics it's enough.
|
||||||
Not working features:
|
|
||||||
|
|
||||||
- A config gui, lol. All features are sort of on all the time. There is a config gui, but it is quite barren and not well documented.
|
|
||||||
|
|
||||||
|
|
||||||
### Building your own
|
### Building your own
|
||||||
|
|||||||
@@ -1,17 +1,20 @@
|
|||||||
package moe.nea.firmament.commands
|
package moe.nea.firmament.commands
|
||||||
|
|
||||||
import com.mojang.brigadier.CommandDispatcher
|
import com.mojang.brigadier.CommandDispatcher
|
||||||
import io.github.cottonmc.cotton.gui.client.CottonClientScreen
|
|
||||||
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource
|
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource
|
||||||
import net.minecraft.text.Text
|
import net.minecraft.text.Text
|
||||||
import moe.nea.firmament.features.world.FairySouls
|
import moe.nea.firmament.features.world.FairySouls
|
||||||
import moe.nea.firmament.gui.repoGui
|
import moe.nea.firmament.gui.config.AllConfigsGui
|
||||||
import moe.nea.firmament.repo.RepoManager
|
import moe.nea.firmament.repo.RepoManager
|
||||||
import moe.nea.firmament.util.SBData
|
import moe.nea.firmament.util.SBData
|
||||||
import moe.nea.firmament.util.ScreenUtil.setScreenLater
|
|
||||||
|
|
||||||
|
|
||||||
fun firmamentCommand() = literal("firmament") {
|
fun firmamentCommand() = literal("firmament") {
|
||||||
|
thenLiteral("config") {
|
||||||
|
thenExecute {
|
||||||
|
AllConfigsGui.showAllGuis()
|
||||||
|
}
|
||||||
|
}
|
||||||
thenLiteral("repo") {
|
thenLiteral("repo") {
|
||||||
thenLiteral("reload") {
|
thenLiteral("reload") {
|
||||||
thenLiteral("fetch") {
|
thenLiteral("fetch") {
|
||||||
@@ -25,9 +28,6 @@ fun firmamentCommand() = literal("firmament") {
|
|||||||
RepoManager.reload()
|
RepoManager.reload()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
thenExecute {
|
|
||||||
setScreenLater(CottonClientScreen(repoGui()))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
thenLiteral("dev") {
|
thenLiteral("dev") {
|
||||||
thenLiteral("config") {
|
thenLiteral("config") {
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ object FeatureManager : DataHolder<FeatureManager.Config>(serializer(), "feature
|
|||||||
|
|
||||||
private val features = mutableMapOf<String, FirmamentFeature>()
|
private val features = mutableMapOf<String, FirmamentFeature>()
|
||||||
|
|
||||||
|
val allFeatures: Collection<FirmamentFeature> get() = features.values
|
||||||
|
|
||||||
private var hasAutoloaded = false
|
private var hasAutoloaded = false
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package moe.nea.firmament.features
|
package moe.nea.firmament.features
|
||||||
|
|
||||||
import moe.nea.firmament.util.config.ManagedConfig
|
import moe.nea.firmament.gui.config.ManagedConfig
|
||||||
|
|
||||||
interface FirmamentFeature {
|
interface FirmamentFeature {
|
||||||
val name: String
|
val name: String
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import moe.nea.firmament.events.WorldRenderLastEvent
|
|||||||
import moe.nea.firmament.features.FirmamentFeature
|
import moe.nea.firmament.features.FirmamentFeature
|
||||||
import moe.nea.firmament.util.MC
|
import moe.nea.firmament.util.MC
|
||||||
import moe.nea.firmament.util.TimeMark
|
import moe.nea.firmament.util.TimeMark
|
||||||
import moe.nea.firmament.util.config.ManagedConfig
|
import moe.nea.firmament.gui.config.ManagedConfig
|
||||||
import moe.nea.firmament.util.render.RenderBlockContext.Companion.renderBlocks
|
import moe.nea.firmament.util.render.RenderBlockContext.Companion.renderBlocks
|
||||||
|
|
||||||
object FishingWarning : FirmamentFeature {
|
object FishingWarning : FirmamentFeature {
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import moe.nea.firmament.repo.RepoManager
|
|||||||
import moe.nea.firmament.util.MC
|
import moe.nea.firmament.util.MC
|
||||||
import moe.nea.firmament.util.SBData
|
import moe.nea.firmament.util.SBData
|
||||||
import moe.nea.firmament.util.blockPos
|
import moe.nea.firmament.util.blockPos
|
||||||
import moe.nea.firmament.util.config.ManagedConfig
|
import moe.nea.firmament.gui.config.ManagedConfig
|
||||||
import moe.nea.firmament.util.data.ProfileSpecificDataHolder
|
import moe.nea.firmament.util.data.ProfileSpecificDataHolder
|
||||||
import moe.nea.firmament.util.render.RenderBlockContext.Companion.renderBlocks
|
import moe.nea.firmament.util.render.RenderBlockContext.Companion.renderBlocks
|
||||||
import moe.nea.firmament.util.unformattedString
|
import moe.nea.firmament.util.unformattedString
|
||||||
|
|||||||
@@ -1,94 +0,0 @@
|
|||||||
package moe.nea.firmament.gui
|
|
||||||
|
|
||||||
import io.github.cottonmc.cotton.gui.client.LightweightGuiDescription
|
|
||||||
import io.github.cottonmc.cotton.gui.widget.WButton
|
|
||||||
import io.github.cottonmc.cotton.gui.widget.WLabel
|
|
||||||
import io.github.cottonmc.cotton.gui.widget.WTextField
|
|
||||||
import io.github.cottonmc.cotton.gui.widget.WToggleButton
|
|
||||||
import io.github.cottonmc.cotton.gui.widget.data.HorizontalAlignment
|
|
||||||
import io.github.cottonmc.cotton.gui.widget.data.Insets
|
|
||||||
import io.github.cottonmc.cotton.gui.widget.data.VerticalAlignment
|
|
||||||
import moe.nea.firmament.Firmament
|
|
||||||
import moe.nea.firmament.util.data.DataHolder
|
|
||||||
import net.minecraft.text.Text
|
|
||||||
import kotlin.reflect.KMutableProperty1
|
|
||||||
|
|
||||||
class ConfigGui<K>(val holder: DataHolder<K>, val build: ConfigGui<K>.() -> Unit) : LightweightGuiDescription() {
|
|
||||||
private val root = WGridPanelWithPadding(verticalPadding = 4)
|
|
||||||
private val reloadables = mutableListOf<(() -> Unit)>()
|
|
||||||
|
|
||||||
init {
|
|
||||||
setRootPanel(root)
|
|
||||||
root.insets = Insets.ROOT_PANEL
|
|
||||||
build()
|
|
||||||
reload()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun title(text: Text) {
|
|
||||||
if (col != 0) {
|
|
||||||
Firmament.logger.warn("Set title not at the top of the ConfigGui")
|
|
||||||
}
|
|
||||||
val label = WLabel(text)
|
|
||||||
label.verticalAlignment = VerticalAlignment.TOP
|
|
||||||
label.horizontalAlignment = HorizontalAlignment.CENTER
|
|
||||||
root.add(label, 0, col, 11, 1)
|
|
||||||
col++
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun label(text: Text) {
|
|
||||||
val label = WLabel(text)
|
|
||||||
label.verticalAlignment = VerticalAlignment.CENTER
|
|
||||||
root.add(label, 0, col, 5, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun toggle(text: Text, prop: KMutableProperty1<K, Boolean>) {
|
|
||||||
val toggle = WToggleButton(text)
|
|
||||||
reloadables.add { toggle.toggle = prop.get(holder.data) }
|
|
||||||
toggle.setOnToggle {
|
|
||||||
prop.set(holder.data, true)
|
|
||||||
holder.markDirty()
|
|
||||||
}
|
|
||||||
root.add(toggle, 5, col, 6, 1)
|
|
||||||
label(text)
|
|
||||||
col++
|
|
||||||
}
|
|
||||||
|
|
||||||
fun button(text: Text, buttonText: Text, runnable: () -> Unit) {
|
|
||||||
val button = WButton(buttonText)
|
|
||||||
button.setOnClick {
|
|
||||||
runnable.invoke()
|
|
||||||
}
|
|
||||||
root.add(button, 5, col, 6, 1)
|
|
||||||
label(text)
|
|
||||||
col++
|
|
||||||
}
|
|
||||||
|
|
||||||
fun textfield(
|
|
||||||
text: Text,
|
|
||||||
background: Text,
|
|
||||||
prop: KMutableProperty1<K, String>,
|
|
||||||
maxLength: Int = 255
|
|
||||||
) {
|
|
||||||
val textfield = WTextField(background)
|
|
||||||
textfield.isEditable = true
|
|
||||||
reloadables.add {
|
|
||||||
textfield.text = prop.get(holder.data)
|
|
||||||
}
|
|
||||||
textfield.maxLength = maxLength
|
|
||||||
textfield.setChangedListener {
|
|
||||||
prop.set(holder.data, it)
|
|
||||||
holder.markDirty()
|
|
||||||
}
|
|
||||||
root.add(textfield, 5, col, 6, 11)
|
|
||||||
label(text)
|
|
||||||
col++
|
|
||||||
}
|
|
||||||
|
|
||||||
fun reload() {
|
|
||||||
reloadables.forEach { it.invoke() }
|
|
||||||
}
|
|
||||||
|
|
||||||
private var col = 0
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
package moe.nea.firmament.gui
|
|
||||||
|
|
||||||
import io.github.cottonmc.cotton.gui.widget.WPanelWithInsets
|
|
||||||
import io.github.cottonmc.cotton.gui.widget.WWidget
|
|
||||||
import io.github.cottonmc.cotton.gui.widget.data.Insets
|
|
||||||
|
|
||||||
class WGridPanelWithPadding(
|
|
||||||
val grid: Int = 18,
|
|
||||||
val verticalPadding: Int = 0,
|
|
||||||
val horizontalPadding: Int = 0,
|
|
||||||
) : WPanelWithInsets() {
|
|
||||||
|
|
||||||
private inline val vertOffset get() = grid + verticalPadding
|
|
||||||
private inline val horiOffset get() = grid + horizontalPadding
|
|
||||||
|
|
||||||
fun add(w: WWidget, x: Int, y: Int, width: Int = 1, height: Int = 1) {
|
|
||||||
children.add(w)
|
|
||||||
w.parent = this
|
|
||||||
w.setLocation(x * horiOffset + insets.left, y * vertOffset + insets.top)
|
|
||||||
if (w.canResize())
|
|
||||||
w.setSize(
|
|
||||||
grid + (horiOffset * (width - 1)),
|
|
||||||
grid + (vertOffset * (height - 1)),
|
|
||||||
)
|
|
||||||
expandToFit(w, insets)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setInsets(insets: Insets): WGridPanelWithPadding {
|
|
||||||
super.setInsets(insets)
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package moe.nea.firmament.gui.config
|
||||||
|
|
||||||
|
import io.github.cottonmc.cotton.gui.client.BackgroundPainter
|
||||||
|
import io.github.cottonmc.cotton.gui.client.CottonClientScreen
|
||||||
|
import io.github.cottonmc.cotton.gui.client.LightweightGuiDescription
|
||||||
|
import io.github.cottonmc.cotton.gui.widget.WButton
|
||||||
|
import io.github.cottonmc.cotton.gui.widget.WGridPanel
|
||||||
|
import io.github.cottonmc.cotton.gui.widget.WLabel
|
||||||
|
import io.github.cottonmc.cotton.gui.widget.WListPanel
|
||||||
|
import io.github.cottonmc.cotton.gui.widget.data.Insets
|
||||||
|
import net.minecraft.text.Text
|
||||||
|
import moe.nea.firmament.features.FeatureManager
|
||||||
|
import moe.nea.firmament.repo.RepoManager
|
||||||
|
import moe.nea.firmament.util.ScreenUtil.setScreenLater
|
||||||
|
|
||||||
|
object AllConfigsGui {
|
||||||
|
|
||||||
|
fun showAllGuis() {
|
||||||
|
val lwgd = LightweightGuiDescription()
|
||||||
|
var screen: CottonClientScreen? = null
|
||||||
|
lwgd.setRootPanel(WListPanel(
|
||||||
|
listOf(
|
||||||
|
RepoManager.Config
|
||||||
|
) + FeatureManager.allFeatures.mapNotNull { it.config }, ::WGridPanel
|
||||||
|
) { config, panel ->
|
||||||
|
panel.insets = Insets.ROOT_PANEL
|
||||||
|
panel.backgroundPainter = BackgroundPainter.VANILLA
|
||||||
|
panel.add(WLabel(Text.translatable("firmament.config.${config.name}")), 0, 0, 10, 1)
|
||||||
|
panel.add(WButton(Text.translatable("firmanent.config.edit")).also {
|
||||||
|
it.setOnClick {
|
||||||
|
config.showConfigEditor(screen)
|
||||||
|
}
|
||||||
|
}, 0, 1, 10, 1)
|
||||||
|
println("Panel size: ${panel.width} ${panel.height}")
|
||||||
|
}.also {
|
||||||
|
it.setListItemHeight(52)
|
||||||
|
it.setSize(10 * 18 + 14 + 16, 300)
|
||||||
|
})
|
||||||
|
screen = CottonClientScreen(lwgd)
|
||||||
|
setScreenLater(screen)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package moe.nea.firmament.gui.config
|
||||||
|
|
||||||
|
import io.github.cottonmc.cotton.gui.widget.WLabel
|
||||||
|
import io.github.cottonmc.cotton.gui.widget.WToggleButton
|
||||||
|
import io.github.cottonmc.cotton.gui.widget.data.VerticalAlignment
|
||||||
|
import kotlinx.serialization.json.JsonElement
|
||||||
|
import kotlinx.serialization.json.JsonPrimitive
|
||||||
|
import kotlinx.serialization.json.boolean
|
||||||
|
import kotlinx.serialization.json.jsonPrimitive
|
||||||
|
import net.minecraft.text.Text
|
||||||
|
|
||||||
|
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: ManagedConfig.Option<Boolean>, guiAppender: GuiAppender) {
|
||||||
|
guiAppender.appendLabeledRow(
|
||||||
|
opt.labelText,
|
||||||
|
WToggleButton(opt.labelText).apply {
|
||||||
|
guiAppender.onReload { toggle = opt.value }
|
||||||
|
setOnToggle {
|
||||||
|
opt.value = it
|
||||||
|
config.save()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
25
src/main/kotlin/moe/nea/firmament/gui/config/ClickHandler.kt
Normal file
25
src/main/kotlin/moe/nea/firmament/gui/config/ClickHandler.kt
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package moe.nea.firmament.gui.config
|
||||||
|
|
||||||
|
import io.github.cottonmc.cotton.gui.widget.WButton
|
||||||
|
import io.github.cottonmc.cotton.gui.widget.WLabel
|
||||||
|
import kotlinx.serialization.json.JsonElement
|
||||||
|
import net.minecraft.text.Text
|
||||||
|
|
||||||
|
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: ManagedConfig.Option<Unit>, guiAppender: GuiAppender) {
|
||||||
|
guiAppender.appendLabeledRow(
|
||||||
|
Text.translatable("firmament.config.${config.name}.${opt.propertyName}"),
|
||||||
|
WButton(Text.translatable("firmament.config.${config.name}.${opt.propertyName}")).apply {
|
||||||
|
setOnClick {
|
||||||
|
runnable()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
44
src/main/kotlin/moe/nea/firmament/gui/config/GuiAppender.kt
Normal file
44
src/main/kotlin/moe/nea/firmament/gui/config/GuiAppender.kt
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
package moe.nea.firmament.gui.config
|
||||||
|
|
||||||
|
import io.github.cottonmc.cotton.gui.widget.WGridPanel
|
||||||
|
import io.github.cottonmc.cotton.gui.widget.WLabel
|
||||||
|
import io.github.cottonmc.cotton.gui.widget.WWidget
|
||||||
|
import io.github.cottonmc.cotton.gui.widget.data.VerticalAlignment
|
||||||
|
import net.minecraft.text.Text
|
||||||
|
|
||||||
|
class GuiAppender(val width: Int) {
|
||||||
|
private var row = 0
|
||||||
|
internal val panel = WGridPanel().also { it.setGaps(4, 4) }
|
||||||
|
internal val reloadables = mutableListOf<(() -> Unit)>()
|
||||||
|
fun set(x: Int, y: Int, w: Int, h: Int, widget: WWidget) {
|
||||||
|
panel.add(widget, x, y, w, h)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun onReload(reloadable: () -> Unit) {
|
||||||
|
reloadables.add(reloadable)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun skipRows(r: Int) {
|
||||||
|
row += r
|
||||||
|
}
|
||||||
|
|
||||||
|
fun appendLabeledRow(label: Text, right: WWidget) {
|
||||||
|
appendSplitRow(
|
||||||
|
WLabel(label).setVerticalAlignment(VerticalAlignment.CENTER),
|
||||||
|
right
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun appendSplitRow(left: WWidget, right: WWidget) {
|
||||||
|
val lw = width / 2
|
||||||
|
set(0, row, lw, 1, left)
|
||||||
|
set(lw, row, width - lw, 1, right)
|
||||||
|
skipRows(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun appendFullRow(widget: WWidget) {
|
||||||
|
set(0, row, width, 1, widget)
|
||||||
|
skipRows(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,61 +1,25 @@
|
|||||||
package moe.nea.firmament.util.config
|
package moe.nea.firmament.gui.config
|
||||||
|
|
||||||
import io.github.cottonmc.cotton.gui.client.CottonClientScreen
|
import io.github.cottonmc.cotton.gui.client.CottonClientScreen
|
||||||
import io.github.cottonmc.cotton.gui.client.LightweightGuiDescription
|
import io.github.cottonmc.cotton.gui.client.LightweightGuiDescription
|
||||||
import io.github.cottonmc.cotton.gui.widget.WButton
|
|
||||||
import io.github.cottonmc.cotton.gui.widget.WLabel
|
|
||||||
import io.github.cottonmc.cotton.gui.widget.WToggleButton
|
|
||||||
import io.github.cottonmc.cotton.gui.widget.WWidget
|
|
||||||
import io.github.cottonmc.cotton.gui.widget.data.Insets
|
import io.github.cottonmc.cotton.gui.widget.data.Insets
|
||||||
import kotlinx.serialization.decodeFromString
|
import kotlinx.serialization.decodeFromString
|
||||||
import kotlinx.serialization.encodeToString
|
import kotlinx.serialization.encodeToString
|
||||||
import kotlinx.serialization.json.JsonElement
|
import kotlinx.serialization.json.JsonElement
|
||||||
import kotlinx.serialization.json.JsonObject
|
import kotlinx.serialization.json.JsonObject
|
||||||
import kotlinx.serialization.json.JsonPrimitive
|
|
||||||
import kotlinx.serialization.json.boolean
|
|
||||||
import kotlinx.serialization.json.jsonPrimitive
|
|
||||||
import kotlin.io.path.createDirectories
|
import kotlin.io.path.createDirectories
|
||||||
import kotlin.io.path.readText
|
import kotlin.io.path.readText
|
||||||
import kotlin.io.path.writeText
|
import kotlin.io.path.writeText
|
||||||
import kotlin.properties.ReadOnlyProperty
|
import kotlin.properties.ReadWriteProperty
|
||||||
import kotlin.reflect.KProperty
|
import kotlin.reflect.KProperty
|
||||||
|
import net.minecraft.client.gui.screen.Screen
|
||||||
import net.minecraft.text.Text
|
import net.minecraft.text.Text
|
||||||
import moe.nea.firmament.Firmament
|
import moe.nea.firmament.Firmament
|
||||||
import moe.nea.firmament.gui.WGridPanelWithPadding
|
import moe.nea.firmament.util.MC
|
||||||
import moe.nea.firmament.util.ScreenUtil.setScreenLater
|
import moe.nea.firmament.util.ScreenUtil.setScreenLater
|
||||||
|
|
||||||
abstract class ManagedConfig(val name: String) {
|
abstract class ManagedConfig(val name: String) {
|
||||||
|
|
||||||
class GuiAppender(val width: Int) {
|
|
||||||
private var row = 0
|
|
||||||
internal val panel = WGridPanelWithPadding(verticalPadding = 4, horizontalPadding = 4)
|
|
||||||
internal val reloadables = mutableListOf<(() -> Unit)>()
|
|
||||||
fun set(x: Int, y: Int, w: Int, h: Int, widget: WWidget) {
|
|
||||||
panel.add(widget, x, y, w, h)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fun onReload(reloadable: () -> Unit) {
|
|
||||||
reloadables.add(reloadable)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun skipRows(r: Int) {
|
|
||||||
row += r
|
|
||||||
}
|
|
||||||
|
|
||||||
fun appendSplitRow(left: WWidget, right: WWidget) {
|
|
||||||
val lw = width / 2
|
|
||||||
set(0, row, lw, 1, left)
|
|
||||||
set(lw, row, width - lw, 1, right)
|
|
||||||
skipRows(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun appendFullRow(widget: WWidget) {
|
|
||||||
set(0, row, width, 1, widget)
|
|
||||||
skipRows(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
interface OptionHandler<T : Any> {
|
interface OptionHandler<T : Any> {
|
||||||
fun toJson(element: T): JsonElement?
|
fun toJson(element: T): JsonElement?
|
||||||
fun fromJson(element: JsonElement): T
|
fun fromJson(element: JsonElement): T
|
||||||
@@ -63,10 +27,14 @@ abstract class ManagedConfig(val name: String) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inner class Option<T : Any> internal constructor(
|
inner class Option<T : Any> internal constructor(
|
||||||
|
val config: ManagedConfig,
|
||||||
val propertyName: String,
|
val propertyName: String,
|
||||||
val default: () -> T,
|
val default: () -> T,
|
||||||
val handler: OptionHandler<T>
|
val handler: OptionHandler<T>
|
||||||
) : ReadOnlyProperty<Any?, T> {
|
) : ReadWriteProperty<Any?, T> {
|
||||||
|
|
||||||
|
val rawLabelText = "firmament.config.${config.name}.${propertyName}"
|
||||||
|
val labelText = Text.translatable(rawLabelText)
|
||||||
|
|
||||||
private lateinit var _value: T
|
private lateinit var _value: T
|
||||||
private var loaded = false
|
private var loaded = false
|
||||||
@@ -81,6 +49,10 @@ abstract class ManagedConfig(val name: String) {
|
|||||||
_value = value
|
_value = value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
|
||||||
|
this.value = value
|
||||||
|
}
|
||||||
|
|
||||||
override fun getValue(thisRef: Any?, property: KProperty<*>): T {
|
override fun getValue(thisRef: Any?, property: KProperty<*>): T {
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
@@ -134,71 +106,48 @@ abstract class ManagedConfig(val name: String) {
|
|||||||
val allOptions = mutableMapOf<String, Option<*>>()
|
val allOptions = mutableMapOf<String, Option<*>>()
|
||||||
val sortedOptions = mutableListOf<Option<*>>()
|
val sortedOptions = mutableListOf<Option<*>>()
|
||||||
|
|
||||||
|
private var latestGuiAppender: GuiAppender? = null
|
||||||
|
|
||||||
protected fun <T : Any> option(propertyName: String, default: () -> T, handler: OptionHandler<T>): Option<T> {
|
protected fun <T : Any> option(propertyName: String, default: () -> T, handler: OptionHandler<T>): Option<T> {
|
||||||
if (propertyName in allOptions) error("Cannot register the same name twice")
|
if (propertyName in allOptions) error("Cannot register the same name twice")
|
||||||
return Option(propertyName, default, handler).also {
|
return Option(this, propertyName, default, handler).also {
|
||||||
allOptions[propertyName] = it
|
allOptions[propertyName] = it
|
||||||
sortedOptions.add(it)
|
sortedOptions.add(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class BooleanHandler(val config: 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: Option<Boolean>, guiAppender: GuiAppender) {
|
|
||||||
guiAppender.appendFullRow(
|
|
||||||
WToggleButton(Text.translatable("firmament.config.${config.name}.${opt.propertyName}")).apply {
|
|
||||||
guiAppender.onReload { toggle = opt.value }
|
|
||||||
setOnToggle {
|
|
||||||
opt.value = it
|
|
||||||
config.save()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class ClickHandler(val config: ManagedConfig, val runnable: () -> Unit) : OptionHandler<Unit> {
|
|
||||||
override fun toJson(element: Unit): JsonElement? {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun fromJson(element: JsonElement) {}
|
|
||||||
|
|
||||||
override fun emitGuiElements(opt: Option<Unit>, guiAppender: GuiAppender) {
|
|
||||||
guiAppender.appendSplitRow(
|
|
||||||
WLabel(Text.translatable("firmament.config.${config.name}.${opt.propertyName}")),
|
|
||||||
WButton(Text.translatable("firmament.config.${config.name}.${opt.propertyName}")).apply {
|
|
||||||
setOnClick {
|
|
||||||
runnable()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected fun toggle(propertyName: String, default: () -> Boolean): Option<Boolean> {
|
protected fun toggle(propertyName: String, default: () -> Boolean): Option<Boolean> {
|
||||||
return option(propertyName, default, BooleanHandler(this))
|
return option(propertyName, default, BooleanHandler(this))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun showConfigEditor() {
|
|
||||||
val lwgd = LightweightGuiDescription()
|
|
||||||
val guiapp = GuiAppender(20)
|
|
||||||
guiapp.panel.insets = Insets.ROOT_PANEL
|
|
||||||
sortedOptions.forEach { it.appendToGui(guiapp) }
|
|
||||||
guiapp.reloadables.forEach { it() }
|
|
||||||
lwgd.setRootPanel(guiapp.panel)
|
|
||||||
setScreenLater(CottonClientScreen(lwgd))
|
|
||||||
}
|
|
||||||
|
|
||||||
protected fun button(propertyName: String, runnable: () -> Unit): Option<Unit> {
|
protected fun button(propertyName: String, runnable: () -> Unit): Option<Unit> {
|
||||||
return option(propertyName, { }, ClickHandler(this, runnable))
|
return option(propertyName, { }, ClickHandler(this, runnable))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected fun string(propertyName: String, default: () -> String): Option<String> {
|
||||||
|
return option(propertyName, default, StringHandler(this))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
fun reloadGui() {
|
||||||
|
latestGuiAppender?.reloadables?.forEach {it() }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun showConfigEditor(parent: Screen? = null) {
|
||||||
|
val lwgd = LightweightGuiDescription()
|
||||||
|
val guiapp = GuiAppender(20)
|
||||||
|
latestGuiAppender = guiapp
|
||||||
|
guiapp.panel.insets = Insets.ROOT_PANEL
|
||||||
|
sortedOptions.forEach { it.appendToGui(guiapp) }
|
||||||
|
guiapp.reloadables.forEach { it() }
|
||||||
|
lwgd.setRootPanel(guiapp.panel)
|
||||||
|
setScreenLater(object : CottonClientScreen(lwgd) {
|
||||||
|
override fun close() {
|
||||||
|
latestGuiAppender = null
|
||||||
|
MC.screen = parent
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package moe.nea.firmament.gui.config
|
||||||
|
|
||||||
|
import io.github.cottonmc.cotton.gui.widget.WLabel
|
||||||
|
import io.github.cottonmc.cotton.gui.widget.WTextField
|
||||||
|
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.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun emitGuiElements(opt: ManagedConfig.Option<String>, guiAppender: GuiAppender) {
|
||||||
|
guiAppender.appendLabeledRow(
|
||||||
|
opt.labelText,
|
||||||
|
WTextField(opt.labelText).apply {
|
||||||
|
suggestion = Text.translatableWithFallback(opt.rawLabelText + ".hint", "")
|
||||||
|
guiAppender.onReload { text = opt.value }
|
||||||
|
setChangedListener {
|
||||||
|
opt.value = it
|
||||||
|
config.save()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
package moe.nea.firmament.gui
|
|
||||||
|
|
||||||
import net.minecraft.text.Text
|
|
||||||
import moe.nea.firmament.repo.RepoManager
|
|
||||||
|
|
||||||
fun repoGui(): ConfigGui<RepoManager.Config> {
|
|
||||||
return ConfigGui(RepoManager) {
|
|
||||||
title(Text.translatable("firmament.gui.repo.title"))
|
|
||||||
toggle(Text.translatable("firmament.gui.repo.autoupdate"), RepoManager.Config::autoUpdate)
|
|
||||||
textfield(
|
|
||||||
Text.translatable("firmament.gui.repo.username"),
|
|
||||||
Text.translatable("firmament.gui.repo.hint.username"),
|
|
||||||
RepoManager.Config::user,
|
|
||||||
maxLength = 255
|
|
||||||
)
|
|
||||||
textfield(
|
|
||||||
Text.translatable("firmament.gui.repo.reponame"),
|
|
||||||
Text.translatable("firmament.gui.repo.hint.reponame"),
|
|
||||||
RepoManager.Config::repo
|
|
||||||
)
|
|
||||||
textfield(
|
|
||||||
Text.translatable("firmament.gui.repo.branch"),
|
|
||||||
Text.translatable("firmament.gui.repo.hint.branch"),
|
|
||||||
RepoManager.Config::branch
|
|
||||||
)
|
|
||||||
button(
|
|
||||||
Text.translatable("firmament.gui.repo.reset.label"),
|
|
||||||
Text.translatable("firmament.gui.repo.reset"),
|
|
||||||
) {
|
|
||||||
RepoManager.data.user = "NotEnoughUpdates"
|
|
||||||
RepoManager.data.repo = "NotEnoughUpdates-REPO"
|
|
||||||
RepoManager.data.branch = "dangerous"
|
|
||||||
reload()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -50,7 +50,7 @@ object RepoDownloadManager {
|
|||||||
|
|
||||||
private suspend fun requestLatestGithubSha(): String? {
|
private suspend fun requestLatestGithubSha(): String? {
|
||||||
val response =
|
val response =
|
||||||
Firmament.httpClient.get("https://api.github.com/repos/${RepoManager.data.user}/${RepoManager.data.repo}/commits/${RepoManager.data.branch}")
|
Firmament.httpClient.get("https://api.github.com/repos/${RepoManager.Config.username}/${RepoManager.Config.reponame}/commits/${RepoManager.Config.branch}")
|
||||||
if (response.status.value != 200) {
|
if (response.status.value != 200) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
@@ -77,7 +77,7 @@ object RepoDownloadManager {
|
|||||||
}
|
}
|
||||||
val currentSha = loadSavedVersionHash()
|
val currentSha = loadSavedVersionHash()
|
||||||
if (latestSha != currentSha || force) {
|
if (latestSha != currentSha || force) {
|
||||||
val requestUrl = "https://github.com/${RepoManager.data.user}/${RepoManager.data.repo}/archive/$latestSha.zip"
|
val requestUrl = "https://github.com/${RepoManager.Config.username}/${RepoManager.Config.reponame}/archive/$latestSha.zip"
|
||||||
logger.info("Planning to upgrade repository from $currentSha to $latestSha from $requestUrl")
|
logger.info("Planning to upgrade repository from $currentSha to $latestSha from $requestUrl")
|
||||||
val zipFile = downloadGithubArchive(requestUrl)
|
val zipFile = downloadGithubArchive(requestUrl)
|
||||||
logger.info("Download repository zip file to $zipFile. Deleting old repository")
|
logger.info("Download repository zip file to $zipFile. Deleting old repository")
|
||||||
|
|||||||
@@ -8,8 +8,6 @@ import io.github.moulberry.repo.data.NEUItem
|
|||||||
import io.github.moulberry.repo.data.NEURecipe
|
import io.github.moulberry.repo.data.NEURecipe
|
||||||
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents
|
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.serialization.Serializable
|
|
||||||
import kotlinx.serialization.serializer
|
|
||||||
import net.minecraft.client.MinecraftClient
|
import net.minecraft.client.MinecraftClient
|
||||||
import net.minecraft.network.packet.s2c.play.SynchronizeRecipesS2CPacket
|
import net.minecraft.network.packet.s2c.play.SynchronizeRecipesS2CPacket
|
||||||
import net.minecraft.text.Text
|
import net.minecraft.text.Text
|
||||||
@@ -17,16 +15,21 @@ import moe.nea.firmament.Firmament
|
|||||||
import moe.nea.firmament.Firmament.logger
|
import moe.nea.firmament.Firmament.logger
|
||||||
import moe.nea.firmament.hud.ProgressBar
|
import moe.nea.firmament.hud.ProgressBar
|
||||||
import moe.nea.firmament.util.SkyblockId
|
import moe.nea.firmament.util.SkyblockId
|
||||||
import moe.nea.firmament.util.data.DataHolder
|
import moe.nea.firmament.gui.config.ManagedConfig
|
||||||
|
|
||||||
object RepoManager : DataHolder<RepoManager.Config>(serializer(), "repo", ::Config) {
|
object RepoManager {
|
||||||
@Serializable
|
object Config : ManagedConfig("repo") {
|
||||||
data class Config(
|
var username by string("username") { "NotEnoughUpdates" }
|
||||||
var user: String = "NotEnoughUpdates",
|
var reponame by string("reponame") { "NotEnoughUpdates-REPO" }
|
||||||
var repo: String = "NotEnoughUpdates-REPO",
|
var branch by string("branch") { "prerelease" }
|
||||||
var autoUpdate: Boolean = true,
|
val autoUpdate by toggle("autoUpdate") { true }
|
||||||
var branch: String = "dangerous",
|
val reset by button("reset") {
|
||||||
)
|
username = "NotEnoughUpdates"
|
||||||
|
reponame = "NotEnoughUpdates-REPO"
|
||||||
|
branch = "prerelease"
|
||||||
|
save()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val currentDownloadedSha by RepoDownloadManager::latestSavedVersionHash
|
val currentDownloadedSha by RepoDownloadManager::latestSavedVersionHash
|
||||||
|
|
||||||
@@ -93,7 +96,7 @@ object RepoManager : DataHolder<RepoManager.Config>(serializer(), "repo", ::Conf
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun initialize() {
|
fun initialize() {
|
||||||
if (data.autoUpdate) {
|
if (Config.autoUpdate) {
|
||||||
launchAsyncUpdate()
|
launchAsyncUpdate()
|
||||||
} else {
|
} else {
|
||||||
reload()
|
reload()
|
||||||
|
|||||||
@@ -4,13 +4,14 @@ import io.github.moulberry.repo.data.Coordinate
|
|||||||
import net.minecraft.client.MinecraftClient
|
import net.minecraft.client.MinecraftClient
|
||||||
import net.minecraft.client.gui.screen.ingame.HandledScreen
|
import net.minecraft.client.gui.screen.ingame.HandledScreen
|
||||||
import net.minecraft.util.math.BlockPos
|
import net.minecraft.util.math.BlockPos
|
||||||
import moe.nea.firmament.mixins.accessor.AccessorHandledScreen
|
|
||||||
|
|
||||||
object MC {
|
object MC {
|
||||||
inline val soundManager get() = MinecraftClient.getInstance().soundManager
|
inline val soundManager get() = MinecraftClient.getInstance().soundManager
|
||||||
inline val player get() = MinecraftClient.getInstance().player
|
inline val player get() = MinecraftClient.getInstance().player
|
||||||
inline val world get() = MinecraftClient.getInstance().world
|
inline val world get() = MinecraftClient.getInstance().world
|
||||||
inline val screen get() = MinecraftClient.getInstance().currentScreen
|
inline var screen
|
||||||
|
get() = MinecraftClient.getInstance().currentScreen
|
||||||
|
set(value) = MinecraftClient.getInstance().setScreen(value)
|
||||||
inline val handledScreen: HandledScreen<*>? get() = MinecraftClient.getInstance().currentScreen as? HandledScreen<*>
|
inline val handledScreen: HandledScreen<*>? get() = MinecraftClient.getInstance().currentScreen as? HandledScreen<*>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,24 +3,26 @@
|
|||||||
"firmament.repo.reload.disk": "Reloading repository from disk. This may lag a bit.",
|
"firmament.repo.reload.disk": "Reloading repository from disk. This may lag a bit.",
|
||||||
"firmament.repo.cache": "Recaching items",
|
"firmament.repo.cache": "Recaching items",
|
||||||
"firmament.repo.brokenitem": "Failed to render item: %s",
|
"firmament.repo.brokenitem": "Failed to render item: %s",
|
||||||
"firmament.gui.repo.title": "firmament Repo Settings",
|
"firmanent.config.edit": "Edit",
|
||||||
"firmament.gui.repo.autoupdate": "Auto Update",
|
"firmament.config.repo": "Firmament Repo Settings",
|
||||||
"firmament.gui.repo.username": "Repo Username",
|
"firmament.config.repo.autoUpdate": "Auto Update",
|
||||||
"firmament.gui.repo.hint.username": "NotEnoughUpdates",
|
"firmament.config.repo.username": "Repo Username",
|
||||||
"firmament.gui.repo.reponame": "Repo Name",
|
"firmament.config.repo.username.hint": "NotEnoughUpdates",
|
||||||
"firmament.gui.repo.hint.reponame": "NotEnoughUpdates-REPO",
|
"firmament.config.repo.reponame": "Repo Name",
|
||||||
"firmament.gui.repo.branch": "Repo Branch",
|
"firmament.config.repo.reponame.hint": "NotEnoughUpdates-REPO",
|
||||||
"firmament.gui.repo.hint.branch": "dangerous",
|
"firmament.config.repo.branch": "Repo Branch",
|
||||||
"firmament.gui.repo.reset": "Reset",
|
"firmament.config.repo.branch.hint": "dangerous",
|
||||||
"firmament.gui.repo.reset.label": "Reset to Defaults",
|
"firmament.config.repo.reset": "Reset",
|
||||||
"firmament.sbinfo.nolocraw": "No locraw data available",
|
"firmament.sbinfo.nolocraw": "No locraw data available",
|
||||||
"firmament.sbinfo.profile": "Current profile cutename: %s",
|
"firmament.sbinfo.profile": "Current profile cutename: %s",
|
||||||
"firmament.sbinfo.server": "Locraw Server: %s",
|
"firmament.sbinfo.server": "Locraw Server: %s",
|
||||||
"firmament.sbinfo.gametype": "Locraw Gametype: %s",
|
"firmament.sbinfo.gametype": "Locraw Gametype: %s",
|
||||||
"firmament.sbinfo.mode": "Locraw Mode: %s",
|
"firmament.sbinfo.mode": "Locraw Mode: %s",
|
||||||
"firmament.sbinfo.map": "Locraw Map: %s",
|
"firmament.sbinfo.map": "Locraw Map: %s",
|
||||||
|
"firmament.config.fairy-souls": "Fairy Souls",
|
||||||
"firmament.config.fairy-souls.show": "Show Fairy Soul Waypoints",
|
"firmament.config.fairy-souls.show": "Show Fairy Soul Waypoints",
|
||||||
"firmament.config.fairy-souls.reset": "Reset Collected Fairy Souls",
|
"firmament.config.fairy-souls.reset": "Reset Collected Fairy Souls",
|
||||||
|
"firmament.config.fishing-warning": "Fishing Warning",
|
||||||
"firmament.config.fishing-warning.display-warning": "Display a warning when you are about to hook a fish",
|
"firmament.config.fishing-warning.display-warning": "Display a warning when you are about to hook a fish",
|
||||||
"firmament.config.fishing-warning.highlight-wake-chain": "Highlight fishing particles",
|
"firmament.config.fishing-warning.highlight-wake-chain": "Highlight fishing particles",
|
||||||
"firmament.key.slotlocking": "Lock Slot / Slot Binding",
|
"firmament.key.slotlocking": "Lock Slot / Slot Binding",
|
||||||
|
|||||||
Reference in New Issue
Block a user