Fix most issues with xp cost

This commit is contained in:
alexcrea 2024-02-03 22:24:33 +01:00
parent 0bb496938c
commit 87b8738c6e
6 changed files with 94 additions and 79 deletions

View file

@ -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
}
}

View file

@ -89,16 +89,4 @@ object EnchantmentUtil {
return false
}
/**
* Calculate the value of a set of enchantments
*/
fun Map<Enchantment, Int>.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
}
}

View file

@ -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
}
/**