Added persistent data storage and kotlin

This commit is contained in:
Auxilor 2021-10-18 17:32:03 +01:00
parent fb4206d6a6
commit d7b503f3f1
11 changed files with 275 additions and 0 deletions

View File

@ -1,3 +1,13 @@
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.21"
}
}
plugins {
id 'java-library'
id 'com.github.johnrengelman.shadow' version '7.0.0'
@ -14,6 +24,7 @@ allprojects {
apply plugin: 'java'
apply plugin: 'maven-publish'
apply plugin: 'com.github.johnrengelman.shadow'
apply plugin: 'kotlin'
repositories {
mavenCentral()
@ -53,6 +64,7 @@ allprojects {
compileOnly 'com.willfp:eco:6.9.4'
compileOnly 'org.jetbrains:annotations:19.0.0'
compileOnly 'org.jetbrains.kotlin:kotlin-stdlib:1.5.21'
compileOnly 'org.projectlombok:lombok:1.18.20'
annotationProcessor 'org.projectlombok:lombok:1.18.20'

View File

@ -9,4 +9,8 @@ dependencies {
compileOnly 'net.essentialsx:EssentialsX:2.19.0'
compileOnly 'io.papermc.paper:paper-api:1.17.1-R0.1-SNAPSHOT'
compileOnly 'com.sk89q.worldguard:worldguard-bukkit:7.0.4-SNAPSHOT'
compileOnly 'org.jetbrains.exposed:exposed-core:0.34.1'
compileOnly 'org.jetbrains.exposed:exposed-dao:0.34.1'
compileOnly 'org.jetbrains.exposed:exposed-jdbc:0.34.1'
compileOnly 'mysql:mysql-connector-java:5.1.48'
}

View File

@ -11,6 +11,9 @@ import com.willfp.ecoenchants.command.CommandEnchantinfo;
import com.willfp.ecoenchants.config.RarityYml;
import com.willfp.ecoenchants.config.TargetYml;
import com.willfp.ecoenchants.config.VanillaEnchantsYml;
import com.willfp.ecoenchants.data.storage.DataHandler;
import com.willfp.ecoenchants.data.storage.MySQLDataHandler;
import com.willfp.ecoenchants.data.storage.YamlDataHandler;
import com.willfp.ecoenchants.display.EnchantDisplay;
import com.willfp.ecoenchants.enchantments.EcoEnchant;
import com.willfp.ecoenchants.enchantments.EcoEnchants;
@ -60,6 +63,12 @@ public class EcoEnchantsPlugin extends EcoPlugin {
@Getter
private final VanillaEnchantsYml vanillaEnchantsYml;
/**
* The data handler.
*/
@Getter
private final DataHandler dataHandler;
/**
* Internal constructor called by bukkit on plugin load.
*/
@ -70,6 +79,8 @@ public class EcoEnchantsPlugin extends EcoPlugin {
rarityYml = new RarityYml(this);
targetYml = new TargetYml(this);
vanillaEnchantsYml = new VanillaEnchantsYml(this);
dataHandler = this.getConfigYml().getBool("mysql.enabled")
? new MySQLDataHandler(this) : new YamlDataHandler(this);
}
@Override

View File

@ -0,0 +1,30 @@
package com.willfp.ecoenchants.data
import com.willfp.ecoenchants.EcoEnchantsPlugin
import com.willfp.ecoenchants.data.storage.PlayerProfile
import org.bukkit.Bukkit
class SaveHandler {
companion object {
fun save(plugin: EcoEnchantsPlugin) {
if (Bukkit.getOnlinePlayers().isEmpty()) {
return
}
if (plugin.configYml.getBool("autosave.log")) {
plugin.logger.info("Auto-Saving player data!")
}
PlayerProfile.saveAll(plugin.configYml.getBool("autosave.async"))
if (plugin.configYml.getBool("autosave.log")) {
plugin.logger.info("Saved data!")
}
}
}
class Runnable(
private val plugin: EcoEnchantsPlugin
) : java.lang.Runnable {
override fun run() {
save(plugin)
}
}
}

View File

@ -0,0 +1,13 @@
package com.willfp.ecoenchants.data.storage
import java.util.*
interface DataHandler {
fun save()
fun <T> write(uuid: UUID, key: String, value: T)
fun <T> read(uuid: UUID, key: String): T?
fun <T : Any> read(uuid: UUID, key: String, default: T): T {
return read<T>(uuid, key) ?: default
}
}

View File

@ -0,0 +1,69 @@
package com.willfp.ecoenchants.data.storage
import com.willfp.ecoenchants.EcoEnchantsPlugin
import org.jetbrains.exposed.dao.id.EntityID
import org.jetbrains.exposed.dao.id.UUIDTable
import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.transactions.transaction
import java.util.*
@Suppress("UNCHECKED_CAST")
class MySQLDataHandler(
plugin: EcoEnchantsPlugin
) : DataHandler {
init {
Database.connect(
"jdbc:mysql://" +
"${plugin.configYml.getString("mysql.host")}:" +
"${plugin.configYml.getString("mysql.port")}/" +
plugin.configYml.getString("mysql.database"),
driver = "com.mysql.cj.jdbc.Driver",
user = plugin.configYml.getString("mysql.user"),
password = plugin.configYml.getString("mysql.password")
)
transaction {
Players.apply {
/*
Optional for auto-add fields
*/
}
SchemaUtils.create(Players)
}
}
override fun save() {
// Do nothing
}
override fun <T> write(uuid: UUID, key: String, value: T) {
transaction {
Players.select { Players.id eq uuid }.firstOrNull() ?: run {
Players.insert {
it[this.id] = uuid
}
}
val column: Column<T> = Players.columns.stream().filter { it.name == key }.findFirst().get() as Column<T>
Players.update({ Players.id eq uuid }) {
it[column] = value
}
}
}
override fun <T> read(uuid: UUID, key: String): T? {
var value: T? = null
transaction {
val player = Players.select { Players.id eq uuid }.firstOrNull() ?: return@transaction
value = player[Players.columns.stream().filter { it.name == key }.findFirst().get()] as T?
}
return value
}
object Players : UUIDTable("EcoEnchants_Players") {
override val id: Column<EntityID<UUID>> = uuid("uuid")
.entityId()
val descriptions = bool("descriptions")
.default(true)
}
}

View File

@ -0,0 +1,85 @@
package com.willfp.ecoenchants.data.storage
import com.willfp.ecoenchants.EcoEnchantsPlugin
import org.bukkit.OfflinePlayer
import java.util.*
@Suppress("UNCHECKED_CAST")
class PlayerProfile private constructor(
private val data: MutableMap<String, Any>
) {
fun <T : Any> write(key: String, value: T) {
data[key] = value
}
fun <T : Any> read(key: String, default: T): T {
return data[key] as T? ?: default
}
companion object {
private val handler = EcoEnchantsPlugin.getInstance().dataHandler
private val loaded = mutableMapOf<UUID, PlayerProfile>()
private val keys = mutableMapOf<String, Type>()
private fun load(uuid: UUID): PlayerProfile {
val found = loaded[uuid]
if (found != null) {
return found
}
val data = mutableMapOf<String, Any>()
for ((key, type) in keys) {
when (type) {
Type.INT -> data[key] = handler.read(uuid, key, 0)
Type.DOUBLE -> data[key] = handler.read(uuid, key, 0.0)
Type.STRING -> data[key] = handler.read(uuid, key, "Unknown")
Type.BOOLEAN -> data[key] = handler.read(uuid, key, false)
}
}
val profile = PlayerProfile(data)
loaded[uuid] = profile
return profile
}
fun saveAll(async: Boolean) {
val saver = {
for ((uuid, profile) in loaded) {
for ((key, type) in keys) {
when (type) {
Type.INT -> handler.write(uuid, key, profile.read(key, 0))
Type.DOUBLE -> handler.write(uuid, key, profile.read(key, 0.0))
Type.STRING -> handler.write(uuid, key, profile.read(key, "Unknown Value"))
Type.BOOLEAN -> handler.write(uuid, key, profile.read(key, false))
}
}
}
handler.save()
}
if (async) {
EcoEnchantsPlugin.getInstance().scheduler.runAsync(saver)
} else {
saver.invoke()
}
}
@JvmStatic
val OfflinePlayer.profile: PlayerProfile
get() {
return load(this.uniqueId)
}
init {
keys["descriptions"] = Type.BOOLEAN
}
}
private enum class Type {
STRING,
DOUBLE,
BOOLEAN,
INT
}
}

View File

@ -0,0 +1,32 @@
package com.willfp.ecoenchants.data.storage
import com.willfp.eco.core.config.yaml.YamlBaseConfig
import com.willfp.ecoenchants.EcoEnchantsPlugin
import java.util.*
@Suppress("UNCHECKED_CAST")
class YamlDataHandler(
plugin: EcoEnchantsPlugin
) : DataHandler {
private val dataYml = DataYml(plugin)
override fun save() {
dataYml.save()
}
override fun <T> write(uuid: UUID, key: String, value: T) {
dataYml.set("player.$uuid.$key", value)
}
override fun <T> read(uuid: UUID, key: String): T? {
return dataYml.get("player.$uuid.$key") as T?
}
class DataYml(
plugin: EcoEnchantsPlugin
) : YamlBaseConfig(
"data",
false,
plugin
)
}

View File

@ -3,6 +3,18 @@
# by Auxilor
#
mysql:
enabled: false # Set to false, data.yml will be used instead.
host: localhost
port: 3306
database: database
user: username
password: passy
autosave:
log: true # If auto-save messages should be sent to console
async: false # If saves should be performed asynchronously. May cause bugs without MySQL
allow-on-npc: false # If enchantments should activate against NPCs.
commands:

View File

@ -0,0 +1 @@
# Do not modify this file, it is purely for internal storage.

View File

@ -22,6 +22,12 @@ softdepend:
- Essentials
- PlaceholderAPI
- mcMMO
libraries:
- 'org.jetbrains.kotlin:kotlin-stdlib:1.5.21'
- 'org.jetbrains.exposed:exposed-core:0.34.1'
- 'org.jetbrains.exposed:exposed-dao:0.34.1'
- 'org.jetbrains.exposed:exposed-jdbc:0.34.1'
- 'mysql:mysql-connector-java:5.1.48'
commands:
enchantinfo: