数据库添加缓存 优化性能
This commit is contained in:
@@ -19,6 +19,8 @@ taboolib {
|
|||||||
contributors {
|
contributors {
|
||||||
name("xbaimiao")
|
name("xbaimiao")
|
||||||
}
|
}
|
||||||
|
val bukkitNodes = bukkitNodes as MutableMap<Any, Any>
|
||||||
|
bukkitNodes["update-info"] = "数据库添加缓存 优化性能"
|
||||||
}
|
}
|
||||||
env {
|
env {
|
||||||
install(NMS_UTIL, UI)
|
install(NMS_UTIL, UI)
|
||||||
@@ -39,6 +41,7 @@ repositories {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
compileOnly("com.mojang:authlib:1.5.25")
|
||||||
compileOnly("ink.ptms:nms-all:1.0.0")
|
compileOnly("ink.ptms:nms-all:1.0.0")
|
||||||
compileOnly("public:MythicMobs:4.14.1")
|
compileOnly("public:MythicMobs:4.14.1")
|
||||||
compileOnly("public:papi:1.0.0")
|
compileOnly("public:papi:1.0.0")
|
||||||
|
|||||||
+1
-1
@@ -1,2 +1,2 @@
|
|||||||
group=com.github.xbaimiao.shoppro
|
group=com.github.xbaimiao.shoppro
|
||||||
version=1.2.6-SNAPSHOT
|
version=1.2.6
|
||||||
|
|||||||
@@ -6,9 +6,14 @@ import com.github.xbaimiao.shoppro.core.database.SQLiteDatabase
|
|||||||
import com.github.xbaimiao.shoppro.core.item.ItemLoaderManager
|
import com.github.xbaimiao.shoppro.core.item.ItemLoaderManager
|
||||||
import com.github.xbaimiao.shoppro.core.shop.ShopManager
|
import com.github.xbaimiao.shoppro.core.shop.ShopManager
|
||||||
import com.github.xbaimiao.shoppro.core.vault.DiyCurrency
|
import com.github.xbaimiao.shoppro.core.vault.DiyCurrency
|
||||||
|
import com.github.xbaimiao.shoppro.core.vault.VaultImpl
|
||||||
import com.xbaimiao.ktor.KtorPluginsBukkit
|
import com.xbaimiao.ktor.KtorPluginsBukkit
|
||||||
import com.xbaimiao.ktor.KtorStat
|
import com.xbaimiao.ktor.KtorStat
|
||||||
|
import org.bukkit.Bukkit
|
||||||
|
import org.bukkit.event.player.PlayerJoinEvent
|
||||||
|
import org.bukkit.event.player.PlayerQuitEvent
|
||||||
import taboolib.common.platform.Plugin
|
import taboolib.common.platform.Plugin
|
||||||
|
import taboolib.common.platform.event.SubscribeEvent
|
||||||
import taboolib.common.platform.function.info
|
import taboolib.common.platform.function.info
|
||||||
import taboolib.module.configuration.Config
|
import taboolib.module.configuration.Config
|
||||||
import taboolib.module.configuration.Configuration
|
import taboolib.module.configuration.Configuration
|
||||||
@@ -33,7 +38,13 @@ object ShopPro : Plugin(), KtorStat {
|
|||||||
}
|
}
|
||||||
ShopManager.load()
|
ShopManager.load()
|
||||||
DiyCurrency.load()
|
DiyCurrency.load()
|
||||||
|
VaultImpl.startTask()
|
||||||
|
|
||||||
database = if (config.getBoolean("mysql.enable")) MysqlDatabase(config) else SQLiteDatabase()
|
database = if (config.getBoolean("mysql.enable")) MysqlDatabase(config) else SQLiteDatabase()
|
||||||
|
|
||||||
|
Bukkit.getOnlinePlayers().forEach {
|
||||||
|
database.loadPlayerData(it)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun reload() {
|
fun reload() {
|
||||||
@@ -41,7 +52,31 @@ object ShopPro : Plugin(), KtorStat {
|
|||||||
ShopManager.shops.clear()
|
ShopManager.shops.clear()
|
||||||
ShopManager.load()
|
ShopManager.load()
|
||||||
DiyCurrency.load()
|
DiyCurrency.load()
|
||||||
|
|
||||||
|
Bukkit.getOnlinePlayers().forEach {
|
||||||
|
database.releasePlayerData(it)
|
||||||
|
}
|
||||||
|
|
||||||
database = if (config.getBoolean("mysql.enable")) MysqlDatabase(config) else SQLiteDatabase()
|
database = if (config.getBoolean("mysql.enable")) MysqlDatabase(config) else SQLiteDatabase()
|
||||||
|
Bukkit.getOnlinePlayers().forEach {
|
||||||
|
database.loadPlayerData(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDisable() {
|
||||||
|
VaultImpl.flush()
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
fun join(event: PlayerJoinEvent) {
|
||||||
|
val player = event.player
|
||||||
|
database.loadPlayerData(player)
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
fun quit(event: PlayerQuitEvent) {
|
||||||
|
val player = event.player
|
||||||
|
database.releasePlayerData(player)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -29,4 +29,8 @@ interface Database {
|
|||||||
|
|
||||||
fun reset()
|
fun reset()
|
||||||
|
|
||||||
|
fun loadPlayerData(player: Player)
|
||||||
|
|
||||||
|
fun releasePlayerData(player: Player)
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -3,6 +3,7 @@ package com.github.xbaimiao.shoppro.core.database
|
|||||||
import com.github.xbaimiao.shoppro.core.item.Item
|
import com.github.xbaimiao.shoppro.core.item.Item
|
||||||
import com.github.xbaimiao.shoppro.core.item.impl.ItemsAdderShopItem
|
import com.github.xbaimiao.shoppro.core.item.impl.ItemsAdderShopItem
|
||||||
import org.bukkit.entity.Player
|
import org.bukkit.entity.Player
|
||||||
|
import taboolib.common.platform.function.submitAsync
|
||||||
import taboolib.module.database.Host
|
import taboolib.module.database.Host
|
||||||
import taboolib.module.database.Table
|
import taboolib.module.database.Table
|
||||||
import javax.sql.DataSource
|
import javax.sql.DataSource
|
||||||
@@ -25,6 +26,8 @@ abstract class SqlDatabase : Database {
|
|||||||
// ServerTable 无 User
|
// ServerTable 无 User
|
||||||
val playerLine = "user"
|
val playerLine = "user"
|
||||||
|
|
||||||
|
private val playerAlreadyDataCache = HashMap<String, HashMap<String, LimitData>>()
|
||||||
|
|
||||||
override fun reset() {
|
override fun reset() {
|
||||||
serverTable.workspace(dataSource) {
|
serverTable.workspace(dataSource) {
|
||||||
executeUpdate("DELETE FROM $serverTableName;").run()
|
executeUpdate("DELETE FROM $serverTableName;").run()
|
||||||
@@ -50,8 +53,20 @@ abstract class SqlDatabase : Database {
|
|||||||
} ?: LimitData.ofNull()
|
} ?: LimitData.ofNull()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun Item.toCacheKey(): String {
|
||||||
|
val item = this
|
||||||
|
return "${item.key}-${item.material}-${if (item is ItemsAdderShopItem) item.custom else 0}"
|
||||||
|
}
|
||||||
|
|
||||||
override fun getPlayerAlreadyData(player: Player, item: Item): LimitData {
|
override fun getPlayerAlreadyData(player: Player, item: Item): LimitData {
|
||||||
return playerTable.workspace(dataSource) {
|
val cache = playerAlreadyDataCache[player.name] ?: error("玩家 ${player.name} 数据缓存未加载")
|
||||||
|
|
||||||
|
val cacheKey = item.toCacheKey()
|
||||||
|
if (cache.containsKey(cacheKey)) {
|
||||||
|
return cache[cacheKey]!!
|
||||||
|
}
|
||||||
|
|
||||||
|
val databaseLimitData = playerTable.workspace(dataSource) {
|
||||||
select {
|
select {
|
||||||
where {
|
where {
|
||||||
playerLine eq player.uniqueId.toString()
|
playerLine eq player.uniqueId.toString()
|
||||||
@@ -65,6 +80,57 @@ abstract class SqlDatabase : Database {
|
|||||||
}.firstOrNull {
|
}.firstOrNull {
|
||||||
LimitData.formString(this.getString(dataLine))
|
LimitData.formString(this.getString(dataLine))
|
||||||
} ?: LimitData.ofNull()
|
} ?: LimitData.ofNull()
|
||||||
|
|
||||||
|
cache[cacheKey] = databaseLimitData
|
||||||
|
return databaseLimitData
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setPlayerAlreadyData(player: Player, item: Item, amount: LimitData) {
|
||||||
|
val cache = playerAlreadyDataCache[player.name] ?: error("玩家 ${player.name} 数据缓存未加载")
|
||||||
|
val cacheKey = item.toCacheKey()
|
||||||
|
cache[cacheKey] = amount
|
||||||
|
|
||||||
|
submitAsync {
|
||||||
|
if (playerTable.workspace(dataSource) {
|
||||||
|
select {
|
||||||
|
where {
|
||||||
|
playerLine eq player.uniqueId.toString()
|
||||||
|
itemKeyLine eq item.key.toString()
|
||||||
|
itemMaterialLine eq item.material.toString()
|
||||||
|
if (item is ItemsAdderShopItem) {
|
||||||
|
itemCustomLine eq item.custom
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.find()) {
|
||||||
|
playerTable.workspace(dataSource) {
|
||||||
|
update {
|
||||||
|
where {
|
||||||
|
playerLine eq player.uniqueId.toString()
|
||||||
|
itemKeyLine eq item.key.toString()
|
||||||
|
itemMaterialLine eq item.material.toString()
|
||||||
|
if (item is ItemsAdderShopItem) {
|
||||||
|
itemCustomLine eq item.custom
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set(dataLine, amount.toString())
|
||||||
|
}
|
||||||
|
}.run()
|
||||||
|
} else {
|
||||||
|
val custom = if (item is ItemsAdderShopItem) item.custom else 0
|
||||||
|
playerTable.workspace(dataSource) {
|
||||||
|
insert {
|
||||||
|
value(
|
||||||
|
item.key.toString(),
|
||||||
|
item.material.toString(),
|
||||||
|
custom,
|
||||||
|
amount.toString(),
|
||||||
|
player.uniqueId.toString()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}.run()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun addAmount(item: Item, player: Player, amount: LimitData) {
|
override fun addAmount(item: Item, player: Player, amount: LimitData) {
|
||||||
@@ -106,46 +172,12 @@ abstract class SqlDatabase : Database {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setPlayerAlreadyData(player: Player, item: Item, amount: LimitData) {
|
override fun loadPlayerData(player: Player) {
|
||||||
if (playerTable.workspace(dataSource) {
|
playerAlreadyDataCache[player.name] = HashMap()
|
||||||
select {
|
|
||||||
where {
|
|
||||||
playerLine eq player.uniqueId.toString()
|
|
||||||
itemKeyLine eq item.key.toString()
|
|
||||||
itemMaterialLine eq item.material.toString()
|
|
||||||
if (item is ItemsAdderShopItem) {
|
|
||||||
itemCustomLine eq item.custom
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}.find()) {
|
|
||||||
playerTable.workspace(dataSource) {
|
|
||||||
update {
|
|
||||||
where {
|
|
||||||
playerLine eq player.uniqueId.toString()
|
|
||||||
itemKeyLine eq item.key.toString()
|
|
||||||
itemMaterialLine eq item.material.toString()
|
|
||||||
if (item is ItemsAdderShopItem) {
|
|
||||||
itemCustomLine eq item.custom
|
|
||||||
}
|
|
||||||
}
|
|
||||||
set(dataLine, amount.toString())
|
|
||||||
}
|
|
||||||
}.run()
|
|
||||||
} else {
|
|
||||||
val custom = if (item is ItemsAdderShopItem) item.custom else 0
|
|
||||||
playerTable.workspace(dataSource) {
|
|
||||||
insert {
|
|
||||||
value(
|
|
||||||
item.key.toString(),
|
|
||||||
item.material.toString(),
|
|
||||||
custom,
|
|
||||||
amount.toString(),
|
|
||||||
player.uniqueId.toString()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}.run()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun releasePlayerData(player: Player) {
|
||||||
|
playerAlreadyDataCache.remove(player.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -29,7 +29,7 @@ interface KetherCondition {
|
|||||||
if (conditionIcon == null || conditionName == null) {
|
if (conditionIcon == null || conditionName == null) {
|
||||||
return ItemStack(Material.AIR)
|
return ItemStack(Material.AIR)
|
||||||
}
|
}
|
||||||
return taboolib.platform.util.buildItem(conditionIcon!!) {
|
return com.github.xbaimiao.shoppro.util.buildItem(conditionIcon!!) {
|
||||||
name = conditionName!!.colored().replacePapi(player)
|
name = conditionName!!.colored().replacePapi(player)
|
||||||
conditionLore.forEach {
|
conditionLore.forEach {
|
||||||
lore += it.colored().replacePapi(player)
|
lore += it.colored().replacePapi(player)
|
||||||
|
|||||||
@@ -9,9 +9,7 @@ import org.bukkit.configuration.ConfigurationSection
|
|||||||
import org.bukkit.entity.Player
|
import org.bukkit.entity.Player
|
||||||
import org.bukkit.inventory.ItemStack
|
import org.bukkit.inventory.ItemStack
|
||||||
import taboolib.library.xseries.XMaterial
|
import taboolib.library.xseries.XMaterial
|
||||||
import taboolib.library.xseries.XSkull
|
|
||||||
import taboolib.library.xseries.parseToMaterial
|
import taboolib.library.xseries.parseToMaterial
|
||||||
import taboolib.platform.util.ItemBuilder
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class HeadShopItem(
|
class HeadShopItem(
|
||||||
@@ -29,8 +27,8 @@ class HeadShopItem(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun vanillaItem(player: Player): ItemStack {
|
override fun vanillaItem(player: Player): ItemStack {
|
||||||
return taboolib.platform.util.buildItem(material) {
|
return com.github.xbaimiao.shoppro.util.buildItem(material) {
|
||||||
skullTexture = XSkull.SkullTexture(head, UUID.randomUUID())
|
skullTexture = com.github.xbaimiao.shoppro.util.ItemBuilder.SkullTexture(head, UUID.randomUUID())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,10 +37,10 @@ class HeadShopItem(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun buildItem(player: Player): ItemStack {
|
override fun buildItem(player: Player): ItemStack {
|
||||||
return taboolib.platform.util.buildItem(material) {
|
return com.github.xbaimiao.shoppro.util.buildItem(material) {
|
||||||
this.name = this@HeadShopItem.name
|
this.name = this@HeadShopItem.name
|
||||||
this.lore.addAll(this@HeadShopItem.lore)
|
this.lore.addAll(this@HeadShopItem.lore)
|
||||||
skullTexture = XSkull.SkullTexture(head, UUID.randomUUID())
|
skullTexture = com.github.xbaimiao.shoppro.util.ItemBuilder.SkullTexture(head, UUID.randomUUID())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import org.bukkit.configuration.ConfigurationSection
|
|||||||
import org.bukkit.entity.Player
|
import org.bukkit.entity.Player
|
||||||
import org.bukkit.inventory.ItemStack
|
import org.bukkit.inventory.ItemStack
|
||||||
import taboolib.library.xseries.XMaterial
|
import taboolib.library.xseries.XMaterial
|
||||||
import taboolib.library.xseries.XSkull
|
|
||||||
import taboolib.module.chat.colored
|
import taboolib.module.chat.colored
|
||||||
import taboolib.platform.util.modifyLore
|
import taboolib.platform.util.modifyLore
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@@ -49,12 +48,12 @@ class ItemImpl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun buildItem(player: Player): ItemStack {
|
override fun buildItem(player: Player): ItemStack {
|
||||||
return taboolib.platform.util.buildItem(material) {
|
return com.github.xbaimiao.shoppro.util.buildItem(material) {
|
||||||
this.name = this@ItemImpl.name
|
this.name = this@ItemImpl.name
|
||||||
this.lore.addAll(this@ItemImpl.lore)
|
this.lore.addAll(this@ItemImpl.lore)
|
||||||
custom?.let { customModelData = it }
|
custom?.let { customModelData = it }
|
||||||
head?.let {
|
head?.let {
|
||||||
skullTexture = XSkull.SkullTexture(it, UUID.randomUUID())
|
skullTexture = com.github.xbaimiao.shoppro.util.ItemBuilder.SkullTexture(it, UUID.randomUUID())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ class ItemsAdderShopItem(
|
|||||||
itemSetting: ItemSetting
|
itemSetting: ItemSetting
|
||||||
) : ShopItem(itemSetting) {
|
) : ShopItem(itemSetting) {
|
||||||
|
|
||||||
final override val material: Material
|
override val material: Material
|
||||||
|
|
||||||
val custom: Int
|
val custom: Int
|
||||||
|
|
||||||
@@ -34,13 +34,13 @@ class ItemsAdderShopItem(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun vanillaItem(player: Player): ItemStack {
|
override fun vanillaItem(player: Player): ItemStack {
|
||||||
return taboolib.platform.util.buildItem(material) {
|
return com.github.xbaimiao.shoppro.util.buildItem(material) {
|
||||||
this.customModelData = custom
|
this.customModelData = custom
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun buildItem(player: Player): ItemStack {
|
override fun buildItem(player: Player): ItemStack {
|
||||||
return taboolib.platform.util.buildItem(material) {
|
return com.github.xbaimiao.shoppro.util.buildItem(material) {
|
||||||
this.name = this@ItemsAdderShopItem.name
|
this.name = this@ItemsAdderShopItem.name
|
||||||
this.lore.addAll(this@ItemsAdderShopItem.lore)
|
this.lore.addAll(this@ItemsAdderShopItem.lore)
|
||||||
this.customModelData = custom
|
this.customModelData = custom
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package com.github.xbaimiao.shoppro.core.item.impl
|
|||||||
import com.github.xbaimiao.shoppro.core.item.Item
|
import com.github.xbaimiao.shoppro.core.item.Item
|
||||||
import com.github.xbaimiao.shoppro.core.item.ItemLoader
|
import com.github.xbaimiao.shoppro.core.item.ItemLoader
|
||||||
import com.github.xbaimiao.shoppro.core.shop.Shop
|
import com.github.xbaimiao.shoppro.core.shop.Shop
|
||||||
import ink.ptms.zaphkiel.Zaphkiel
|
|
||||||
import org.bukkit.Bukkit
|
import org.bukkit.Bukkit
|
||||||
import org.bukkit.Material
|
import org.bukkit.Material
|
||||||
import org.bukkit.configuration.ConfigurationSection
|
import org.bukkit.configuration.ConfigurationSection
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import taboolib.platform.util.hasLore
|
|||||||
open class VanillaShopItem(itemSetting: ItemSetting) : ShopItem(itemSetting) {
|
open class VanillaShopItem(itemSetting: ItemSetting) : ShopItem(itemSetting) {
|
||||||
|
|
||||||
override fun vanillaItem(player: Player): ItemStack {
|
override fun vanillaItem(player: Player): ItemStack {
|
||||||
return taboolib.platform.util.buildItem(material)
|
return com.github.xbaimiao.shoppro.util.buildItem(material)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun equal(itemStack: ItemStack): Boolean {
|
override fun equal(itemStack: ItemStack): Boolean {
|
||||||
@@ -20,7 +20,7 @@ open class VanillaShopItem(itemSetting: ItemSetting) : ShopItem(itemSetting) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun buildItem(player: Player): ItemStack {
|
override fun buildItem(player: Player): ItemStack {
|
||||||
return taboolib.platform.util.buildItem(material) {
|
return com.github.xbaimiao.shoppro.util.buildItem(material) {
|
||||||
this.name = this@VanillaShopItem.name
|
this.name = this@VanillaShopItem.name
|
||||||
this.lore.addAll(this@VanillaShopItem.lore)
|
this.lore.addAll(this@VanillaShopItem.lore)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import taboolib.module.chat.colored
|
|||||||
import taboolib.module.ui.ClickType
|
import taboolib.module.ui.ClickType
|
||||||
import taboolib.module.ui.openMenu
|
import taboolib.module.ui.openMenu
|
||||||
import taboolib.module.ui.type.Basic
|
import taboolib.module.ui.type.Basic
|
||||||
|
import taboolib.module.ui.type.Chest
|
||||||
import taboolib.platform.util.giveItem
|
import taboolib.platform.util.giveItem
|
||||||
import taboolib.platform.util.hasItem
|
import taboolib.platform.util.hasItem
|
||||||
import taboolib.platform.util.sendLang
|
import taboolib.platform.util.sendLang
|
||||||
|
|||||||
@@ -2,16 +2,59 @@ package com.github.xbaimiao.shoppro.core.vault
|
|||||||
|
|
||||||
import com.github.xbaimiao.shoppro.util.Util.format
|
import com.github.xbaimiao.shoppro.util.Util.format
|
||||||
import org.bukkit.entity.Player
|
import org.bukkit.entity.Player
|
||||||
|
import org.bukkit.event.player.PlayerQuitEvent
|
||||||
|
import taboolib.common.platform.event.EventPriority
|
||||||
|
import taboolib.common.platform.event.SubscribeEvent
|
||||||
|
import taboolib.common.platform.function.submit
|
||||||
import taboolib.platform.compat.VaultService
|
import taboolib.platform.compat.VaultService
|
||||||
|
import java.util.concurrent.ConcurrentLinkedQueue
|
||||||
|
|
||||||
object VaultImpl : Currency {
|
object VaultImpl : Currency {
|
||||||
|
|
||||||
|
private val queue = ConcurrentLinkedQueue<ValueQueue>()
|
||||||
|
|
||||||
|
private data class ValueQueue(val player: Player, val money: Double)
|
||||||
|
|
||||||
|
fun startTask() {
|
||||||
|
submit(period = 20) {
|
||||||
|
flush()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent(priority = EventPriority.LOWEST)
|
||||||
|
fun quit(event: PlayerQuitEvent) {
|
||||||
|
val iterator = queue.iterator()
|
||||||
|
var amount = 0.0
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
val queue = iterator.next()
|
||||||
|
if (queue.player.uniqueId == event.player.uniqueId) {
|
||||||
|
amount += queue.money
|
||||||
|
iterator.remove()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (amount > 0) {
|
||||||
|
realGiveMoney(event.player, amount)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun flush() {
|
||||||
|
queue.groupBy { it.player }.forEach { (player, valueQueues) ->
|
||||||
|
val amount = valueQueues.sumOf { it.money }
|
||||||
|
realGiveMoney(player, amount)
|
||||||
|
}
|
||||||
|
queue.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun realGiveMoney(player: Player, double: Double) {
|
||||||
|
VaultService.economy!!.depositPlayer(player, double.format())
|
||||||
|
}
|
||||||
|
|
||||||
override fun hasMoney(player: Player, double: Double): Boolean {
|
override fun hasMoney(player: Player, double: Double): Boolean {
|
||||||
return getMoney(player) >= double.format()
|
return getMoney(player) >= double.format()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun giveMoney(player: Player, double: Double) {
|
override fun giveMoney(player: Player, double: Double) {
|
||||||
VaultService.economy!!.depositPlayer(player, double.format())
|
queue.offer(ValueQueue(player, double))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun takeMoney(player: Player, double: Double): Boolean {
|
override fun takeMoney(player: Player, double: Double): Boolean {
|
||||||
@@ -26,5 +69,4 @@ object VaultImpl : Currency {
|
|||||||
return VaultService.economy!!.getBalance(player).format()
|
return VaultService.economy!!.getBalance(player).format()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,363 @@
|
|||||||
|
package com.github.xbaimiao.shoppro.util
|
||||||
|
|
||||||
|
import com.mojang.authlib.GameProfile
|
||||||
|
import com.mojang.authlib.properties.Property
|
||||||
|
import org.bukkit.ChatColor
|
||||||
|
import org.bukkit.Color
|
||||||
|
import org.bukkit.Material
|
||||||
|
import org.bukkit.block.banner.Pattern
|
||||||
|
import org.bukkit.enchantments.Enchantment
|
||||||
|
import org.bukkit.entity.EntityType
|
||||||
|
import org.bukkit.inventory.ItemStack
|
||||||
|
import org.bukkit.inventory.meta.*
|
||||||
|
import org.bukkit.potion.PotionData
|
||||||
|
import org.bukkit.potion.PotionEffect
|
||||||
|
import taboolib.library.reflex.Reflex.Companion.getProperty
|
||||||
|
import taboolib.library.reflex.Reflex.Companion.invokeMethod
|
||||||
|
import taboolib.library.reflex.Reflex.Companion.setProperty
|
||||||
|
import taboolib.library.xseries.XMaterial
|
||||||
|
import taboolib.module.chat.colored
|
||||||
|
import taboolib.platform.util.isAir
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过现有物品构建新的物品
|
||||||
|
*
|
||||||
|
* @param itemStack 原始物品
|
||||||
|
* @param builder 构建器
|
||||||
|
* @return 新的物品
|
||||||
|
* @throws IllegalArgumentException 如果物品为空气
|
||||||
|
*/
|
||||||
|
fun buildItem(itemStack: ItemStack, builder: ItemBuilder.() -> Unit = {}): ItemStack {
|
||||||
|
if (itemStack.isAir()) {
|
||||||
|
error("air")
|
||||||
|
}
|
||||||
|
return ItemBuilder(itemStack).also(builder).build()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过 [Material] 材质构建新的物品
|
||||||
|
*
|
||||||
|
* @param material 材质
|
||||||
|
* @param builder 构建器
|
||||||
|
* @return 新的物品
|
||||||
|
* @throws IllegalArgumentException 如果材质为空气
|
||||||
|
*/
|
||||||
|
fun buildItem(material: Material, builder: ItemBuilder.() -> Unit = {}): ItemStack {
|
||||||
|
// 在低版本, 并没有 Material.isAir() 方法
|
||||||
|
if (material == Material.AIR) {
|
||||||
|
error("air")
|
||||||
|
}
|
||||||
|
return ItemBuilder(material).also(builder).build()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过 [XMaterial] 材质构建新的物品
|
||||||
|
*
|
||||||
|
* @param material 材质
|
||||||
|
* @param builder 构建器
|
||||||
|
* @return 新的物品
|
||||||
|
* @throws IllegalArgumentException 如果材质为空气
|
||||||
|
*/
|
||||||
|
fun buildItem(material: XMaterial, builder: ItemBuilder.() -> Unit = {}): ItemStack {
|
||||||
|
// 在低版本, 并没有 Material.isAir() 方法
|
||||||
|
if (material == XMaterial.AIR) {
|
||||||
|
error("air")
|
||||||
|
}
|
||||||
|
return ItemBuilder(material.parseMaterial() ?: error("material.parseMaterial() is null")).also(builder).build()
|
||||||
|
}
|
||||||
|
|
||||||
|
open class ItemBuilder {
|
||||||
|
|
||||||
|
class SkullTexture(val textures: String, val uuid: UUID? = UUID.randomUUID())
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 物品材质
|
||||||
|
*/
|
||||||
|
var material: Material
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数量
|
||||||
|
*/
|
||||||
|
var amount = 1
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 附加值(损伤值)
|
||||||
|
*/
|
||||||
|
var damage = 0
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 展示名称
|
||||||
|
*/
|
||||||
|
var name: String? = null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 描述
|
||||||
|
*/
|
||||||
|
val lore = ArrayList<String>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 标签
|
||||||
|
*/
|
||||||
|
val flags = ArrayList<ItemFlag>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 附魔
|
||||||
|
*/
|
||||||
|
val enchants = HashMap<Enchantment, Int>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 旗帜花纹
|
||||||
|
*/
|
||||||
|
val patterns = ArrayList<Pattern>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 颜色
|
||||||
|
*/
|
||||||
|
var color: Color? = null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 药水效果
|
||||||
|
*/
|
||||||
|
val potions = ArrayList<PotionEffect>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 基础药水效果
|
||||||
|
*/
|
||||||
|
var potionData: PotionData? = null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生物类型
|
||||||
|
*/
|
||||||
|
var spawnType: EntityType? = null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 头颅信息
|
||||||
|
*/
|
||||||
|
var skullOwner: String? = null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 头颅材质信息
|
||||||
|
*/
|
||||||
|
var skullTexture: SkullTexture? = null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 无法破坏
|
||||||
|
*/
|
||||||
|
var isUnbreakable = false
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CustomModelData
|
||||||
|
*/
|
||||||
|
var customModelData = -1
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 原始数据
|
||||||
|
* 尝试修复自定义 nbt 失效的问题
|
||||||
|
*/
|
||||||
|
var originMeta: ItemMeta? = null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当构建完成时,做出最后修改
|
||||||
|
*/
|
||||||
|
var finishing: (ItemStack) -> Unit = {}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 使其发光
|
||||||
|
*/
|
||||||
|
fun shiny() {
|
||||||
|
flags += ItemFlag.HIDE_ENCHANTS
|
||||||
|
enchants[Enchantment.LURE] = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 隐藏所有附加信息(赋予所有 ItemFlag)
|
||||||
|
*/
|
||||||
|
fun hideAll() {
|
||||||
|
flags.addAll(ItemFlag.values())
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun getSkinValue(skull: ItemMeta): SkullTexture? {
|
||||||
|
var profile: GameProfile? = null
|
||||||
|
try {
|
||||||
|
profile = skull.getProperty("profile")
|
||||||
|
} catch (ignored: Exception) {
|
||||||
|
}
|
||||||
|
if (profile != null && !profile.properties["textures"].isEmpty()) {
|
||||||
|
for (property in profile.properties["textures"]) {
|
||||||
|
if (property.value.isNotEmpty()) {
|
||||||
|
return SkullTexture(property.value, profile.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上色
|
||||||
|
*/
|
||||||
|
fun colored() {
|
||||||
|
if (name != null) {
|
||||||
|
name = try {
|
||||||
|
name!!.colored()
|
||||||
|
} catch (ex: NoClassDefFoundError) {
|
||||||
|
ChatColor.translateAlternateColorCodes('&', name!!)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (lore.isNotEmpty()) {
|
||||||
|
val newLore = try {
|
||||||
|
lore.colored()
|
||||||
|
} catch (ex: NoClassDefFoundError) {
|
||||||
|
lore.map { ChatColor.translateAlternateColorCodes('&', it) }
|
||||||
|
}
|
||||||
|
lore.clear()
|
||||||
|
lore += newLore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建物品
|
||||||
|
*/
|
||||||
|
open fun build(): ItemStack {
|
||||||
|
val itemStack = ItemStack(material)
|
||||||
|
itemStack.amount = amount
|
||||||
|
if (damage != 0) {
|
||||||
|
itemStack.durability = damage.toShort()
|
||||||
|
}
|
||||||
|
val itemMeta = originMeta ?: itemStack.itemMeta ?: return itemStack
|
||||||
|
itemMeta.setDisplayName(name)
|
||||||
|
itemMeta.lore = lore
|
||||||
|
kotlin.runCatching {
|
||||||
|
itemMeta.addItemFlags(*flags.map { org.bukkit.inventory.ItemFlag.valueOf(it.name) }.toTypedArray())
|
||||||
|
}
|
||||||
|
if (itemMeta is EnchantmentStorageMeta) {
|
||||||
|
enchants.forEach { (e, lvl) -> itemMeta.addStoredEnchant(e, lvl, true) }
|
||||||
|
} else {
|
||||||
|
enchants.forEach { (e, lvl) -> itemMeta.addEnchant(e, lvl, true) }
|
||||||
|
}
|
||||||
|
when (itemMeta) {
|
||||||
|
is LeatherArmorMeta -> {
|
||||||
|
itemMeta.setColor(color)
|
||||||
|
}
|
||||||
|
|
||||||
|
is PotionMeta -> {
|
||||||
|
itemMeta.color = color
|
||||||
|
potions.forEach { itemMeta.addCustomEffect(it, true) }
|
||||||
|
if (potionData != null) {
|
||||||
|
itemMeta.basePotionData = potionData!!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
is SkullMeta -> {
|
||||||
|
if (skullOwner != null) {
|
||||||
|
itemMeta.owner = skullOwner
|
||||||
|
}
|
||||||
|
if (skullTexture != null) {
|
||||||
|
itemMeta.setProperty("profile", GameProfile(skullTexture!!.uuid, null).also {
|
||||||
|
it.properties.put("textures", Property("textures", skullTexture!!.textures))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
itemMeta.isUnbreakable = isUnbreakable
|
||||||
|
} catch (ex: NoSuchMethodError) {
|
||||||
|
try {
|
||||||
|
itemMeta.invokeMethod<Any>("spigot")!!.invokeMethod<Any>("setUnbreakable", isUnbreakable)
|
||||||
|
} catch (ignored: NoSuchMethodException) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
if (spawnType != null && itemMeta is SpawnEggMeta) {
|
||||||
|
itemMeta.spawnedType = spawnType
|
||||||
|
}
|
||||||
|
} catch (ignored: NoClassDefFoundError) {
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
if (patterns.isNotEmpty() && itemMeta is BannerMeta) {
|
||||||
|
patterns.forEach { itemMeta.addPattern(it) }
|
||||||
|
}
|
||||||
|
} catch (ignored: NoClassDefFoundError) {
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
if (customModelData != -1) {
|
||||||
|
itemMeta.invokeMethod<Void>("setCustomModelData", customModelData)
|
||||||
|
}
|
||||||
|
} catch (ignored: NoSuchMethodException) {
|
||||||
|
}
|
||||||
|
itemStack.itemMeta = itemMeta
|
||||||
|
finishing(itemStack)
|
||||||
|
return itemStack
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(material: Material) {
|
||||||
|
this.material = material
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过现有物品构建新的物品
|
||||||
|
* 读取基本信息
|
||||||
|
*/
|
||||||
|
constructor(item: ItemStack) {
|
||||||
|
material = item.type
|
||||||
|
amount = item.amount
|
||||||
|
damage = item.durability.toInt()
|
||||||
|
// 如果物品没有 ItemMeta 则不进行后续操作
|
||||||
|
val itemMeta = item.itemMeta ?: return
|
||||||
|
originMeta = itemMeta
|
||||||
|
name = itemMeta.displayName
|
||||||
|
lore += itemMeta.lore ?: emptyList()
|
||||||
|
flags += kotlin.runCatching { itemMeta.itemFlags.map { ItemFlag.valueOf(it.name) } }.getOrElse { emptyList() }
|
||||||
|
enchants += if (itemMeta is EnchantmentStorageMeta) {
|
||||||
|
itemMeta.storedEnchants
|
||||||
|
} else {
|
||||||
|
itemMeta.enchants
|
||||||
|
}
|
||||||
|
when (itemMeta) {
|
||||||
|
is LeatherArmorMeta -> {
|
||||||
|
color = itemMeta.color
|
||||||
|
}
|
||||||
|
|
||||||
|
is PotionMeta -> {
|
||||||
|
color = itemMeta.color
|
||||||
|
potions += itemMeta.customEffects
|
||||||
|
potionData = itemMeta.basePotionData
|
||||||
|
}
|
||||||
|
|
||||||
|
is SkullMeta -> {
|
||||||
|
if (itemMeta.owner != null) {
|
||||||
|
skullOwner = itemMeta.owner
|
||||||
|
}
|
||||||
|
skullTexture = getSkinValue(itemMeta)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
customModelData = itemMeta.getProperty<Int>("customModelData") ?: -1
|
||||||
|
} catch (ignored: NoSuchFieldException) {
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
isUnbreakable = itemMeta.isUnbreakable
|
||||||
|
} catch (ex: NoSuchMethodError) {
|
||||||
|
try {
|
||||||
|
isUnbreakable = itemMeta.invokeMethod<Any>("spigot")!!.invokeMethod<Boolean>("isUnbreakable") ?: false
|
||||||
|
} catch (ignored: NoSuchMethodException) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
if (itemMeta is SpawnEggMeta && itemMeta.spawnedType != null) {
|
||||||
|
spawnType = itemMeta.spawnedType
|
||||||
|
}
|
||||||
|
} catch (ignored: NoClassDefFoundError) {
|
||||||
|
} catch (ignored: UnsupportedOperationException) {
|
||||||
|
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
if (itemMeta is BannerMeta && itemMeta.patterns.isNotEmpty()) {
|
||||||
|
patterns += itemMeta.patterns
|
||||||
|
}
|
||||||
|
} catch (ignored: NoClassDefFoundError) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package com.github.xbaimiao.shoppro.util;
|
||||||
|
|
||||||
|
public enum ItemFlag {
|
||||||
|
HIDE_ENCHANTS,
|
||||||
|
HIDE_ATTRIBUTES,
|
||||||
|
HIDE_UNBREAKABLE,
|
||||||
|
HIDE_DESTROYS,
|
||||||
|
HIDE_PLACED_ON,
|
||||||
|
HIDE_POTION_EFFECTS,
|
||||||
|
HIDE_DYE
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user