diff options
Diffstat (limited to 'src/main/kotlin/util/data/IDataHolder.kt')
| -rw-r--r-- | src/main/kotlin/util/data/IDataHolder.kt | 154 |
1 files changed, 100 insertions, 54 deletions
diff --git a/src/main/kotlin/util/data/IDataHolder.kt b/src/main/kotlin/util/data/IDataHolder.kt index 1e9ba98..3229011 100644 --- a/src/main/kotlin/util/data/IDataHolder.kt +++ b/src/main/kotlin/util/data/IDataHolder.kt @@ -1,71 +1,117 @@ 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 java.util.concurrent.CompletableFuture +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 class IDataHolder<T> { + fun markDirty(future: CompletableFuture<Void?>? = null) { + FirmamentConfigLoader.markDirty(this, future) + } - internal fun <T : IDataHolder<K>, K> putDataHolder(kClass: KClass<T>, inst: IDataHolder<K>) { - allConfigs[kClass] = inst - } + init { + require(this.javaClass.getAnnotation(Config::class.java) != null) + } + + abstract fun keys(): Collection<T> + abstract fun saveTo(key: T): JsonObject + abstract fun loadFrom(key: T, jsonObject: JsonObject) + abstract fun explicitDefaultLoad() + abstract fun clear() + abstract val storageClass: ConfigStorageClass +} + +open class ProfileKeyedConfig<T>( + val prefix: String, + val serializer: KSerializer<T>, + val default: () -> T & Any, +) : IDataHolder<UUID>() { + + override val storageClass: ConfigStorageClass + get() = ConfigStorageClass.PROFILE + private var _data: MutableMap<UUID, T>? = null - 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) + val data: T & Any + get() { + val map = _data ?: error("Config $this not loaded — forgot to register?") + map[SBData.profileIdOrNil]?.let { return it } + val newValue = default() + map[SBData.profileIdOrNil] = newValue + return newValue } - 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 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)) } + } - 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 loadFrom(key: UUID, jsonObject: JsonObject) { + var map = _data + if (map == null) { + map = mutableMapOf() + _data = map } + map[key] = + jsonObject[prefix] + ?.let { + Firmament.json.decodeFromJsonElement(serializer, it) + } ?: default() + } - fun registerEvents() { - ScreenChangeEvent.subscribe("IDataHolder:saveOnScreenChange") { event -> - performSaves() - warnForResetConfigs() - } - ClientLifecycleEvents.CLIENT_STOPPING.register(ClientLifecycleEvents.ClientStopping { - performSaves() - }) + override fun explicitDefaultLoad() { + _data = mutableMapOf() + } + + 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) + } + + override fun explicitDefaultLoad() { + _data = default() + } + + 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 + } } |
