From a646d5ab02c940382fca605401b752565e205ad7 Mon Sep 17 00:00:00 2001 From: alexcrea Date: Sun, 7 Apr 2024 04:20:07 +0200 Subject: [PATCH] Fix multiple issue about custom recipes - Gui item not using a clone of the result item. - Every recipe item being removed even if there was leftover --- .../gui/config/settings/ItemSettingGui.java | 10 ++- .../io/delilaheve/AnvilEventListener.kt | 84 ++++++++++++++++--- .../cuanvil/recipe/AnvilCustomRecipe.kt | 30 +++++-- 3 files changed, 105 insertions(+), 19 deletions(-) diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/ItemSettingGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/ItemSettingGui.java index 1c5e758..8f44e5e 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/ItemSettingGui.java +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/settings/ItemSettingGui.java @@ -115,7 +115,7 @@ public class ItemSettingGui extends AbstractSettingGui { // Get displayed value for this config. ItemStack displayedItem; if(this.now != null){ - displayedItem = this.now; + displayedItem = this.now.clone(); }else{ displayedItem = new ItemStack(Material.BARRIER); ItemMeta valueMeta = displayedItem.getItemMeta(); @@ -161,7 +161,7 @@ public class ItemSettingGui extends AbstractSettingGui { @Override public boolean onSave() { - holder.config.getConfig().set(holder.configPath, now); + holder.config.getConfig().set(holder.configPath, this.now); MetricsUtil.INSTANCE.notifyChange(this.holder.config, this.holder.configPath); if (GuiSharedConstant.TEMPORARY_DO_SAVE_TO_DISK_EVERY_CHANGE) { @@ -172,7 +172,11 @@ public class ItemSettingGui extends AbstractSettingGui { @Override public boolean hadChange() { - return now != before; + if(now == null) { + return before != null; + } + + return !now.equals(before); } /** diff --git a/src/main/kotlin/io/delilaheve/AnvilEventListener.kt b/src/main/kotlin/io/delilaheve/AnvilEventListener.kt index 0718d81..dca6723 100644 --- a/src/main/kotlin/io/delilaheve/AnvilEventListener.kt +++ b/src/main/kotlin/io/delilaheve/AnvilEventListener.kt @@ -11,7 +11,6 @@ import io.delilaheve.util.ItemUtil.setEnchantmentsUnsafe import io.delilaheve.util.ItemUtil.unitRepair import org.bukkit.GameMode import org.bukkit.Material -import org.bukkit.entity.Item import org.bukkit.entity.Player import org.bukkit.event.Event import org.bukkit.event.EventHandler @@ -62,16 +61,12 @@ class AnvilEventListener : Listener { // Test custom recipe val recipe = getCustomRecipe(first, second) + CustomAnvil.verboseLog("custom recipe not null? ${recipe != null}") if(recipe != null){ val amount = getCustomRecipeAmount(recipe, first, second) - val resultItem: ItemStack - if(amount <= 1){ - resultItem = recipe.resultItem!! - }else{ - resultItem = recipe.resultItem!!.clone() - resultItem.amount *= amount - } + val resultItem: ItemStack = recipe.resultItem!!.clone() + resultItem.amount *= amount event.result = resultItem handleAnvilXp(inventory, event, recipe.xpCostPerCraft * amount, true) @@ -190,10 +185,13 @@ class AnvilEventListener : Listener { val leftItem = inventory.getItem(ANVIL_INPUT_LEFT) ?: return val rightItem = inventory.getItem(ANVIL_INPUT_RIGHT) - // Test custom craft + // Test custom recipe val recipe = getCustomRecipe(leftItem, rightItem) if(recipe != null){ event.result = Event.Result.ALLOW + onCustomCraft( + event, recipe, player, + leftItem, rightItem, output, inventory) return } @@ -227,6 +225,69 @@ class AnvilEventListener : Listener { } } + private fun onCustomCraft(event: InventoryClickEvent, + recipe: AnvilCustomRecipe, + player: Player, + leftItem: ItemStack, + rightItem: ItemStack?, + output: ItemStack, + inventory: AnvilInventory) { + event.result = Event.Result.DENY + + if(recipe.leftItem == null) return // in case it changed + + val amount = getCustomRecipeAmount(recipe, leftItem, rightItem) + val xpCost = amount * recipe.xpCostPerCraft + + if ((player.gameMode != GameMode.CREATIVE) && (player.level < xpCost)) return + + // We give the item manually + // But first we check if we should give the item + val slotDestination = getActionSlot(event, player) + if (slotDestination.type == SlotType.NO_SLOT) return + + // If not creative middle click... + if (event.click != ClickType.MIDDLE) { + // We remove what should be removed + leftItem.amount -= amount * recipe.leftItem!!.amount + inventory.setItem(ANVIL_INPUT_LEFT, leftItem) + + if(rightItem != null){ + if(recipe.rightItem == null) return // in case it changed + + rightItem.amount -= amount * recipe.rightItem!!.amount + inventory.setItem(ANVIL_INPUT_RIGHT, rightItem) + } + player.level -= amount + + // Then we try to find the new values for the anvil + val newAmount = getCustomRecipeAmount(recipe, leftItem, rightItem) + + if(newAmount <= 0){ + inventory.setItem(ANVIL_OUTPUT_SLOT, null) + }else{ + val resultItem: ItemStack = recipe.resultItem!!.clone() + resultItem.amount *= newAmount + + val newXp = newAmount * newAmount + + inventory.repairCost = newXp + event.view.setProperty(REPAIR_COST, newXp) + + inventory.setItem(ANVIL_OUTPUT_SLOT, resultItem) + } + } + + // Finally, we add the item to the player + if (slotDestination.type == SlotType.CURSOR) { + player.setItemOnCursor(output) + } else {// We assume SlotType == SlotType.INVENTORY + player.inventory.setItem(slotDestination.slot, output) + } + + + } + private fun onUnitRepairExtract( leftItem: ItemStack, rightItem: ItemStack, @@ -405,6 +466,7 @@ class AnvilEventListener : Listener { val recipeList = ConfigHolder.CUSTOM_RECIPE_HOLDER.recipeManager.recipeByMat[leftItem.type] ?: return null + CustomAnvil.verboseLog("Testing " + recipeList.size+" recipe...") for (recipe in recipeList) { if(recipe.testItem(leftItem, rightItem)){ return recipe @@ -425,7 +487,9 @@ class AnvilEventListener : Listener { val resultItem = recipe.resultItem!! // we know exist as the recipe was returned to us val maxResultAmount = resultItem.type.maxStackSize/resultItem.amount val maxLeftAmount = leftItem.amount/recipe.leftItem!!.amount - val maxRightAmount = if(rightItem == null){ 1 } else{ rightItem.amount/recipe.rightItem!!.amount } + val maxRightAmount = if(rightItem == null){ maxLeftAmount } else{ rightItem.amount/recipe.rightItem!!.amount } + + CustomAnvil.verboseLog("resultItem: $resultItem, maxResultAmount: $maxResultAmount, maxLeftAmount: $maxLeftAmount, maxRightAmount: $maxRightAmount") min(min(maxResultAmount, maxLeftAmount), maxRightAmount) } diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/recipe/AnvilCustomRecipe.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/recipe/AnvilCustomRecipe.kt index 41b7b09..fbd2866 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/recipe/AnvilCustomRecipe.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/recipe/AnvilCustomRecipe.kt @@ -1,5 +1,6 @@ package xyz.alexcrea.cuanvil.recipe +import io.delilaheve.CustomAnvil import org.bukkit.configuration.ConfigurationSection import org.bukkit.inventory.ItemStack import xyz.alexcrea.cuanvil.config.ConfigHolder @@ -105,7 +106,7 @@ class AnvilCustomRecipe( ) // Update items - this.leftItem = ConfigHolder.CUSTOM_RECIPE_HOLDER.config.getItemStack( + val leftItem = ConfigHolder.CUSTOM_RECIPE_HOLDER.config.getItemStack( "$name.$LEFT_ITEM_CONFIG", DEFAULT_LEFT_ITEM_CONFIG ) @@ -119,27 +120,44 @@ class AnvilCustomRecipe( "$name.$RESULT_ITEM_CONFIG", DEFAULT_RESULT_ITEM_CONFIG ) + + // Update material map + ConfigHolder.CUSTOM_RECIPE_HOLDER.recipeManager.cleanSetLeftItem(this, leftItem) + } fun testItem(item1: ItemStack, item2: ItemStack?): Boolean { + CustomAnvil.verboseLog("Testing $name $leftItem") // We assume this function can be call only if leftItem != null // Test is valid if(!validate()) return false + val leftSimilar = leftItem!!.isSimilar(item1) + CustomAnvil.verboseLog("Validated test !") + // test of left item - if(!leftItem!!.isSimilar(item1)) return false // Test similar + if(!leftSimilar) return false // Test similar if(exactCount){ if((leftItem!!.amount != item1.amount)) return false // test exact amount }else if(item1.amount < leftItem!!.amount) return false // test if it has at least the amount we ask + CustomAnvil.verboseLog("Left item passed !") + // we don't know if right item can be if(rightItem == null){ // null test if(item2 != null) return false - }else if(!rightItem!!.isSimilar(item2)) return false // test if similar when not null - else if(exactCount) { - if (rightItem!!.amount != item2!!.amount) return false // test exact amount - }else if(item2!!.amount < rightItem!!.amount) return false // test if it has at least the amount we ask + }else { + val rightSimilar = rightItem!!.isSimilar(item2) + CustomAnvil.verboseLog("Right similar: $rightSimilar") + if(!rightSimilar) return false // test if similar when not null + + if(exactCount) { + if (rightItem!!.amount != item2!!.amount) return false // test exact amount + }else if(item2!!.amount < rightItem!!.amount) return false // test if it has at least the amount we ask + } + + CustomAnvil.verboseLog("Right item passed !") return true }