diff --git a/src/main/java/de/ellpeck/prettypipes/network/PipeNetwork.java b/src/main/java/de/ellpeck/prettypipes/network/PipeNetwork.java index ac52186..615a04c 100644 --- a/src/main/java/de/ellpeck/prettypipes/network/PipeNetwork.java +++ b/src/main/java/de/ellpeck/prettypipes/network/PipeNetwork.java @@ -26,6 +26,7 @@ import net.minecraftforge.common.util.Constants; import net.minecraftforge.common.util.Constants.NBT; import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.ItemHandlerHelper; import org.apache.commons.lang3.tuple.Pair; import org.jgrapht.GraphPath; import org.jgrapht.ListenableGraph; @@ -41,6 +42,7 @@ import org.jgrapht.traverse.BreadthFirstIterator; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.*; +import java.util.function.BiFunction; import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -129,31 +131,36 @@ public class PipeNetwork implements ICapabilitySerializable, GraphL } } - public boolean tryInsertItem(BlockPos startPipePos, BlockPos startInventory, ItemStack stack, boolean preventOversending) { - return this.routeItem(startPipePos, startInventory, stack, speed -> new PipeItem(stack, speed), preventOversending); + public ItemStack tryInsertItem(BlockPos startPipePos, BlockPos startInventory, ItemStack stack, boolean preventOversending) { + return this.routeItem(startPipePos, startInventory, stack, PipeItem::new, preventOversending); } - public boolean routeItem(BlockPos startPipePos, BlockPos startInventory, ItemStack stack, Function itemSupplier, boolean preventOversending) { + public ItemStack routeItem(BlockPos startPipePos, BlockPos startInventory, ItemStack stack, BiFunction itemSupplier, boolean preventOversending) { if (!this.isNode(startPipePos)) - return false; + return stack; if (!this.world.isBlockLoaded(startPipePos)) - return false; + return stack; PipeTileEntity startPipe = this.getPipe(startPipePos); if (startPipe == null) - return false; + return stack; this.startProfile("find_destination"); for (BlockPos pipePos : this.getOrderedNetworkNodes(startPipePos)) { if (!this.world.isBlockLoaded(pipePos)) continue; PipeTileEntity pipe = this.getPipe(pipePos); - BlockPos dest = pipe.getAvailableDestination(stack, false, preventOversending); - if (dest == null || dest.equals(startInventory)) + Pair dest = pipe.getAvailableDestination(stack, false, preventOversending); + if (dest == null || dest.getLeft().equals(startInventory)) continue; - this.endProfile(); - return this.routeItemToLocation(startPipePos, startInventory, pipe.getPos(), dest, itemSupplier); + Function sup = speed -> itemSupplier.apply(dest.getRight(), speed); + if (this.routeItemToLocation(startPipePos, startInventory, pipe.getPos(), dest.getLeft(), sup)) { + ItemStack remain = stack.copy(); + remain.shrink(dest.getRight().getCount()); + this.endProfile(); + return remain; + } } this.endProfile(); - return false; + return stack; } public boolean routeItemToLocation(BlockPos startPipePos, BlockPos startInventory, BlockPos destPipePos, BlockPos destInventory, Function itemSupplier) { diff --git a/src/main/java/de/ellpeck/prettypipes/pipe/PipeTileEntity.java b/src/main/java/de/ellpeck/prettypipes/pipe/PipeTileEntity.java index 147e8aa..0ba9bfe 100644 --- a/src/main/java/de/ellpeck/prettypipes/pipe/PipeTileEntity.java +++ b/src/main/java/de/ellpeck/prettypipes/pipe/PipeTileEntity.java @@ -135,7 +135,7 @@ public class PipeTileEntity extends TileEntity implements INamedContainerProvide return this.getBlockState().get(PipeBlock.DIRECTIONS.get(dir)).isConnected(); } - public BlockPos getAvailableDestination(ItemStack stack, boolean force, boolean preventOversending) { + public Pair getAvailableDestination(ItemStack stack, boolean force, boolean preventOversending) { if (!this.canWork()) return null; if (!force && this.streamModules().anyMatch(m -> !m.getRight().canAcceptItem(m.getLeft(), this, stack))) @@ -144,11 +144,16 @@ public class PipeTileEntity extends TileEntity implements INamedContainerProvide IItemHandler handler = this.getItemHandler(dir, null); if (handler == null) continue; - if (!ItemHandlerHelper.insertItem(handler, stack, true).isEmpty()) + ItemStack remain = ItemHandlerHelper.insertItem(handler, stack, true); + // did we insert anything? + if (remain.getCount() == stack.getCount()) continue; + ItemStack toInsert = stack.copy(); + toInsert.shrink(remain.getCount()); + // limit to the max amount that modules allow us to insert int maxAmount = this.streamModules().mapToInt(m -> m.getRight().getMaxInsertionAmount(m.getLeft(), this, stack, handler)).min().orElse(Integer.MAX_VALUE); - if (maxAmount < stack.getCount()) - continue; + if (maxAmount < toInsert.getCount()) + toInsert.setCount(maxAmount); BlockPos offset = this.pos.offset(dir); if (preventOversending || maxAmount < Integer.MAX_VALUE) { PipeNetwork network = PipeNetwork.get(this.world); @@ -159,8 +164,8 @@ public class PipeTileEntity extends TileEntity implements INamedContainerProvide // these are the items on the way, limited to items of the same type as stack int onTheWaySame = network.getItemsOnTheWay(offset, stack); // check if any modules are limiting us - if (onTheWaySame + stack.getCount() > maxAmount) - continue; + if (toInsert.getCount() + onTheWaySame > maxAmount) + toInsert.setCount(maxAmount - onTheWaySame); } ItemStack copy = stack.copy(); copy.setCount(copy.getMaxStackSize()); @@ -169,15 +174,17 @@ public class PipeTileEntity extends TileEntity implements INamedContainerProvide for (int i = 0; i < handler.getSlots(); i++) { // this is an inaccurate check since it ignores the fact that some slots might // have space for items of other types, but it'll be good enough for us - ItemStack remain = handler.insertItem(i, copy, true); - totalSpace += copy.getMaxStackSize() - remain.getCount(); + ItemStack left = handler.insertItem(i, copy, true); + totalSpace += copy.getMaxStackSize() - left.getCount(); } - // if the items on the way plus the items we're trying to move are too much, abort - if (onTheWay + stack.getCount() > totalSpace) - continue; + // if the items on the way plus the items we're trying to move are too much, reduce + if (onTheWay + toInsert.getCount() > totalSpace) + toInsert.setCount(totalSpace - onTheWay); } } - return offset; + // we return the item that can actually be inserted, NOT the remainder! + if (!toInsert.isEmpty()) + return Pair.of(offset, toInsert); } return null; } diff --git a/src/main/java/de/ellpeck/prettypipes/pipe/modules/extraction/ExtractionModuleItem.java b/src/main/java/de/ellpeck/prettypipes/pipe/modules/extraction/ExtractionModuleItem.java index ebf724d..3480a6f 100644 --- a/src/main/java/de/ellpeck/prettypipes/pipe/modules/extraction/ExtractionModuleItem.java +++ b/src/main/java/de/ellpeck/prettypipes/pipe/modules/extraction/ExtractionModuleItem.java @@ -48,8 +48,9 @@ public class ExtractionModuleItem extends ModuleItem { continue; if (!filter.isAllowed(stack)) continue; - if (network.tryInsertItem(tile.getPos(), tile.getPos().offset(dir), stack, this.preventOversending)) { - handler.extractItem(j, this.maxExtraction, false); + ItemStack remain = network.tryInsertItem(tile.getPos(), tile.getPos().offset(dir), stack, this.preventOversending); + if (remain.getCount() != stack.getCount()) { + handler.extractItem(j, stack.getCount() - remain.getCount(), false); return; } } 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 3ca56d7..6a288ec 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 @@ -16,6 +16,7 @@ import net.minecraft.entity.player.PlayerInventory; import net.minecraft.item.ItemStack; import net.minecraft.util.math.BlockPos; import net.minecraftforge.items.IItemHandler; +import org.apache.commons.lang3.tuple.Pair; import java.util.List; @@ -50,10 +51,10 @@ public class RetrievalModuleItem extends ModuleItem { continue; ItemStack copy = filtered.copy(); copy.setCount(this.maxExtraction); - BlockPos dest = tile.getAvailableDestination(copy, true, this.preventOversending); + Pair dest = tile.getAvailableDestination(copy, true, this.preventOversending); if (dest == null) continue; - if (network.requestItem(tile.getPos(), dest, copy, filter.getEqualityTypes()).isEmpty()) + if (network.requestItem(tile.getPos(), dest.getLeft(), dest.getRight(), 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 7648f69..dcef7d1 100644 --- a/src/main/java/de/ellpeck/prettypipes/terminal/ItemTerminalTileEntity.java +++ b/src/main/java/de/ellpeck/prettypipes/terminal/ItemTerminalTileEntity.java @@ -75,9 +75,10 @@ public class ItemTerminalTileEntity extends TileEntity implements INamedContaine ItemStack extracted = this.items.extractItem(i, Integer.MAX_VALUE, true); if (extracted.isEmpty()) continue; - if (!network.tryInsertItem(pipe.getPos(), this.pos, extracted, true)) + ItemStack remain = network.tryInsertItem(pipe.getPos(), this.pos, extracted, true); + if (remain.getCount() == extracted.getCount()) continue; - this.items.extractItem(i, extracted.getCount(), false); + this.items.extractItem(i, extracted.getCount() - remain.getCount(), false); break; }