diff --git a/src/main/java/mezz/jei/network/packets/PacketRecipeTransfer.java b/src/main/java/mezz/jei/network/packets/PacketRecipeTransfer.java index 8a793e1e0..deebc602d 100644 --- a/src/main/java/mezz/jei/network/packets/PacketRecipeTransfer.java +++ b/src/main/java/mezz/jei/network/packets/PacketRecipeTransfer.java @@ -8,7 +8,6 @@ import java.util.Map; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.ItemStack; import net.minecraft.network.PacketBuffer; import mezz.jei.network.IPacketId; @@ -17,7 +16,7 @@ public class PacketRecipeTransfer extends PacketJEI { - private Map recipeMap; + private Map recipeMap; private List craftingSlots; private List inventorySlots; private boolean maxTransfer; @@ -26,7 +25,7 @@ public PacketRecipeTransfer() { } - public PacketRecipeTransfer(@Nonnull Map recipeMap, @Nonnull List craftingSlots, @Nonnull List inventorySlots, boolean maxTransfer) { + public PacketRecipeTransfer(@Nonnull Map recipeMap, @Nonnull List craftingSlots, @Nonnull List inventorySlots, boolean maxTransfer) { this.recipeMap = recipeMap; this.craftingSlots = craftingSlots; this.inventorySlots = inventorySlots; @@ -44,7 +43,7 @@ public void readPacketData(PacketBuffer buf, EntityPlayer player) throws IOExcep recipeMap = new HashMap<>(recipeMapSize); for (int i = 0; i < recipeMapSize; i++) { int slotIndex = buf.readVarIntFromBuffer(); - ItemStack recipeItem = buf.readItemStackFromBuffer(); + int recipeItem = buf.readVarIntFromBuffer(); recipeMap.put(slotIndex, recipeItem); } @@ -70,9 +69,9 @@ public void readPacketData(PacketBuffer buf, EntityPlayer player) throws IOExcep @Override public void writePacketData(PacketBuffer buf) throws IOException { buf.writeVarIntToBuffer(recipeMap.size()); - for (Map.Entry recipeMapEntry : recipeMap.entrySet()) { + for (Map.Entry recipeMapEntry : recipeMap.entrySet()) { buf.writeVarIntToBuffer(recipeMapEntry.getKey()); - buf.writeItemStackToBuffer(recipeMapEntry.getValue()); + buf.writeVarIntToBuffer(recipeMapEntry.getValue()); } buf.writeVarIntToBuffer(craftingSlots.size()); diff --git a/src/main/java/mezz/jei/transfer/BasicRecipeTransferHandler.java b/src/main/java/mezz/jei/transfer/BasicRecipeTransferHandler.java index 81c53ac1d..df3ffc51c 100644 --- a/src/main/java/mezz/jei/transfer/BasicRecipeTransferHandler.java +++ b/src/main/java/mezz/jei/transfer/BasicRecipeTransferHandler.java @@ -81,7 +81,7 @@ public IRecipeTransferError transferRecipe(@Nonnull Container container, @Nonnul return handlerHelper.createInternalError(); } - List availableItemStacks = new ArrayList<>(); + Map availableItemStacks = new HashMap<>(); int filledCraftSlotCount = 0; int emptySlotCount = 0; @@ -92,13 +92,13 @@ public IRecipeTransferError transferRecipe(@Nonnull Container container, @Nonnul return handlerHelper.createInternalError(); } filledCraftSlotCount++; - availableItemStacks.add(slot.getStack().copy()); + availableItemStacks.put(slot.slotNumber, slot.getStack().copy()); } } for (Slot slot : inventorySlots.values()) { if (slot.getHasStack()) { - availableItemStacks.add(slot.getStack().copy()); + availableItemStacks.put(slot.slotNumber, slot.getStack().copy()); } else { emptySlotCount++; } @@ -124,7 +124,7 @@ public IRecipeTransferError transferRecipe(@Nonnull Container container, @Nonnul Collections.sort(inventorySlotIndexes); // check that the slots exist and can be altered - for (Map.Entry entry : matchingItemsResult.matchingItems.entrySet()) { + for (Map.Entry entry : matchingItemsResult.matchingItems.entrySet()) { int craftNumber = entry.getKey(); int slotNumber = craftingSlotIndexes.get(craftNumber); if (slotNumber >= container.inventorySlots.size()) { @@ -132,7 +132,7 @@ public IRecipeTransferError transferRecipe(@Nonnull Container container, @Nonnul return handlerHelper.createInternalError(); } Slot slot = container.getSlot(slotNumber); - ItemStack stack = entry.getValue(); + ItemStack stack = container.getSlot(entry.getValue()).getStack(); if (slot == null) { Log.error("The slot number {} does not exist in the container.", slotNumber); return handlerHelper.createInternalError(); @@ -154,10 +154,22 @@ public IRecipeTransferError transferRecipe(@Nonnull Container container, @Nonnul /** * Called server-side to actually put the items in place. */ - public static void setItems(@Nonnull EntityPlayer player, @Nonnull Map slotMap, @Nonnull List craftingSlots, @Nonnull List inventorySlots, boolean maxTransfer) { + public static void setItems(@Nonnull EntityPlayer player, @Nonnull Map slotIdMap, @Nonnull List craftingSlots, @Nonnull List inventorySlots, boolean maxTransfer) { Container container = player.openContainer; StackHelper stackHelper = Internal.getStackHelper(); + // grab items from slots + Map slotMap = new HashMap<>(slotIdMap.size()); + for (Map.Entry entry : slotIdMap.entrySet()) { + Slot slot = container.getSlot(entry.getValue()); + if (slot == null || !slot.getHasStack()) { + return; + } + ItemStack stack = slot.getStack().copy(); + stack.stackSize = 1; + slotMap.put(entry.getKey(), stack); + } + // remove required recipe items int removedSets = removeSetsFromInventory(container, slotMap.values(), craftingSlots, inventorySlots, maxTransfer); if (removedSets == 0) { diff --git a/src/main/java/mezz/jei/util/StackHelper.java b/src/main/java/mezz/jei/util/StackHelper.java index b4a50d133..8ca5be683 100644 --- a/src/main/java/mezz/jei/util/StackHelper.java +++ b/src/main/java/mezz/jei/util/StackHelper.java @@ -8,6 +8,7 @@ import java.util.Collections; import java.util.EnumMap; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Objects; @@ -76,7 +77,7 @@ public String getOreDictEquivalent(@Nonnull Collection itemStacks) { * Returns a result that contains missingItems if there are not enough items in availableItemStacks. */ @Nonnull - public MatchingItemsResult getMatchingItems(@Nonnull List availableItemStacks, @Nonnull Map> ingredientsMap) { + public MatchingItemsResult getMatchingItems(@Nonnull Map availableItemStacks, @Nonnull Map> ingredientsMap) { MatchingItemsResult matchingItemResult = new MatchingItemsResult(); int recipeSlotNumber = -1; @@ -92,16 +93,17 @@ public MatchingItemsResult getMatchingItems(@Nonnull List availableIt if (requiredStacks.isEmpty()) { continue; } - - ItemStack matching = containsStack(availableItemStacks, requiredStacks); + + Integer matching = containsAnyStackIndexed(availableItemStacks, requiredStacks); if (matching == null) { matchingItemResult.missingItems.add(key); } else { - ItemStack matchingSplit = matching.splitStack(1); - if (matching.stackSize == 0) { + ItemStack matchingStack = availableItemStacks.get(matching); + matchingStack.stackSize--; + if (matchingStack.stackSize == 0) { availableItemStacks.remove(matching); } - matchingItemResult.matchingItems.put(recipeSlotNumber, matchingSplit); + matchingItemResult.matchingItems.put(recipeSlotNumber, matching); } } @@ -122,15 +124,19 @@ public Slot getSlotWithStack(@Nonnull Container container, @Nonnull Iterable stacks, @Nonnull Collection contains) { + return containsSameStacks(new MatchingIterable(stacks), new MatchingIterable(contains)); + } + /** Returns true if all stacks from "contains" are found in "stacks" and the opposite is true as well. */ - public boolean containsSameStacks(@Nonnull Iterable stacks, @Nonnull Iterable contains) { - for (ItemStack stack : contains) { + public boolean containsSameStacks(@Nonnull Iterable> stacks, @Nonnull Iterable> contains) { + for (ItemStackMatchable stack : contains) { if (containsStack(stacks, stack) == null) { return false; } } - for (ItemStack stack : stacks) { + for (ItemStackMatchable stack : stacks) { if (containsStack(contains, stack) == null) { return false; } @@ -139,15 +145,26 @@ public boolean containsSameStacks(@Nonnull Iterable stacks, @Nonnull return true; } + public Integer containsAnyStackIndexed(@Nullable Map stacks, @Nullable Iterable contains) { + return containsStackMatchable(stacks == null ? null : new MatchingIndexed(stacks), contains == null ? null : (Iterable>) (Iterable) new MatchingIterable(contains)); + } + + public ItemStack containsStack(@Nullable Iterable stacks, @Nullable ItemStack contains) { + return containsAnyStack(stacks == null ? null : stacks, contains == null ? null : Collections.singletonList(contains)); + } + + public ItemStack containsAnyStack(@Nullable Iterable stacks, @Nullable Iterable contains) { + return containsStackMatchable(stacks == null ? null : new MatchingIterable(stacks), contains == null ? null : (Iterable>) (Iterable) new MatchingIterable(contains)); + } + /* Returns an ItemStack from "stacks" if it isEquivalent to an ItemStack from "contains" */ - @Nullable - public ItemStack containsStack(@Nullable Iterable stacks, @Nullable Iterable contains) { + public R containsStackMatchable(@Nullable Iterable> stacks, @Nullable Iterable> contains) { if (stacks == null || contains == null) { return null; } - for (ItemStack containStack : contains) { - ItemStack matchingStack = containsStack(stacks, containStack); + for (ItemStackMatchable containStack : contains) { + R matchingStack = containsStack(stacks, containStack); if (matchingStack != null) { return matchingStack; } @@ -157,15 +174,14 @@ public ItemStack containsStack(@Nullable Iterable stacks, @Nullable I } /* Returns an ItemStack from "stacks" if it isEquivalent to "contains" */ - @Nullable - public ItemStack containsStack(@Nullable Iterable stacks, @Nullable ItemStack contains) { + public R containsStack(@Nullable Iterable> stacks, @Nullable ItemStackMatchable contains) { if (stacks == null || contains == null) { return null; } - for (ItemStack stack : stacks) { - if (isEquivalent(contains, stack)) { - return stack; + for (ItemStackMatchable stack : stacks) { + if (isEquivalent(contains.getStack(), stack.getStack())) { + return stack.getResult(); } } return null; @@ -476,8 +492,101 @@ public int addStack(@Nonnull Container container, @Nonnull Collection s public static class MatchingItemsResult { @Nonnull - public final Map matchingItems = new HashMap<>(); + public final Map matchingItems = new HashMap<>(); @Nonnull public final List missingItems = new ArrayList<>(); } + + private interface ItemStackMatchable { + @Nonnull + ItemStack getStack(); + @Nonnull + R getResult(); + } + + private static abstract class DelegateIterator implements Iterator { + @Nonnull + protected final Iterator delegate; + + public DelegateIterator(@Nonnull Iterator delegate) { + this.delegate = delegate; + } + + @Override + public boolean hasNext() { + return delegate.hasNext(); + } + + @Override + public void remove() { + delegate.remove(); + } + } + + private static class MatchingIterable implements Iterable> { + @Nonnull + private final Iterable list; + + public MatchingIterable(@Nonnull Iterable list) { + this.list = list; + } + + @Nonnull + @Override + public Iterator> iterator() { + Iterator stacks = list.iterator(); + return new DelegateIterator>(stacks) { + @Override + public ItemStackMatchable next() { + final ItemStack stack = delegate.next(); + return new ItemStackMatchable() { + @Nonnull + @Override + public ItemStack getStack() { + return stack; + } + + @Nonnull + @Override + public ItemStack getResult() { + return stack; + } + }; + } + }; + } + } + + private static class MatchingIndexed implements Iterable> { + @Nonnull + private final Map map; + + public MatchingIndexed(@Nonnull Map map) { + this.map = map; + } + + @Nonnull + @Override + public Iterator> iterator() { + return new DelegateIterator, ItemStackMatchable>(map.entrySet().iterator()) { + @Override + public ItemStackMatchable next() { + final Map.Entry entry = delegate.next(); + return new ItemStackMatchable() { + @Nonnull + @Override + public ItemStack getStack() { + return entry.getValue(); + } + + @Nonnull + @Override + public Integer getResult() { + return entry.getKey(); + } + }; + } + }; + } + } }