Server persistence changes
This commit is contained in:
@@ -3,7 +3,9 @@ package com.willfp.eco.core.data.keys;
|
||||
import com.willfp.eco.core.Eco;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
@@ -27,6 +29,11 @@ public class PersistentDataKey<T> {
|
||||
*/
|
||||
private final PersistentDataKeyType<T> type;
|
||||
|
||||
/**
|
||||
* If the key is for server data.
|
||||
*/
|
||||
private final boolean isServerKey;
|
||||
|
||||
/**
|
||||
* Create a new Persistent Data Key.
|
||||
*
|
||||
@@ -37,9 +44,25 @@ public class PersistentDataKey<T> {
|
||||
public PersistentDataKey(@NotNull final NamespacedKey key,
|
||||
@NotNull final PersistentDataKeyType<T> type,
|
||||
@NotNull final T defaultValue) {
|
||||
this(key, type, defaultValue, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Persistent Data Key.
|
||||
*
|
||||
* @param key The key.
|
||||
* @param type The data type.
|
||||
* @param defaultValue The default value.
|
||||
* @param isServerKey If the key is for server data.
|
||||
*/
|
||||
public PersistentDataKey(@NotNull final NamespacedKey key,
|
||||
@NotNull final PersistentDataKeyType<T> type,
|
||||
@NotNull final T defaultValue,
|
||||
final boolean isServerKey) {
|
||||
this.key = key;
|
||||
this.defaultValue = defaultValue;
|
||||
this.type = type;
|
||||
this.isServerKey = isServerKey;
|
||||
|
||||
Eco.getHandler().getKeyRegistry().registerKey(this);
|
||||
}
|
||||
@@ -80,6 +103,15 @@ public class PersistentDataKey<T> {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get if the key is for server data.
|
||||
*
|
||||
* @return If server key.
|
||||
*/
|
||||
public boolean isServerKey() {
|
||||
return isServerKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all persistent data keys.
|
||||
*
|
||||
@@ -88,4 +120,20 @@ public class PersistentDataKey<T> {
|
||||
public static Set<PersistentDataKey<?>> values() {
|
||||
return Eco.getHandler().getKeyRegistry().getRegisteredKeys();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable final Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof PersistentDataKey that)) {
|
||||
return false;
|
||||
}
|
||||
return Objects.equals(this.getKey(), that.getKey());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(this.getKey());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ class EcoHandler : EcoSpigotPlugin(), Handler {
|
||||
@Suppress("DEPRECATION")
|
||||
private val requirementFactory = com.willfp.eco.internal.requirement.EcoRequirementFactory()
|
||||
private var adventure: BukkitAudiences? = null
|
||||
private val keyRegistry = EcoKeyRegistry(this)
|
||||
private val keyRegistry = EcoKeyRegistry()
|
||||
private val playerProfileHandler = EcoProfileHandler(this.configYml.getBool("mysql.enabled"), this)
|
||||
|
||||
@Suppress("RedundantNullableReturnType")
|
||||
|
||||
@@ -4,12 +4,9 @@ import com.willfp.eco.core.Eco
|
||||
import com.willfp.eco.core.data.keys.KeyRegistry
|
||||
import com.willfp.eco.core.data.keys.PersistentDataKey
|
||||
import com.willfp.eco.core.data.keys.PersistentDataKeyType
|
||||
import com.willfp.eco.internal.spigot.EcoSpigotPlugin
|
||||
import org.bukkit.NamespacedKey
|
||||
|
||||
class EcoKeyRegistry(
|
||||
private val plugin: EcoSpigotPlugin
|
||||
) : KeyRegistry {
|
||||
class EcoKeyRegistry: KeyRegistry {
|
||||
private val registry = mutableMapOf<NamespacedKey, PersistentDataKey<*>>()
|
||||
|
||||
override fun registerKey(key: PersistentDataKey<*>) {
|
||||
|
||||
@@ -2,10 +2,12 @@ package com.willfp.eco.internal.spigot.data.storage
|
||||
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder
|
||||
import com.willfp.eco.core.Eco
|
||||
import com.willfp.eco.core.EcoPlugin
|
||||
import com.willfp.eco.core.data.keys.PersistentDataKey
|
||||
import com.willfp.eco.core.data.keys.PersistentDataKeyType
|
||||
import com.willfp.eco.internal.spigot.EcoSpigotPlugin
|
||||
import com.willfp.eco.internal.spigot.data.EcoProfileHandler
|
||||
import com.willfp.eco.internal.spigot.data.serverProfileUUID
|
||||
import com.zaxxer.hikari.HikariConfig
|
||||
import com.zaxxer.hikari.HikariDataSource
|
||||
import org.apache.logging.log4j.Level
|
||||
@@ -31,8 +33,64 @@ import java.util.concurrent.Executors
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
class MySQLDataHandler(
|
||||
plugin: EcoSpigotPlugin,
|
||||
private val handler: EcoProfileHandler
|
||||
handler: EcoProfileHandler
|
||||
) : DataHandler {
|
||||
private val playerHandler = ImplementedMySQLHandler(
|
||||
handler,
|
||||
UUIDTable("eco_players"),
|
||||
plugin
|
||||
) { !it.isServerKey }
|
||||
|
||||
private val serverHandler = ImplementedMySQLHandler(
|
||||
handler,
|
||||
UUIDTable("eco_server"),
|
||||
plugin
|
||||
) { it.isServerKey }
|
||||
|
||||
override fun saveAll(uuids: Iterable<UUID>) {
|
||||
serverHandler.saveAll(uuids.filter { it == serverProfileUUID })
|
||||
playerHandler.saveAll(uuids.filter { it != serverProfileUUID })
|
||||
}
|
||||
|
||||
override fun <T> write(uuid: UUID, key: NamespacedKey, value: T) {
|
||||
applyFor(uuid) {
|
||||
it.write(uuid, key, value)
|
||||
}
|
||||
}
|
||||
|
||||
override fun saveKeysForPlayer(uuid: UUID, keys: Set<PersistentDataKey<*>>) {
|
||||
applyFor(uuid) {
|
||||
it.saveKeysForRow(uuid, keys)
|
||||
}
|
||||
}
|
||||
|
||||
override fun <T> read(uuid: UUID, key: NamespacedKey): T? {
|
||||
return applyFor(uuid) {
|
||||
it.read(uuid, key)
|
||||
}
|
||||
}
|
||||
|
||||
override fun updateKeys() {
|
||||
playerHandler.updateKeys()
|
||||
serverHandler.updateKeys()
|
||||
}
|
||||
|
||||
private inline fun <R> applyFor(uuid: UUID, function: (ImplementedMySQLHandler) -> R): R {
|
||||
return if (uuid == serverProfileUUID) {
|
||||
function(serverHandler)
|
||||
} else {
|
||||
function(playerHandler)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private class ImplementedMySQLHandler(
|
||||
private val handler: EcoProfileHandler,
|
||||
private val table: UUIDTable,
|
||||
plugin: EcoPlugin,
|
||||
private val validator: (PersistentDataKey<*>) -> Boolean
|
||||
) {
|
||||
private val columns = mutableMapOf<String, Column<*>>()
|
||||
private val threadFactory = ThreadFactoryBuilder().setNameFormat("eco-mysql-thread-%d").build()
|
||||
private val executor = Executors.newFixedThreadPool(plugin.configYml.getInt("mysql.threads"), threadFactory)
|
||||
@@ -52,7 +110,7 @@ class MySQLDataHandler(
|
||||
|
||||
|
||||
transaction {
|
||||
SchemaUtils.create(Players)
|
||||
SchemaUtils.create(table)
|
||||
}
|
||||
|
||||
// Get Exposed to shut the hell up
|
||||
@@ -67,18 +125,20 @@ class MySQLDataHandler(
|
||||
}
|
||||
}
|
||||
|
||||
override fun updateKeys() {
|
||||
fun updateKeys() {
|
||||
transaction {
|
||||
for (key in Eco.getHandler().keyRegistry.registeredKeys) {
|
||||
registerColumn(key, Players)
|
||||
if (validator(key)) {
|
||||
registerColumn(key, table)
|
||||
}
|
||||
}
|
||||
|
||||
SchemaUtils.createMissingTablesAndColumns(Players, withLogs = false)
|
||||
SchemaUtils.createMissingTablesAndColumns(table, withLogs = false)
|
||||
}
|
||||
}
|
||||
|
||||
override fun <T> write(uuid: UUID, key: NamespacedKey, value: T) {
|
||||
getPlayer(uuid)
|
||||
fun <T> write(uuid: UUID, key: NamespacedKey, value: T) {
|
||||
getRow(uuid)
|
||||
writeAsserted(uuid, key, value)
|
||||
}
|
||||
|
||||
@@ -87,42 +147,44 @@ class MySQLDataHandler(
|
||||
|
||||
executor.submit {
|
||||
transaction {
|
||||
Players.update({ Players.id eq uuid }) {
|
||||
table.update({ table.id eq uuid }) {
|
||||
it[column] = value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun saveKeysForPlayer(uuid: UUID, keys: Set<PersistentDataKey<*>>) {
|
||||
savePlayer(uuid, keys)
|
||||
fun saveKeysForRow(uuid: UUID, keys: Set<PersistentDataKey<*>>) {
|
||||
saveRow(uuid, keys)
|
||||
}
|
||||
|
||||
override fun saveAll(uuids: Iterable<UUID>) {
|
||||
fun saveAll(uuids: Iterable<UUID>) {
|
||||
for (uuid in uuids) {
|
||||
savePlayer(uuid)
|
||||
saveRow(uuid, PersistentDataKey.values())
|
||||
}
|
||||
}
|
||||
|
||||
private fun savePlayer(uuid: UUID, keys: Set<PersistentDataKey<*>>) {
|
||||
private fun saveRow(uuid: UUID, keys: Set<PersistentDataKey<*>>) {
|
||||
val profile = handler.loadGenericProfile(uuid)
|
||||
|
||||
executor.submit {
|
||||
transaction {
|
||||
getPlayer(uuid)
|
||||
getRow(uuid)
|
||||
|
||||
for (key in keys) {
|
||||
writeAsserted(uuid, key.key, profile.read(key))
|
||||
if (validator(key)) {
|
||||
writeAsserted(uuid, key.key, profile.read(key))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun <T> read(uuid: UUID, key: NamespacedKey): T? {
|
||||
fun <T> read(uuid: UUID, key: NamespacedKey): T? {
|
||||
val doRead = Callable<T?> {
|
||||
var value: T? = null
|
||||
transaction {
|
||||
val player = getPlayer(uuid)
|
||||
val player = getRow(uuid)
|
||||
value = player[getColumn(key.toString())] as T?
|
||||
}
|
||||
|
||||
@@ -136,8 +198,6 @@ class MySQLDataHandler(
|
||||
}
|
||||
}
|
||||
|
||||
object Players : UUIDTable("eco_players")
|
||||
|
||||
private fun <T> registerColumn(key: PersistentDataKey<T>, table: UUIDTable) {
|
||||
table.apply {
|
||||
if (this.columns.stream().anyMatch { it.name == key.key.toString() }) {
|
||||
@@ -165,22 +225,22 @@ class MySQLDataHandler(
|
||||
return cached
|
||||
}
|
||||
|
||||
columns[name] = Players.columns.stream().filter { it.name == name }.findFirst().get()
|
||||
columns[name] = table.columns.stream().filter { it.name == name }.findFirst().get()
|
||||
return getColumn(name)
|
||||
}
|
||||
|
||||
private fun getPlayer(uuid: UUID): ResultRow {
|
||||
private fun getRow(uuid: UUID): ResultRow {
|
||||
val player = transaction {
|
||||
Players.select { Players.id eq uuid }.limit(1).singleOrNull()
|
||||
table.select { table.id eq uuid }.limit(1).singleOrNull()
|
||||
}
|
||||
|
||||
return if (player != null) {
|
||||
player
|
||||
} else {
|
||||
transaction {
|
||||
Players.insert { it[id] = uuid }
|
||||
table.insert { it[id] = uuid }
|
||||
}
|
||||
getPlayer(uuid)
|
||||
getRow(uuid)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,4 +51,4 @@ class YamlDataHandler(
|
||||
false,
|
||||
ConfigType.YAML
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user