PhysicalConnectivity/src/main/kotlin/net/shadowfacts/phycon/util/TerminalSettings.kt

84 lines
2.3 KiB
Kotlin

package net.shadowfacts.phycon.util
import net.minecraft.nbt.NbtCompound
import net.minecraft.util.Identifier
import net.shadowfacts.phycon.PhysicalConnectivityClient
import net.shadowfacts.phycon.api.TerminalSettingKey
import net.shadowfacts.phycon.api.TerminalSetting
/**
* @author shadowfacts
*/
class TerminalSettings {
companion object {
private val SETTINGS = mutableMapOf<Identifier, SettingKey<*>>()
private val DEFAULTS = mutableMapOf<TerminalSettingKey<*>, Enum<*>>()
val allKeys: Collection<SettingKey<*>>
get() = SETTINGS.values
fun <E> register(id: Identifier, defaultValue: E): SettingKey<E> where E: Enum<E>, E: TerminalSetting {
val setting = SettingKey(id, defaultValue.javaClass)
SETTINGS[id] = setting
DEFAULTS[setting] = defaultValue
return setting
}
fun <E> getDefault(setting: TerminalSettingKey<E>): E where E: Enum<E>, E: TerminalSetting {
@Suppress("UNCHECKED_CAST")
return DEFAULTS[setting] as E
}
}
class SettingKey<E>(
val id: Identifier,
val clazz: Class<E>,
): TerminalSettingKey<E> where E: Enum<E>, E: TerminalSetting {
fun value(ordinal: Int): E? {
@Suppress("UNCHECKED_CAST")
return if (clazz.enumConstants.size <= ordinal) null
else clazz.enumConstants[ordinal] as E
}
override fun getID() = id
override fun getValue() = PhysicalConnectivityClient.terminalSettings[this]
}
private val settings = mutableMapOf<TerminalSettingKey<*>, Enum<*>>()
operator fun <E> get(key: TerminalSettingKey<E>): E where E: Enum<E>, E: TerminalSetting {
@Suppress("UNCHECKED_CAST")
return settings[key] as? E ?: getDefault(key)
}
operator fun <E> set(key: SettingKey<E>, value: E) where E: Enum<E>, E: TerminalSetting {
settings[key] = value
}
fun toTag(): NbtCompound {
return NbtCompound().also {
settings.forEach { (s, v) ->
it.putInt(s.id.toString(), v.ordinal)
}
}
}
fun fromTag(tag: NbtCompound) {
settings.clear()
tag.keys.forEach { k ->
val id = Identifier.tryParse(k) ?: return@forEach
val setting = SETTINGS[id] ?: return@forEach
setValueFromOrdinal(setting, tag.getInt(k))
}
}
private fun <E> setValueFromOrdinal(setting: SettingKey<E>, ordinal: Int) where E: Enum<E>, E: TerminalSetting {
val value = setting.value(ordinal)
if (value != null) {
this[setting] = value
}
}
}