rudimentary config gui (again)
This commit is contained in:
1
TODO.txt
1
TODO.txt
@@ -1,4 +1,3 @@
|
||||
- translations
|
||||
- recipes
|
||||
- fairy souls
|
||||
- easy config gui builder
|
||||
|
||||
@@ -26,7 +26,7 @@ import moe.nea.notenoughupdates.dbus.NEUDbusObject
|
||||
import moe.nea.notenoughupdates.features.FeatureManager
|
||||
import moe.nea.notenoughupdates.repo.RepoManager
|
||||
import moe.nea.notenoughupdates.util.SBData
|
||||
import moe.nea.notenoughupdates.util.config.IConfigHolder
|
||||
import moe.nea.notenoughupdates.util.data.IDataHolder
|
||||
|
||||
object NotEnoughUpdates : ModInitializer, ClientModInitializer {
|
||||
const val MOD_ID = "notenoughupdates"
|
||||
@@ -72,7 +72,7 @@ object NotEnoughUpdates : ModInitializer, ClientModInitializer {
|
||||
override fun onInitialize() {
|
||||
dbusConnection.requestBusName("moe.nea.notenoughupdates")
|
||||
dbusConnection.exportObject(NEUDbusObject)
|
||||
IConfigHolder.registerEvents()
|
||||
IDataHolder.registerEvents()
|
||||
RepoManager.initialize()
|
||||
SBData.init()
|
||||
FeatureManager.autoload()
|
||||
|
||||
@@ -4,6 +4,7 @@ import com.mojang.brigadier.CommandDispatcher
|
||||
import io.github.cottonmc.cotton.gui.client.CottonClientScreen
|
||||
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource
|
||||
import net.minecraft.text.Text
|
||||
import moe.nea.notenoughupdates.features.world.FairySouls
|
||||
import moe.nea.notenoughupdates.gui.repoGui
|
||||
import moe.nea.notenoughupdates.repo.RepoManager
|
||||
import moe.nea.notenoughupdates.util.SBData
|
||||
@@ -29,6 +30,11 @@ fun neuCommand() = literal("neu") {
|
||||
}
|
||||
}
|
||||
thenLiteral("dev") {
|
||||
thenLiteral("config") {
|
||||
thenExecute {
|
||||
FairySouls.TConfig.showConfigEditor()
|
||||
}
|
||||
}
|
||||
thenLiteral("sbdata") {
|
||||
thenExecute {
|
||||
source.sendFeedback(Text.translatable("notenoughupdates.sbinfo.profile", SBData.profileCuteName))
|
||||
|
||||
@@ -4,9 +4,9 @@ import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.serializer
|
||||
import moe.nea.notenoughupdates.NotEnoughUpdates
|
||||
import moe.nea.notenoughupdates.features.world.FairySouls
|
||||
import moe.nea.notenoughupdates.util.config.ConfigHolder
|
||||
import moe.nea.notenoughupdates.util.data.DataHolder
|
||||
|
||||
object FeatureManager : ConfigHolder<FeatureManager.Config>(serializer(), "features", ::Config) {
|
||||
object FeatureManager : DataHolder<FeatureManager.Config>(serializer(), "features", ::Config) {
|
||||
@Serializable
|
||||
data class Config(
|
||||
val enabledFeatures: MutableMap<String, Boolean> = mutableMapOf()
|
||||
@@ -40,11 +40,11 @@ object FeatureManager : ConfigHolder<FeatureManager.Config>(serializer(), "featu
|
||||
}
|
||||
|
||||
fun isEnabled(identifier: String): Boolean? =
|
||||
config.enabledFeatures[identifier]
|
||||
data.enabledFeatures[identifier]
|
||||
|
||||
|
||||
fun setEnabled(identifier: String, value: Boolean) {
|
||||
config.enabledFeatures[identifier] = value
|
||||
data.enabledFeatures[identifier] = value
|
||||
markDirty()
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package moe.nea.notenoughupdates.features.world
|
||||
import io.github.moulberry.repo.data.Coordinate
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.serializer
|
||||
import net.minecraft.client.MinecraftClient
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import moe.nea.notenoughupdates.events.ServerChatLineReceivedEvent
|
||||
import moe.nea.notenoughupdates.events.SkyblockServerUpdateEvent
|
||||
@@ -11,7 +12,8 @@ import moe.nea.notenoughupdates.features.NEUFeature
|
||||
import moe.nea.notenoughupdates.repo.RepoManager
|
||||
import moe.nea.notenoughupdates.util.MC
|
||||
import moe.nea.notenoughupdates.util.SBData
|
||||
import moe.nea.notenoughupdates.util.config.ProfileSpecificConfigHolder
|
||||
import moe.nea.notenoughupdates.util.config.ManagedConfig
|
||||
import moe.nea.notenoughupdates.util.data.ProfileSpecificDataHolder
|
||||
import moe.nea.notenoughupdates.util.render.RenderBlockContext.Companion.renderBlocks
|
||||
import moe.nea.notenoughupdates.util.unformattedString
|
||||
|
||||
@@ -19,12 +21,22 @@ val Coordinate.blockPos: BlockPos
|
||||
get() = BlockPos(x, y, z)
|
||||
|
||||
object FairySouls : NEUFeature,
|
||||
ProfileSpecificConfigHolder<FairySouls.Config>(serializer(), "fairy-souls.json", ::Config) {
|
||||
ProfileSpecificDataHolder<FairySouls.Config>(serializer(), "found-fairysouls", ::Config) {
|
||||
@Serializable
|
||||
data class Config(
|
||||
val foundSouls: MutableMap<String, MutableSet<Int>> = mutableMapOf()
|
||||
)
|
||||
|
||||
object TConfig : ManagedConfig("fairysouls") {
|
||||
|
||||
val displaySouls by toggle("show") { false }
|
||||
val resetSouls by button("reset") {
|
||||
FairySouls.data?.foundSouls?.clear() != null
|
||||
updateMissingSouls()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override val name: String get() = "Fairy Souls"
|
||||
override val identifier: String get() = "fairy-souls"
|
||||
|
||||
@@ -37,7 +49,7 @@ object FairySouls : NEUFeature,
|
||||
|
||||
fun updateMissingSouls() {
|
||||
currentMissingSouls = emptyList()
|
||||
val c = config ?: return
|
||||
val c = data ?: return
|
||||
val fi = c.foundSouls[currentLocationName] ?: setOf()
|
||||
val cms = currentLocationSouls.toMutableList()
|
||||
fi.asSequence().sortedDescending().filter { it in cms.indices }.forEach { cms.removeAt(it) }
|
||||
@@ -65,7 +77,7 @@ object FairySouls : NEUFeature,
|
||||
|
||||
private fun markNearestSoul() {
|
||||
val nearestSoul = findNearestClickableSoul() ?: return
|
||||
val c = config ?: return
|
||||
val c = data ?: return
|
||||
val loc = currentLocationName ?: return
|
||||
val idx = currentLocationSouls.indexOf(nearestSoul)
|
||||
c.foundSouls.computeIfAbsent(loc) { mutableSetOf() }.add(idx)
|
||||
@@ -92,6 +104,7 @@ object FairySouls : NEUFeature,
|
||||
}
|
||||
}
|
||||
WorldRenderLastEvent.subscribe {
|
||||
if (!TConfig.displaySouls) return@subscribe
|
||||
renderBlocks(it.camera) {
|
||||
color(1F, 1F, 0F, 0.8F)
|
||||
currentMissingSouls.forEach {
|
||||
|
||||
@@ -9,11 +9,11 @@ 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.notenoughupdates.NotEnoughUpdates
|
||||
import moe.nea.notenoughupdates.util.config.ConfigHolder
|
||||
import moe.nea.notenoughupdates.util.data.DataHolder
|
||||
import net.minecraft.text.Text
|
||||
import kotlin.reflect.KMutableProperty1
|
||||
|
||||
class ConfigGui<K>(val holder: ConfigHolder<K>, val build: ConfigGui<K>.() -> Unit) : LightweightGuiDescription() {
|
||||
class ConfigGui<K>(val holder: DataHolder<K>, val build: ConfigGui<K>.() -> Unit) : LightweightGuiDescription() {
|
||||
private val root = WGridPanelWithPadding(verticalPadding = 4)
|
||||
private val reloadables = mutableListOf<(() -> Unit)>()
|
||||
|
||||
@@ -43,9 +43,9 @@ class ConfigGui<K>(val holder: ConfigHolder<K>, val build: ConfigGui<K>.() -> Un
|
||||
|
||||
fun toggle(text: Text, prop: KMutableProperty1<K, Boolean>) {
|
||||
val toggle = WToggleButton(text)
|
||||
reloadables.add { toggle.toggle = prop.get(holder.config) }
|
||||
reloadables.add { toggle.toggle = prop.get(holder.data) }
|
||||
toggle.setOnToggle {
|
||||
prop.set(holder.config, true)
|
||||
prop.set(holder.data, true)
|
||||
holder.markDirty()
|
||||
}
|
||||
root.add(toggle, 5, col, 6, 1)
|
||||
@@ -72,11 +72,11 @@ class ConfigGui<K>(val holder: ConfigHolder<K>, val build: ConfigGui<K>.() -> Un
|
||||
val textfield = WTextField(background)
|
||||
textfield.isEditable = true
|
||||
reloadables.add {
|
||||
textfield.text = prop.get(holder.config)
|
||||
textfield.text = prop.get(holder.data)
|
||||
}
|
||||
textfield.maxLength = maxLength
|
||||
textfield.setChangedListener {
|
||||
prop.set(holder.config, it)
|
||||
prop.set(holder.data, it)
|
||||
holder.markDirty()
|
||||
}
|
||||
root.add(textfield, 5, col, 6, 11)
|
||||
|
||||
@@ -27,9 +27,9 @@ fun repoGui(): ConfigGui<RepoManager.Config> {
|
||||
Text.translatable("notenoughupdates.gui.repo.reset.label"),
|
||||
Text.translatable("notenoughupdates.gui.repo.reset"),
|
||||
) {
|
||||
RepoManager.config.user = "NotEnoughUpdates"
|
||||
RepoManager.config.repo = "NotEnoughUpdates-REPO"
|
||||
RepoManager.config.branch = "dangerous"
|
||||
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? {
|
||||
val response =
|
||||
NotEnoughUpdates.httpClient.get("https://api.github.com/repos/${RepoManager.config.user}/${RepoManager.config.repo}/commits/${RepoManager.config.branch}")
|
||||
NotEnoughUpdates.httpClient.get("https://api.github.com/repos/${RepoManager.data.user}/${RepoManager.data.repo}/commits/${RepoManager.data.branch}")
|
||||
if (response.status.value != 200) {
|
||||
return null
|
||||
}
|
||||
@@ -77,7 +77,7 @@ object RepoDownloadManager {
|
||||
}
|
||||
val currentSha = loadSavedVersionHash()
|
||||
if (latestSha != currentSha || force) {
|
||||
val requestUrl = "https://github.com/${RepoManager.config.user}/${RepoManager.config.repo}/archive/$latestSha.zip"
|
||||
val requestUrl = "https://github.com/${RepoManager.data.user}/${RepoManager.data.repo}/archive/$latestSha.zip"
|
||||
logger.info("Planning to upgrade repository from $currentSha to $latestSha from $requestUrl")
|
||||
val zipFile = downloadGithubArchive(requestUrl)
|
||||
logger.info("Download repository zip file to $zipFile. Deleting old repository")
|
||||
|
||||
@@ -9,13 +9,13 @@ import kotlinx.serialization.serializer
|
||||
import moe.nea.notenoughupdates.NotEnoughUpdates
|
||||
import moe.nea.notenoughupdates.NotEnoughUpdates.logger
|
||||
import moe.nea.notenoughupdates.hud.ProgressBar
|
||||
import moe.nea.notenoughupdates.util.config.ConfigHolder
|
||||
import moe.nea.notenoughupdates.util.data.DataHolder
|
||||
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents
|
||||
import net.minecraft.client.MinecraftClient
|
||||
import net.minecraft.network.packet.s2c.play.SynchronizeRecipesS2CPacket
|
||||
import net.minecraft.text.Text
|
||||
|
||||
object RepoManager : ConfigHolder<RepoManager.Config>(serializer(), "repo", ::Config) {
|
||||
object RepoManager : DataHolder<RepoManager.Config>(serializer(), "repo", ::Config) {
|
||||
@Serializable
|
||||
data class Config(
|
||||
var user: String = "NotEnoughUpdates",
|
||||
@@ -80,7 +80,7 @@ object RepoManager : ConfigHolder<RepoManager.Config>(serializer(), "repo", ::Co
|
||||
}
|
||||
|
||||
fun initialize() {
|
||||
if (config.autoUpdate) {
|
||||
if (data.autoUpdate) {
|
||||
launchAsyncUpdate()
|
||||
} else {
|
||||
reload()
|
||||
|
||||
@@ -0,0 +1,206 @@
|
||||
package moe.nea.notenoughupdates.util.config
|
||||
|
||||
import io.github.cottonmc.cotton.gui.client.CottonClientScreen
|
||||
import io.github.cottonmc.cotton.gui.client.LibGui
|
||||
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 kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.encodeToString
|
||||
import kotlinx.serialization.json.JsonElement
|
||||
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.readText
|
||||
import kotlin.io.path.writeText
|
||||
import kotlin.properties.ReadOnlyProperty
|
||||
import kotlin.reflect.KProperty
|
||||
import net.minecraft.client.MinecraftClient
|
||||
import net.minecraft.text.Text
|
||||
import moe.nea.notenoughupdates.NotEnoughUpdates
|
||||
import moe.nea.notenoughupdates.gui.WGridPanelWithPadding
|
||||
import moe.nea.notenoughupdates.util.ScreenUtil.setScreenLater
|
||||
|
||||
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> {
|
||||
fun toJson(element: T): JsonElement?
|
||||
fun fromJson(element: JsonElement): T
|
||||
fun emitGuiElements(opt: Option<T>, guiAppender: GuiAppender)
|
||||
}
|
||||
|
||||
inner class Option<T : Any> internal constructor(
|
||||
val propertyName: String,
|
||||
val default: () -> T,
|
||||
val handler: OptionHandler<T>
|
||||
) : ReadOnlyProperty<Any?, T> {
|
||||
|
||||
private lateinit var _value: T
|
||||
private var loaded = false
|
||||
var value: T
|
||||
get() {
|
||||
if (!loaded)
|
||||
load()
|
||||
return _value
|
||||
}
|
||||
set(value) {
|
||||
loaded = true
|
||||
_value = value
|
||||
}
|
||||
|
||||
override fun getValue(thisRef: Any?, property: KProperty<*>): T {
|
||||
return value
|
||||
}
|
||||
|
||||
private fun load() {
|
||||
if (data.containsKey(propertyName)) {
|
||||
try {
|
||||
value = handler.fromJson(data[propertyName]!!)
|
||||
} catch (e: Exception) {
|
||||
NotEnoughUpdates.logger.error(
|
||||
"Exception during loading of config file $name. This will reset this config.",
|
||||
e
|
||||
)
|
||||
}
|
||||
}
|
||||
value = default()
|
||||
}
|
||||
|
||||
internal fun toJson(): JsonElement? {
|
||||
return handler.toJson(value)
|
||||
}
|
||||
|
||||
fun appendToGui(guiapp: GuiAppender) {
|
||||
handler.emitGuiElements(this, guiapp)
|
||||
}
|
||||
}
|
||||
|
||||
val file = NotEnoughUpdates.CONFIG_DIR.resolve("$name.json")
|
||||
val data: JsonObject by lazy {
|
||||
try {
|
||||
NotEnoughUpdates.json.decodeFromString(
|
||||
file.readText()
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
NotEnoughUpdates.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(NotEnoughUpdates.json.encodeToString(data))
|
||||
}
|
||||
|
||||
|
||||
val allOptions = mutableMapOf<String, Option<*>>()
|
||||
val sortedOptions = mutableListOf<Option<*>>()
|
||||
|
||||
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")
|
||||
return Option(propertyName, default, handler).also {
|
||||
allOptions[propertyName] = 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("neu.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("neu.config.${config.name}.${opt.propertyName}")),
|
||||
WButton(Text.translatable("neu.config.${config.name}.${opt.propertyName}")).apply {
|
||||
setOnClick {
|
||||
runnable()
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
protected fun toggle(propertyName: String, default: () -> Boolean): Option<Boolean> {
|
||||
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> {
|
||||
return option(propertyName, { }, ClickHandler(this, runnable))
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package moe.nea.notenoughupdates.util.config
|
||||
package moe.nea.notenoughupdates.util.data
|
||||
|
||||
import java.nio.file.Path
|
||||
import kotlinx.serialization.KSerializer
|
||||
@@ -7,19 +7,19 @@ import kotlin.io.path.readText
|
||||
import kotlin.io.path.writeText
|
||||
import moe.nea.notenoughupdates.NotEnoughUpdates
|
||||
|
||||
abstract class ConfigHolder<T>(
|
||||
abstract class DataHolder<T>(
|
||||
val serializer: KSerializer<T>,
|
||||
val name: String,
|
||||
val default: () -> T
|
||||
) : IConfigHolder<T> {
|
||||
) : IDataHolder<T> {
|
||||
|
||||
|
||||
final override var config: T
|
||||
final override var data: T
|
||||
private set
|
||||
|
||||
init {
|
||||
config = readValueOrDefault()
|
||||
IConfigHolder.putConfig(this::class, this)
|
||||
data = readValueOrDefault()
|
||||
IDataHolder.putDataHolder(this::class, this)
|
||||
}
|
||||
|
||||
private val file: Path get() = NotEnoughUpdates.CONFIG_DIR.resolve("$name.json")
|
||||
@@ -32,7 +32,7 @@ abstract class ConfigHolder<T>(
|
||||
file.readText()
|
||||
)
|
||||
} catch (e: Exception) {/* Expecting IOException and SerializationException, but Kotlin doesn't allow multi catches*/
|
||||
IConfigHolder.badLoads.add(name)
|
||||
IDataHolder.badLoads.add(name)
|
||||
NotEnoughUpdates.logger.error(
|
||||
"Exception during loading of config file $name. This will reset this config.",
|
||||
e
|
||||
@@ -46,15 +46,15 @@ abstract class ConfigHolder<T>(
|
||||
}
|
||||
|
||||
override fun save() {
|
||||
writeValue(config)
|
||||
writeValue(data)
|
||||
}
|
||||
|
||||
override fun load() {
|
||||
config = readValueOrDefault()
|
||||
data = readValueOrDefault()
|
||||
}
|
||||
|
||||
override fun markDirty() {
|
||||
IConfigHolder.markDirty(this::class)
|
||||
IDataHolder.markDirty(this::class)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package moe.nea.notenoughupdates.util.config
|
||||
package moe.nea.notenoughupdates.util.data
|
||||
|
||||
import java.util.concurrent.CopyOnWriteArrayList
|
||||
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents
|
||||
@@ -9,17 +9,17 @@ import net.minecraft.text.Text
|
||||
import moe.nea.notenoughupdates.NotEnoughUpdates
|
||||
import moe.nea.notenoughupdates.events.ScreenOpenEvent
|
||||
|
||||
interface IConfigHolder<T> {
|
||||
interface IDataHolder<T> {
|
||||
companion object {
|
||||
internal var badLoads: MutableList<String> = CopyOnWriteArrayList()
|
||||
private val allConfigs: MutableMap<KClass<out IConfigHolder<*>>, IConfigHolder<*>> = mutableMapOf()
|
||||
private val dirty: MutableSet<KClass<out IConfigHolder<*>>> = mutableSetOf()
|
||||
private val allConfigs: MutableMap<KClass<out IDataHolder<*>>, IDataHolder<*>> = mutableMapOf()
|
||||
private val dirty: MutableSet<KClass<out IDataHolder<*>>> = mutableSetOf()
|
||||
|
||||
internal fun <T : IConfigHolder<K>, K> putConfig(kClass: KClass<T>, inst: IConfigHolder<K>) {
|
||||
internal fun <T : IDataHolder<K>, K> putDataHolder(kClass: KClass<T>, inst: IDataHolder<K>) {
|
||||
allConfigs[kClass] = inst
|
||||
}
|
||||
|
||||
fun <T : IConfigHolder<K>, K> markDirty(kClass: KClass<T>) {
|
||||
fun <T : IDataHolder<K>, K> markDirty(kClass: KClass<T>) {
|
||||
if (kClass !in allConfigs) {
|
||||
NotEnoughUpdates.logger.error("Tried to markDirty '${kClass.qualifiedName}', which isn't registered as 'IConfigHolder'")
|
||||
return
|
||||
@@ -68,7 +68,7 @@ interface IConfigHolder<T> {
|
||||
|
||||
}
|
||||
|
||||
val config: T
|
||||
val data: T
|
||||
fun save()
|
||||
fun markDirty()
|
||||
fun load()
|
||||
@@ -1,4 +1,4 @@
|
||||
package moe.nea.notenoughupdates.util.config
|
||||
package moe.nea.notenoughupdates.util.data
|
||||
|
||||
import java.nio.file.Path
|
||||
import kotlinx.serialization.KSerializer
|
||||
@@ -13,15 +13,15 @@ import kotlin.io.path.writeText
|
||||
import moe.nea.notenoughupdates.NotEnoughUpdates
|
||||
import moe.nea.notenoughupdates.util.SBData
|
||||
|
||||
abstract class ProfileSpecificConfigHolder<S>(
|
||||
private val configSerializer: KSerializer<S>,
|
||||
abstract class ProfileSpecificDataHolder<S>(
|
||||
private val dataSerializer: KSerializer<S>,
|
||||
val configName: String,
|
||||
private val configDefault: () -> S
|
||||
) : IConfigHolder<S?> {
|
||||
) : IDataHolder<S?> {
|
||||
|
||||
var allConfigs: MutableMap<String, S>
|
||||
|
||||
override val config: S?
|
||||
override val data: S?
|
||||
get() = SBData.profileCuteName?.let {
|
||||
allConfigs.computeIfAbsent(it) { configDefault() }
|
||||
}
|
||||
@@ -29,10 +29,10 @@ abstract class ProfileSpecificConfigHolder<S>(
|
||||
init {
|
||||
allConfigs = readValues()
|
||||
readValues()
|
||||
IConfigHolder.putConfig(this::class, this)
|
||||
IDataHolder.putDataHolder(this::class, this)
|
||||
}
|
||||
|
||||
private val configDirectory: Path get() = NotEnoughUpdates.CONFIG_DIR.resolve("profiles")
|
||||
private val configDirectory: Path get() = NotEnoughUpdates.CONFIG_DIR.resolve("profiles").resolve(configName)
|
||||
|
||||
private fun readValues(): MutableMap<String, S> {
|
||||
if (!configDirectory.exists()) {
|
||||
@@ -43,9 +43,9 @@ abstract class ProfileSpecificConfigHolder<S>(
|
||||
.filter { it.extension == "json" }
|
||||
.mapNotNull {
|
||||
try {
|
||||
it.nameWithoutExtension to NotEnoughUpdates.json.decodeFromString(configSerializer, it.readText())
|
||||
it.nameWithoutExtension to NotEnoughUpdates.json.decodeFromString(dataSerializer, it.readText())
|
||||
} catch (e: Exception) { /* Expecting IOException and SerializationException, but Kotlin doesn't allow multi catches*/
|
||||
IConfigHolder.badLoads.add(configName)
|
||||
IDataHolder.badLoads.add(configName)
|
||||
NotEnoughUpdates.logger.error(
|
||||
"Exception during loading of profile specific config file $it ($configName). This will reset that profiles config.",
|
||||
e
|
||||
@@ -67,12 +67,12 @@ abstract class ProfileSpecificConfigHolder<S>(
|
||||
}
|
||||
c.forEach { (name, value) ->
|
||||
val f = configDirectory.resolve("$name.json")
|
||||
f.writeText(NotEnoughUpdates.json.encodeToString(configSerializer, value))
|
||||
f.writeText(NotEnoughUpdates.json.encodeToString(dataSerializer, value))
|
||||
}
|
||||
}
|
||||
|
||||
override fun markDirty() {
|
||||
IConfigHolder.markDirty(this::class)
|
||||
IDataHolder.markDirty(this::class)
|
||||
}
|
||||
|
||||
override fun load() {
|
||||
Reference in New Issue
Block a user