made modules be able to send less than their expected amount

Closes #16
This commit is contained in:
Ellpeck 2020-05-17 16:14:27 +02:00
parent 2a8d43bb30
commit a026cfc550
5 changed files with 46 additions and 29 deletions

View file

@ -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<CompoundNBT>, 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<Float, PipeItem> itemSupplier, boolean preventOversending) {
public ItemStack routeItem(BlockPos startPipePos, BlockPos startInventory, ItemStack stack, BiFunction<ItemStack, Float, PipeItem> 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<BlockPos, ItemStack> 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<Float, PipeItem> 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<Float, PipeItem> itemSupplier) {

View file

@ -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<BlockPos, ItemStack> 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;
}

View file

@ -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;
}
}

View file

@ -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<BlockPos, ItemStack> 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;
}
}

View file

@ -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;
}