From 96b0d87b79e7043eacec429860afd4f05ebf8ebf Mon Sep 17 00:00:00 2001 From: iGabyTM Date: Mon, 11 Mar 2024 22:10:30 +0200 Subject: [PATCH] fix: potion handling for crate reloaded serialization --- .../minecraft/guihelper/functions/Numbers.kt | 24 ++- .../CrateReloadedImplementation.kt | 142 ++++++++++-------- .../serializers/EssentialsXImplementation.kt | 5 +- 3 files changed, 103 insertions(+), 68 deletions(-) diff --git a/src/main/kotlin/me/gabytm/minecraft/guihelper/functions/Numbers.kt b/src/main/kotlin/me/gabytm/minecraft/guihelper/functions/Numbers.kt index e39c61f..421276c 100644 --- a/src/main/kotlin/me/gabytm/minecraft/guihelper/functions/Numbers.kt +++ b/src/main/kotlin/me/gabytm/minecraft/guihelper/functions/Numbers.kt @@ -19,6 +19,8 @@ package me.gabytm.minecraft.guihelper.functions +import net.kyori.adventure.util.Ticks + /** * Run code only if the number is greater than 0 * @param function function to run @@ -37,4 +39,24 @@ fun Short.ifNotZero(function: (Short) -> Unit) { if (this > 0) { function(this) } -} \ No newline at end of file +} + +/** + * Convert from seconds to ticks + */ +fun Int.secondsToTicks(): Int = this * Ticks.TICKS_PER_SECOND + +/** + * Convert from seconds to ticks + */ +fun Long.secondsToTicks(): Long = this * Ticks.TICKS_PER_SECOND + +/** + * Convert from ticks to seconds + */ +fun Int.ticksToSeconds(): Int = this / Ticks.TICKS_PER_SECOND + +/** + * Convert from ticks to seconds + */ +fun Long.ticksToSeconds(): Long = this / Ticks.TICKS_PER_SECOND diff --git a/src/main/kotlin/me/gabytm/minecraft/guihelper/item/serialization/serializers/CrateReloadedImplementation.kt b/src/main/kotlin/me/gabytm/minecraft/guihelper/item/serialization/serializers/CrateReloadedImplementation.kt index f9ebd26..d971c99 100644 --- a/src/main/kotlin/me/gabytm/minecraft/guihelper/item/serialization/serializers/CrateReloadedImplementation.kt +++ b/src/main/kotlin/me/gabytm/minecraft/guihelper/item/serialization/serializers/CrateReloadedImplementation.kt @@ -26,81 +26,93 @@ import org.bukkit.inventory.meta.ItemMeta import org.bukkit.inventory.meta.LeatherArmorMeta import org.bukkit.inventory.meta.PotionMeta import org.bukkit.potion.Potion -import org.bukkit.potion.PotionData @Suppress("DEPRECATION") class CrateReloadedImplementation : ItemSerializer() { - private val rgbFormat: (String) -> String = { "{#$it}" } - - override fun serialize(item: ItemStack): String { - checkItem(item) - - return buildString { - append(item.type.name) - item.durability.ifNotZero { append(':').append(it) } - append(' ').append(item.amount) - - val meta = item.meta ?: return@buildString - - if (meta.hasDisplayName()) { - append(" name:").append(item.displayName(rgbFormat).removeSpace()) - } - - if (meta.hasLore()) { - append(" lore:").append(item.lore().joinToString("|").removeSpace()) - } - - item.isUnbreakable.takeIf { it }?.let { append(" unbreakable:true") } - - item.enchants { enchantment, level -> "${enchantment.name.lowercase()}:$level" } - .ifNotEmpty { append(it.joinToString(" ", " ")) } - - meta.itemFlags.ifNotEmpty { append(it.joinToString(",", " flag:")) } - appendMetaSpecificValues(this, item, meta) - } - } - - private fun appendMetaSpecificValues(builder: StringBuilder, item: ItemStack, meta: ItemMeta) { - when { - item.isLeatherArmor -> { - (meta as LeatherArmorMeta).color.ifNotDefault { builder.append(" color:").append(it.asString()) } - } - item.isPlayerHead -> { - builder.append(" skull:").append(item.skullTexture) - } - item.isPotion -> { - if (ServerVersion.IS_ANCIENT) { - builder.appendPotion(Potion.fromItemStack(item)) - } else { - builder.appendPotion((meta as PotionMeta).basePotionData, item.isSplashPotion) - } - } - } - } + private val rgbFormat: (String) -> String = { "{#$it}" } + + override fun serialize(item: ItemStack): String { + checkItem(item) + + return buildString { + append(item.type.name) + item.durability.ifNotZero { append(':').append(it) } + append(' ').append(item.amount) + + val meta = item.meta ?: return@buildString + + if (meta.hasDisplayName()) { + append(" name:").append(item.displayName(rgbFormat).removeSpace()) + } + + if (meta.hasLore()) { + append(" lore:").append(item.lore().joinToString("|").removeSpace()) + } + + item.customModelData.ifNotZero { append("custommodeldata:$it") } + item.isUnbreakable.takeIf { it }?.let { append(" unbreakable:true") } + + item.enchants { enchantment, level -> "${enchantment.name}:$level" } + .ifNotEmpty { append(it.joinToString(" ", " ")) } + + meta.itemFlags.ifNotEmpty { append(it.joinToString(",", " flag:")) } + appendMetaSpecificValues(this, item, meta) + } + } + + private fun appendMetaSpecificValues(builder: StringBuilder, item: ItemStack, meta: ItemMeta) { + when { + item.isLeatherArmor -> { + (meta as LeatherArmorMeta).color.ifNotDefault { builder.append(" color:").append(it.asString()) } + } + + item.isPlayerHead -> { + builder.append(" skull:").append(item.skullTexture) + } + + item.isPotion -> { + if (ServerVersion.IS_ANCIENT) { + builder.appendPotion(Potion.fromItemStack(item)) + } else { + builder.appendPotion(meta as PotionMeta, item.isSplashPotion) + } + } + } + } } private fun StringBuilder.appendPotion(potion: Potion) { - if (potion.type.effectType == null) { - return - } - - this.append(" effect:").append(potion.type.effectType?.name) - .append(" power:").append(potion.level) - .append(" duration:").append(potion.effects.first().duration) - .append(" splash:").append(potion.isSplash) + if (potion.type.effectType == null) { + return + } + + this.append(" effect:").append(potion.type.effectType?.name) + .append(" power:").append(potion.level) + .append(" duration:").append(potion.effects.first().duration) + .append(" splash:").append(potion.isSplash) } -private fun StringBuilder.appendPotion(potion: PotionData, splash: Boolean) { - if (potion.type.effectType == null) { - return - } - - this.append(" effect:").append(potion.type.effectType?.name) - .append(" power:").append(if (potion.isUpgraded) 2 else 1) - .append(" duration:1") // TODO: Find a way to get the duration of a potion - .append(" splash:").append(splash) +private fun StringBuilder.appendPotion(potionMeta: PotionMeta, splash: Boolean) { + val basePotionData = potionMeta.basePotionData + + if (basePotionData.type.effectType != null) { + append(" effect:").append(basePotionData.type.effectType?.name) + append(" power:").append(if (basePotionData.isUpgraded) 2 else 1) + } + + if (potionMeta.hasCustomEffects()) { + potionMeta.customEffects.forEach { customEffect -> + append(" effect:").append(customEffect.type.name) + customEffect.amplifier.ifNotZero { append(" power:").append(it) } + append(" duration:").append(customEffect.duration.ticksToSeconds()) // The time is in ticks and CR uses seconds + } + } + + if (splash) { + append(" splash:true") + } } private fun String.removeSpace() = this.replace(' ', '_') diff --git a/src/main/kotlin/me/gabytm/minecraft/guihelper/item/serialization/serializers/EssentialsXImplementation.kt b/src/main/kotlin/me/gabytm/minecraft/guihelper/item/serialization/serializers/EssentialsXImplementation.kt index e76a1dc..e112277 100644 --- a/src/main/kotlin/me/gabytm/minecraft/guihelper/item/serialization/serializers/EssentialsXImplementation.kt +++ b/src/main/kotlin/me/gabytm/minecraft/guihelper/item/serialization/serializers/EssentialsXImplementation.kt @@ -25,6 +25,7 @@ import me.gabytm.minecraft.guihelper.functions.* import me.gabytm.minecraft.guihelper.item.ItemsManager import me.gabytm.minecraft.guihelper.item.heads.providers.HeadIdProvider import me.gabytm.minecraft.guihelper.util.ServerVersion +import net.kyori.adventure.util.Ticks import org.bukkit.Color import org.bukkit.FireworkEffect import org.bukkit.Material @@ -140,7 +141,7 @@ private fun StringBuilder.appendPotion(potion: Potion) { private fun StringBuilder.appendPotion(potion: PotionData, splash: Boolean) { with (potion) { - appendPotion(splash, type.name, if (isExtended) 1 else 0, 20) + appendPotion(splash, type.name, if (isExtended) 1 else 0, Ticks.TICKS_PER_SECOND) } } @@ -148,7 +149,7 @@ private fun StringBuilder.appendPotion(splash: Boolean, effect: String, amplifie this.append(" splash:").append(splash) .append(" effect:").append(effect.lowercase()) .append(" power:").append(amplifier) - .append(" duration:").append(duration / 20) + .append(" duration:").append(duration.ticksToSeconds()) } private fun StringBuilder.appendShieldOrBanner(item: ItemStack) {