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.ConfigOptions
|
||||||
import io.delilaheve.util.EnchantmentUtil.combineWith
|
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.canMergeWith
|
||||||
import io.delilaheve.util.ItemUtil.findEnchantments
|
import io.delilaheve.util.ItemUtil.findEnchantments
|
||||||
import io.delilaheve.util.ItemUtil.isBook
|
import io.delilaheve.util.ItemUtil.isBook
|
||||||
import io.delilaheve.util.ItemUtil.repairCost
|
|
||||||
import io.delilaheve.util.ItemUtil.repairFrom
|
import io.delilaheve.util.ItemUtil.repairFrom
|
||||||
import io.delilaheve.util.ItemUtil.setEnchantmentsUnsafe
|
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.Event
|
||||||
import org.bukkit.event.EventHandler
|
import org.bukkit.event.EventHandler
|
||||||
import org.bukkit.event.EventPriority.HIGHEST
|
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.AnvilInventory
|
||||||
import org.bukkit.inventory.InventoryView.Property.REPAIR_COST
|
import org.bukkit.inventory.InventoryView.Property.REPAIR_COST
|
||||||
import org.bukkit.inventory.ItemStack
|
import org.bukkit.inventory.ItemStack
|
||||||
|
import org.bukkit.inventory.meta.Repairable
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -43,20 +41,19 @@ class AnvilEventListener : Listener {
|
||||||
val first = inventory.getItem(ANVIL_INPUT_LEFT) ?: return
|
val first = inventory.getItem(ANVIL_INPUT_LEFT) ?: return
|
||||||
val second = inventory.getItem(ANVIL_INPUT_RIGHT) ?: return
|
val second = inventory.getItem(ANVIL_INPUT_RIGHT) ?: return
|
||||||
if (first.canMergeWith(second)) {
|
if (first.canMergeWith(second)) {
|
||||||
// Try to find player
|
// Should find player
|
||||||
val player = event.view.player
|
val player = event.view.player
|
||||||
|
|
||||||
val newEnchants = first.findEnchantments()
|
val newEnchants = first.findEnchantments()
|
||||||
.combineWith(second.findEnchantments(), first.type, player)
|
.combineWith(second.findEnchantments(), first.type, player)
|
||||||
val resultItem = first.clone()
|
val resultItem = first.clone()
|
||||||
resultItem.setEnchantmentsUnsafe(newEnchants)
|
resultItem.setEnchantmentsUnsafe(newEnchants)
|
||||||
var repairCost: Int
|
|
||||||
|
var anvilCost = calculateCost(first, second, resultItem, player.hasPermission(UnsafeEnchants.bypassFusePermission))
|
||||||
if (!first.isBook() && !second.isBook()) {
|
if (!first.isBook() && !second.isBook()) {
|
||||||
repairCost = first.repairCost + second.repairCost
|
|
||||||
// we only need to be concerned with repair when neither item is a book
|
// we only need to be concerned with repair when neither item is a book
|
||||||
resultItem.repairFrom(first, second)
|
val repaired = resultItem.repairFrom(first, second)
|
||||||
}else{
|
anvilCost += if(repaired) 2 else 0
|
||||||
repairCost = resultItem.repairCost
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test if nothing change and stop.
|
// Test if nothing change and stop.
|
||||||
|
|
@ -69,13 +66,13 @@ class AnvilEventListener : Listener {
|
||||||
resultItem.itemMeta?.let {
|
resultItem.itemMeta?.let {
|
||||||
if(!it.displayName.contentEquals(inventory.renameText)){
|
if(!it.displayName.contentEquals(inventory.renameText)){
|
||||||
it.setDisplayName(inventory.renameText)
|
it.setDisplayName(inventory.renameText)
|
||||||
resultItem.itemMeta = it
|
anvilCost += 1
|
||||||
repairCost += 1
|
|
||||||
}
|
}
|
||||||
|
resultItem.itemMeta = it
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ConfigOptions.limitRepairCost) {
|
if (ConfigOptions.limitRepairCost) {
|
||||||
repairCost = min(repairCost, ConfigOptions.limitRepairValue)
|
anvilCost = min(anvilCost, ConfigOptions.limitRepairValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
event.result = resultItem
|
event.result = resultItem
|
||||||
|
|
@ -90,8 +87,8 @@ class AnvilEventListener : Listener {
|
||||||
if (ConfigOptions.removeRepairLimit) {
|
if (ConfigOptions.removeRepairLimit) {
|
||||||
inventory.maximumRepairCost = Int.MAX_VALUE
|
inventory.maximumRepairCost = Int.MAX_VALUE
|
||||||
}
|
}
|
||||||
inventory.repairCost = repairCost
|
inventory.repairCost = anvilCost
|
||||||
event.view.setProperty(REPAIR_COST, repairCost)
|
event.view.setProperty(REPAIR_COST, anvilCost)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -113,4 +110,58 @@ class AnvilEventListener : Listener {
|
||||||
event.result = Event.Result.ALLOW
|
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
|
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
|
package io.delilaheve.util
|
||||||
|
|
||||||
import io.delilaheve.UnsafeEnchants
|
import io.delilaheve.UnsafeEnchants
|
||||||
import io.delilaheve.util.EnchantmentUtil.calculateValue
|
|
||||||
import org.bukkit.Material.BOOK
|
import org.bukkit.Material.BOOK
|
||||||
import org.bukkit.Material.ENCHANTED_BOOK
|
import org.bukkit.Material.ENCHANTED_BOOK
|
||||||
import org.bukkit.enchantments.Enchantment
|
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.Damageable
|
||||||
import org.bukkit.inventory.meta.EnchantmentStorageMeta
|
import org.bukkit.inventory.meta.EnchantmentStorageMeta
|
||||||
import org.bukkit.inventory.meta.ItemMeta
|
import org.bukkit.inventory.meta.ItemMeta
|
||||||
import org.bukkit.inventory.meta.Repairable
|
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -17,19 +15,6 @@ import kotlin.math.min
|
||||||
*/
|
*/
|
||||||
object ItemUtil {
|
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]
|
* 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
|
* Set this [ItemStack]s durability from a combination of the
|
||||||
* [first] and [second] item's durability values
|
* [first] and [second] item's durability values
|
||||||
|
* @return if the item was repaired
|
||||||
*/
|
*/
|
||||||
fun ItemStack.repairFrom(
|
fun ItemStack.repairFrom(
|
||||||
first: ItemStack,
|
first: ItemStack,
|
||||||
second: ItemStack
|
second: ItemStack
|
||||||
) {
|
): Boolean {
|
||||||
(itemMeta as? Damageable)?.let {
|
(itemMeta as? Damageable)?.let {
|
||||||
val durability = type.maxDurability.toInt()
|
val durability = type.maxDurability.toInt()
|
||||||
val firstDamage = (first.itemMeta as? Damageable)?.damage ?: 0
|
val firstDamage = (first.itemMeta as? Damageable)?.damage ?: 0
|
||||||
|
if( firstDamage == 0) return false
|
||||||
|
|
||||||
val firstDurability = durability - firstDamage
|
val firstDurability = durability - firstDamage
|
||||||
val secondDamage = (second.itemMeta as? Damageable)?.damage ?: 0
|
val secondDamage = (second.itemMeta as? Damageable)?.damage ?: 0
|
||||||
val secondDurability = durability - secondDamage
|
val secondDurability = durability - secondDamage
|
||||||
|
|
@ -108,7 +96,9 @@ object ItemUtil {
|
||||||
val newDurability = min(combinedDurability, durability)
|
val newDurability = min(combinedDurability, durability)
|
||||||
it.damage = durability - newDurability
|
it.damage = durability - newDurability
|
||||||
itemMeta = it as ItemMeta
|
itemMeta = it as ItemMeta
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -6,29 +6,43 @@ import java.util.EnumSet
|
||||||
abstract class AbstractMaterialGroup(private val name: String) {
|
abstract class AbstractMaterialGroup(private val name: String) {
|
||||||
protected val includedMaterial by lazy {createDefaultSet()}
|
protected val includedMaterial by lazy {createDefaultSet()}
|
||||||
|
|
||||||
// Get the group as a set
|
/**
|
||||||
|
* Get the group default set
|
||||||
|
*/
|
||||||
protected abstract fun createDefaultSet(): EnumSet<Material>
|
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 {
|
fun contain(mat : Material): Boolean {
|
||||||
return mat in includedMaterial
|
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
|
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)
|
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)
|
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 {
|
fun getName(): String {
|
||||||
return name
|
return name
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the group as a set
|
/**
|
||||||
|
* Get the group as a set
|
||||||
|
*/
|
||||||
fun getSet(): Set<Material> {
|
fun getSet(): Set<Material> {
|
||||||
return includedMaterial
|
return includedMaterial
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,7 @@
|
||||||
package xyz.alexcrea.group
|
package xyz.alexcrea.group
|
||||||
|
|
||||||
import io.delilaheve.util.ItemUtil.findEnchantments
|
|
||||||
import org.bukkit.Material
|
import org.bukkit.Material
|
||||||
import org.bukkit.enchantments.Enchantment
|
import org.bukkit.enchantments.Enchantment
|
||||||
import org.bukkit.inventory.ItemStack
|
|
||||||
|
|
||||||
class EnchantConflictGroup(private val cantConflict: AbstractMaterialGroup, private val minBeforeBlock: Int){
|
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){
|
fun addEnchantment(ench: Enchantment){
|
||||||
enchantments.add(ench)
|
enchantments.add(ench)
|
||||||
}
|
}
|
||||||
|
fun allowed(enchants: Set<Enchantment>, mat: Material) : Boolean{
|
||||||
fun allowed(item: ItemStack) : Boolean{
|
|
||||||
if(enchantments.size < minBeforeBlock){
|
if(enchantments.size < minBeforeBlock){
|
||||||
return true
|
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)){
|
if(cantConflict.contain(mat)){
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ import org.bukkit.NamespacedKey
|
||||||
import org.bukkit.configuration.ConfigurationSection
|
import org.bukkit.configuration.ConfigurationSection
|
||||||
import org.bukkit.configuration.file.YamlConfiguration
|
import org.bukkit.configuration.file.YamlConfiguration
|
||||||
import org.bukkit.enchantments.Enchantment
|
import org.bukkit.enchantments.Enchantment
|
||||||
import org.bukkit.inventory.ItemStack
|
|
||||||
import kotlin.collections.ArrayList
|
import kotlin.collections.ArrayList
|
||||||
|
|
||||||
class EnchantConflictManager {
|
class EnchantConflictManager {
|
||||||
|
|
@ -123,23 +122,6 @@ class EnchantConflictManager {
|
||||||
return group
|
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{
|
fun isConflicting(base: Set<Enchantment>,mat: Material, newEnchant: Enchantment): Boolean{
|
||||||
val conflictList = conflictMap[newEnchant] ?: return false
|
val conflictList = conflictMap[newEnchant] ?: return false
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue