fix durability repair and item naming

This commit is contained in:
DelilahEve 2022-08-24 11:49:29 -04:00
parent 745ebcde29
commit af99913eae
7 changed files with 97 additions and 29 deletions

View file

@ -1,22 +1,23 @@
package io.delilaheve
import io.delilaheve.util.ConfigOptions
import io.delilaheve.util.EnchantmentUtil.calculateValue
import io.delilaheve.util.EnchantmentUtil.combineWith
import io.delilaheve.util.EnchantmentUtil.hasConflicts
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.Material
import org.bukkit.entity.Player
import org.bukkit.event.Event
import org.bukkit.event.EventHandler
import org.bukkit.event.EventPriority.HIGHEST
import org.bukkit.event.Listener
import org.bukkit.event.inventory.InventoryClickEvent
import org.bukkit.event.inventory.PrepareAnvilEvent
import org.bukkit.inventory.AnvilInventory
import org.bukkit.inventory.InventoryView
import org.bukkit.inventory.InventoryView.Property.REPAIR_COST
import org.bukkit.permissions.Permission
import kotlin.math.min
@ -26,8 +27,6 @@ import kotlin.math.min
class AnvilEventListener : Listener {
companion object {
// Vanilla repair cost limit
private const val VANILLA_REPAIR_LIMIT = 40
// Anvil's output slot
private const val ANVIL_OUTPUT_SLOT = 2
}
@ -39,34 +38,42 @@ class AnvilEventListener : Listener {
/**
* Event handler logic for when an anvil contains items to be combined
*/
@EventHandler
@EventHandler(priority = HIGHEST)
fun anvilCombineCheck(event: PrepareAnvilEvent) {
val inventory = event.inventory
val first = inventory.getItem(0) ?: return
val second = inventory.getItem(1) ?: return
if (first.canMergeWith(second)) {
val firstEnchants = first.findEnchantments().toMutableMap()
val secondEnchants = second.findEnchantments().toMutableMap()
if (ConfigOptions.removeRepairLimit) {
inventory.maximumRepairCost = Int.MAX_VALUE
}
val newEnchants = firstEnchants.combineWith(secondEnchants)
val enchantsString = newEnchants.map { "${it.key.key} ${it.value}" }.joinToString(", ")
UnsafeEnchants.log("New enchants for this item: $enchantsString")
val newEnchants = first.findEnchantments()
.combineWith(second.findEnchantments())
val resultItem = first.clone()
resultItem.itemMeta?.let {
it.setDisplayName(inventory.renameText)
resultItem.itemMeta = it
}
resultItem.setEnchantmentsUnsafe(newEnchants)
val firstValue = firstEnchants.calculateValue(first.isBook())
val secondValue = secondEnchants.calculateValue(second.isBook())
var repairCost = firstValue + secondValue
if (first.isBook() && second.isBook()) {
repairCost = firstEnchants.values.sum() + secondEnchants.values.sum()
if (!first.isBook() && !second.isBook()) {
// we only need to be concerned with repair when neither item is a book
resultItem.repairFrom(first, second)
}
var repairCost = first.repairCost + second.repairCost
if (ConfigOptions.limitRepairCost) {
repairCost = min(repairCost, VANILLA_REPAIR_LIMIT)
repairCost = min(repairCost, ConfigOptions.limitRepairValue)
}
inventory.repairCost = repairCost
event.view.setProperty(InventoryView.Property.REPAIR_COST, repairCost)
event.result = resultItem
/* Because Minecraft likes to have the final say in the repair cost displayed
* we need to wait for the event to end before overriding it, this ensures that
* we have the final say in the process. */
UnsafeEnchants.instance
.server
.scheduler
.runTask(UnsafeEnchants.instance, Runnable {
if (ConfigOptions.removeRepairLimit) {
inventory.maximumRepairCost = Int.MAX_VALUE
}
inventory.repairCost = repairCost
event.view.setProperty(REPAIR_COST, repairCost)
})
}
}
@ -80,8 +87,6 @@ class AnvilEventListener : Listener {
val output = inventory.getItem(ANVIL_OUTPUT_SLOT) ?: return
if (output.findEnchantments().hasConflicts() && !player.hasPermission(requirePermission)) { return }
if (event.rawSlot != ANVIL_OUTPUT_SLOT) { return }
if (output.type == Material.AIR) { return }
if (player.level < inventory.repairCost) { return }
event.result = Event.Result.ALLOW
}

View file

@ -15,6 +15,8 @@ object ConfigOptions {
private const val ALLOW_UNSAFE_PATH = "allow_unsafe"
// Path for limiting repair cost
private const val LIMIT_REPAIR_COST = "limit_repair_cost"
// Path for repair value limit
private const val LIMIT_REPAIR_VALUE = "limit_repair_value"
// Path for removing repair cost limits
private const val REMOVE_REPAIR_LIMIT = "remove_repair_limit"
// Root path for enchantment limits
@ -33,6 +35,10 @@ object ConfigOptions {
private const val DEFAULT_ALLOW_UNSAFE = true
// Default value for limiting repair cost
private const val DEFAULT_LIMIT_REPAIR = true
// Default value for repair cost limit
private const val DEFAULT_LIMIT_REPAIR_VALUE = 39
// Valid range for repair cost limit
private val REPAIR_LIMIT_RANGE = 1..39
// Default for removing repair cost limits
private const val DEFAULT_REMOVE_LIMIT = false
// Valid range for an enchantment limit
@ -72,6 +78,18 @@ object ConfigOptions {
.getBoolean(LIMIT_REPAIR_COST, DEFAULT_LIMIT_REPAIR)
}
/**
* Value to limit repair costs to
*/
val limitRepairValue: Int
get() {
return UnsafeEnchants.instance
.config
.getInt(LIMIT_REPAIR_VALUE, DEFAULT_LIMIT_REPAIR_VALUE)
.takeIf { it in REPAIR_LIMIT_RANGE }
?: DEFAULT_LIMIT_REPAIR_VALUE
}
/**
* Whether to remove repair cost limit
*/

View file

@ -19,8 +19,8 @@ object EnchantmentUtil {
/**
* Combine 2 sets of enchantments according to our configuration
*/
fun MutableMap<Enchantment, Int>.combineWith(
other: MutableMap<Enchantment, Int>
fun Map<Enchantment, Int>.combineWith(
other: Map<Enchantment, Int>
) = mutableMapOf<Enchantment, Int>().apply {
putAll(this@combineWith)
other.forEach { (enchantment, level) ->

View file

@ -1,17 +1,36 @@
package io.delilaheve.util
import io.delilaheve.UnsafeEnchants
import io.delilaheve.util.EnchantmentUtil.calculateValue
import io.delilaheve.util.ItemUtil.isBook
import org.bukkit.Material.BOOK
import org.bukkit.Material.ENCHANTED_BOOK
import org.bukkit.enchantments.Enchantment
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
/**
* Item manipulation utilities
*/
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]
*/
@ -72,6 +91,25 @@ object ItemUtil {
}
}
/**
* Set this [ItemStack]s durability from a combination of the
* [first] and [second] item's durability values
*/
fun ItemStack.repairFrom(
first: ItemStack,
second: ItemStack
) {
(itemMeta as? Damageable)?.let {
val maxDurability = type.maxDurability.toInt()
val firstDurability = (first.itemMeta as? Damageable)?.damage ?: 0
val secondDurability = (second.itemMeta as? Damageable)?.damage ?: 0
var newDurability = firstDurability + secondDurability
newDurability = min(maxDurability, newDurability)
it.damage = newDurability
itemMeta = it as ItemMeta
}
}
/**
* Check that this [ItemStack] can merge with the [other]
*