Added PersistentDataKeyType#STRING_LIST

This commit is contained in:
Auxilor
2022-05-27 14:56:53 +01:00
parent d7847e9efc
commit 5f8ec4f94a
6 changed files with 79 additions and 34 deletions

View File

@@ -25,7 +25,7 @@ class EcoProfileHandler(
val handler: DataHandler = when (type) {
HandlerType.YAML -> YamlDataHandler(plugin, this)
HandlerType.MYSQL -> MySQLDataHandler(plugin, this)
HandlerType.MONGO -> MongoDataHandler(plugin)
HandlerType.MONGO -> MongoDataHandler(plugin, this)
}
fun loadGenericProfile(uuid: UUID): Profile {
@@ -55,7 +55,7 @@ class EcoProfileHandler(
val profile = loadGenericProfile(uuid)
for (key in keys) {
handler.write(uuid, key.key, profile.read(key))
handler.write(uuid, key, profile.read(key))
}
}
@@ -90,7 +90,7 @@ class EcoProfileHandler(
val previousHandler = when (previousHandlerType) {
HandlerType.YAML -> YamlDataHandler(plugin, this)
HandlerType.MYSQL -> MySQLDataHandler(plugin, this)
HandlerType.MONGO -> MongoDataHandler(plugin)
HandlerType.MONGO -> MongoDataHandler(plugin, this)
}
plugin.logger.info("eco has detected a change in data handler!")
@@ -104,8 +104,9 @@ class EcoProfileHandler(
var i = 1
for (uuid in players) {
plugin.logger.info("Migrating data for $uuid... ($i / ${players.size})")
for (key in PersistentDataKey.values()) {
handler.write(uuid, key.key, previousHandler.read(uuid, key))
handler.write(uuid, key, previousHandler.read(uuid, key) as Any)
}
i++

View File

@@ -2,10 +2,12 @@ package com.willfp.eco.internal.spigot.data.storage
import com.willfp.eco.core.data.keys.KeyRegistry
import com.willfp.eco.core.data.keys.PersistentDataKey
import org.bukkit.NamespacedKey
import java.util.UUID
interface DataHandler {
fun <T : Any> write(uuid: UUID, key: PersistentDataKey<T>, value: Any)
fun <T : Any> read(uuid: UUID, key: PersistentDataKey<T>): T?
fun save() {
}
@@ -24,7 +26,5 @@ interface DataHandler {
saveKeysFor(uuid, PersistentDataKey.values())
}
fun <T> write(uuid: UUID, key: NamespacedKey, value: T)
fun saveKeysFor(uuid: UUID, keys: Set<PersistentDataKey<*>>)
fun <T> read(uuid: UUID, key: PersistentDataKey<T>): T?
}

View File

@@ -1,7 +1,8 @@
package com.willfp.eco.internal.spigot.data.storage
import com.willfp.eco.core.EcoPlugin
import com.willfp.eco.core.data.keys.PersistentDataKey
import com.willfp.eco.internal.spigot.EcoSpigotPlugin
import com.willfp.eco.internal.spigot.data.EcoProfileHandler
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@@ -18,7 +19,8 @@ import java.util.UUID
@Suppress("UNCHECKED_CAST")
class MongoDataHandler(
plugin: EcoPlugin
plugin: EcoSpigotPlugin,
private val handler: EcoProfileHandler
) : DataHandler {
private val client: CoroutineClient
private val collection: CoroutineCollection<UUIDProfile>
@@ -43,9 +45,9 @@ class MongoDataHandler(
}
}
override fun <T> write(uuid: UUID, key: NamespacedKey, value: T) {
override fun <T : Any> write(uuid: UUID, key: PersistentDataKey<T>, value: Any) {
scope.launch {
doWrite(uuid, key, value)
doWrite(uuid, key.key, value)
}
}
@@ -64,14 +66,16 @@ class MongoDataHandler(
}
override fun saveKeysFor(uuid: UUID, keys: Set<PersistentDataKey<*>>) {
val profile = handler.loadGenericProfile(uuid)
scope.launch {
for (key in keys) {
doWrite(uuid, key.key, read(uuid, key))
doWrite(uuid, key.key, profile.read(key))
}
}
}
override fun <T> read(uuid: UUID, key: PersistentDataKey<T>): T? {
override fun <T : Any> read(uuid: UUID, key: PersistentDataKey<T>): T? {
return runBlocking {
doRead(uuid, key)
}

View File

@@ -90,7 +90,7 @@ class MySQLDataHandler(
playerHandler.saveAll(uuids.filter { it != serverProfileUUID })
}
override fun <T> write(uuid: UUID, key: NamespacedKey, value: T) {
override fun <T : Any> write(uuid: UUID, key: PersistentDataKey<T>, value: Any) {
applyFor(uuid) {
it.write(uuid, key, value)
}
@@ -102,9 +102,9 @@ class MySQLDataHandler(
}
}
override fun <T> read(uuid: UUID, key: PersistentDataKey<T>): T? {
override fun <T : Any> read(uuid: UUID, key: PersistentDataKey<T>): T? {
return applyFor(uuid) {
it.read(uuid, key.key)
it.read(uuid, key)
}
}
@@ -212,18 +212,18 @@ private class ImplementedMySQLHandler(
}
}
fun <T> write(uuid: UUID, key: NamespacedKey, value: T) {
fun <T : Any> write(uuid: UUID, key: PersistentDataKey<T>, value: Any) {
getOrCreateRow(uuid)
doWrite(uuid, key, value)
doWrite(uuid, key.key, key.type.constrainSQLTypes(value))
}
private fun <T> doWrite(uuid: UUID, key: NamespacedKey, value: T) {
val column: Column<T> = getColumn(key) as Column<T>
private fun doWrite(uuid: UUID, key: NamespacedKey, constrainedValue: Any) {
val column: Column<Any> = getColumn(key) as Column<Any>
executor.submit {
transaction {
table.update({ table.id eq uuid }) {
it[column] = value
it[column] = constrainedValue
}
}
}
@@ -247,24 +247,24 @@ private class ImplementedMySQLHandler(
getOrCreateRow(uuid)
for (key in keys) {
doWrite(uuid, key.key, profile.read(key))
doWrite(uuid, key.key, key.type.constrainSQLTypes(profile.read(key)))
}
}
}
}
fun <T> read(uuid: UUID, key: NamespacedKey): T? {
fun <T> read(uuid: UUID, key: PersistentDataKey<T>): T? {
val doRead = Callable<T?> {
var value: T? = null
transaction {
val row = getOrCreateRow(uuid)
value = row[getColumn(key)] as T?
value = key.type.fromConstrained(row[getColumn(key.key)])
}
return@Callable value
}
ensureKeyRegistration(key) // DON'T DELETE THIS LINE! I know it's covered in getColumn, but I need to do it here as well.
ensureKeyRegistration(key.key) // DON'T DELETE THIS LINE! I know it's covered in getColumn, but I need to do it here as well.
return if (Eco.getHandler().ecoPlugin.configYml.getBool("mysql.async-reads")) {
executor.submit(doRead).get()
@@ -288,6 +288,8 @@ private class ImplementedMySQLHandler(
.default(key.defaultValue as Boolean)
PersistentDataKeyType.STRING -> registerColumn<String>(key.key.toString(), VarCharColumnType(512))
.default(key.defaultValue as String)
PersistentDataKeyType.STRING_LIST -> registerColumn<String>(key.key.toString(), VarCharColumnType(8192))
.default(PersistentDataKeyType.STRING_LIST.constrainSQLTypes(key.defaultValue as List<String>) as String)
else -> throw NullPointerException("Null value found!")
}
@@ -325,3 +327,27 @@ private class ImplementedMySQLHandler(
}
}
}
private fun <T> PersistentDataKeyType<T>.constrainSQLTypes(value: Any): Any {
return if (this == PersistentDataKeyType.STRING_LIST) {
@Suppress("UNCHECKED_CAST")
value as List<String>
value.joinToString(separator = ";")
} else {
this
}
}
private fun <T> PersistentDataKeyType<T>.fromConstrained(constrained: Any?): T? {
if (constrained == null) {
return null
}
@Suppress("UNCHECKED_CAST")
return if (this == PersistentDataKeyType.STRING_LIST) {
constrained as String
constrained.split(";").toList()
} else {
constrained
} as T
}

View File

@@ -30,22 +30,28 @@ class YamlDataHandler(
val profile = handler.loadGenericProfile(uuid)
for (key in keys) {
write(uuid, key.key, profile.read(key))
doWrite(uuid, key.key, profile.read(key))
}
}
override fun <T> write(uuid: UUID, key: NamespacedKey, value: T) {
override fun <T : Any> write(uuid: UUID, key: PersistentDataKey<T>, value: Any) {
doWrite(uuid, key.key, value)
}
private fun doWrite(uuid: UUID, key: NamespacedKey, value: Any) {
dataYml.set("player.$uuid.$key", value)
}
override fun <T> read(uuid: UUID, key: PersistentDataKey<T>): T? {
override fun <T : Any> read(uuid: UUID, key: PersistentDataKey<T>): T? {
// Separate `as T?` for each branch to prevent compiler warnings.
val value = when (key.type) {
PersistentDataKeyType.INT -> dataYml.getIntOrNull("player.$uuid.${key.key}")
PersistentDataKeyType.DOUBLE -> dataYml.getDoubleOrNull("player.$uuid.${key.key}")
PersistentDataKeyType.STRING -> dataYml.getStringOrNull("player.$uuid.${key.key}")
PersistentDataKeyType.BOOLEAN -> dataYml.getBoolOrNull("player.$uuid.${key.key}")
PersistentDataKeyType.INT -> dataYml.getIntOrNull("player.$uuid.${key.key}") as T?
PersistentDataKeyType.DOUBLE -> dataYml.getDoubleOrNull("player.$uuid.${key.key}") as T?
PersistentDataKeyType.STRING -> dataYml.getStringOrNull("player.$uuid.${key.key}") as T?
PersistentDataKeyType.BOOLEAN -> dataYml.getBoolOrNull("player.$uuid.${key.key}") as T?
PersistentDataKeyType.STRING_LIST -> dataYml.getStringsOrNull("player.$uuid.${key.key}") as T?
else -> null
} as? T?
}
return value
}