diff --git a/src/main/kotlin/io/delilaheve/AnvilEventListener.kt b/src/main/kotlin/io/delilaheve/AnvilEventListener.kt index 12a9da5..ccb37d8 100644 --- a/src/main/kotlin/io/delilaheve/AnvilEventListener.kt +++ b/src/main/kotlin/io/delilaheve/AnvilEventListener.kt @@ -2,15 +2,12 @@ package io.delilaheve import io.delilaheve.util.ConfigOptions import io.delilaheve.util.EnchantmentUtil.combineWith -import io.delilaheve.util.EnchantmentUtil.hasConflicts +import io.delilaheve.util.EnchantmentUtil.enchantmentName import io.delilaheve.util.ItemUtil.canMergeWith import io.delilaheve.util.ItemUtil.findEnchantments import io.delilaheve.util.ItemUtil.isBook -import io.delilaheve.util.ItemUtil.repairCost import io.delilaheve.util.ItemUtil.repairFrom import io.delilaheve.util.ItemUtil.setEnchantmentsUnsafe -import org.bukkit.entity.HumanEntity -import org.bukkit.entity.Player import org.bukkit.event.Event import org.bukkit.event.EventHandler import org.bukkit.event.EventPriority.HIGHEST @@ -20,6 +17,7 @@ import org.bukkit.event.inventory.PrepareAnvilEvent import org.bukkit.inventory.AnvilInventory import org.bukkit.inventory.InventoryView.Property.REPAIR_COST import org.bukkit.inventory.ItemStack +import org.bukkit.inventory.meta.Repairable import kotlin.math.min /** @@ -43,20 +41,19 @@ class AnvilEventListener : Listener { val first = inventory.getItem(ANVIL_INPUT_LEFT) ?: return val second = inventory.getItem(ANVIL_INPUT_RIGHT) ?: return if (first.canMergeWith(second)) { - // Try to find player + // Should find player val player = event.view.player val newEnchants = first.findEnchantments() .combineWith(second.findEnchantments(), first.type, player) val resultItem = first.clone() resultItem.setEnchantmentsUnsafe(newEnchants) - var repairCost: Int + + var anvilCost = calculateCost(first, second, resultItem, player.hasPermission(UnsafeEnchants.bypassFusePermission)) if (!first.isBook() && !second.isBook()) { - repairCost = first.repairCost + second.repairCost // we only need to be concerned with repair when neither item is a book - resultItem.repairFrom(first, second) - }else{ - repairCost = resultItem.repairCost + val repaired = resultItem.repairFrom(first, second) + anvilCost += if(repaired) 2 else 0 } // Test if nothing change and stop. @@ -69,13 +66,13 @@ class AnvilEventListener : Listener { resultItem.itemMeta?.let { if(!it.displayName.contentEquals(inventory.renameText)){ it.setDisplayName(inventory.renameText) - resultItem.itemMeta = it - repairCost += 1 + anvilCost += 1 } + resultItem.itemMeta = it } if (ConfigOptions.limitRepairCost) { - repairCost = min(repairCost, ConfigOptions.limitRepairValue) + anvilCost = min(anvilCost, ConfigOptions.limitRepairValue) } event.result = resultItem @@ -90,8 +87,8 @@ class AnvilEventListener : Listener { if (ConfigOptions.removeRepairLimit) { inventory.maximumRepairCost = Int.MAX_VALUE } - inventory.repairCost = repairCost - event.view.setProperty(REPAIR_COST, repairCost) + inventory.repairCost = anvilCost + event.view.setProperty(REPAIR_COST, anvilCost) }) } } @@ -113,4 +110,58 @@ class AnvilEventListener : Listener { event.result = Event.Result.ALLOW } + /** + * Function to calculate most of the xp requirement for the anvil fuse + * Change result work penalty for future use + */ + private fun calculateCost(left: ItemStack, right: ItemStack, result: ItemStack, bypassFuse: Boolean): Int{ + // Extracted From https://minecraft.fandom.com/wiki/Anvil_mechanics#Enchantment_equation + // Calculate work penality + val leftPenality = (left.itemMeta as? Repairable)?.repairCost ?: 0 + val rightPenality = (right.itemMeta as? Repairable)?.repairCost ?: 0 + + // Calculate right value and illegal enchant penalty + var rightValue = 0 + var illegalPenalty = 0 + + val rightIsFormBook = right.isBook() + val resultEnchs = result.findEnchantments().keys + + for (enchantment in right.findEnchantments()) { + // count enchant as illegal enchant if it conflicts with another enchant or not in result + if(!bypassFuse && ( + (enchantment.key !in resultEnchs) || + UnsafeEnchants.conflictManager.isConflicting(resultEnchs,result.type,enchantment.key) + )){ + // There may an issue when illegal enchant are trying to combine + // at least that what I think, but can't find why + illegalPenalty++ + UnsafeEnchants.log("Conflict for ${enchantment.key.enchantmentName}, add 1 of value") + continue + } + + val enchantmentMultiplier = ConfigOptions.enchantmentValue(enchantment.key, rightIsFormBook) + val value = enchantment.value * enchantmentMultiplier + UnsafeEnchants.log("Value for ${enchantment.key.enchantmentName} level ${enchantment.value} is $value") + rightValue+=value + + } + + // Try to set work penality for the result item + result.itemMeta?.let { + (it as? Repairable)?.repairCost = leftPenality*2+1 + result.itemMeta = it + } + + UnsafeEnchants.log("Calculated cost: " + + "leftPenality: $leftPenality, " + + "rightPenality: $rightPenality, " + + "rightValue: $rightValue, " + + "illegalPenalty: $illegalPenalty," + + "result penality: ${(result.itemMeta as? Repairable)?.repairCost ?: "none"}") + + // We are missing [Renaming Cost] + [Refilling Durability] but it will be handled later + return rightValue + leftPenality + rightPenality + illegalPenalty + } + } diff --git a/src/main/kotlin/io/delilaheve/util/EnchantmentUtil.kt b/src/main/kotlin/io/delilaheve/util/EnchantmentUtil.kt index ebe962f..5c5f1a1 100644 --- a/src/main/kotlin/io/delilaheve/util/EnchantmentUtil.kt +++ b/src/main/kotlin/io/delilaheve/util/EnchantmentUtil.kt @@ -89,16 +89,4 @@ object EnchantmentUtil { return false } - /** - * Calculate the value of a set of enchantments - */ - fun Map.calculateValue( - fromBook: Boolean - ) = entries.sumOf { (enchantment, level) -> - val enchantmentMultiplier = ConfigOptions.enchantmentValue(enchantment, fromBook) - val value = level * enchantmentMultiplier - UnsafeEnchants.log("Value for ${enchantment.enchantmentName} is $value") - value - } - } diff --git a/src/main/kotlin/io/delilaheve/util/ItemUtil.kt b/src/main/kotlin/io/delilaheve/util/ItemUtil.kt index 3173ff9..1f8f9c8 100644 --- a/src/main/kotlin/io/delilaheve/util/ItemUtil.kt +++ b/src/main/kotlin/io/delilaheve/util/ItemUtil.kt @@ -1,7 +1,6 @@ package io.delilaheve.util import io.delilaheve.UnsafeEnchants -import io.delilaheve.util.EnchantmentUtil.calculateValue import org.bukkit.Material.BOOK import org.bukkit.Material.ENCHANTED_BOOK import org.bukkit.enchantments.Enchantment @@ -9,7 +8,6 @@ import org.bukkit.inventory.ItemStack import org.bukkit.inventory.meta.Damageable import org.bukkit.inventory.meta.EnchantmentStorageMeta import org.bukkit.inventory.meta.ItemMeta -import org.bukkit.inventory.meta.Repairable import kotlin.math.min /** @@ -17,19 +15,6 @@ import kotlin.math.min */ object ItemUtil { - /** - * Determine the value of an item for repair - * - * ToDo - use native repair cost - */ - val ItemStack.repairCost: Int - get() { - val nativeCost = (itemMeta as? Repairable)?.repairCost - val pluginCost = findEnchantments().calculateValue(isBook()) - UnsafeEnchants.log("Native Cost: $nativeCost; Plugin Cost: $pluginCost") - return nativeCost.takeIf { it != 0 } ?: pluginCost - } - /** * Check if this [ItemStack] is a [BOOK] or [ENCHANTED_BOOK] */ @@ -93,14 +78,17 @@ object ItemUtil { /** * Set this [ItemStack]s durability from a combination of the * [first] and [second] item's durability values + * @return if the item was repaired */ fun ItemStack.repairFrom( first: ItemStack, second: ItemStack - ) { + ): Boolean { (itemMeta as? Damageable)?.let { val durability = type.maxDurability.toInt() val firstDamage = (first.itemMeta as? Damageable)?.damage ?: 0 + if( firstDamage == 0) return false + val firstDurability = durability - firstDamage val secondDamage = (second.itemMeta as? Damageable)?.damage ?: 0 val secondDurability = durability - secondDamage @@ -108,7 +96,9 @@ object ItemUtil { val newDurability = min(combinedDurability, durability) it.damage = durability - newDurability itemMeta = it as ItemMeta + return true } + return false } /** diff --git a/src/main/kotlin/xyz/alexcrea/group/AbstractMaterialGroup.kt b/src/main/kotlin/xyz/alexcrea/group/AbstractMaterialGroup.kt index 07921b0..b253da9 100644 --- a/src/main/kotlin/xyz/alexcrea/group/AbstractMaterialGroup.kt +++ b/src/main/kotlin/xyz/alexcrea/group/AbstractMaterialGroup.kt @@ -6,29 +6,43 @@ import java.util.EnumSet abstract class AbstractMaterialGroup(private val name: String) { protected val includedMaterial by lazy {createDefaultSet()} - // Get the group as a set + /** + * Get the group default set + */ protected abstract fun createDefaultSet(): EnumSet - // Get if a material is allowed following the group policy + /** + * Get if a material is allowed following the group policy + */ fun contain(mat : Material): Boolean { return mat in includedMaterial } - // Get if a group is referenced by this + /** + * Get if a group is referenced by this: + */ abstract fun isReferencing(other : AbstractMaterialGroup): Boolean - // Push a material to this group to follow this group policy + /** + * Push a material to this group to follow this group policy + */ abstract fun addToPolicy(mat : Material) - // Push a group to this group to follow this group policy + /** + * Push a group to this group to follow this group policy + */ abstract fun addToPolicy(other : AbstractMaterialGroup) - // Get the group name in case something is wrong + /** + * Get the group name in case something is wrong + */ fun getName(): String { return name } - // Get the group as a set + /** + * Get the group as a set + */ fun getSet(): Set { return includedMaterial } diff --git a/src/main/kotlin/xyz/alexcrea/group/EnchantConflictGroup.kt b/src/main/kotlin/xyz/alexcrea/group/EnchantConflictGroup.kt index c4cded9..adef2fe 100644 --- a/src/main/kotlin/xyz/alexcrea/group/EnchantConflictGroup.kt +++ b/src/main/kotlin/xyz/alexcrea/group/EnchantConflictGroup.kt @@ -1,9 +1,7 @@ package xyz.alexcrea.group -import io.delilaheve.util.ItemUtil.findEnchantments import org.bukkit.Material import org.bukkit.enchantments.Enchantment -import org.bukkit.inventory.ItemStack class EnchantConflictGroup(private val cantConflict: AbstractMaterialGroup, private val minBeforeBlock: Int){ @@ -12,19 +10,11 @@ class EnchantConflictGroup(private val cantConflict: AbstractMaterialGroup, priv fun addEnchantment(ench: Enchantment){ enchantments.add(ench) } - - fun allowed(item: ItemStack) : Boolean{ + fun allowed(enchants: Set, mat: Material) : Boolean{ if(enchantments.size < minBeforeBlock){ return true } - if(cantConflict.contain(item.type)){ - return true - } - - return allowed(item.enchantments.keys, item.type) - } - fun allowed(enchants: Set, mat: Material) : Boolean{ if(cantConflict.contain(mat)){ return true } diff --git a/src/main/kotlin/xyz/alexcrea/group/EnchantConflictManager.kt b/src/main/kotlin/xyz/alexcrea/group/EnchantConflictManager.kt index 1e90544..40016ce 100644 --- a/src/main/kotlin/xyz/alexcrea/group/EnchantConflictManager.kt +++ b/src/main/kotlin/xyz/alexcrea/group/EnchantConflictManager.kt @@ -6,7 +6,6 @@ import org.bukkit.NamespacedKey import org.bukkit.configuration.ConfigurationSection import org.bukkit.configuration.file.YamlConfiguration import org.bukkit.enchantments.Enchantment -import org.bukkit.inventory.ItemStack import kotlin.collections.ArrayList class EnchantConflictManager { @@ -123,23 +122,6 @@ class EnchantConflictManager { return group } - fun isConflicting(item: ItemStack): Boolean{ - val toTest = HashSet() - item.enchantments.forEach{enchant -> - val conflictList = conflictMap[enchant.key] - if(conflictList != null){ - toTest.addAll(conflictList) - } - } - - for (conflict in toTest) { - if(!conflict.allowed(item)) { - return true - } - } - return false - } - fun isConflicting(base: Set,mat: Material, newEnchant: Enchantment): Boolean{ val conflictList = conflictMap[newEnchant] ?: return false