9
0
mirror of https://github.com/Auxilor/EcoSkills.git synced 2026-01-02 05:46:57 +00:00

Updated to new eco storage system

This commit is contained in:
Auxilor
2021-11-03 19:05:10 +00:00
parent 2b67b3b9dc
commit d84b07edfb
14 changed files with 161 additions and 212 deletions

View File

@@ -8,10 +8,10 @@ import com.willfp.ecoskills.commands.CommandSkills;
import com.willfp.ecoskills.config.EffectsYml;
import com.willfp.ecoskills.data.DataListener;
import com.willfp.ecoskills.data.LeaderboardHandler;
import com.willfp.ecoskills.data.SaveHandler;
import com.willfp.ecoskills.data.storage.DataHandler;
import com.willfp.ecoskills.data.storage.MySQLDataHandler;
import com.willfp.ecoskills.data.storage.YamlDataHandler;
import com.willfp.ecoskills.data.legacy.DataHandler;
import com.willfp.ecoskills.data.legacy.LegacyPlayerProfile;
import com.willfp.ecoskills.data.legacy.MySQLDataHandler;
import com.willfp.ecoskills.data.legacy.YamlDataHandler;
import com.willfp.ecoskills.effects.Effect;
import com.willfp.ecoskills.effects.Effects;
import com.willfp.ecoskills.integrations.EcoEnchantsEnchantingLeveller;
@@ -53,6 +53,8 @@ public class EcoSkillsPlugin extends EcoPlugin {
effectsYml = new EffectsYml(this);
dataHandler = this.getConfigYml().getBool("mysql.enabled")
? new MySQLDataHandler(this) : new YamlDataHandler(this);
LegacyPlayerProfile.Companion.migrateAll();
}
@Override
@@ -69,21 +71,10 @@ public class EcoSkillsPlugin extends EcoPlugin {
this.getEventManager().unregisterListener(skill);
this.getEventManager().registerListener(skill);
}
SaveHandler.Companion.save(this);
this.getScheduler().runTimer(
new SaveHandler.Runnable(this),
this.getConfigYml().getInt("autosave.ticks"),
this.getConfigYml().getInt("autosave.ticks")
);
this.getScheduler().runTimer(new LeaderboardHandler.Runnable(), 50, 2400);
}
@Override
protected void handleDisable() {
SaveHandler.Companion.save(this);
}
/**
* Get data handler.
*

View File

@@ -1,8 +1,8 @@
package com.willfp.ecoskills
import com.willfp.eco.core.data.PlayerProfile
import com.willfp.ecoskills.api.PlayerSkillExpGainEvent
import com.willfp.ecoskills.api.PlayerSkillLevelUpEvent
import com.willfp.ecoskills.data.storage.PlayerProfile.Companion.profile
import com.willfp.ecoskills.effects.Effect
import com.willfp.ecoskills.skills.Skill
import com.willfp.ecoskills.skills.Skills
@@ -95,11 +95,11 @@ fun Player.giveSkillExperience(skill: Skill, experience: Double, noMultiply: Boo
}
fun OfflinePlayer.getSkillLevel(skill: Skill): Int {
return profile.read(skill.id, 0)
return PlayerProfile.load(this).read(skill.dataKey)
}
fun OfflinePlayer.setSkillLevel(skill: Skill, level: Int) {
profile.write(skill.id, level)
PlayerProfile.load(this).write(skill.dataKey, level)
}
fun OfflinePlayer.getSkillProgressToNextLevel(skill: Skill): Double {
@@ -111,19 +111,19 @@ fun OfflinePlayer.getSkillProgressRequired(skill: Skill): Int {
}
fun OfflinePlayer.getSkillProgress(skill: Skill): Double {
return profile.read(skill.xpKey.key, 0.0)
return PlayerProfile.load(this).read(skill.dataXPKey)
}
fun OfflinePlayer.setSkillProgress(skill: Skill, level: Double) {
profile.write(skill.xpKey.key, level)
PlayerProfile.load(this).write(skill.dataXPKey, level)
}
fun OfflinePlayer.getEffectLevel(effect: Effect): Int {
return profile.read(effect.id, 0)
return PlayerProfile.load(this).read(effect.dataKey)
}
fun OfflinePlayer.setEffectLevel(effect: Effect, level: Int) {
profile.write(effect.id, level)
PlayerProfile.load(this).write(effect.dataKey, level)
}
fun OfflinePlayer.getStatLevel(stat: Stat): Int {
@@ -145,11 +145,11 @@ fun Player.getBonusStatLevel(stat: Stat): Int {
}
fun OfflinePlayer.getBaseStatLevel(stat: Stat): Int {
return profile.read(stat.id, 0)
return PlayerProfile.load(this).read(stat.dataKey)
}
fun Player.setStatLevel(stat: Stat, level: Int) {
profile.write(stat.id, level)
PlayerProfile.load(this).write(stat.dataKey, level)
stat.updateStatLevel(this)
}

View File

@@ -1,6 +1,5 @@
package com.willfp.ecoskills.data
import com.willfp.ecoskills.data.storage.PlayerProfile
import com.willfp.ecoskills.effects.Effect
import com.willfp.ecoskills.effects.Effects
import com.willfp.ecoskills.getSkillLevel
@@ -11,7 +10,6 @@ import org.bukkit.attribute.Attribute
import org.bukkit.event.EventHandler
import org.bukkit.event.Listener
import org.bukkit.event.player.PlayerJoinEvent
import org.bukkit.event.player.PlayerQuitEvent
class DataListener : Listener {
@EventHandler
@@ -55,9 +53,4 @@ class DataListener : Listener {
stat.updateStatLevel(event.player)
}
}
@EventHandler
fun onLeave(event: PlayerQuitEvent) {
PlayerProfile.savePlayer(event.player.uniqueId)
}
}

View File

@@ -1,32 +0,0 @@
package com.willfp.ecoskills.data
import com.willfp.ecoskills.EcoSkillsPlugin
import com.willfp.ecoskills.data.storage.PlayerProfile
import com.willfp.ecoskills.expMultiplierCache
import org.bukkit.Bukkit
class SaveHandler {
companion object {
fun save(plugin: EcoSkillsPlugin) {
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"))
expMultiplierCache.clear()
if (plugin.configYml.getBool("autosave.log")) {
plugin.logger.info("Saved data!")
}
}
}
class Runnable(
private val plugin: EcoSkillsPlugin
) : java.lang.Runnable {
override fun run() {
save(plugin)
}
}
}

View File

@@ -1,11 +1,8 @@
package com.willfp.ecoskills.data.storage
package com.willfp.ecoskills.data.legacy
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,110 @@
package com.willfp.ecoskills.data.legacy
import com.willfp.eco.core.data.PlayerProfile
import com.willfp.eco.core.data.keys.PersistentDataKey
import com.willfp.ecoskills.EcoSkillsPlugin
import com.willfp.ecoskills.effects.Effects
import com.willfp.ecoskills.plugin
import com.willfp.ecoskills.skills.Skills
import com.willfp.ecoskills.stats.Stats
import org.bukkit.Bukkit
import org.bukkit.OfflinePlayer
import java.util.*
@Suppress("UNCHECKED_CAST", "DEPRECATED")
class LegacyPlayerProfile private constructor(
private val data: MutableMap<String, Any>
) {
private fun <T : Any> read(key: String, default: T): T {
return data[key] as T? ?: default
}
companion object {
private val handler = EcoSkillsPlugin.getInstance().dataHandler
private val loaded = mutableMapOf<UUID, LegacyPlayerProfile>()
private val keys = mutableMapOf<String, Type>()
private val mappedKeys = mutableMapOf<String, PersistentDataKey<*>>()
private fun load(uuid: UUID): LegacyPlayerProfile {
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)
}
}
val profile = LegacyPlayerProfile(data)
loaded[uuid] = profile
return profile
}
fun migrateAll() {
if (plugin.configYml.getBool("mysql.migrated")) {
return
}
plugin.logger.info("-----------------------------------------")
plugin.logger.info("Migrating player data! (Automatic)")
plugin.logger.info("This will only run once, ever - not every time your server starts up")
plugin.logger.info("so there's no need to worry about how long it takes. Once this is complete,")
plugin.logger.info("feel free to delete data.yml as it won't be used anymore")
plugin.logger.info("-----------------------------------------")
for (offlinePlayer in Bukkit.getServer().offlinePlayers) {
plugin.logger.info("Migrating player ${offlinePlayer.uniqueId}...")
migrate(offlinePlayer)
}
plugin.logger.info("Migration complete!")
plugin.configYml.set("mysql.migrated", true)
}
private fun migrate(player: OfflinePlayer) {
fun <T> writeKey(profile: PlayerProfile, key: PersistentDataKey<T>, value: Any) {
value as T
profile.write(key, value)
}
val ecoProfile = PlayerProfile.load(player)
for ((key, type) in keys) {
val value = load(player.uniqueId).read(
key, when (type) {
Type.INT -> 0
Type.DOUBLE -> 0.0
}
)
val newKey = mappedKeys[key] ?: continue
writeKey(ecoProfile, newKey, value)
}
}
init {
for (skill in Skills.values()) {
keys[skill.id] = Type.INT
mappedKeys[skill.id] = skill.dataKey
keys[skill.id + "_progress"] = Type.DOUBLE
mappedKeys[skill.id + "_progress"] = skill.dataXPKey
}
for (stat in Stats.values()) {
keys[stat.id] = Type.INT
mappedKeys[stat.id] = stat.dataKey
}
for (effect in Effects.values()) {
keys[effect.id] = Type.INT
mappedKeys[effect.id] = effect.dataKey
}
}
}
private enum class Type {
DOUBLE,
INT
}
}

View File

@@ -1,4 +1,4 @@
package com.willfp.ecoskills.data.storage
package com.willfp.ecoskills.data.legacy
import com.willfp.ecoskills.EcoSkillsPlugin
import com.willfp.ecoskills.effects.Effects
@@ -30,7 +30,7 @@ class MySQLDataHandler(
for (skill in Skills.values()) {
registerColumn<Int>(skill.id, IntegerColumnType())
.default(0)
registerColumn<Double>(skill.xpKey.key, DoubleColumnType())
registerColumn<Double>(skill.id + "_progress", DoubleColumnType())
.default(0.0)
}
@@ -49,24 +49,6 @@ class MySQLDataHandler(
}
}
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 {
@@ -79,7 +61,5 @@ class MySQLDataHandler(
object Players : UUIDTable("EcoSkills_Players") {
override val id: Column<EntityID<UUID>> = uuid("uuid")
.entityId()
val name = varchar("name", 100)
.default("Unknown Player")
}
}

View File

@@ -1,4 +1,4 @@
package com.willfp.ecoskills.data.storage
package com.willfp.ecoskills.data.legacy
import com.willfp.eco.core.config.yaml.YamlBaseConfig
import com.willfp.ecoskills.EcoSkillsPlugin
@@ -10,14 +10,6 @@ class YamlDataHandler(
) : 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?
}

View File

@@ -1,112 +0,0 @@
package com.willfp.ecoskills.data.storage
import com.willfp.ecoskills.EcoSkillsPlugin
import com.willfp.ecoskills.effects.Effects
import com.willfp.ecoskills.plugin
import com.willfp.ecoskills.skills.Skills
import com.willfp.ecoskills.stats.Stats
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 = EcoSkillsPlugin.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")
}
}
val profile = PlayerProfile(data)
loaded[uuid] = profile
return profile
}
fun savePlayer(uuid: UUID) {
writeToHandler(uuid)
saveToHandler()
}
private fun writeToHandler(uuid: UUID) {
val profile = loaded[uuid] ?: return
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"))
}
}
}
private fun saveToHandler() {
handler.save()
}
fun saveAll(async: Boolean) {
val saver = {
for ((uuid, _) in loaded) {
writeToHandler(uuid)
}
saveToHandler()
}
if (async) {
plugin.scheduler.runAsync(saver)
} else {
saver.invoke()
}
}
val OfflinePlayer.profile: PlayerProfile
get() {
return load(this.uniqueId)
}
init {
keys["name"] = Type.STRING
for (skill in Skills.values()) {
keys[skill.id] = Type.INT
keys[skill.xpKey.key] = Type.DOUBLE
}
for (stat in Stats.values()) {
keys[stat.id] = Type.INT
}
for (effect in Effects.values()) {
keys[effect.id] = Type.INT
}
}
}
private enum class Type {
STRING,
DOUBLE,
INT
}
}

View File

@@ -1,6 +1,8 @@
package com.willfp.ecoskills.effects
import com.willfp.eco.core.config.interfaces.Config
import com.willfp.eco.core.data.keys.PersistentDataKey
import com.willfp.eco.core.data.keys.PersistentDataKeyType
import com.willfp.eco.core.integrations.placeholder.PlaceholderEntry
import com.willfp.eco.util.NumberUtils
import com.willfp.eco.util.StringUtils
@@ -17,6 +19,11 @@ abstract class Effect(
protected val plugin: EcoSkillsPlugin = EcoSkillsPlugin.getInstance()
val key: NamespacedKey = plugin.namespacedKeyFactory.create(id)
val dataKey = PersistentDataKey<Int>(
plugin.namespacedKeyFactory.create(id),
PersistentDataKeyType.INT,
0
)
val uuid: UUID = UUID.nameUUIDFromBytes(id.toByteArray())
lateinit var config: Config

View File

@@ -2,6 +2,8 @@ package com.willfp.ecoskills.skills
import com.willfp.eco.core.EcoPlugin
import com.willfp.eco.core.config.interfaces.Config
import com.willfp.eco.core.data.keys.PersistentDataKey
import com.willfp.eco.core.data.keys.PersistentDataKeyType
import com.willfp.eco.core.integrations.placeholder.PlaceholderEntry
import com.willfp.eco.util.NumberUtils
import com.willfp.eco.util.StringUtils
@@ -21,7 +23,16 @@ abstract class Skill(
protected val plugin: EcoPlugin = EcoSkillsPlugin.getInstance()
val key: NamespacedKey = plugin.namespacedKeyFactory.create(id)
val xpKey: NamespacedKey = plugin.namespacedKeyFactory.create(id + "_progress")
val dataKey = PersistentDataKey<Int>(
plugin.namespacedKeyFactory.create(id),
PersistentDataKeyType.INT,
0
)
val dataXPKey = PersistentDataKey<Double>(
plugin.namespacedKeyFactory.create("${id}_xp"),
PersistentDataKeyType.DOUBLE,
0.0
)
lateinit var config: Config
lateinit var name: String
lateinit var description: String

View File

@@ -2,6 +2,8 @@ package com.willfp.ecoskills.stats
import com.willfp.eco.core.EcoPlugin
import com.willfp.eco.core.config.interfaces.Config
import com.willfp.eco.core.data.keys.PersistentDataKey
import com.willfp.eco.core.data.keys.PersistentDataKeyType
import com.willfp.eco.core.integrations.placeholder.PlaceholderEntry
import com.willfp.eco.util.NumberUtils
import com.willfp.ecoskills.*
@@ -17,6 +19,11 @@ abstract class Stat(
val key: NamespacedKey = plugin.namespacedKeyFactory.create(id)
val uuid: UUID = UUID.nameUUIDFromBytes(id.toByteArray())
val dataKey = PersistentDataKey<Int>(
plugin.namespacedKeyFactory.create(id),
PersistentDataKeyType.INT,
0
)
lateinit var config: Config
lateinit var name: String

View File

@@ -3,7 +3,12 @@
# by Auxilor
#
# EcoSkills now uses eco's data storage system, this section will be removed in the future
# This exists purely to be able to migrate player data
# Go to /plugins/eco/config.yml to change MySQL settings
mysql:
migrated: false # Internal value - DO NOT CHANGE
enabled: false # Set to false, data.yml will be used instead.
host: localhost
port: 3306

View File

@@ -1 +1 @@
# Don't edit this file - it's for internal storage only
# This file exists for legacy support, it will be removed in the future