diff --git a/src/main/java/de/ellpeck/prettypipes/Utility.java b/src/main/java/de/ellpeck/prettypipes/Utility.java index c1ca0da..bc2a204 100644 --- a/src/main/java/de/ellpeck/prettypipes/Utility.java +++ b/src/main/java/de/ellpeck/prettypipes/Utility.java @@ -114,6 +114,18 @@ public final class Utility { return items; } + public static List splitStackToFitMax(ItemStack stack) { + List ret = new ArrayList<>(); + int amount = stack.getCount(); + while (amount > 0) { + ItemStack copy = stack.copy(); + copy.setCount(Math.min(amount, stack.getMaxStackSize())); + ret.add(copy); + amount -= copy.getCount(); + } + return ret; + } + public interface IMergeItemStack { boolean mergeItemStack(ItemStack stack, int startIndex, int endIndex, boolean reverseDirection); } diff --git a/src/main/java/de/ellpeck/prettypipes/network/NetworkLock.java b/src/main/java/de/ellpeck/prettypipes/network/NetworkLock.java index 19ba7fb..d88f2d6 100644 --- a/src/main/java/de/ellpeck/prettypipes/network/NetworkLock.java +++ b/src/main/java/de/ellpeck/prettypipes/network/NetworkLock.java @@ -6,9 +6,14 @@ import net.minecraft.nbt.ListNBT; import net.minecraftforge.common.util.INBTSerializable; import java.util.Collection; +import java.util.Objects; +import java.util.UUID; public class NetworkLock implements INBTSerializable { + // identify locks by UUID since network locks can't be identified by location and locked item alone + // (two locks could be set for the same item and the same amount if it exists twice in the chest) + private UUID lockId = UUID.randomUUID(); public NetworkLocation location; public ItemStack stack; @@ -24,6 +29,7 @@ public class NetworkLock implements INBTSerializable { @Override public CompoundNBT serializeNBT() { CompoundNBT nbt = new CompoundNBT(); + nbt.putUniqueId("id", this.lockId); nbt.put("location", this.location.serializeNBT()); nbt.put("stack", this.stack.write(new CompoundNBT())); return nbt; @@ -31,7 +37,22 @@ public class NetworkLock implements INBTSerializable { @Override public void deserializeNBT(CompoundNBT nbt) { + this.lockId = nbt.getUniqueId("id"); this.location = new NetworkLocation(nbt.getCompound("location")); this.stack = ItemStack.read(nbt.getCompound("stack")); } + + @Override + public boolean equals(Object o) { + if (o instanceof NetworkLock) { + NetworkLock that = (NetworkLock) o; + return this.lockId.equals(that.lockId); + } + return false; + } + + @Override + public int hashCode() { + return Objects.hash(this.lockId); + } } diff --git a/src/main/java/de/ellpeck/prettypipes/network/PipeNetwork.java b/src/main/java/de/ellpeck/prettypipes/network/PipeNetwork.java index 3173188..b3678b0 100644 --- a/src/main/java/de/ellpeck/prettypipes/network/PipeNetwork.java +++ b/src/main/java/de/ellpeck/prettypipes/network/PipeNetwork.java @@ -177,28 +177,35 @@ public class PipeNetwork implements ICapabilitySerializable, GraphL return true; } - public boolean requestItem(BlockPos destPipe, BlockPos destInventory, ItemStack stack, int amount, ItemEqualityType... equalityTypes) { + public ItemStack requestItem(BlockPos destPipe, BlockPos destInventory, ItemStack stack, ItemEqualityType... equalityTypes) { List locations = this.getOrderedNetworkItems(destPipe); + if (locations.isEmpty()) + return stack; + ItemStack remain = stack.copy(); for (NetworkLocation location : locations) { - if (this.requestItem(location, destPipe, destInventory, stack, amount, equalityTypes)) - return true; + remain = this.requestItem(location, destPipe, destInventory, remain, equalityTypes); + if (remain.isEmpty()) + break; } - return false; + return remain; } - public boolean requestItem(NetworkLocation location, BlockPos destPipe, BlockPos destInventory, ItemStack stack, int amount, ItemEqualityType... equalityTypes) { + public ItemStack requestItem(NetworkLocation location, BlockPos destPipe, BlockPos destInventory, ItemStack stack, ItemEqualityType... equalityTypes) { if (location.pipePos.equals(destPipe)) - return false; + return stack; + ItemStack remain = stack.copy(); for (int slot : location.getStackSlots(this.world, stack, equalityTypes)) { // try to extract from that location's inventory and send the item IItemHandler handler = location.getItemHandler(this.world); - ItemStack extracted = handler.extractItem(slot, amount, true); + ItemStack extracted = handler.extractItem(slot, remain.getCount(), true); if (this.routeItemToLocation(location.pipePos, location.getPos(), destPipe, destInventory, speed -> new PipeItem(extracted, speed))) { handler.extractItem(slot, extracted.getCount(), false); - return true; + remain.shrink(extracted.getCount()); + if (remain.isEmpty()) + break; } } - return false; + return remain; } public PipeTileEntity getPipe(BlockPos pos) { diff --git a/src/main/java/de/ellpeck/prettypipes/pipe/modules/retrieval/RetrievalModuleItem.java b/src/main/java/de/ellpeck/prettypipes/pipe/modules/retrieval/RetrievalModuleItem.java index e730fe6..3ca56d7 100644 --- a/src/main/java/de/ellpeck/prettypipes/pipe/modules/retrieval/RetrievalModuleItem.java +++ b/src/main/java/de/ellpeck/prettypipes/pipe/modules/retrieval/RetrievalModuleItem.java @@ -53,7 +53,7 @@ public class RetrievalModuleItem extends ModuleItem { BlockPos dest = tile.getAvailableDestination(copy, true, this.preventOversending); if (dest == null) continue; - if (network.requestItem(tile.getPos(), dest, filtered, this.maxExtraction, filter.getEqualityTypes())) + if (network.requestItem(tile.getPos(), dest, copy, filter.getEqualityTypes()).isEmpty()) break; } } diff --git a/src/main/java/de/ellpeck/prettypipes/terminal/ItemTerminalTileEntity.java b/src/main/java/de/ellpeck/prettypipes/terminal/ItemTerminalTileEntity.java index 9f96897..7648f69 100644 --- a/src/main/java/de/ellpeck/prettypipes/terminal/ItemTerminalTileEntity.java +++ b/src/main/java/de/ellpeck/prettypipes/terminal/ItemTerminalTileEntity.java @@ -84,8 +84,8 @@ public class ItemTerminalTileEntity extends TileEntity implements INamedContaine if (!this.pendingRequests.isEmpty()) { NetworkLock request = this.pendingRequests.remove(); network.resolveNetworkLock(request); - if (network.requestItem(request.location, pipe.getPos(), this.pos, request.stack, request.stack.getCount(), ItemEqualityType.NBT)) - update = true; + network.requestItem(request.location, pipe.getPos(), this.pos, request.stack, ItemEqualityType.NBT); + update = true; } } @@ -158,10 +158,16 @@ public class ItemTerminalTileEntity extends TileEntity implements INamedContaine if (amount > 0) { if (remain < amount) amount = remain; - NetworkLock lock = new NetworkLock(location, stack); - this.pendingRequests.add(lock); - network.createNetworkLock(lock); remain -= amount; + while (amount > 0) { + ItemStack copy = stack.copy(); + copy.setCount(Math.min(stack.getMaxStackSize(), amount)); + NetworkLock lock = new NetworkLock(location, copy); + this.pendingRequests.add(lock); + network.createNetworkLock(lock); + amount -= copy.getCount(); + + } if (remain <= 0) break; }