Skip to content

Commit

Permalink
Improve non-tool catalyst handling (#10392)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
uecasm authored Nov 17, 2024
1 parent c624f30 commit fa28c16
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 20 deletions.
32 changes: 19 additions & 13 deletions src/main/java/com/minecolonies/api/crafting/RecipeStorage.java
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ private void processInputsAndTools(@Nullable final List<ItemStack> 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);
Expand Down Expand Up @@ -525,25 +525,31 @@ public List<ItemStack> 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
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -173,11 +172,8 @@ protected List<IToken<?>> 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))
{
Expand Down

0 comments on commit fa28c16

Please sign in to comment.