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.client.MinecraftClient import net.minecraft.server.command.CommandOutput import net.minecraft.text.Text import moe.nea.firmament.Firmament import moe.nea.firmament.events.ScreenChangeEvent interface IDataHolder { companion object { internal var badLoads: MutableList = CopyOnWriteArrayList() private val allConfigs: MutableMap>, IDataHolder<*>> = mutableMapOf() private val dirty: MutableSet>> = mutableSetOf() internal fun , K> putDataHolder(kClass: KClass, inst: IDataHolder) { allConfigs[kClass] = inst } fun , K> markDirty(kClass: KClass) { if (kClass !in allConfigs) { Firmament.logger.error("Tried to markDirty '${kClass.qualifiedName}', which isn't registered as 'IConfigHolder'") return } dirty.add(kClass) } 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() } } private fun warnForResetConfigs(player: CommandOutput) { if (badLoads.isNotEmpty()) { player.sendMessage( Text.literal( "The following configs have been reset: ${badLoads.joinToString(", ")}. " + "This can be intentional, but probably isn't." ) ) badLoads.clear() } } fun registerEvents() { ScreenChangeEvent.subscribe("IDataHolder:saveOnScreenChange") { event -> performSaves() val p = MinecraftClient.getInstance().player if (p != null) { warnForResetConfigs(p) } } ClientLifecycleEvents.CLIENT_STOPPING.register(ClientLifecycleEvents.ClientStopping { performSaves() }) } } val data: T fun save() fun markDirty() fun load() }