custom craft logic deduplication

This commit is contained in:
alexcrea 2026-06-02 16:18:16 +02:00
parent 106bc724a1
commit edceba879f
Signed by: alexcrea
GPG key ID: E346CD16413450E3
5 changed files with 51 additions and 40 deletions

View file

@ -19,6 +19,7 @@ import org.bukkit.persistence.PersistentDataType
import xyz.alexcrea.cuanvil.dependency.DependencyManager import xyz.alexcrea.cuanvil.dependency.DependencyManager
import xyz.alexcrea.cuanvil.dialog.AnvilRenameDialog import xyz.alexcrea.cuanvil.dialog.AnvilRenameDialog
import xyz.alexcrea.cuanvil.enchant.CAEnchantment import xyz.alexcrea.cuanvil.enchant.CAEnchantment
import xyz.alexcrea.cuanvil.recipe.AnvilCustomRecipe
import xyz.alexcrea.cuanvil.util.CasedStringUtil import xyz.alexcrea.cuanvil.util.CasedStringUtil
import xyz.alexcrea.cuanvil.util.CustomRecipeUtil import xyz.alexcrea.cuanvil.util.CustomRecipeUtil
import xyz.alexcrea.cuanvil.util.MaterialUtil.isAir import xyz.alexcrea.cuanvil.util.MaterialUtil.isAir
@ -28,6 +29,7 @@ import xyz.alexcrea.cuanvil.util.anvil.AnvilColorUtil
import xyz.alexcrea.cuanvil.util.anvil.AnvilLoreEditUtil import xyz.alexcrea.cuanvil.util.anvil.AnvilLoreEditUtil
import xyz.alexcrea.cuanvil.util.anvil.AnvilXpUtil import xyz.alexcrea.cuanvil.util.anvil.AnvilXpUtil
import xyz.alexcrea.cuanvil.util.anvil.AnvilXpUtil.AnvilCost import xyz.alexcrea.cuanvil.util.anvil.AnvilXpUtil.AnvilCost
import xyz.alexcrea.cuanvil.util.anvil.AnvilXpUtil.CustomCraftCost
import xyz.alexcrea.cuanvil.util.config.LoreEditType import xyz.alexcrea.cuanvil.util.config.LoreEditType
import xyz.alexcrea.cuanvil.util.dialog.AnvilRenameDialogUtil import xyz.alexcrea.cuanvil.util.dialog.AnvilRenameDialogUtil
@ -65,6 +67,22 @@ object AnvilMergeLogic {
} }
} }
class CustomCraftResult: AnvilResult {
companion object {
val EMPTY = CustomCraftResult(null, CustomCraftCost(0), 0, null)
}
val customCraftCost: CustomCraftCost
val amount: Int
val recipe: AnvilCustomRecipe?
constructor(item: ItemStack?, cost: CustomCraftCost,
amount: Int, recipe: AnvilCustomRecipe?) : super(item, cost, true) {
this.customCraftCost = cost
this.amount = amount
this.recipe = recipe
}
}
class LoreEditResult: AnvilResult { class LoreEditResult: AnvilResult {
companion object { companion object {
@ -211,10 +229,10 @@ object AnvilMergeLogic {
fun testCustomRecipe( fun testCustomRecipe(
player: Player, player: Player,
first: ItemStack, second: ItemStack? first: ItemStack, second: ItemStack?
): AnvilResult { ): CustomCraftResult {
val recipe = CustomRecipeUtil.getCustomRecipe(first, second) val recipe = CustomRecipeUtil.getCustomRecipe(first, second)
CustomAnvil.verboseLog("custom recipe not null? ${recipe != null}") CustomAnvil.verboseLog("custom recipe not null? ${recipe != null}")
if (recipe == null) return AnvilResult.EMPTY if (recipe == null) return CustomCraftResult.EMPTY
val amount = CustomRecipeUtil.getCustomRecipeAmount(recipe, first, second) val amount = CustomRecipeUtil.getCustomRecipeAmount(recipe, first, second)
@ -224,12 +242,13 @@ object AnvilMergeLogic {
// Maybe add an option on custom craft to ignore/not ignore penalty ?? // Maybe add an option on custom craft to ignore/not ignore penalty ??
val xpCost = recipe.determineCost(amount, first, resultItem) val xpCost = recipe.determineCost(amount, first, resultItem)
val cost = AnvilCost() val cost = CustomCraftCost(xpCost)
// This is for displayed cost
cost.recipe = if (recipe.removeExactLinearXp) AnvilXpUtil.calculateMinimumLevelForXp(xpCost) cost.recipe = if (recipe.removeExactLinearXp) AnvilXpUtil.calculateMinimumLevelForXp(xpCost)
else AnvilXpUtil.calculateLevelForXp(xpCost) else AnvilXpUtil.calculateLevelForXp(xpCost)
val result = DependencyManager.tryTreatAnvilResult(resultItem, AnvilUseType.CUSTOM_CRAFT, cost) val result = DependencyManager.tryTreatAnvilResult(resultItem, AnvilUseType.CUSTOM_CRAFT, cost)
return AnvilResult(result, cost, true) return CustomCraftResult(result, cost, amount, recipe)
} }
fun testUnitRepair( fun testUnitRepair(

View file

@ -17,7 +17,9 @@ import org.bukkit.inventory.ItemStack
import org.bukkit.inventory.meta.BookMeta import org.bukkit.inventory.meta.BookMeta
import xyz.alexcrea.cuanvil.anvil.AnvilMergeLogic import xyz.alexcrea.cuanvil.anvil.AnvilMergeLogic
import xyz.alexcrea.cuanvil.anvil.AnvilMergeLogic.AnvilResult import xyz.alexcrea.cuanvil.anvil.AnvilMergeLogic.AnvilResult
import xyz.alexcrea.cuanvil.anvil.AnvilMergeLogic.CustomCraftResult
import xyz.alexcrea.cuanvil.anvil.AnvilMergeLogic.LoreEditResult import xyz.alexcrea.cuanvil.anvil.AnvilMergeLogic.LoreEditResult
import xyz.alexcrea.cuanvil.anvil.AnvilMergeLogic.UnitRepairResult
import xyz.alexcrea.cuanvil.dependency.DependencyManager import xyz.alexcrea.cuanvil.dependency.DependencyManager
import xyz.alexcrea.cuanvil.dependency.economy.EconomyManager import xyz.alexcrea.cuanvil.dependency.economy.EconomyManager
import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil.setComponentDisplayName import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil.setComponentDisplayName
@ -27,7 +29,6 @@ import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener.Companion.ANVIL_OUTPUT
import xyz.alexcrea.cuanvil.recipe.AnvilCustomRecipe import xyz.alexcrea.cuanvil.recipe.AnvilCustomRecipe
import xyz.alexcrea.cuanvil.util.CustomRecipeUtil import xyz.alexcrea.cuanvil.util.CustomRecipeUtil
import xyz.alexcrea.cuanvil.util.MiniMessageUtil import xyz.alexcrea.cuanvil.util.MiniMessageUtil
import xyz.alexcrea.cuanvil.util.UnitRepairUtil.getRepair
import xyz.alexcrea.cuanvil.util.anvil.AnvilLoreEditUtil import xyz.alexcrea.cuanvil.util.anvil.AnvilLoreEditUtil
import xyz.alexcrea.cuanvil.util.anvil.AnvilXpUtil import xyz.alexcrea.cuanvil.util.anvil.AnvilXpUtil
import xyz.alexcrea.cuanvil.util.anvil.AnvilXpUtil.AnvilCost import xyz.alexcrea.cuanvil.util.anvil.AnvilXpUtil.AnvilCost
@ -73,12 +74,11 @@ class AnvilResultListener : Listener {
} }
// Test custom recipe // Test custom recipe
val recipe = CustomRecipeUtil.getCustomRecipe(leftItem, rightItem) val customRecipeResult = AnvilMergeLogic.testCustomRecipe(player, leftItem, rightItem)
if (recipe != null) { if (!customRecipeResult.isEmpty()) {
event.result = Event.Result.ALLOW
onCustomCraft( onCustomCraft(
event, recipe, player, event, player, inventory,
leftItem, rightItem, output, inventory leftItem, rightItem, customRecipeResult
) )
return return
} }
@ -103,11 +103,13 @@ class AnvilResultListener : Listener {
} }
// Unit repair // Unit repair
val unitRepairResult = leftItem.getRepair(rightItem) // Maybe this should be handlded "above" and like prepare result val unitRepairResult = AnvilMergeLogic.testUnitRepair(
if (unitRepairResult != null) { inventory, player,
leftItem, rightItem)
if (unitRepairResult.isEmpty()) {
onUnitRepairExtract( onUnitRepairExtract(
leftItem, rightItem, rightItem, event, player, inventory,
unitRepairResult, event, player, inventory unitRepairResult
) )
return return
} }
@ -125,19 +127,14 @@ class AnvilResultListener : Listener {
private fun onCustomCraft( private fun onCustomCraft(
event: InventoryClickEvent, event: InventoryClickEvent,
recipe: AnvilCustomRecipe,
player: Player, player: Player,
inventory: AnvilInventory,
leftItem: ItemStack, leftItem: ItemStack,
rightItem: ItemStack?, rightItem: ItemStack?,
output: ItemStack, result: CustomCraftResult,
inventory: AnvilInventory
) { ) {
event.result = Event.Result.DENY val recipe = result.recipe!!
val xpCost = result.customCraftCost.rawCost
if (recipe.leftItem == null) return // in case it changed
val amount = CustomRecipeUtil.getCustomRecipeAmount(recipe, leftItem, rightItem)
val xpCost = recipe.determineCost(amount, leftItem, output)
val finalCost = val finalCost =
if (recipe.removeExactLinearXp) xpCost if (recipe.removeExactLinearXp) xpCost
else AnvilXpUtil.calculateLevelForXp(xpCost) else AnvilXpUtil.calculateLevelForXp(xpCost)
@ -166,7 +163,7 @@ class AnvilResultListener : Listener {
player, player,
leftItem, leftItem,
rightItem, rightItem,
amount, result.amount,
finalCost, finalCost,
recipe.removeExactLinearXp recipe.removeExactLinearXp
) )
@ -174,9 +171,9 @@ class AnvilResultListener : Listener {
// Finally, we add the item to the player // Finally, we add the item to the player
if (slotDestination.type == SlotType.CURSOR) { if (slotDestination.type == SlotType.CURSOR) {
player.setItemOnCursor(output) player.setItemOnCursor(result.item)
} else {// We assume SlotType == SlotType.INVENTORY } else {// We assume SlotType == SlotType.INVENTORY
player.inventory.setItem(slotDestination.slot, output) player.inventory.setItem(slotDestination.slot, result.item)
} }
} }
@ -335,20 +332,13 @@ class AnvilResultListener : Listener {
} }
private fun onUnitRepairExtract( private fun onUnitRepairExtract(
leftItem: ItemStack,
rightItem: ItemStack, rightItem: ItemStack,
unitRepairResult: Double,
event: InventoryClickEvent, event: InventoryClickEvent,
player: Player, player: Player,
inventory: AnvilInventory inventory: AnvilInventory,
result: UnitRepairResult,
) { ) {
val result = AnvilMergeLogic.testUnitRepair(inventory, player, // We give the item manually
leftItem.clone(), rightItem,
unitRepairResult)
if(result.isEmpty()) return
// And then we give the item manually
extractAnvilResult( extractAnvilResult(
event, player, inventory, event, player, inventory,
null, 0, null, 0,

View file

@ -104,7 +104,7 @@ class PrepareAnvilListener : Listener {
return AnvilResult.EMPTY return AnvilResult.EMPTY
// Test custom recipe // Test custom recipe
var result = testCustomRecipe(player, first, second) var result: AnvilResult = testCustomRecipe(player, first, second)
if (!result.isEmpty()) if (!result.isEmpty())
return result return result

View file

@ -29,7 +29,7 @@ object AnvilXpUtil {
const val EXCLUSIVE_PENALTY_PREFIX = "repair_cost" const val EXCLUSIVE_PENALTY_PREFIX = "repair_cost"
class AnvilCost { open class AnvilCost {
private val isAlone: Boolean private val isAlone: Boolean
var valid = true // Get set as invalid if cost can be satisfied var valid = true // Get set as invalid if cost can be satisfied
var isMonetary = false var isMonetary = false
@ -71,6 +71,8 @@ object AnvilXpUtil {
} }
} }
class CustomCraftCost(val rawCost: Int): AnvilCost()
/** /**
* Display the required cost (either as xp or as ) * Display the required cost (either as xp or as )
*/ */

View file

@ -195,7 +195,7 @@ public class AnvilFuseTestUtil {
simulateClick(anvil, player, data.expectedResult()); simulateClick(anvil, player, data.expectedResult());
// Should have similated the click // Should have simulated the click
assertEqual(data.leftItem(), anvil.getFirstItem()); assertEqual(data.leftItem(), anvil.getFirstItem());
assertEqual(data.rightItem(), anvil.getSecondItem()); assertEqual(data.rightItem(), anvil.getSecondItem());
assertEqual(data.resultSlotItem(), anvil.getResult()); assertEqual(data.resultSlotItem(), anvil.getResult());
@ -260,7 +260,7 @@ public class AnvilFuseTestUtil {
} }
public static boolean isAir(@Nullable ItemStack item) { public static boolean isAir(@Nullable ItemStack item) {
return item == null || item.isEmpty(); return item == null || item.isEmpty() || item.getAmount() == 0;
} }
public static void assertPriceEqual(Integer expectedPrice, int price) { public static void assertPriceEqual(Integer expectedPrice, int price) {