Better work penalty (#52)

- Created per use type work penalty (rename/merge/repair)
- auto migration of previous work penalty system. 
- new exclusive work penalty per use type
This commit is contained in:
alexcrea 2025-02-12 22:40:23 +01:00 committed by GitHub
parent ea19ffc4a1
commit c5c32ce386
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 494 additions and 218 deletions

View file

@ -4,7 +4,10 @@ import io.delilaheve.CustomAnvil
import io.delilaheve.util.EnchantmentUtil.enchantmentName
import xyz.alexcrea.cuanvil.config.ConfigHolder
import xyz.alexcrea.cuanvil.config.WorkPenaltyType
import xyz.alexcrea.cuanvil.config.WorkPenaltyType.WorkPenaltyPart
import xyz.alexcrea.cuanvil.enchant.CAEnchantment
import xyz.alexcrea.cuanvil.util.AnvilUseType
import java.util.EnumMap
/**
* Config option accessors
@ -34,7 +37,11 @@ object ConfigOptions {
const val PERMISSION_NEEDED_FOR_COLOR = "permission_needed_for_color"
const val USE_OF_COLOR_COST = "use_of_color_cost"
const val WORK_PENALTY_TYPE = "work_penalty_type"
const val WORK_PENALTY_ROOT = "work_penalty"
const val WORK_PENALTY_INCREASE = "shared_increase"
const val WORK_PENALTY_ADDITIVE = "shared_additive"
const val EXCLUSIVE_WORK_PENALTY_INCREASE = "exclusive_increase"
const val EXCLUSIVE_WORK_PENALTY_ADDITIVE = "exclusive_additive"
const val DEFAULT_LIMIT_PATH = "default_limit"
@ -113,7 +120,7 @@ object ConfigOptions {
private const val DEFAULT_ENCHANT_VALUE = 0
// Default max before merge disabled (negative mean enabled)
const val DEFAULT_MAX_BEFORE_MERGE_DISABLED = -1;
const val DEFAULT_MAX_BEFORE_MERGE_DISABLED = -1
// -------------
// Get methods
@ -257,16 +264,38 @@ object ConfigOptions {
}
/**
* How many xp should use of color should cost
* How work penalties should work
*/
val workPenaltyType: WorkPenaltyType
get() {
return WorkPenaltyType.fromString(
ConfigHolder.DEFAULT_CONFIG
.config
.getString(WORK_PENALTY_TYPE));
val penaltyMap = EnumMap<AnvilUseType, WorkPenaltyPart>(AnvilUseType::class.java)
for (type in AnvilUseType.entries) {
penaltyMap[type] = workPenaltyPart(type)
}
return WorkPenaltyType(penaltyMap)
}
/**
* How work penalty should work
*/
fun workPenaltyPart(type: AnvilUseType): WorkPenaltyPart {
val config = ConfigHolder.DEFAULT_CONFIG.config
val path = WORK_PENALTY_ROOT + "." + type.typeName
// Find values
val defaultPenalty = type.defaultPenalty
val section = config.getConfigurationSection(path) ?: return defaultPenalty
val penaltyIncrease = section.getBoolean(WORK_PENALTY_INCREASE, defaultPenalty.penaltyIncrease)
val penaltyAdditive = section.getBoolean(WORK_PENALTY_ADDITIVE, defaultPenalty.penaltyAdditive)
val exclusivePenaltyIncrease = section.getBoolean(EXCLUSIVE_WORK_PENALTY_INCREASE, defaultPenalty.exclusivePenaltyIncrease)
val exclusivePenaltyAdditive = section.getBoolean(EXCLUSIVE_WORK_PENALTY_ADDITIVE, defaultPenalty.exclusivePenaltyAdditive)
return WorkPenaltyPart(penaltyIncrease, penaltyAdditive, exclusivePenaltyIncrease, exclusivePenaltyAdditive)
}
/**
* Default enchantment limit
*/
@ -303,11 +332,11 @@ object ConfigOptions {
fun enchantLimit(enchantment: CAEnchantment): Int {
// Test namespace
var limit = enchantLimit(enchantment.key.toString())
if(limit != null) return limit;
if(limit != null) return limit
// Test legacy (name only)
limit = enchantLimit(enchantment.enchantmentName)
if(limit != null) return limit;
if(limit != null) return limit
// get default (and test old legacy if present)
return getDefaultLevel(enchantment.enchantmentName)
@ -348,11 +377,11 @@ object ConfigOptions {
): Int {
// Test namespace
var limit = enchantmentValue(enchantment.key.toString(), isFromBook)
if(limit != null) return limit;
if(limit != null) return limit
// Test legacy (name only)
limit = enchantmentValue(enchantment.enchantmentName, isFromBook)
if(limit != null) return limit;
if(limit != null) return limit
// get default (and test old legacy if present)
return getDefaultValue(enchantment, isFromBook)

View file

@ -23,8 +23,6 @@ import xyz.alexcrea.cuanvil.util.AnvilUseType
import xyz.alexcrea.cuanvil.util.AnvilXpUtil
import xyz.alexcrea.cuanvil.util.CustomRecipeUtil
import xyz.alexcrea.cuanvil.util.UnitRepairUtil.getRepair
import java.util.logging.Level
/**
* Listener for anvil events
*/
@ -93,7 +91,12 @@ class PrepareAnvilListener : Listener {
event.result = resultItem
if(DependencyManager.tryTreatAnvilResult(event, resultItem)) return true
AnvilXpUtil.setAnvilInvXp(inventory, event.view, player, recipe.xpCostPerCraft * amount, true)
// Maybe add an option on custom craft to ignore/not ignore penalty ??
var xpCost = recipe.xpCostPerCraft * amount
xpCost += AnvilXpUtil.calculatePenalty(first, null, resultItem, AnvilUseType.CUSTOM_CRAFT)
AnvilXpUtil.setAnvilInvXp(inventory, event.view, player, xpCost, true)
return true
}

View file

@ -1,9 +1,29 @@
package xyz.alexcrea.cuanvil.util
enum class AnvilUseType {
import org.bukkit.Material
import xyz.alexcrea.cuanvil.config.WorkPenaltyType.WorkPenaltyPart
RENAME_ONLY,
MERGE,
UNIT_REPAIR
enum class AnvilUseType(val typeName: String,
val defaultPenalty: WorkPenaltyPart,
val displayName: String, val displayMat: Material
) {
RENAME_ONLY("rename_only",
WorkPenaltyPart(false, true),
"Rename Only", Material.NAME_TAG
),
MERGE("merge",
WorkPenaltyPart(true, true),
"Merge", Material.ANVIL
),
UNIT_REPAIR("unit_repair",
WorkPenaltyPart(true, true),
"Unit Repair", Material.DIAMOND
),
CUSTOM_CRAFT("custom_craft",
WorkPenaltyPart(false, false),
"Custom Craft", Material.CRAFTING_TABLE
),
;
}

View file

@ -6,6 +6,7 @@ import io.delilaheve.util.EnchantmentUtil.enchantmentName
import io.delilaheve.util.ItemUtil.findEnchantments
import io.delilaheve.util.ItemUtil.isEnchantedBook
import org.bukkit.GameMode
import org.bukkit.NamespacedKey
import org.bukkit.entity.HumanEntity
import org.bukkit.entity.Player
import org.bukkit.inventory.AnvilInventory
@ -13,6 +14,7 @@ import org.bukkit.inventory.InventoryView
import org.bukkit.inventory.InventoryView.Property.REPAIR_COST
import org.bukkit.inventory.ItemStack
import org.bukkit.inventory.meta.Repairable
import org.bukkit.persistence.PersistentDataType
import xyz.alexcrea.cuanvil.config.ConfigHolder
import xyz.alexcrea.cuanvil.dependency.DependencyManager
import xyz.alexcrea.cuanvil.group.ConflictType
@ -20,6 +22,8 @@ import kotlin.math.min
object AnvilXpUtil {
const val EXCLUSIVE_PENALTY_PREFIX = "repair_cost"
/**
* Display xp needed for the work on the anvil inventory
*/
@ -34,7 +38,8 @@ object AnvilXpUtil {
val finalAnvilCost = if (
!ignoreRules &&
!ConfigOptions.doRemoveCostLimit &&
ConfigOptions.doCapCost) {
ConfigOptions.doCapCost
) {
min(anvilCost, ConfigOptions.maxAnvilCost)
} else {
anvilCost
@ -47,17 +52,18 @@ object AnvilXpUtil {
CustomAnvil.instance, player,
Runnable {
inventory.maximumRepairCost =
if (ConfigOptions.doRemoveCostLimit || ignoreRules)
{ Int.MAX_VALUE }
else
{ ConfigOptions.maxAnvilCost + 1 }
if (ConfigOptions.doRemoveCostLimit || ignoreRules) {
Int.MAX_VALUE
} else {
ConfigOptions.maxAnvilCost + 1
}
inventory.repairCost = finalAnvilCost
view.setProperty(REPAIR_COST, finalAnvilCost)
player.openInventory.setProperty(REPAIR_COST, finalAnvilCost)
if(player is Player){
if(player.gameMode != GameMode.CREATIVE ){
if (player is Player) {
if (player.gameMode != GameMode.CREATIVE) {
val bypassToExpensive = (ConfigOptions.doReplaceTooExpensive) &&
(finalAnvilCost >= 40) &&
finalAnvilCost < inventory.maximumRepairCost
@ -77,22 +83,26 @@ object AnvilXpUtil {
fun calculatePenalty(left: ItemStack, right: ItemStack?, result: ItemStack, useType: AnvilUseType): Int {
// Extracted From https://minecraft.fandom.com/wiki/Anvil_mechanics#Enchantment_equation
// Calculate work penalty
val penaltyType = ConfigOptions.workPenaltyType
val penaltyType = ConfigOptions.workPenaltyPart(useType)
val leftPenalty = (left.itemMeta as? Repairable)?.repairCost ?: 0
val leftExclusivePenalty = findExclusivePenalty(left, useType)
val rightPenalty =
if (right == null) 0
else (right.itemMeta as? Repairable)?.repairCost ?: 0
val rightExclusivePenalty = findExclusivePenalty(right, useType)
// Increase penalty on fusing or unit repair
if(penaltyType.isPenaltyIncreasing && (right != null || AnvilUseType.UNIT_REPAIR == useType)){
if (penaltyType.penaltyIncrease) {
result.itemMeta?.let {
(it as? Repairable)?.repairCost = leftPenalty * 2 + 1
result.itemMeta = it
}
}
if (penaltyType.exclusivePenaltyIncrease) {
val resultPenalty = leftExclusivePenalty * 2 + 1
setExclusivePenalty(result, resultPenalty, useType)
}
CustomAnvil.log(
"Calculated penalty: " +
@ -101,9 +111,40 @@ object AnvilXpUtil {
"result penalty: ${(result.itemMeta as? Repairable)?.repairCost ?: "none"}"
)
if(!penaltyType.isPenaltyAdditive) return 0
var resultSum = 0
if (penaltyType.penaltyAdditive) {
resultSum += leftPenalty + rightPenalty
}
if (penaltyType.exclusivePenaltyAdditive) {
resultSum += leftExclusivePenalty + rightExclusivePenalty
}
return leftPenalty + rightPenalty
return resultSum
}
private fun setExclusivePenalty(
result: ItemStack,
resultPenalty: Int,
useType: AnvilUseType
) {
val tagPath = EXCLUSIVE_PENALTY_PREFIX + "_" + useType.typeName
val key = NamespacedKey(CustomAnvil.instance, tagPath)
val meta = result.itemMeta!!
meta.persistentDataContainer.set(key, PersistentDataType.INTEGER, resultPenalty)
result.itemMeta = meta
}
private fun findExclusivePenalty(
left: ItemStack?,
useType: AnvilUseType
): Int {
if (left == null) return 0
val tagPath = EXCLUSIVE_PENALTY_PREFIX + "_" + useType.typeName
val key = NamespacedKey(CustomAnvil.instance, tagPath)
val meta = left.itemMeta!!
return meta.persistentDataContainer.get(key, PersistentDataType.INTEGER) ?: return 0
}
/**