From c72b15c3a6bf466389b20a2be8a1b01547ce6780 Mon Sep 17 00:00:00 2001 From: Auxilor Date: Thu, 4 Nov 2021 12:57:39 +0000 Subject: [PATCH] Several performance and stability improvements --- .../eco/core/data/PlayerProfileHandler.java | 11 ++- .../com/willfp/eco/spigot/EcoSpigotPlugin.kt | 29 ++------ .../spigot/data/EcoPlayerProfileHandler.kt | 33 ++------- .../eco/spigot/data/storage/DataHandler.kt | 11 ++- .../spigot/data/storage/MySQLDataHandler.kt | 72 ++++++++++++------- .../spigot/data/storage/YamlDataHandler.kt | 10 ++- .../eco/spigot/display/PacketWindowItems.kt | 27 ++++--- .../core-plugin/src/main/resources/config.yml | 1 - 8 files changed, 102 insertions(+), 92 deletions(-) diff --git a/eco-api/src/main/java/com/willfp/eco/core/data/PlayerProfileHandler.java b/eco-api/src/main/java/com/willfp/eco/core/data/PlayerProfileHandler.java index 04c1cb60..47b46c1a 100644 --- a/eco-api/src/main/java/com/willfp/eco/core/data/PlayerProfileHandler.java +++ b/eco-api/src/main/java/com/willfp/eco/core/data/PlayerProfileHandler.java @@ -27,6 +27,15 @@ public interface PlayerProfileHandler { * Save all player data. * * @param async If the saving should be done asynchronously. + * @deprecated async is now handled automatically depending on implementation. */ - void saveAll(boolean async); + @Deprecated + default void saveAll(boolean async) { + saveAll(); + } + + /** + * Save all player data. + */ + void saveAll(); } diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/spigot/EcoSpigotPlugin.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/spigot/EcoSpigotPlugin.kt index 3de33571..f70b917a 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/spigot/EcoSpigotPlugin.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/spigot/EcoSpigotPlugin.kt @@ -30,12 +30,7 @@ import com.willfp.eco.spigot.data.PlayerBlockListener import com.willfp.eco.spigot.data.storage.DataHandler import com.willfp.eco.spigot.data.storage.MySQLDataHandler import com.willfp.eco.spigot.data.storage.YamlDataHandler -import com.willfp.eco.spigot.display.PacketAutoRecipe -import com.willfp.eco.spigot.display.PacketChat -import com.willfp.eco.spigot.display.PacketOpenWindowMerchant -import com.willfp.eco.spigot.display.PacketSetCreativeSlot -import com.willfp.eco.spigot.display.PacketSetSlot -import com.willfp.eco.spigot.display.PacketWindowItems +import com.willfp.eco.spigot.display.* import com.willfp.eco.spigot.display.frame.clearFrames import com.willfp.eco.spigot.drops.CollatedRunnable import com.willfp.eco.spigot.eventlisteners.EntityDeathByEntityListeners @@ -46,22 +41,8 @@ import com.willfp.eco.spigot.eventlisteners.armor.ArmorListener import com.willfp.eco.spigot.gui.GUIListener import com.willfp.eco.spigot.integrations.afk.AFKIntegrationCMI import com.willfp.eco.spigot.integrations.afk.AFKIntegrationEssentials -import com.willfp.eco.spigot.integrations.anticheat.AnticheatAAC -import com.willfp.eco.spigot.integrations.anticheat.AnticheatAlice -import com.willfp.eco.spigot.integrations.anticheat.AnticheatMatrix -import com.willfp.eco.spigot.integrations.anticheat.AnticheatNCP -import com.willfp.eco.spigot.integrations.anticheat.AnticheatSpartan -import com.willfp.eco.spigot.integrations.anticheat.AnticheatVulcan -import com.willfp.eco.spigot.integrations.antigrief.AntigriefBentoBox -import com.willfp.eco.spigot.integrations.antigrief.AntigriefCombatLogXV10 -import com.willfp.eco.spigot.integrations.antigrief.AntigriefCombatLogXV11 -import com.willfp.eco.spigot.integrations.antigrief.AntigriefFactionsUUID -import com.willfp.eco.spigot.integrations.antigrief.AntigriefGriefPrevention -import com.willfp.eco.spigot.integrations.antigrief.AntigriefKingdoms -import com.willfp.eco.spigot.integrations.antigrief.AntigriefLands -import com.willfp.eco.spigot.integrations.antigrief.AntigriefSuperiorSkyblock2 -import com.willfp.eco.spigot.integrations.antigrief.AntigriefTowny -import com.willfp.eco.spigot.integrations.antigrief.AntigriefWorldGuard +import com.willfp.eco.spigot.integrations.anticheat.* +import com.willfp.eco.spigot.integrations.antigrief.* import com.willfp.eco.spigot.integrations.customitems.CustomItemsHeadDatabase import com.willfp.eco.spigot.integrations.customitems.CustomItemsItemsAdder import com.willfp.eco.spigot.integrations.customitems.CustomItemsOraxen @@ -145,6 +126,8 @@ abstract class EcoSpigotPlugin : EcoPlugin( override fun handleDisable() { Eco.getHandler().adventure?.close() + this.logger.info("Saving player data...") + Eco.getHandler().playerProfileHandler.saveAll() } override fun handleReload() { @@ -158,7 +141,7 @@ abstract class EcoSpigotPlugin : EcoPlugin( this.scheduler.runTimer( { (Eco.getHandler().playerProfileHandler as EcoPlayerProfileHandler) - .autosave(this.configYml.getBool("autosave.async")) + .autosave() }, this.configYml.getInt("autosave.ticks").toLong(), this.configYml.getInt("autosave.ticks").toLong() diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/spigot/data/EcoPlayerProfileHandler.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/spigot/data/EcoPlayerProfileHandler.kt index 1f74dbf9..31407976 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/spigot/data/EcoPlayerProfileHandler.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/spigot/data/EcoPlayerProfileHandler.kt @@ -33,39 +33,18 @@ class EcoPlayerProfileHandler( } override fun savePlayer(uuid: UUID) { - writeToHandler(uuid) - saveToHandler() + handler.savePlayer(uuid) } - private fun writeToHandler(uuid: UUID) { - val profile = load(uuid) - - for (key in Eco.getHandler().keyRegistry.registeredKeys) { - handler.write(uuid, key.key, profile.read(key) ?: key.defaultValue) + override fun saveAll() { + for ((uuid, _) in loaded) { + handler.savePlayer(uuid) } - } - private fun saveToHandler() { handler.save() } - override fun saveAll(async: Boolean) { - val saver = { - for ((uuid, _) in loaded) { - writeToHandler(uuid) - } - - saveToHandler() - } - - if (async) { - plugin.scheduler.runAsync(saver) - } else { - saver.invoke() - } - } - - fun autosave(async: Boolean) { + fun autosave() { if (Bukkit.getOnlinePlayers().isEmpty()) { return } @@ -74,7 +53,7 @@ class EcoPlayerProfileHandler( plugin.logger.info("Auto-Saving player data!") } - saveAll(async) + saveAll() if (plugin.configYml.getBool("autosave.log")) { plugin.logger.info("Saved player data!") diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/spigot/data/storage/DataHandler.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/spigot/data/storage/DataHandler.kt index fca50995..5d04f65c 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/spigot/data/storage/DataHandler.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/spigot/data/storage/DataHandler.kt @@ -4,10 +4,15 @@ import org.bukkit.NamespacedKey import java.util.* interface DataHandler { - fun save() + fun save() { + + } + + fun updateKeys() { + + } fun write(uuid: UUID, key: NamespacedKey, value: T) + fun savePlayer(uuid: UUID) fun read(uuid: UUID, key: NamespacedKey): T? - - fun updateKeys() } \ No newline at end of file diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/spigot/data/storage/MySQLDataHandler.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/spigot/data/storage/MySQLDataHandler.kt index 5e563cd6..e702caa1 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/spigot/data/storage/MySQLDataHandler.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/spigot/data/storage/MySQLDataHandler.kt @@ -1,30 +1,25 @@ package com.willfp.eco.spigot.data.storage +import com.google.common.util.concurrent.ThreadFactoryBuilder import com.willfp.eco.core.Eco +import com.willfp.eco.core.data.PlayerProfile import com.willfp.eco.core.data.keys.PersistentDataKey import com.willfp.eco.core.data.keys.PersistentDataKeyType import com.willfp.eco.spigot.EcoSpigotPlugin import org.bukkit.NamespacedKey import org.jetbrains.exposed.dao.id.UUIDTable -import org.jetbrains.exposed.sql.BooleanColumnType -import org.jetbrains.exposed.sql.Column -import org.jetbrains.exposed.sql.Database -import org.jetbrains.exposed.sql.DoubleColumnType -import org.jetbrains.exposed.sql.IntegerColumnType -import org.jetbrains.exposed.sql.ResultRow -import org.jetbrains.exposed.sql.SchemaUtils -import org.jetbrains.exposed.sql.VarCharColumnType -import org.jetbrains.exposed.sql.insert -import org.jetbrains.exposed.sql.select +import org.jetbrains.exposed.sql.* import org.jetbrains.exposed.sql.transactions.transaction -import org.jetbrains.exposed.sql.update -import java.util.UUID +import java.util.* +import java.util.concurrent.Executors @Suppress("UNCHECKED_CAST") class MySQLDataHandler( plugin: EcoSpigotPlugin ) : DataHandler { private val columns = mutableMapOf>() + private val threadFactory = ThreadFactoryBuilder().setNameFormat("eco-mysql-thread-%d").build() + private val executor = Executors.newCachedThreadPool(threadFactory) init { Database.connect( @@ -52,17 +47,39 @@ class MySQLDataHandler( } } - override fun save() { - // Do nothing + override fun write(uuid: UUID, key: NamespacedKey, value: T) { + writeSafely(uuid, key, value) } - override fun write(uuid: UUID, key: NamespacedKey, value: T) { - transaction { - getPlayer(uuid) - val column: Column = getColumn(key.toString()) as Column + private fun writeSafely( + uuid: UUID, + key: NamespacedKey, + value: T, + assumeCreated: Boolean = false + ) { + val column: Column = getColumn(key.toString()) as Column - Players.update({ Players.id eq uuid }) { - it[column] = value + executor.execute { + if (!assumeCreated) { + getPlayer(uuid) + } + + transaction { + Players.update({ Players.id eq uuid }) { + it[column] = value + } + } + } + } + + override fun savePlayer(uuid: UUID) { + val profile = PlayerProfile.load(uuid) + + getPlayer(uuid) + + transaction { + for (key in Eco.getHandler().keyRegistry.registeredKeys) { + writeSafely(uuid, key.key, profile.read(key), assumeCreated = true) } } } @@ -112,12 +129,15 @@ class MySQLDataHandler( } private fun getPlayer(uuid: UUID): ResultRow { - Players.select { Players.id eq uuid }.firstOrNull() ?: run { - Players.insert { - it[id] = uuid - } - } + val player = Players.select { Players.id eq uuid }.limit(1).singleOrNull() - return Players.select { Players.id eq uuid }.first() + return if (player != null) { + player + } else { + transaction { + Players.insert { it[id] = uuid } + } + getPlayer(uuid) + } } } \ No newline at end of file diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/spigot/data/storage/YamlDataHandler.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/spigot/data/storage/YamlDataHandler.kt index 6f26b630..912b0fe4 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/spigot/data/storage/YamlDataHandler.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/spigot/data/storage/YamlDataHandler.kt @@ -1,6 +1,8 @@ package com.willfp.eco.spigot.data.storage +import com.willfp.eco.core.Eco import com.willfp.eco.core.config.yaml.YamlBaseConfig +import com.willfp.eco.core.data.PlayerProfile import com.willfp.eco.spigot.EcoSpigotPlugin import org.bukkit.NamespacedKey import java.util.* @@ -15,8 +17,12 @@ class YamlDataHandler( dataYml.save() } - override fun updateKeys() { - // Do nothing + override fun savePlayer(uuid: UUID) { + val profile = PlayerProfile.load(uuid) + + for (key in Eco.getHandler().keyRegistry.registeredKeys) { + write(uuid, key.key, profile.read(key)) + } } override fun write(uuid: UUID, key: NamespacedKey, value: T) { diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/spigot/display/PacketWindowItems.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/spigot/display/PacketWindowItems.kt index dd1e6a0b..6835a32a 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/spigot/display/PacketWindowItems.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/spigot/display/PacketWindowItems.kt @@ -47,14 +47,8 @@ class PacketWindowItems(plugin: EcoPlugin) : AbstractPacketAdapter(plugin, Packe handleRateLimit(player) if (usingAsync(player)) { - executor.execute { - try { - modifyWindowItems(itemStacks, windowId, player) - } catch (e: Exception) { - if (this.getPlugin().configYml.getBool("async-display.log-errors")) { - this.getPlugin().logger.warning("Error happened in async processing! Disable async display (/plugins/eco/config.yml) if this is a frequent issue") - } - } + fun modifyAndSend(itemStacks: MutableList, windowId: Int, player: Player) { + modifyWindowItems(itemStacks, windowId, player) val newPacket = packet.deepClone() newPacket.itemListModifier.write(0, itemStacks) @@ -63,6 +57,20 @@ class PacketWindowItems(plugin: EcoPlugin) : AbstractPacketAdapter(plugin, Packe ProtocolLibrary.getProtocolManager().sendServerPacket(player, newPacket) } + + executor.execute { + try { + modifyAndSend(itemStacks, windowId, player) + } catch (e: Exception) { + if (this.getPlugin().configYml.getBool("async-display.log-errors")) { + this.getPlugin().logger.warning("Error happened in async processing! Disable async display (/plugins/eco/config.yml) if this is a frequent issue") + } + + this.getPlugin().scheduler.run { + modifyAndSend(itemStacks, windowId, player) + } + } + } } else { packet.itemListModifier.write(0, modifyWindowItems(itemStacks, windowId, player)) } @@ -91,7 +99,8 @@ class PacketWindowItems(plugin: EcoPlugin) : AbstractPacketAdapter(plugin, Packe private fun usingAsync(player: Player): Boolean { if (this.getPlugin().configYml.getStrings("async-display.disable-on-types", false) - .map { it.lowercase() }.contains(player.openInventory.type.name.lowercase())) { + .map { it.lowercase() }.contains(player.openInventory.type.name.lowercase()) + ) { return false } diff --git a/eco-core/core-plugin/src/main/resources/config.yml b/eco-core/core-plugin/src/main/resources/config.yml index e5b7032e..17a76f38 100644 --- a/eco-core/core-plugin/src/main/resources/config.yml +++ b/eco-core/core-plugin/src/main/resources/config.yml @@ -14,7 +14,6 @@ mysql: autosave: ticks: 20000 # The amount of ticks between autosaves log: false # If auto-save messages should be sent to console - async: false # If saves should be performed asynchronously. May cause bugs without MySQL # Options to fix villager bugs left behind from old (buggy) versions.