From 5f8ec4f94ae2e87f1a135bb20de4b0bcd1d91647 Mon Sep 17 00:00:00 2001 From: Auxilor Date: Fri, 27 May 2022 14:56:53 +0100 Subject: [PATCH] Added PersistentDataKeyType#STRING_LIST --- .../core/data/keys/PersistentDataKeyType.java | 10 +++- .../internal/spigot/data/EcoProfileHandler.kt | 9 ++-- .../spigot/data/storage/DataHandler.kt | 6 +-- .../spigot/data/storage/MongoDataHandler.kt | 16 +++--- .../spigot/data/storage/MySQLDataHandler.kt | 50 ++++++++++++++----- .../spigot/data/storage/YamlDataHandler.kt | 22 +++++--- 6 files changed, 79 insertions(+), 34 deletions(-) diff --git a/eco-api/src/main/java/com/willfp/eco/core/data/keys/PersistentDataKeyType.java b/eco-api/src/main/java/com/willfp/eco/core/data/keys/PersistentDataKeyType.java index 0738f2ca..4c4aa140 100644 --- a/eco-api/src/main/java/com/willfp/eco/core/data/keys/PersistentDataKeyType.java +++ b/eco-api/src/main/java/com/willfp/eco/core/data/keys/PersistentDataKeyType.java @@ -38,6 +38,11 @@ public final class PersistentDataKeyType { */ public static final PersistentDataKeyType DOUBLE = new PersistentDataKeyType<>(Double.class, "DOUBLE"); + /** + * String List. + */ + public static final PersistentDataKeyType> STRING_LIST = new PersistentDataKeyType<>(null, "STRING_LIST"); + /** * The class of the type. */ @@ -52,7 +57,10 @@ public final class PersistentDataKeyType { * Get the class of the type. * * @return The class. + * @deprecated String list type will return null. */ + @Deprecated(since = "6.36.0", forRemoval = true) + @Nullable public Class getTypeClass() { return typeClass; } @@ -72,7 +80,7 @@ public final class PersistentDataKeyType { * @param typeClass The type class. * @param name The name. */ - private PersistentDataKeyType(@NotNull final Class typeClass, + private PersistentDataKeyType(@Nullable final Class typeClass, @NotNull final String name) { VALUES.add(this); diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/data/EcoProfileHandler.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/data/EcoProfileHandler.kt index 4f061a44..459ce54c 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/data/EcoProfileHandler.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/data/EcoProfileHandler.kt @@ -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++ diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/data/storage/DataHandler.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/data/storage/DataHandler.kt index 2315d706..8009ec69 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/data/storage/DataHandler.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/data/storage/DataHandler.kt @@ -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 write(uuid: UUID, key: PersistentDataKey, value: Any) + fun read(uuid: UUID, key: PersistentDataKey): T? + fun save() { } @@ -24,7 +26,5 @@ interface DataHandler { saveKeysFor(uuid, PersistentDataKey.values()) } - fun write(uuid: UUID, key: NamespacedKey, value: T) fun saveKeysFor(uuid: UUID, keys: Set>) - fun read(uuid: UUID, key: PersistentDataKey): T? } \ No newline at end of file diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/data/storage/MongoDataHandler.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/data/storage/MongoDataHandler.kt index c96690cf..41a36e75 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/data/storage/MongoDataHandler.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/data/storage/MongoDataHandler.kt @@ -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 @@ -43,9 +45,9 @@ class MongoDataHandler( } } - override fun write(uuid: UUID, key: NamespacedKey, value: T) { + override fun write(uuid: UUID, key: PersistentDataKey, 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>) { + 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 read(uuid: UUID, key: PersistentDataKey): T? { + override fun read(uuid: UUID, key: PersistentDataKey): T? { return runBlocking { doRead(uuid, key) } diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/data/storage/MySQLDataHandler.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/data/storage/MySQLDataHandler.kt index da4f432f..c12ed798 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/data/storage/MySQLDataHandler.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/data/storage/MySQLDataHandler.kt @@ -90,7 +90,7 @@ class MySQLDataHandler( playerHandler.saveAll(uuids.filter { it != serverProfileUUID }) } - override fun write(uuid: UUID, key: NamespacedKey, value: T) { + override fun write(uuid: UUID, key: PersistentDataKey, value: Any) { applyFor(uuid) { it.write(uuid, key, value) } @@ -102,9 +102,9 @@ class MySQLDataHandler( } } - override fun read(uuid: UUID, key: PersistentDataKey): T? { + override fun read(uuid: UUID, key: PersistentDataKey): T? { return applyFor(uuid) { - it.read(uuid, key.key) + it.read(uuid, key) } } @@ -212,18 +212,18 @@ private class ImplementedMySQLHandler( } } - fun write(uuid: UUID, key: NamespacedKey, value: T) { + fun write(uuid: UUID, key: PersistentDataKey, value: Any) { getOrCreateRow(uuid) - doWrite(uuid, key, value) + doWrite(uuid, key.key, key.type.constrainSQLTypes(value)) } - private fun doWrite(uuid: UUID, key: NamespacedKey, value: T) { - val column: Column = getColumn(key) as Column + private fun doWrite(uuid: UUID, key: NamespacedKey, constrainedValue: Any) { + val column: Column = getColumn(key) as Column 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 read(uuid: UUID, key: NamespacedKey): T? { + fun read(uuid: UUID, key: PersistentDataKey): T? { val doRead = Callable { 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(key.key.toString(), VarCharColumnType(512)) .default(key.defaultValue as String) + PersistentDataKeyType.STRING_LIST -> registerColumn(key.key.toString(), VarCharColumnType(8192)) + .default(PersistentDataKeyType.STRING_LIST.constrainSQLTypes(key.defaultValue as List) as String) else -> throw NullPointerException("Null value found!") } @@ -325,3 +327,27 @@ private class ImplementedMySQLHandler( } } } + +private fun PersistentDataKeyType.constrainSQLTypes(value: Any): Any { + return if (this == PersistentDataKeyType.STRING_LIST) { + @Suppress("UNCHECKED_CAST") + value as List + value.joinToString(separator = ";") + } else { + this + } +} + +private fun PersistentDataKeyType.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 +} diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/data/storage/YamlDataHandler.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/data/storage/YamlDataHandler.kt index 68f04a22..73f82695 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/data/storage/YamlDataHandler.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/data/storage/YamlDataHandler.kt @@ -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 write(uuid: UUID, key: NamespacedKey, value: T) { + override fun write(uuid: UUID, key: PersistentDataKey, value: Any) { + doWrite(uuid, key.key, value) + } + + private fun doWrite(uuid: UUID, key: NamespacedKey, value: Any) { dataYml.set("player.$uuid.$key", value) } - override fun read(uuid: UUID, key: PersistentDataKey): T? { + override fun read(uuid: UUID, key: PersistentDataKey): 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 }