Skip to content

Commit 40909f9

Browse files
committed
Fix handling of restricted slots in recipe transfers
1 parent 58fef1d commit 40909f9

File tree

4 files changed

+57
-51
lines changed

4 files changed

+57
-51
lines changed

Common/src/main/java/mezz/jei/common/transfer/BasicRecipeTransferHandlerServer.java

Lines changed: 33 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,10 @@ private static List<ItemStack> clearCraftingGrid(List<Slot> craftingSlots, Playe
103103
if (!craftingSlot.mayPickup(player)) {
104104
continue;
105105
}
106-
if (craftingSlot.hasItem()) {
107-
ItemStack craftingItem = craftingSlot.remove(Integer.MAX_VALUE);
106+
107+
ItemStack item = craftingSlot.getItem();
108+
if (!item.isEmpty() && craftingSlot.mayPlace(item)) {
109+
ItemStack craftingItem = craftingSlot.safeTake(Integer.MAX_VALUE, Integer.MAX_VALUE, player);
108110
clearedCraftingItems.add(craftingItem);
109111
}
110112
}
@@ -119,13 +121,9 @@ private static List<ItemStack> putItemsIntoCraftingGrid(
119121
List<ItemStack> remainderItems = new ArrayList<>();
120122

121123
recipeSlotToTakenStacks.forEach((slot, stack) -> {
122-
if (slot.getItem().isEmpty() && slot.mayPlace(stack)) {
123-
ItemStack remainder = slot.safeInsert(stack, slotStackLimit);
124-
if (!remainder.isEmpty()) {
125-
remainderItems.add(remainder);
126-
}
127-
} else {
128-
remainderItems.add(stack);
124+
ItemStack remainder = slot.safeInsert(stack, slotStackLimit);
125+
if (!remainder.isEmpty()) {
126+
remainderItems.add(remainder);
129127
}
130128
});
131129

@@ -136,9 +134,9 @@ private static List<ItemStack> putItemsIntoCraftingGrid(
136134
private static Map<Slot, ItemStackWithSlotHint> calculateRequiredStacks(List<TransferOperation> transferOperations, Player player) {
137135
Map<Slot, ItemStackWithSlotHint> recipeSlotToRequired = new HashMap<>(transferOperations.size());
138136
for (TransferOperation transferOperation : transferOperations) {
139-
Slot recipeSlot = transferOperation.craftingSlot();
140-
Slot inventorySlot = transferOperation.inventorySlot();
141-
if (!inventorySlot.mayPickup(player)) {
137+
Slot recipeSlot = transferOperation.craftingSlot(player.containerMenu);
138+
Slot inventorySlot = transferOperation.inventorySlot(player.containerMenu);
139+
if (!inventorySlot.allowModification(player)) {
142140
LOGGER.error(
143141
"Tried to transfer recipe but was given an" +
144142
" inventory slot that the player can't pickup from: {}" ,
@@ -231,18 +229,18 @@ private static Map<Slot, ItemStack> removeOneSetOfItemsFromInventory(
231229
final Slot hint = entry.getValue().hint;
232230

233231
// Locate a slot that has what we need.
234-
final Slot slot = getSlotWithStack(player, requiredStack, craftingSlots, inventorySlots, hint)
232+
final Slot sourceSlot = getSlotWithStack(player, requiredStack, craftingSlots, inventorySlots, hint)
235233
.orElse(null);
236-
if (slot != null) {
234+
if (sourceSlot != null) {
237235
// the item was found
238236

239237
// Keep a copy of the slot's original contents in case we need to roll back.
240-
if (originalSlotContents != null && !originalSlotContents.containsKey(slot)) {
241-
originalSlotContents.put(slot, slot.getItem().copy());
238+
if (originalSlotContents != null && !originalSlotContents.containsKey(sourceSlot)) {
239+
originalSlotContents.put(sourceSlot, sourceSlot.getItem().copy());
242240
}
243241

244242
// Reduce the size of the found slot.
245-
ItemStack removedItemStack = slot.remove(1);
243+
ItemStack removedItemStack = sourceSlot.safeTake(1, Integer.MAX_VALUE, player);
246244
foundItemsInSet.put(recipeSlot, removedItemStack);
247245
} else {
248246
// We can't find any more slots to fulfill the requirements.
@@ -252,7 +250,8 @@ private static Map<Slot, ItemStack> removeOneSetOfItemsFromInventory(
252250
// slot changes we've made during this set iteration.
253251
for (Map.Entry<Slot, ItemStack> slotEntry : originalSlotContents.entrySet()) {
254252
ItemStack stack = slotEntry.getValue();
255-
slotEntry.getKey().set(stack);
253+
Slot slot = slotEntry.getKey();
254+
slot.set(stack);
256255
}
257256
return Map.of();
258257
}
@@ -290,10 +289,7 @@ private static Optional<Slot> getSlotWithStack(Player player, ItemStack stack, L
290289
}
291290

292291
private static Optional<Slot> getValidatedHintSlot(Player player, ItemStack stack, Slot hint) {
293-
if (hint.mayPickup(player) &&
294-
!hint.getItem().isEmpty() &&
295-
ItemStack.isSameItemSameTags(stack, hint.getItem())
296-
) {
292+
if (isValidAndMatches(player, hint, stack)) {
297293
return Optional.of(hint);
298294
}
299295

@@ -302,7 +298,7 @@ private static Optional<Slot> getValidatedHintSlot(Player player, ItemStack stac
302298

303299
private static void stowItems(Player player, List<Slot> inventorySlots, List<ItemStack> itemStacks) {
304300
for (ItemStack itemStack : itemStacks) {
305-
ItemStack remainder = stowItem(inventorySlots, itemStack);
301+
ItemStack remainder = stowItem(player, inventorySlots, itemStack);
306302
if (!remainder.isEmpty()) {
307303
if (!player.getInventory().add(remainder)) {
308304
player.drop(remainder, false);
@@ -311,18 +307,21 @@ private static void stowItems(Player player, List<Slot> inventorySlots, List<Ite
311307
}
312308
}
313309

314-
private static ItemStack stowItem(Collection<Slot> slots, ItemStack stack) {
310+
private static ItemStack stowItem(Player player, Collection<Slot> slots, ItemStack stack) {
315311
if (stack.isEmpty()) {
316312
return ItemStack.EMPTY;
317313
}
318314

319-
final ItemStack remainder = stack.copy();
315+
ItemStack remainder = stack.copy();
320316

321317
// Add to existing stacks first
322318
for (Slot slot : slots) {
319+
if (!slot.mayPickup(player)) {
320+
continue;
321+
}
323322
final ItemStack inventoryStack = slot.getItem();
324323
if (!inventoryStack.isEmpty() && inventoryStack.isStackable()) {
325-
slot.safeInsert(remainder);
324+
remainder = slot.safeInsert(remainder);
326325
if (remainder.isEmpty()) {
327326
return ItemStack.EMPTY;
328327
}
@@ -332,7 +331,7 @@ private static ItemStack stowItem(Collection<Slot> slots, ItemStack stack) {
332331
// Try adding to empty slots
333332
for (Slot slot : slots) {
334333
if (slot.getItem().isEmpty()) {
335-
slot.safeInsert(remainder);
334+
remainder = slot.safeInsert(remainder);
336335
if (remainder.isEmpty()) {
337336
return ItemStack.EMPTY;
338337
}
@@ -351,13 +350,15 @@ private static ItemStack stowItem(Collection<Slot> slots, ItemStack stack) {
351350
*/
352351
private static Optional<Slot> getSlotWithStack(Player player, Collection<Slot> slots, ItemStack itemStack) {
353352
return slots.stream()
354-
.filter(slot -> {
355-
ItemStack slotStack = slot.getItem();
356-
return ItemStack.isSameItemSameTags(itemStack, slotStack) &&
357-
slot.mayPickup(player);
358-
})
353+
.filter(slot -> isValidAndMatches(player, slot, itemStack))
359354
.findFirst();
360355
}
361356

357+
private static boolean isValidAndMatches(Player player, Slot slot, ItemStack stack) {
358+
ItemStack containedStack = slot.getItem();
359+
return ItemStack.isSameItemSameTags(stack, containedStack) &&
360+
slot.allowModification(player);
361+
}
362+
362363
private record ItemStackWithSlotHint(Slot hint, ItemStack stack) {}
363364
}

Common/src/main/java/mezz/jei/common/transfer/RecipeTransferUtil.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -96,15 +96,15 @@ public static boolean validateSlots(
9696
// check that all craftingTargetSlots are included in craftingSlots
9797
{
9898
List<Integer> invalidRecipeIndexes = transferOperations.stream()
99-
.map(TransferOperation::craftingSlot)
99+
.map(op -> op.craftingSlot(player.containerMenu))
100100
.map(s -> s.index)
101101
.filter(s -> !craftingSlotIndexes.contains(s))
102102
.toList();
103103
if (!invalidRecipeIndexes.isEmpty()) {
104104
LOGGER.error(
105-
"Transfer handler has invalid slots for the destination of the recipe, " +
106-
"the slots are not included in the list of crafting slots. " +
107-
StringUtil.intsToString(invalidRecipeIndexes)
105+
"Transfer request has invalid slots for the destination of the recipe, " +
106+
"the slots are not included in the list of crafting slots. {}",
107+
StringUtil.intsToString(invalidRecipeIndexes)
108108
);
109109
return false;
110110
}
@@ -113,7 +113,7 @@ public static boolean validateSlots(
113113
// check that all ingredientTargetSlots are included in inventorySlots or recipeSlots
114114
{
115115
List<Integer> invalidInventorySlotIndexes = transferOperations.stream()
116-
.map(TransferOperation::inventorySlot)
116+
.map(op -> op.inventorySlot(player.containerMenu))
117117
.map(s -> s.index)
118118
.filter(s -> !inventorySlotIndexes.contains(s) && !craftingSlotIndexes.contains(s))
119119
.toList();
@@ -293,7 +293,7 @@ public boolean equals(ItemStack a, ItemStack b) {
293293
Slot matchingSlot = matching.slot;
294294
ItemStack matchingStack = matching.itemStack;
295295
matchingStack.shrink(1);
296-
transferOperations.results.add(new TransferOperation(matchingSlot, craftingSlot));
296+
transferOperations.results.add(new TransferOperation(matchingSlot.index, craftingSlot.index));
297297
}
298298
}
299299

Common/src/main/java/mezz/jei/common/transfer/TransferOperation.java

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,23 @@
77
/**
88
* Represents transferring an ItemStack from inventorySlot to craftingSlot.
99
*/
10-
public record TransferOperation(Slot inventorySlot, Slot craftingSlot) {
10+
public record TransferOperation(int inventorySlotId, int craftingSlotId) {
1111
public static TransferOperation readPacketData(FriendlyByteBuf buf, AbstractContainerMenu container) {
12-
int inventorySlotIndex = buf.readVarInt();
13-
int craftingSlotIndex = buf.readVarInt();
14-
15-
Slot inventorySlot = container.getSlot(inventorySlotIndex);
16-
Slot craftingSlot = container.getSlot(craftingSlotIndex);
17-
return new TransferOperation(inventorySlot, craftingSlot);
12+
int inventorySlotId = buf.readVarInt();
13+
int craftingSlotId = buf.readVarInt();
14+
return new TransferOperation(inventorySlotId, craftingSlotId);
1815
}
1916

2017
public void writePacketData(FriendlyByteBuf buf) {
21-
buf.writeVarInt(inventorySlot.index);
22-
buf.writeVarInt(craftingSlot.index);
18+
buf.writeVarInt(inventorySlotId);
19+
buf.writeVarInt(craftingSlotId);
20+
}
21+
22+
public Slot inventorySlot(AbstractContainerMenu container) {
23+
return container.getSlot(inventorySlotId);
24+
}
25+
26+
public Slot craftingSlot(AbstractContainerMenu container) {
27+
return container.getSlot(craftingSlotId);
2328
}
2429
}

Library/src/main/java/mezz/jei/library/transfer/BasicRecipeTransferHandler.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -146,18 +146,18 @@ public static <C extends AbstractContainerMenu, R> boolean validateTransferInfo(
146146
Player player
147147
) {
148148
for (Slot slot : craftingSlots) {
149-
if (!slot.allowModification(player)) {
149+
if (!slot.mayPickup(player)) {
150150
LOGGER.error("Recipe Transfer helper {} does not work for container {}. " +
151-
"The Recipe Transfer Helper references crafting slot index [{}] but it does not allow modification.",
151+
"The Recipe Transfer Helper references crafting slot index [{}] but the player cannot pickup from it.",
152152
transferInfo.getClass(), container.getClass(), slot.index
153153
);
154154
return false;
155155
}
156156
}
157157
for (Slot slot : inventorySlots) {
158-
if (!slot.allowModification(player)) {
158+
if (!slot.mayPickup(player)) {
159159
LOGGER.error("Recipe Transfer helper {} does not work for container {}. " +
160-
"The Recipe Transfer Helper references inventory slot index [{}] but it does not allow modification.",
160+
"The Recipe Transfer Helper references inventory slot index [{}] but the player cannot pickup from it.",
161161
transferInfo.getClass(), container.getClass(), slot.index
162162
);
163163
return false;

0 commit comments

Comments
 (0)