fix and simplify xp handling

- Fix xp limit not being respected
- Fix player xp not being check causing error
This commit is contained in:
alexcrea 2026-06-19 20:29:10 +02:00
parent 9d616d2fd0
commit bc9cbe0b44
Signed by: alexcrea
GPG key ID: E346CD16413450E3
3 changed files with 40 additions and 27 deletions

View file

@ -1,6 +1,8 @@
package xyz.alexcrea.cuanvil.anvil
import io.delilaheve.util.ConfigOptions
import java.math.BigDecimal
import kotlin.math.min
import io.delilaheve.util.ConfigOptions.getMonetaryMultiplier as moneyMultiplier
open class AnvilCost {
@ -30,6 +32,21 @@ open class AnvilCost {
return generic + enchantment + repair + rename + lore + illegalPenalty + workPenalty + recipe
}
fun filteredXpCost(ignoreRules: Boolean = false): Int {
val original = asXpCost()
// Test repair cost limit
return if (
!ignoreRules &&
!ConfigOptions.doRemoveCostLimit &&
ConfigOptions.doCapCost
) {
min(original, ConfigOptions.maxAnvilCost)
} else {
original
}
}
open fun asMonetaryCost(): BigDecimal {
// multiply by per use type multipliers
return BigDecimal(generic)

View file

@ -270,13 +270,19 @@ class AnvilResultListener : Listener {
}
private fun tryRemoveCost(player: Player, cost: AnvilCost): Boolean {
private fun tryRemoveCost(player: Player, result: AnvilResult): Boolean {
if (player.gameMode == GameMode.CREATIVE) return true
val cost = result.cost
if (cost.isMonetary) {
val result = EconomyManager.economy!!.remove(player, cost.asMonetaryCost())
if (!result) return false
} else {
player.level -= cost.asXpCost()
val xpCost = cost.filteredXpCost()
if (xpCost > AnvilXpUtil.maximumXpCost(result.ignoreXpRules)) return false
if (player.level < xpCost) return false
player.level -= xpCost
}
return true
@ -308,7 +314,7 @@ class AnvilResultListener : Listener {
// If not creative middle click...
if (event.click != ClickType.MIDDLE) {
if (!tryRemoveCost(player, cost)) return false
if (!tryRemoveCost(player, result)) return false
// We remove what should be removed
if (leftItem != null) leftItem.amount -= leftRemoveCount

View file

@ -22,7 +22,6 @@ import xyz.alexcrea.cuanvil.dependency.economy.EconomyManager
import xyz.alexcrea.cuanvil.group.ConflictType
import xyz.alexcrea.cuanvil.util.AnvilTitleUtil
import xyz.alexcrea.cuanvil.util.dialog.AnvilRenameDialogUtil
import kotlin.math.min
object AnvilXpUtil {
@ -42,7 +41,15 @@ object AnvilXpUtil {
cost.isMonetary = true
setAnvilPrice(inventory, view, player, cost)
} else
setAnvilInvXp(inventory, view, player, cost.asXpCost(), ignoreRules)
setAnvilInvXp(inventory, view, player, cost.filteredXpCost(ignoreRules), ignoreRules)
}
fun maximumXpCost(ignoreRules: Boolean = false): Int {
return if (ConfigOptions.doRemoveCostLimit || ignoreRules) {
Int.MAX_VALUE
} else {
ConfigOptions.maxAnvilCost + 1
}
}
/**
@ -55,28 +62,11 @@ object AnvilXpUtil {
anvilCost: Int,
ignoreRules: Boolean = false
) {
// Test repair cost limit
val finalAnvilCost = if (
!ignoreRules &&
!ConfigOptions.doRemoveCostLimit &&
ConfigOptions.doCapCost
) {
min(anvilCost, ConfigOptions.maxAnvilCost)
} else {
anvilCost
}
val maximumRepairCost =
if (ConfigOptions.doRemoveCostLimit || ignoreRules) {
Int.MAX_VALUE
} else {
ConfigOptions.maxAnvilCost + 1
}
val maximumRepairCost = maximumXpCost(ignoreRules)
// Try first just in case another plugin, or the test need this
inventory.maximumRepairCost = maximumRepairCost
inventory.repairCost = finalAnvilCost
inventory.repairCost = anvilCost
// TODO for 2.x.x use anvil view & set directly there
/* Because Minecraft likes to have the final say in the repair cost displayed
@ -87,15 +77,15 @@ object AnvilXpUtil {
) {
// retry after a tick
inventory.maximumRepairCost = maximumRepairCost
inventory.repairCost = finalAnvilCost
inventory.repairCost = anvilCost
// TODO for 2.x.x use anvil view & set directly there
if (player !is Player) return@scheduleOnEntity
if (player.gameMode != GameMode.CREATIVE) {
val bypassToExpensive = (ConfigOptions.doReplaceTooExpensive) &&
(finalAnvilCost >= 40) &&
finalAnvilCost < inventory.maximumRepairCost
(anvilCost >= 40) &&
anvilCost < inventory.maximumRepairCost
DependencyManager.packetManager.setInstantBuild(player, bypassToExpensive)
}