From 328f5d9cc930a13dc8daa40a8c2b56caf36c7416 Mon Sep 17 00:00:00 2001 From: Yiheng Cao <65160922+Crispy-fried-chicken@users.noreply.github.com> Date: Sat, 31 Aug 2024 20:09:46 +0800 Subject: [PATCH] [backport] Prevent recipe transfers from touching output slots (#3720) cherry-picked from the commit 99ff43ba1009c44c6d935e2ab8a6c9292bb12873 --- .../common/transfer/RecipeTransferUtil.java | 42 ++++++++++++------- .../transfer/BasicRecipeTransferHandler.java | 26 +++++++++--- 2 files changed, 49 insertions(+), 19 deletions(-) diff --git a/Common/src/main/java/mezz/jei/common/transfer/RecipeTransferUtil.java b/Common/src/main/java/mezz/jei/common/transfer/RecipeTransferUtil.java index b876edcdc..0de3f4802 100644 --- a/Common/src/main/java/mezz/jei/common/transfer/RecipeTransferUtil.java +++ b/Common/src/main/java/mezz/jei/common/transfer/RecipeTransferUtil.java @@ -101,9 +101,8 @@ public static boolean validateSlots( .toList(); if (!invalidRecipeIndexes.isEmpty()) { LOGGER.error( - "Transfer handler has invalid slots for the destination of the recipe, " + - "the slots are not included in the list of crafting slots. " + - StringUtil.intsToString(invalidRecipeIndexes) + "Transfer request has invalid slots for the destination of the recipe, the slots are not included in the list of crafting slots. {}", + StringUtil.intsToString(invalidRecipeIndexes) ); return false; } @@ -118,11 +117,10 @@ public static boolean validateSlots( .toList(); if (!invalidInventorySlotIndexes.isEmpty()) { LOGGER.error( - "Transfer handler has invalid source slots for the inventory stacks for the recipe, " + - "the slots are not included in the list of inventory slots or recipe slots. " + - StringUtil.intsToString(invalidInventorySlotIndexes) + - "\n inventory slots: " + StringUtil.intsToString(inventorySlotIndexes) + - "\n crafting slots: " + StringUtil.intsToString(craftingSlotIndexes) + "Transfer request has invalid source slots for the inventory stacks for the recipe, the slots are not included in the list of inventory slots or recipe slots. {}\n inventory slots: {}\n crafting slots: {}", + StringUtil.intsToString(invalidInventorySlotIndexes), + StringUtil.intsToString(inventorySlotIndexes), + StringUtil.intsToString(craftingSlotIndexes) ); return false; } @@ -135,9 +133,8 @@ public static boolean validateSlots( .collect(Collectors.toSet()); if (!overlappingSlots.isEmpty()) { LOGGER.error( - "Transfer handler has invalid slots, " + - "inventorySlots and craftingSlots should not share any slot, but both have: " + - StringUtil.intsToString(overlappingSlots) + "Transfer request has invalid slots, inventorySlots and craftingSlots should not share any slot, but both have: {}", + StringUtil.intsToString(overlappingSlots) ); return false; } @@ -155,14 +152,31 @@ public static boolean validateSlots( .toList(); if (!invalidPickupSlots.isEmpty()) { LOGGER.error( - "Transfer handler has invalid slots, " + - "the player is unable to pickup from them: " + - StringUtil.intsToString(invalidPickupSlots) + "Transfer request has invalid slots, the player is unable to pickup from them: {}", + StringUtil.intsToString(invalidPickupSlots) ); return false; } } + // check that all slots are real (not output slots) + { + List invalidFakeSlots = Stream.concat( + craftingSlots.stream(), + inventorySlots.stream() + ) + .filter(Slot::isFake) + .map(slot -> slot.index) + .toList(); + if (!invalidFakeSlots.isEmpty()) { + LOGGER.error( + "Transfer request has invalid slots, they are fake slots (recipe outputs): {}", + StringUtil.intsToString(invalidFakeSlots) + ); + return false; + } + } + return true; } diff --git a/Library/src/main/java/mezz/jei/library/transfer/BasicRecipeTransferHandler.java b/Library/src/main/java/mezz/jei/library/transfer/BasicRecipeTransferHandler.java index 661a44645..8ee227b18 100644 --- a/Library/src/main/java/mezz/jei/library/transfer/BasicRecipeTransferHandler.java +++ b/Library/src/main/java/mezz/jei/library/transfer/BasicRecipeTransferHandler.java @@ -119,10 +119,8 @@ public IRecipeTransferError transferRecipe(C container, R recipe, IRecipeSlotsVi return handlerHelper.createUserErrorForMissingSlots(message, transferOperations.missingItems); } - { - if (!RecipeTransferUtil.validateSlots(player, transferOperations.results, craftingSlots, inventorySlots)) { - return handlerHelper.createInternalError(); - } + if (!RecipeTransferUtil.validateSlots(player, transferOperations.results, craftingSlots, inventorySlots)) { + return handlerHelper.createInternalError(); } if (doTransfer) { @@ -145,7 +143,25 @@ public static boolean validateTransferInfo( C container, List craftingSlots, List inventorySlots - ) { + ) { + for (Slot slot : craftingSlots) { + if (slot.isFake()) { + LOGGER.error("Recipe Transfer helper {} does not work for container {}. " + + "The Recipe Transfer Helper references crafting slot index [{}] but it is a fake (output) slot, which is not allowed.", + transferInfo.getClass(), container.getClass(), slot.index + ); + return false; + } + } + for (Slot slot : inventorySlots) { + if (slot.isFake()) { + LOGGER.error("Recipe Transfer helper {} does not work for container {}. " + + "The Recipe Transfer Helper references inventory slot index [{}] but it is a fake (output) slot, which is not allowed.", + transferInfo.getClass(), container.getClass(), slot.index + ); + return false; + } + } Collection craftingSlotIndexes = slotIndexes(craftingSlots); Collection inventorySlotIndexes = slotIndexes(inventorySlots); Collection containerSlotIndexes = slotIndexes(container.slots);