数据库添加缓存 优化性能

This commit is contained in:
xbaimiao
2024-04-08 10:57:45 +08:00
parent 652193fcf6
commit c6de9c32c4
15 changed files with 559 additions and 72 deletions
+3
View File
@@ -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
View File
@@ -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() override fun releasePlayerData(player: Player) {
itemKeyLine eq item.key.toString() playerAlreadyDataCache.remove(player.name)
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()
}
} }
} }
@@ -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
@@ -19,14 +18,14 @@ import pers.neige.neigeitems.manager.ItemManager
class NeigeItem( class NeigeItem(
private val neigeItem: ItemGenerator, private val neigeItem: ItemGenerator,
itemSetting: ItemSetting, itemSetting: ItemSetting,
private val neigeId :String private val neigeId: String
) : VanillaShopItem(itemSetting) { ) : VanillaShopItem(itemSetting) {
override val material: Material override val material: Material
get() = neigeItem.staticItemStack.type get() = neigeItem.staticItemStack.type
override fun vanillaItem(player: Player): ItemStack { override fun vanillaItem(player: Player): ItemStack {
return ItemManager.getItemStack(neigeId,player)!! return ItemManager.getItemStack(neigeId, player)!!
} }
override fun equal(itemStack: ItemStack): Boolean { override fun equal(itemStack: ItemStack): Boolean {
@@ -42,8 +41,8 @@ class NeigeItem(
error("NeigeItems Plugin not found") error("NeigeItems Plugin not found")
} }
val neigeId = section.getString("material")!!.substring(prefix.length + 1) val neigeId = section.getString("material")!!.substring(prefix.length + 1)
val item = ItemManager.getItem(neigeId)?: error("NeigeItems $neigeId not found") val item = ItemManager.getItem(neigeId) ?: error("NeigeItems $neigeId not found")
return NeigeItem(item, section.toItemSetting(char, shop),neigeId) return NeigeItem(item, section.toItemSetting(char, shop), neigeId)
} }
override fun parseToMaterial(section: ConfigurationSection): Material { override fun parseToMaterial(section: ConfigurationSection): Material {
@@ -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
}