mirror of
https://github.com/alexcrea/CustomAnvil.git
synced 2026-06-23 08:14:00 +02:00
Fix most issues with xp cost
This commit is contained in:
parent
0bb496938c
commit
87b8738c6e
6 changed files with 94 additions and 79 deletions
|
|
@ -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
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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<Material>
|
||||
|
||||
// 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<Material> {
|
||||
return includedMaterial
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<Enchantment>, 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<Enchantment>, mat: Material) : Boolean{
|
||||
if(cantConflict.contain(mat)){
|
||||
return true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<EnchantConflictGroup>()
|
||||
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<Enchantment>,mat: Material, newEnchant: Enchantment): Boolean{
|
||||
val conflictList = conflictMap[newEnchant] ?: return false
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue