aboutsummaryrefslogtreecommitdiff
path: root/src/main/kotlin/util/data
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/kotlin/util/data')
-rw-r--r--src/main/kotlin/util/data/Config.kt15
-rw-r--r--src/main/kotlin/util/data/DataHolder.kt58
-rw-r--r--src/main/kotlin/util/data/IDataHolder.kt136
-rw-r--r--src/main/kotlin/util/data/MultiFileDataHolder.kt1
-rw-r--r--src/main/kotlin/util/data/ProfileSpecificDataHolder.kt83
5 files changed, 106 insertions, 187 deletions
diff --git a/src/main/kotlin/util/data/Config.kt b/src/main/kotlin/util/data/Config.kt
new file mode 100644
index 0000000..41de039
--- /dev/null
+++ b/src/main/kotlin/util/data/Config.kt
@@ -0,0 +1,15 @@
+package moe.nea.firmament.util.data
+
+import moe.nea.firmament.util.compatloader.CompatLoader
+
+@Retention(AnnotationRetention.RUNTIME)
+@Target(AnnotationTarget.CLASS)
+annotation class Config(val prefix: String = "")
+
+
+interface IConfigProvider {
+ val configs: List<IDataHolder<*>>
+ companion object {
+ val providers = CompatLoader(IConfigProvider::class)
+ }
+}
diff --git a/src/main/kotlin/util/data/DataHolder.kt b/src/main/kotlin/util/data/DataHolder.kt
index 21a6014..9f21125 100644
--- a/src/main/kotlin/util/data/DataHolder.kt
+++ b/src/main/kotlin/util/data/DataHolder.kt
@@ -1,5 +1,3 @@
-
-
package moe.nea.firmament.util.data
import java.nio.file.Path
@@ -8,55 +6,13 @@ import kotlin.io.path.exists
import kotlin.io.path.readText
import kotlin.io.path.writeText
import moe.nea.firmament.Firmament
+import moe.nea.firmament.gui.config.storage.ConfigStorageClass
abstract class DataHolder<T>(
- val serializer: KSerializer<T>,
- val name: String,
- val default: () -> T
-) : IDataHolder<T> {
-
-
- final override var data: T
- private set
-
- init {
- data = readValueOrDefault()
- IDataHolder.putDataHolder(this::class, this)
- }
-
- private val file: Path get() = Firmament.CONFIG_DIR.resolve("$name.json")
-
- protected fun readValueOrDefault(): T {
- if (file.exists())
- try {
- return Firmament.json.decodeFromString(
- serializer,
- file.readText()
- )
- } catch (e: Exception) {/* Expecting IOException and SerializationException, but Kotlin doesn't allow multi catches*/
- IDataHolder.badLoads.add(name)
- Firmament.logger.error(
- "Exception during loading of config file $name. This will reset this config.",
- e
- )
- }
- return default()
- }
-
- private fun writeValue(t: T) {
- file.writeText(Firmament.json.encodeToString(serializer, t))
- }
-
- override fun save() {
- writeValue(data)
- }
-
- override fun load() {
- data = readValueOrDefault()
- }
-
- override fun markDirty() {
- IDataHolder.markDirty(this::class)
- }
-
+ serializer: KSerializer<T>,
+ name: String,
+ default: () -> T
+) : GenericConfig<T>(name, serializer, default) {
+ override val storageClass: ConfigStorageClass
+ get() = ConfigStorageClass.STORAGE
}
diff --git a/src/main/kotlin/util/data/IDataHolder.kt b/src/main/kotlin/util/data/IDataHolder.kt
index 1e9ba98..81198ee 100644
--- a/src/main/kotlin/util/data/IDataHolder.kt
+++ b/src/main/kotlin/util/data/IDataHolder.kt
@@ -1,71 +1,95 @@
package moe.nea.firmament.util.data
-import java.util.concurrent.CopyOnWriteArrayList
-import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents
-import kotlin.reflect.KClass
-import net.minecraft.text.Text
+import java.util.UUID
+import kotlinx.serialization.KSerializer
+import kotlinx.serialization.json.JsonObject
+import kotlinx.serialization.json.buildJsonObject
import moe.nea.firmament.Firmament
-import moe.nea.firmament.events.ScreenChangeEvent
-import moe.nea.firmament.util.MC
+import moe.nea.firmament.gui.config.storage.ConfigStorageClass
+import moe.nea.firmament.gui.config.storage.FirmamentConfigLoader
+import moe.nea.firmament.util.SBData
-interface IDataHolder<T> {
- companion object {
- internal var badLoads: MutableList<String> = CopyOnWriteArrayList()
- private val allConfigs: MutableMap<KClass<out IDataHolder<*>>, IDataHolder<*>> = mutableMapOf()
- private val dirty: MutableSet<KClass<out IDataHolder<*>>> = mutableSetOf()
+sealed interface IDataHolder<T> {
+ fun markDirty() {
+ FirmamentConfigLoader.markDirty(this)
+ }
- internal fun <T : IDataHolder<K>, K> putDataHolder(kClass: KClass<T>, inst: IDataHolder<K>) {
- allConfigs[kClass] = inst
- }
+ fun keys(): Collection<T>
+ fun saveTo(key: T): JsonObject
+ fun loadFrom(key: T, jsonObject: JsonObject)
+ fun clear()
+ val storageClass: ConfigStorageClass
+}
- fun <T : IDataHolder<K>, K> markDirty(kClass: KClass<T>) {
- if (kClass !in allConfigs) {
- Firmament.logger.error("Tried to markDirty '${kClass.qualifiedName}', which isn't registered as 'IConfigHolder'")
- return
- }
- dirty.add(kClass)
- }
+open class ProfileKeyedConfig<T>(
+ val prefix: String,
+ val serializer: KSerializer<T>,
+ val default: () -> T,
+) : IDataHolder<UUID> {
- private fun performSaves() {
- val toSave = dirty.toList().also {
- dirty.clear()
- }
- for (it in toSave) {
- val obj = allConfigs[it]
- if (obj == null) {
- Firmament.logger.error("Tried to save '${it}', which isn't registered as 'ConfigHolder'")
- continue
- }
- obj.save()
- }
- }
+ override val storageClass: ConfigStorageClass
+ get() = ConfigStorageClass.PROFILE
+ private var _data: MutableMap<UUID, T>? = null
+
+ val data
+ get() = _data!!.let { map ->
+ map[SBData.profileIdOrNil]
+ ?: default().also { map[SBData.profileIdOrNil] = it }
+ } ?: error("Config $this not loaded — forgot to register?")
- private fun warnForResetConfigs() {
- if (badLoads.isNotEmpty()) {
- MC.sendChat(
- Text.literal(
- "The following configs have been reset: ${badLoads.joinToString(", ")}. " +
- "This can be intentional, but probably isn't."
- )
- )
- badLoads.clear()
- }
+ override fun keys(): Collection<UUID> {
+ return _data!!.keys
+ }
+
+ override fun saveTo(key: UUID): JsonObject {
+ val d = _data!!
+ return buildJsonObject {
+ put(prefix, Firmament.json.encodeToJsonElement(serializer, d[key] ?: return@buildJsonObject))
}
+ }
- fun registerEvents() {
- ScreenChangeEvent.subscribe("IDataHolder:saveOnScreenChange") { event ->
- performSaves()
- warnForResetConfigs()
- }
- ClientLifecycleEvents.CLIENT_STOPPING.register(ClientLifecycleEvents.ClientStopping {
- performSaves()
- })
+ override fun loadFrom(key: UUID, jsonObject: JsonObject) {
+ (_data ?: mutableMapOf<UUID, T>().also { _data = it })[key] =
+ jsonObject[prefix]
+ ?.let {
+ Firmament.json.decodeFromJsonElement(serializer, it)
+ } ?: default()
+ }
+
+ override fun clear() {
+ _data = null
+ }
+}
+
+abstract class GenericConfig<T>(
+ val prefix: String,
+ val serializer: KSerializer<T>,
+ val default: () -> T,
+) : IDataHolder<Unit> {
+
+ private var _data: T? = null
+
+ val data get() = _data ?: error("Config $this not loaded — forgot to register?")
+
+ override fun keys(): Collection<Unit> {
+ return listOf(Unit)
+ }
+
+ open fun onLoad() {
+ }
+
+ override fun saveTo(key: Unit): JsonObject {
+ return buildJsonObject {
+ put(prefix, Firmament.json.encodeToJsonElement(serializer, data))
}
+ }
+ override fun loadFrom(key: Unit, jsonObject: JsonObject) {
+ _data = jsonObject[prefix]?.let { Firmament.json.decodeFromJsonElement(serializer, it) } ?: default()
+ onLoad()
}
- val data: T
- fun save()
- fun markDirty()
- fun load()
+ override fun clear() {
+ _data = null
+ }
}
diff --git a/src/main/kotlin/util/data/MultiFileDataHolder.kt b/src/main/kotlin/util/data/MultiFileDataHolder.kt
index 94c6f05..209f780 100644
--- a/src/main/kotlin/util/data/MultiFileDataHolder.kt
+++ b/src/main/kotlin/util/data/MultiFileDataHolder.kt
@@ -28,7 +28,6 @@ abstract class MultiFileDataHolder<T>(
try {
it.nameWithoutExtension to Firmament.json.decodeFromString(dataSerializer, it.readText())
} catch (e: Exception) { /* Expecting IOException and SerializationException, but Kotlin doesn't allow multi catches*/
- IDataHolder.badLoads.add(configName)
Firmament.logger.error(
"Exception during loading of multi file data holder $it ($configName). This will reset that profiles config.",
e
diff --git a/src/main/kotlin/util/data/ProfileSpecificDataHolder.kt b/src/main/kotlin/util/data/ProfileSpecificDataHolder.kt
index 1cd4f22..3922c34 100644
--- a/src/main/kotlin/util/data/ProfileSpecificDataHolder.kt
+++ b/src/main/kotlin/util/data/ProfileSpecificDataHolder.kt
@@ -1,84 +1,9 @@
-
-
package moe.nea.firmament.util.data
-import java.nio.file.Path
-import java.util.UUID
import kotlinx.serialization.KSerializer
-import kotlin.io.path.createDirectories
-import kotlin.io.path.deleteExisting
-import kotlin.io.path.exists
-import kotlin.io.path.extension
-import kotlin.io.path.listDirectoryEntries
-import kotlin.io.path.nameWithoutExtension
-import kotlin.io.path.readText
-import kotlin.io.path.writeText
-import moe.nea.firmament.Firmament
-import moe.nea.firmament.util.SBData
abstract class ProfileSpecificDataHolder<S>(
- private val dataSerializer: KSerializer<S>,
- val configName: String,
- private val configDefault: () -> S
-) : IDataHolder<S?> {
-
- var allConfigs: MutableMap<UUID, S>
-
- override val data: S?
- get() = SBData.profileId?.let {
- allConfigs.computeIfAbsent(it) { configDefault() }
- }
-
- init {
- allConfigs = readValues()
- IDataHolder.putDataHolder(this::class, this)
- }
-
- private val configDirectory: Path get() = Firmament.CONFIG_DIR.resolve("profiles").resolve(configName)
-
- private fun readValues(): MutableMap<UUID, S> {
- if (!configDirectory.exists()) {
- configDirectory.createDirectories()
- }
- val profileFiles = configDirectory.listDirectoryEntries()
- return profileFiles
- .filter { it.extension == "json" }
- .mapNotNull {
- try {
- UUID.fromString(it.nameWithoutExtension) to Firmament.json.decodeFromString(dataSerializer, it.readText())
- } catch (e: Exception) { /* Expecting IOException and SerializationException, but Kotlin doesn't allow multi catches*/
- IDataHolder.badLoads.add(configName)
- Firmament.logger.error(
- "Exception during loading of profile specific config file $it ($configName). This will reset that profiles config.",
- e
- )
- null
- }
- }.toMap().toMutableMap()
- }
-
- override fun save() {
- if (!configDirectory.exists()) {
- configDirectory.createDirectories()
- }
- val c = allConfigs
- configDirectory.listDirectoryEntries().forEach {
- if (it.nameWithoutExtension !in c.mapKeys { it.toString() }) {
- it.deleteExisting()
- }
- }
- c.forEach { (name, value) ->
- val f = configDirectory.resolve("$name.json")
- f.writeText(Firmament.json.encodeToString(dataSerializer, value))
- }
- }
-
- override fun markDirty() {
- IDataHolder.markDirty(this::class)
- }
-
- override fun load() {
- allConfigs = readValues()
- }
-
-}
+ dataSerializer: KSerializer<S>,
+ configName: String,
+ configDefault: () -> S
+) : ProfileKeyedConfig<S>(configName, dataSerializer, configDefault)