diff --git a/src/main/java/de/ellpeck/prettypipes/items/IModule.java b/src/main/java/de/ellpeck/prettypipes/items/IModule.java index 22ffa4b..d6dc6f1 100644 --- a/src/main/java/de/ellpeck/prettypipes/items/IModule.java +++ b/src/main/java/de/ellpeck/prettypipes/items/IModule.java @@ -33,7 +33,7 @@ public interface IModule { boolean canPipeWork(ItemStack module, PipeTileEntity tile); - List getCraftables(ItemStack module, PipeTileEntity tile); + List getCraftables(ItemStack module, PipeTileEntity tile, boolean onlyReturnPossible); ItemStack craft(ItemStack module, PipeTileEntity tile, BlockPos destPipe, BlockPos destInventory, ItemStack stack, ItemEqualityType... equalityTypes); } diff --git a/src/main/java/de/ellpeck/prettypipes/items/ModuleItem.java b/src/main/java/de/ellpeck/prettypipes/items/ModuleItem.java index 862e12f..140c813 100644 --- a/src/main/java/de/ellpeck/prettypipes/items/ModuleItem.java +++ b/src/main/java/de/ellpeck/prettypipes/items/ModuleItem.java @@ -78,7 +78,7 @@ public abstract class ModuleItem extends Item implements IModule { } @Override - public List getCraftables(ItemStack module, PipeTileEntity tile) { + public List getCraftables(ItemStack module, PipeTileEntity tile, boolean onlyReturnPossible) { return Collections.emptyList(); } diff --git a/src/main/java/de/ellpeck/prettypipes/misc/ItemFilter.java b/src/main/java/de/ellpeck/prettypipes/misc/ItemFilter.java index db36cc5..5f2471e 100644 --- a/src/main/java/de/ellpeck/prettypipes/misc/ItemFilter.java +++ b/src/main/java/de/ellpeck/prettypipes/misc/ItemFilter.java @@ -82,7 +82,7 @@ public class ItemFilter extends ItemStackHandler { // populate filter from inventories List filters = this.getAllFilters(); for (Direction direction : Direction.values()) { - IItemHandler handler = this.pipe.getItemHandler(direction, null); + IItemHandler handler = this.pipe.getItemHandler(direction); if (handler == null) continue; for (int i = 0; i < handler.getSlots(); i++) { diff --git a/src/main/java/de/ellpeck/prettypipes/network/NetworkLocation.java b/src/main/java/de/ellpeck/prettypipes/network/NetworkLocation.java index 32ac759..0e7e36c 100644 --- a/src/main/java/de/ellpeck/prettypipes/network/NetworkLocation.java +++ b/src/main/java/de/ellpeck/prettypipes/network/NetworkLocation.java @@ -71,7 +71,7 @@ public class NetworkLocation implements INBTSerializable { if (this.handlerCache == null) { PipeNetwork network = PipeNetwork.get(world); PipeTileEntity pipe = network.getPipe(this.pipePos); - this.handlerCache = pipe.getItemHandler(this.direction, null); + this.handlerCache = pipe.getItemHandler(this.direction); } return this.handlerCache; } diff --git a/src/main/java/de/ellpeck/prettypipes/network/PipeItem.java b/src/main/java/de/ellpeck/prettypipes/network/PipeItem.java index a9077ac..c255213 100644 --- a/src/main/java/de/ellpeck/prettypipes/network/PipeItem.java +++ b/src/main/java/de/ellpeck/prettypipes/network/PipeItem.java @@ -189,7 +189,7 @@ public class PipeItem implements INBTSerializable, ILiquidContainer IPipeConnectable connectable = currPipe.getPipeConnectable(dir); if (connectable != null) return connectable.insertItem(currPipe.getWorld(), currPipe.getPos(), dir, this); - IItemHandler handler = currPipe.getItemHandler(dir, this); + IItemHandler handler = currPipe.getItemHandler(dir); if (handler != null) return ItemHandlerHelper.insertItemStacked(handler, this.stack, false); return this.stack; diff --git a/src/main/java/de/ellpeck/prettypipes/network/PipeNetwork.java b/src/main/java/de/ellpeck/prettypipes/network/PipeNetwork.java index 6821a4f..133e743 100644 --- a/src/main/java/de/ellpeck/prettypipes/network/PipeNetwork.java +++ b/src/main/java/de/ellpeck/prettypipes/network/PipeNetwork.java @@ -185,16 +185,29 @@ public class PipeNetwork implements ICapabilitySerializable, GraphL } 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) { + // check existing items + for (NetworkLocation location : this.getOrderedNetworkItems(destPipe)) { remain = this.requestExistingItem(location, destPipe, destInventory, remain, equalityTypes); if (remain.isEmpty()) + return remain; + } + // check craftable items + return this.requestCraftedItem(destPipe, destInventory, remain, equalityTypes); + } + + public ItemStack requestCraftedItem(BlockPos destPipe, BlockPos destInventory, ItemStack stack, ItemEqualityType... equalityTypes) { + for (Pair craftable : this.getOrderedCraftables(destPipe, true)) { + if (!ItemEqualityType.compareItems(stack, craftable.getRight(), equalityTypes)) + continue; + PipeTileEntity pipe = this.getPipe(craftable.getLeft()); + if (pipe == null) + continue; + stack = pipe.craft(destPipe, destInventory, stack, equalityTypes); + if (stack.isEmpty()) break; } - return remain; + return stack; } public ItemStack requestExistingItem(NetworkLocation location, BlockPos destPipe, BlockPos destInventory, ItemStack stack, ItemEqualityType... equalityTypes) { @@ -224,18 +237,19 @@ public class PipeNetwork implements ICapabilitySerializable, GraphL return tile; } - public List> getOrderedCraftables(BlockPos node) { + public List> getOrderedCraftables(BlockPos node, boolean onlyReturnPossible) { if (!this.isNode(node)) return Collections.emptyList(); this.startProfile("get_craftables"); List> craftables = new ArrayList<>(); for (BlockPos dest : this.getOrderedNetworkNodes(node)) { + // don't try to collect recipes for ourselves, since we need these recipes for that + if (dest.equals(node)) + continue; if (!this.world.isBlockLoaded(dest)) continue; PipeTileEntity pipe = this.getPipe(dest); - if (!pipe.canNetworkSee()) - continue; - for (ItemStack stack : pipe.getCraftables()) + for (ItemStack stack : pipe.getCraftables(onlyReturnPossible)) craftables.add(Pair.of(pipe.getPos(), stack)); } this.endProfile(); @@ -254,7 +268,7 @@ public class PipeNetwork implements ICapabilitySerializable, GraphL if (!pipe.canNetworkSee()) continue; for (Direction dir : Direction.values()) { - IItemHandler handler = pipe.getItemHandler(dir, null); + IItemHandler handler = pipe.getItemHandler(dir); if (handler == null) continue; // check if this handler already exists (double-connected pipes, double chests etc.) diff --git a/src/main/java/de/ellpeck/prettypipes/pipe/IPipeConnectable.java b/src/main/java/de/ellpeck/prettypipes/pipe/IPipeConnectable.java index ed8c71a..88338fc 100644 --- a/src/main/java/de/ellpeck/prettypipes/pipe/IPipeConnectable.java +++ b/src/main/java/de/ellpeck/prettypipes/pipe/IPipeConnectable.java @@ -12,10 +12,6 @@ public interface IPipeConnectable { ConnectionType getConnectionType(World world, BlockPos pipePos, Direction direction); - default IItemHandler getItemHandler(World world, BlockPos pipePos, Direction direction, PipeItem item) { - return null; - } - default ItemStack insertItem(World world, BlockPos pipePos, Direction direction, PipeItem item) { return item.stack; } diff --git a/src/main/java/de/ellpeck/prettypipes/pipe/PipeTileEntity.java b/src/main/java/de/ellpeck/prettypipes/pipe/PipeTileEntity.java index be12ac5..f1768cd 100644 --- a/src/main/java/de/ellpeck/prettypipes/pipe/PipeTileEntity.java +++ b/src/main/java/de/ellpeck/prettypipes/pipe/PipeTileEntity.java @@ -20,6 +20,7 @@ import net.minecraft.inventory.container.INamedContainerProvider; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundNBT; +import net.minecraft.nbt.ListNBT; import net.minecraft.profiler.IProfiler; import net.minecraft.tileentity.ChestTileEntity; import net.minecraft.tileentity.ITickableTileEntity; @@ -36,6 +37,7 @@ import net.minecraftforge.items.ItemHandlerHelper; import net.minecraftforge.items.ItemStackHandler; import net.minecraftforge.items.wrapper.InvWrapper; import org.apache.commons.lang3.tuple.Pair; +import org.apache.commons.lang3.tuple.Triple; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -61,6 +63,7 @@ public class PipeTileEntity extends TileEntity implements INamedContainerProvide } }; public final Queue craftIngredientRequests = new ArrayDeque<>(); + public final List> craftResultRequests = new ArrayList<>(); public PressurizerTileEntity pressurizer; public int moduleDropCheck; protected List items; @@ -80,6 +83,15 @@ public class PipeTileEntity extends TileEntity implements INamedContainerProvide compound.put("modules", this.modules.serializeNBT()); compound.putInt("module_drop_check", this.moduleDropCheck); compound.put("requests", Utility.serializeAll(this.craftIngredientRequests)); + ListNBT results = new ListNBT(); + for (Triple triple : this.craftResultRequests) { + CompoundNBT nbt = new CompoundNBT(); + nbt.putLong("dest_pipe", triple.getLeft().toLong()); + nbt.putLong("dest_inv", triple.getMiddle().toLong()); + nbt.put("item", triple.getRight().serializeNBT()); + results.add(nbt); + } + compound.put("craft_results", results); return super.write(compound); } @@ -89,6 +101,15 @@ public class PipeTileEntity extends TileEntity implements INamedContainerProvide this.moduleDropCheck = compound.getInt("module_drop_check"); this.craftIngredientRequests.clear(); this.craftIngredientRequests.addAll(Utility.deserializeAll(compound.getList("requests", NBT.TAG_COMPOUND), NetworkLock::new)); + this.craftResultRequests.clear(); + ListNBT results = compound.getList("craft_results", NBT.TAG_COMPOUND); + for (int i = 0; i < results.size(); i++) { + CompoundNBT nbt = results.getCompound(i); + this.craftResultRequests.add(Triple.of( + BlockPos.fromLong(nbt.getLong("dest_pipe")), + BlockPos.fromLong(nbt.getLong("dest_inv")), + ItemStack.read(nbt.getCompound("item")))); + } super.read(state, compound); } @@ -140,26 +161,6 @@ public class PipeTileEntity extends TileEntity implements INamedContainerProvide PipeNetwork.get(this.world).clearDestinationCache(this.pos); } profiler.endSection(); - - // request crafting ingredients - if (this.world.getGameTime() % 4 == 0 && !this.craftIngredientRequests.isEmpty()) { - PipeNetwork network = PipeNetwork.get(this.world); - NetworkLock request = this.craftIngredientRequests.remove(); - Pair dest = this.getAvailableDestination(request.stack, true, true); - if (dest != null) { - network.requestExistingItem(request.location, this.getPos(), dest.getLeft(), dest.getRight(), ItemEqualityType.NBT); - network.resolveNetworkLock(request); - - // if we couldn't fit all items into the destination, create another request for the rest - ItemStack remain = request.stack.copy(); - remain.shrink(dest.getRight().getCount()); - if (!remain.isEmpty()) { - NetworkLock remainRequest = new NetworkLock(request.location, remain); - this.craftIngredientRequests.add(remainRequest); - network.createNetworkLock(remainRequest); - } - } - } } profiler.startSection("ticking_items"); @@ -197,7 +198,7 @@ public class PipeTileEntity extends TileEntity implements INamedContainerProvide if (!force && this.streamModules().anyMatch(m -> !m.getRight().canAcceptItem(m.getLeft(), this, stack))) return null; for (Direction dir : Direction.values()) { - IItemHandler handler = this.getItemHandler(dir, null); + IItemHandler handler = this.getItemHandler(dir); if (handler == null) continue; ItemStack remain = ItemHandlerHelper.insertItem(handler, stack, true); @@ -259,9 +260,9 @@ public class PipeTileEntity extends TileEntity implements INamedContainerProvide return this.streamModules().allMatch(m -> m.getRight().canPipeWork(m.getLeft(), this)); } - public List getCraftables() { + public List getCraftables(boolean onlyReturnPossible) { return this.streamModules() - .flatMap(m -> m.getRight().getCraftables(m.getLeft(), this).stream()) + .flatMap(m -> m.getRight().getCraftables(m.getLeft(), this, onlyReturnPossible).stream()) .collect(Collectors.toList()); } @@ -276,7 +277,7 @@ public class PipeTileEntity extends TileEntity implements INamedContainerProvide return stack; } - public IItemHandler getItemHandler(Direction dir, PipeItem item) { + public IItemHandler getItemHandler(Direction dir) { if (!this.isConnected(dir)) return null; BlockPos pos = this.pos.offset(dir); @@ -288,13 +289,8 @@ public class PipeTileEntity extends TileEntity implements INamedContainerProvide if (state.getBlock() instanceof ChestBlock) return new InvWrapper(ChestBlock.getChestInventory((ChestBlock) state.getBlock(), state, this.world, tile.getPos(), true)); } - IItemHandler handler = tile.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, dir.getOpposite()).orElse(null); - if (handler != null) - return handler; + return tile.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, dir.getOpposite()).orElse(null); } - IPipeConnectable connectable = this.getPipeConnectable(dir); - if (connectable != null) - return connectable.getItemHandler(this.world, this.pos, dir, item); return null; } @@ -306,7 +302,7 @@ public class PipeTileEntity extends TileEntity implements INamedContainerProvide } public boolean isConnectedInventory(Direction dir) { - return this.getItemHandler(dir, null) != null; + return this.getItemHandler(dir) != null; } public boolean canHaveModules() { diff --git a/src/main/java/de/ellpeck/prettypipes/pipe/modules/craft/CraftingModuleItem.java b/src/main/java/de/ellpeck/prettypipes/pipe/modules/craft/CraftingModuleItem.java index 501de99..b305850 100644 --- a/src/main/java/de/ellpeck/prettypipes/pipe/modules/craft/CraftingModuleItem.java +++ b/src/main/java/de/ellpeck/prettypipes/pipe/modules/craft/CraftingModuleItem.java @@ -8,6 +8,7 @@ import de.ellpeck.prettypipes.misc.ItemEqualityType; import de.ellpeck.prettypipes.misc.ItemFilter; import de.ellpeck.prettypipes.network.NetworkLocation; import de.ellpeck.prettypipes.network.NetworkLock; +import de.ellpeck.prettypipes.network.PipeItem; import de.ellpeck.prettypipes.network.PipeNetwork; import de.ellpeck.prettypipes.pipe.PipeTileEntity; import de.ellpeck.prettypipes.pipe.containers.AbstractPipeContainer; @@ -17,10 +18,16 @@ import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundNBT; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.Direction; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; +import net.minecraftforge.items.CapabilityItemHandler; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.ItemHandlerHelper; import net.minecraftforge.items.ItemStackHandler; import org.apache.commons.lang3.tuple.Pair; +import org.apache.commons.lang3.tuple.Triple; import java.util.ArrayList; import java.util.List; @@ -29,11 +36,15 @@ public class CraftingModuleItem extends ModuleItem { public final int inputSlots; public final int outputSlots; + private final int speed; + private final int maxExtraction; public CraftingModuleItem(String name, ModuleTier tier) { super(name); this.inputSlots = tier.forTier(1, 4, 9); this.outputSlots = tier.forTier(1, 2, 4); + this.speed = tier.forTier(20, 10, 5); + this.maxExtraction = tier.forTier(1, 16, 32); } @Override @@ -52,19 +63,95 @@ public class CraftingModuleItem extends ModuleItem { } @Override - public List getCraftables(ItemStack module, PipeTileEntity tile) { + public boolean canNetworkSee(ItemStack module, PipeTileEntity tile) { + return false; + } + + @Override + public boolean canAcceptItem(ItemStack module, PipeTileEntity tile, ItemStack stack) { + return false; + } + + @Override + public void tick(ItemStack module, PipeTileEntity tile) { + if (tile.getWorld().getGameTime() % this.speed != 0 || !tile.canWork()) + return; + PipeNetwork network = PipeNetwork.get(tile.getWorld()); + // process crafting ingredient requests + if (!tile.craftIngredientRequests.isEmpty()) { + NetworkLock request = tile.craftIngredientRequests.remove(); + Pair dest = tile.getAvailableDestination(request.stack, true, true); + if (dest != null) { + network.requestExistingItem(request.location, tile.getPos(), dest.getLeft(), dest.getRight(), ItemEqualityType.NBT); + network.resolveNetworkLock(request); + + // if we couldn't fit all items into the destination, create another request for the rest + ItemStack remain = request.stack.copy(); + remain.shrink(dest.getRight().getCount()); + if (!remain.isEmpty()) { + NetworkLock remainRequest = new NetworkLock(request.location, remain); + tile.craftIngredientRequests.add(remainRequest); + network.createNetworkLock(remainRequest); + } + } + } + // pull requested crafting results from the network once they are stored + if (!tile.craftResultRequests.isEmpty()) { + List items = network.getOrderedNetworkItems(tile.getPos()); + ItemEqualityType[] equalityTypes = ItemFilter.getEqualityTypes(tile); + for (Triple request : tile.craftResultRequests) { + ItemStack reqItem = request.getRight(); + for (NetworkLocation item : items) { + int amount = item.getItemAmount(tile.getWorld(), reqItem, equalityTypes); + amount -= network.getLockedAmount(item.getPos(), reqItem, equalityTypes); + if (amount <= 0) + continue; + ItemStack remain = reqItem.copy(); + if (remain.getCount() < amount) + amount = remain.getCount(); + remain.shrink(amount); + while (amount > 0) { + ItemStack copy = reqItem.copy(); + copy.setCount(Math.min(reqItem.getMaxStackSize(), amount)); + // we don't need to do any checks here because we just calculated the max amount we can definitely extract + network.requestExistingItem(item, request.getLeft(), request.getMiddle(), copy, equalityTypes); + amount -= copy.getCount(); + } + tile.craftResultRequests.remove(request); + // if we couldn't pull everything, log a new request + if (!remain.isEmpty()) + tile.craftResultRequests.add(Triple.of(request.getLeft(), request.getMiddle(), remain)); + return; + } + } + } + } + + @Override + public List getCraftables(ItemStack module, PipeTileEntity tile, boolean onlyReturnPossible) { + ItemStackHandler output = this.getOutput(module); + if (!onlyReturnPossible) { + // if we only need to return the ones we *could* craft, it's easy + List ret = new ArrayList<>(); + for (int i = 0; i < output.getSlots(); i++) { + ItemStack stack = output.getStackInSlot(i); + if (!stack.isEmpty()) + ret.add(stack); + } + return ret; + } + PipeNetwork network = PipeNetwork.get(tile.getWorld()); List items = network.getOrderedNetworkItems(tile.getPos()); - List> craftables = network.getOrderedCraftables(tile.getPos()); + List> craftables = network.getOrderedCraftables(tile.getPos(), true); ItemEqualityType[] equalityTypes = ItemFilter.getEqualityTypes(tile); - - ItemStackHandler output = this.getOutput(module); ItemStackHandler input = this.getInput(module); List ret = new ArrayList<>(); for (int i = 0; i < output.getSlots(); i++) { ItemStack stack = output.getStackInSlot(i); if (!stack.isEmpty()) { + // figure out how many crafting operations we can actually do with the input items we have in the network int availableCrafts = CraftingTerminalTileEntity.getAvailableCrafts(tile.getWorld(), input.getSlots(), input::getStackInSlot, k -> false, s -> items, craftables, null, equalityTypes); if (availableCrafts > 0) { ItemStack copy = stack.copy(); @@ -79,26 +166,28 @@ public class CraftingModuleItem extends ModuleItem { @Override public ItemStack craft(ItemStack module, PipeTileEntity tile, BlockPos destPipe, BlockPos destInventory, ItemStack stack, ItemEqualityType... equalityTypes) { // check if we can craft the required amount of items - List craftables = this.getCraftables(module, tile); + List craftables = this.getCraftables(module, tile, true); int craftableAmount = craftables.stream() .filter(c -> ItemEqualityType.compareItems(c, stack, equalityTypes)) .mapToInt(ItemStack::getCount).sum(); if (craftableAmount > 0) { PipeNetwork network = PipeNetwork.get(tile.getWorld()); List items = network.getOrderedNetworkItems(tile.getPos()); - List> allCraftables = network.getOrderedCraftables(tile.getPos()); + List> allCraftables = network.getOrderedCraftables(tile.getPos(), true); int resultAmount = this.getResultAmountPerCraft(module, stack, equalityTypes); int requiredCrafts = MathHelper.ceil(stack.getCount() / (float) resultAmount); ItemStackHandler input = this.getInput(module); for (int i = 0; i < input.getSlots(); i++) { - ItemStack in = input.getStackInSlot(i).copy(); + ItemStack in = input.getStackInSlot(i); if (in.isEmpty()) continue; - in.setCount(in.getCount() * requiredCrafts); - List requests = ItemTerminalTileEntity.requestItemLater(tile.getWorld(), destPipe, destInventory, in, items, allCraftables, equalityTypes); - tile.craftIngredientRequests.addAll(requests); + ItemStack copy = in.copy(); + copy.setCount(in.getCount() * requiredCrafts); + Pair, ItemStack> ret = ItemTerminalTileEntity.requestItemLater(tile.getWorld(), destPipe, destInventory, copy, items, allCraftables, equalityTypes); + tile.craftIngredientRequests.addAll(ret.getLeft()); + tile.craftResultRequests.add(Triple.of(destPipe, destInventory, stack)); } ItemStack remain = stack.copy(); 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 3480a6f..3dff4ee 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 @@ -39,7 +39,7 @@ public class ExtractionModuleItem extends ModuleItem { PipeNetwork network = PipeNetwork.get(tile.getWorld()); for (Direction dir : Direction.values()) { - IItemHandler handler = tile.getItemHandler(dir, null); + IItemHandler handler = tile.getItemHandler(dir); if (handler == null) continue; for (int j = 0; j < handler.getSlots(); j++) { diff --git a/src/main/java/de/ellpeck/prettypipes/terminal/ItemTerminalTileEntity.java b/src/main/java/de/ellpeck/prettypipes/terminal/ItemTerminalTileEntity.java index a0d452a..e4b7d1b 100644 --- a/src/main/java/de/ellpeck/prettypipes/terminal/ItemTerminalTileEntity.java +++ b/src/main/java/de/ellpeck/prettypipes/terminal/ItemTerminalTileEntity.java @@ -124,11 +124,13 @@ public class ItemTerminalTileEntity extends TileEntity implements INamedContaine PipeTileEntity pipe = this.getConnectedPipe(); if (pipe == null) return; + PipeNetwork network = PipeNetwork.get(this.world); this.networkItems = this.collectItems(); - this.craftables = PipeNetwork.get(this.world).getOrderedCraftables(pipe.getPos()); + this.craftables = network.getOrderedCraftables(pipe.getPos(), true); if (playersToSync.length > 0) { + // the craftables we display should be displayed even if they can't be crafted! + List clientCraftables = network.getOrderedCraftables(pipe.getPos(), false).stream().map(Pair::getRight).collect(Collectors.toList()); List clientItems = this.networkItems.values().stream().map(NetworkItem::asStack).collect(Collectors.toList()); - List clientCraftables = this.craftables.stream().map(Pair::getRight).collect(Collectors.toList()); for (PlayerEntity player : playersToSync) { if (!(player.openContainer instanceof ItemTerminalContainer)) continue; @@ -153,12 +155,12 @@ public class ItemTerminalTileEntity extends TileEntity implements INamedContaine network.endProfile(); } - public int requestItemImpl(ItemStack stack){ - ItemStack remain = stack.copy(); - NetworkItem item = this.networkItems.get(new EquatableItemStack(remain)); + public int requestItemImpl(ItemStack stack) { + NetworkItem item = this.networkItems.get(new EquatableItemStack(stack)); Collection locations = item == null ? Collections.emptyList() : item.getLocations(); - this.existingRequests.addAll(requestItemLater(this.world, this.getConnectedPipe().getPos(), this.pos, remain, locations, this.craftables, ItemEqualityType.NBT)); - return stack.getCount() - remain.getCount(); + Pair, ItemStack> ret = requestItemLater(this.world, this.getConnectedPipe().getPos(), this.pos, stack, locations, this.craftables, ItemEqualityType.NBT); + this.existingRequests.addAll(ret.getLeft()); + return stack.getCount() - ret.getRight().getCount(); } protected PlayerEntity[] getLookingPlayers() { @@ -210,8 +212,9 @@ public class ItemTerminalTileEntity extends TileEntity implements INamedContaine return new ItemTerminalContainer(Registry.itemTerminalContainer, window, player, this.pos); } - public static List requestItemLater(World world, BlockPos destPipe, BlockPos destInventory, ItemStack stack, Collection locations, List> craftables, ItemEqualityType... equalityTypes) { + public static Pair, ItemStack> requestItemLater(World world, BlockPos destPipe, BlockPos destInventory, ItemStack stack, Collection locations, List> craftables, ItemEqualityType... equalityTypes) { List requests = new ArrayList<>(); + ItemStack remain = stack.copy(); PipeNetwork network = PipeNetwork.get(world); // check for existing items for (NetworkLocation location : locations) { @@ -220,9 +223,9 @@ public class ItemTerminalTileEntity extends TileEntity implements INamedContaine continue; amount -= network.getLockedAmount(location.getPos(), stack, ItemEqualityType.NBT); if (amount > 0) { - if (stack.getCount() < amount) - amount = stack.getCount(); - stack.shrink(amount); + if (remain.getCount() < amount) + amount = remain.getCount(); + remain.shrink(amount); while (amount > 0) { ItemStack copy = stack.copy(); copy.setCount(Math.min(stack.getMaxStackSize(), amount)); @@ -231,21 +234,13 @@ public class ItemTerminalTileEntity extends TileEntity implements INamedContaine requests.add(lock); amount -= copy.getCount(); } - if (stack.isEmpty()) + if (remain.isEmpty()) break; } } // check for craftable items - for (Pair craftable : craftables) { - if (!ItemEqualityType.compareItems(stack, craftable.getRight(), equalityTypes)) - continue; - PipeTileEntity pipe = network.getPipe(craftable.getLeft()); - if (pipe == null) - continue; - stack = pipe.craft(destPipe, destInventory, stack, equalityTypes); - if (stack.isEmpty()) - break; - } - return requests; + if (!remain.isEmpty()) + network.requestCraftedItem(destPipe, destInventory, remain, equalityTypes); + return Pair.of(requests, remain); } }