|
|
|
|
@@ -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)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|