From fa28c1647289c890ad9f8e7ae7ef8e6c3bc01154 Mon Sep 17 00:00:00 2001 From: Gavin Lambert Date: Mon, 18 Nov 2024 01:00:52 +1300 Subject: [PATCH] Improve non-tool catalyst handling (#10392) When improving recipes, don't forget other important recipe details such as secondary outputs. Now supports catalyst "tool" items (that appear as both input and output) that aren't damageable. For example, this should recognise that it only needs 1 template when crafting multiple netherite tools/armour. --- .../api/crafting/RecipeStorage.java | 32 +++++++++++-------- .../AbstractCraftingBuildingModule.java | 8 ++++- .../AbstractCraftingProductionResolver.java | 8 ++--- 3 files changed, 28 insertions(+), 20 deletions(-) diff --git a/src/main/java/com/minecolonies/api/crafting/RecipeStorage.java b/src/main/java/com/minecolonies/api/crafting/RecipeStorage.java index 1091a28bd2e..8c473239177 100755 --- a/src/main/java/com/minecolonies/api/crafting/RecipeStorage.java +++ b/src/main/java/com/minecolonies/api/crafting/RecipeStorage.java @@ -207,7 +207,7 @@ private void processInputsAndTools(@Nullable final List secOutputs) for (ItemStack result : this.secondaryOutputs) { - if (ItemStackUtils.compareItemStacksIgnoreStackSize(inputItem.getItemStack(), result, false, true) && result.isDamageableItem()) + if (ItemStackUtils.compareItemStacksIgnoreStackSize(inputItem.getItemStack(), result, false, true)) { inputItem = new ItemStorage(inputItem.getItemStack(), inputItem.getAmount(), true, inputItem.shouldIgnoreNBTValue); this.tools.add(result); @@ -525,25 +525,31 @@ public List fullfillRecipeAndCopy(final LootParams context, final Lis for (final IItemHandler handler : handlers) { + boolean isTool = ItemStackUtils.compareItemStackListIgnoreStackSize(tools, stack, false, !storage.ignoreNBT()); int slotOfStack = - InventoryUtils.findFirstSlotInItemHandlerNotEmptyWith(handler, itemStack -> !ItemStackUtils.isEmpty(itemStack) && ItemStackUtils.compareItemStacksIgnoreStackSize(itemStack, stack, false, !storage.ignoreNBT())); + InventoryUtils.findFirstSlotInItemHandlerNotEmptyWith(handler, itemStack -> + ItemStackUtils.compareItemStacksIgnoreStackSize(itemStack, stack, false, !storage.ignoreNBT()) && + (!isTool || !stack.isDamageableItem() || ItemStackUtils.getDurability(itemStack) > 0)); while (slotOfStack != -1 && amountNeeded > 0) { - if(citizen != null && ItemStackUtils.compareItemStackListIgnoreStackSize(tools, stack, false, !storage.ignoreNBT()) && ItemStackUtils.getDurability(handler.getStackInSlot(slotOfStack)) > 0 ) + if(citizen != null && isTool) { - ItemStack toDamage = handler.extractItem(slotOfStack,1, false); - if (!ItemStackUtils.isEmpty(toDamage)) + if (stack.isDamageableItem()) { - // The 4 parameter inner call from forge is for adding a callback to alter the damage caused, - // but unlike its description does not actually damage the item(despite the same function name). So used to just calculate the damage. - toDamage.hurtAndBreak(toDamage.getItem().damageItem(stack, 1, citizen, item -> item.broadcastBreakEvent(InteractionHand.MAIN_HAND)), citizen, item -> item.broadcastBreakEvent(InteractionHand.MAIN_HAND)); + ItemStack toDamage = handler.extractItem(slotOfStack, 1, false); + if (!ItemStackUtils.isEmpty(toDamage)) + { + // The 4 parameter inner call from forge is for adding a callback to alter the damage caused, + // but unlike its description does not actually damage the item(despite the same function name). So used to just calculate the damage. + toDamage.hurtAndBreak(toDamage.getItem().damageItem(stack, 1, citizen, item -> item.broadcastBreakEvent(InteractionHand.MAIN_HAND)), citizen, item -> item.broadcastBreakEvent(InteractionHand.MAIN_HAND)); + } + if (!ItemStackUtils.isEmpty(toDamage)) + { + handler.insertItem(slotOfStack, toDamage, false); + } } - if (!ItemStackUtils.isEmpty(toDamage)) - { - handler.insertItem(slotOfStack, toDamage, false); - } - amountNeeded -= stack.getCount(); + --amountNeeded; } else { diff --git a/src/main/java/com/minecolonies/core/colony/buildings/modules/AbstractCraftingBuildingModule.java b/src/main/java/com/minecolonies/core/colony/buildings/modules/AbstractCraftingBuildingModule.java index 44dc9047eab..dd4dd752630 100644 --- a/src/main/java/com/minecolonies/core/colony/buildings/modules/AbstractCraftingBuildingModule.java +++ b/src/main/java/com/minecolonies/core/colony/buildings/modules/AbstractCraftingBuildingModule.java @@ -612,7 +612,13 @@ public void improveRecipe(IRecipeStorage recipe, int count, ICitizenData citizen newRecipe, 1, recipe.getPrimaryOutput(), - Blocks.AIR); + recipe.getIntermediate(), + null, // improved recipes have no source (expected by checkForWorkerSpecificRecipes) + recipe.getRecipeType().getId(), + recipe.getAlternateOutputs(), + recipe.getSecondaryOutputs(), + recipe.getLootTable(), + recipe.getRequiredTool()); final IToken token = IColonyManager.getInstance().getRecipeManager().checkOrAddRecipe(storage); if (isRecipeCompatibleWithCraftingModule(token)) diff --git a/src/main/java/com/minecolonies/core/colony/requestsystem/resolvers/core/AbstractCraftingProductionResolver.java b/src/main/java/com/minecolonies/core/colony/requestsystem/resolvers/core/AbstractCraftingProductionResolver.java index b43ccabdb93..f4a24285e38 100755 --- a/src/main/java/com/minecolonies/core/colony/requestsystem/resolvers/core/AbstractCraftingProductionResolver.java +++ b/src/main/java/com/minecolonies/core/colony/requestsystem/resolvers/core/AbstractCraftingProductionResolver.java @@ -15,7 +15,6 @@ import com.minecolonies.api.crafting.IRecipeStorage; import com.minecolonies.api.crafting.ItemStorage; import com.minecolonies.api.util.CraftingUtils; -import com.minecolonies.api.util.InventoryUtils; import com.minecolonies.api.util.ItemStackUtils; import com.minecolonies.core.colony.buildings.AbstractBuilding; import com.minecolonies.core.colony.requestsystem.requesters.IBuildingBasedRequester; @@ -173,11 +172,8 @@ protected List> createRequestsForRecipe( } else if(!storage.getCraftingTools().isEmpty() && ItemStackUtils.compareItemStackListIgnoreStackSize(storage.getCraftingTools(), craftingHelperStack, false, true)) { - if(InventoryUtils.getItemCountInProvider(building, item -> ItemStackUtils.compareItemStacksIgnoreStackSize(item, craftingHelperStack, false, true)) <= ingredient.getAmount()) - { - int requiredForDurability = (int) Math.ceil((double) count / ingredient.getRemainingDurablityValue()); - materialRequests.add(createNewRequestForStack(manager, craftingHelperStack, requiredForDurability , requiredForDurability, false)); - } + int requiredForDurability = craftingHelperStack.isDamageableItem() ? (int) Math.ceil((double) count / ingredient.getRemainingDurablityValue()) : ingredient.getAmount(); + materialRequests.add(createNewRequestForStack(manager, craftingHelperStack, requiredForDurability, requiredForDurability, false)); } else if (!ItemStackUtils.isEmpty(container) && ItemStackUtils.compareItemStacksIgnoreStackSize(container, craftingHelperStack, false, true)) {