diff --git a/src/main/java/de/ellpeck/prettypipes/items/IModule.java b/src/main/java/de/ellpeck/prettypipes/items/IModule.java index 6481aa4..faf88b8 100644 --- a/src/main/java/de/ellpeck/prettypipes/items/IModule.java +++ b/src/main/java/de/ellpeck/prettypipes/items/IModule.java @@ -9,6 +9,7 @@ import net.minecraft.util.math.BlockPos; import net.minecraftforge.items.IItemHandler; import java.util.List; +import java.util.Stack; import java.util.function.Consumer; public interface IModule { @@ -35,7 +36,7 @@ public interface IModule { List getAllCraftables(ItemStack module, PipeTileEntity tile); - int getCraftableAmount(ItemStack module, PipeTileEntity tile, Consumer unavailableConsumer, ItemStack stack); + int getCraftableAmount(ItemStack module, PipeTileEntity tile, Consumer unavailableConsumer, ItemStack stack, Stack dependencyChain); ItemStack craft(ItemStack module, PipeTileEntity tile, BlockPos destPipe, Consumer unavailableConsumer, ItemStack stack); diff --git a/src/main/java/de/ellpeck/prettypipes/items/ModuleItem.java b/src/main/java/de/ellpeck/prettypipes/items/ModuleItem.java index 8fd3541..f709c50 100644 --- a/src/main/java/de/ellpeck/prettypipes/items/ModuleItem.java +++ b/src/main/java/de/ellpeck/prettypipes/items/ModuleItem.java @@ -20,6 +20,7 @@ import javax.annotation.Nullable; import java.util.Collections; import java.util.List; import java.util.Optional; +import java.util.Stack; import java.util.function.Consumer; public abstract class ModuleItem extends Item implements IModule { @@ -84,7 +85,7 @@ public abstract class ModuleItem extends Item implements IModule { } @Override - public int getCraftableAmount(ItemStack module, PipeTileEntity tile, Consumer unavailableConsumer, ItemStack stack) { + public int getCraftableAmount(ItemStack module, PipeTileEntity tile, Consumer unavailableConsumer, ItemStack stack, Stack dependencyChain) { return 0; } diff --git a/src/main/java/de/ellpeck/prettypipes/network/PipeNetwork.java b/src/main/java/de/ellpeck/prettypipes/network/PipeNetwork.java index 5400f9a..87167e0 100644 --- a/src/main/java/de/ellpeck/prettypipes/network/PipeNetwork.java +++ b/src/main/java/de/ellpeck/prettypipes/network/PipeNetwork.java @@ -6,6 +6,8 @@ import com.google.common.collect.Streams; import de.ellpeck.prettypipes.PrettyPipes; import de.ellpeck.prettypipes.Registry; import de.ellpeck.prettypipes.Utility; +import de.ellpeck.prettypipes.items.IModule; +import de.ellpeck.prettypipes.items.ModuleItem; import de.ellpeck.prettypipes.misc.ItemEqualityType; import de.ellpeck.prettypipes.packets.PacketHandler; import de.ellpeck.prettypipes.packets.PacketItemEnterPipe; @@ -299,7 +301,7 @@ public class PipeNetwork implements ICapabilitySerializable, GraphL return craftables; } - public int getCraftableAmount(BlockPos node, Consumer unavailableConsumer, ItemStack stack, ItemEqualityType... equalityTypes) { + public int getCraftableAmount(BlockPos node, Consumer unavailableConsumer, ItemStack stack, Stack dependencyChain, ItemEqualityType... equalityTypes) { int total = 0; for (Pair pair : this.getAllCraftables(node)) { if (!ItemEqualityType.compareItems(pair.getRight(), stack, equalityTypes)) @@ -308,7 +310,7 @@ public class PipeNetwork implements ICapabilitySerializable, GraphL continue; PipeTileEntity pipe = this.getPipe(pair.getLeft()); if (pipe != null) - total += pipe.getCraftableAmount(unavailableConsumer, stack); + total += pipe.getCraftableAmount(unavailableConsumer, stack, dependencyChain); } return total; } diff --git a/src/main/java/de/ellpeck/prettypipes/pipe/PipeTileEntity.java b/src/main/java/de/ellpeck/prettypipes/pipe/PipeTileEntity.java index f6b0574..cc4c537 100644 --- a/src/main/java/de/ellpeck/prettypipes/pipe/PipeTileEntity.java +++ b/src/main/java/de/ellpeck/prettypipes/pipe/PipeTileEntity.java @@ -4,6 +4,7 @@ import de.ellpeck.prettypipes.PrettyPipes; import de.ellpeck.prettypipes.Registry; import de.ellpeck.prettypipes.Utility; import de.ellpeck.prettypipes.items.IModule; +import de.ellpeck.prettypipes.items.ModuleItem; import de.ellpeck.prettypipes.network.NetworkLock; import de.ellpeck.prettypipes.network.PipeNetwork; import de.ellpeck.prettypipes.pipe.containers.MainPipeContainer; @@ -306,10 +307,19 @@ public class PipeTileEntity extends TileEntity implements INamedContainerProvide .collect(Collectors.toList()); } - public int getCraftableAmount(Consumer unavailableConsumer, ItemStack stack) { - return this.streamModules() - .mapToInt(m -> m.getRight().getCraftableAmount(m.getLeft(), this, unavailableConsumer, stack)) - .sum(); + public int getCraftableAmount(Consumer unavailableConsumer, ItemStack stack, Stack dependencyChain) { + int total = 0; + Iterator> modules = this.streamModules().iterator(); + while (modules.hasNext()) { + Pair module = modules.next(); + // make sure we don't factor in recursive dependencies like ingot -> block -> ingot etc. + if (!dependencyChain.contains(module.getRight())) { + int amount = module.getRight().getCraftableAmount(module.getLeft(), this, unavailableConsumer, stack, dependencyChain); + if (amount > 0) + total += amount; + } + } + return total; } public ItemStack craft(BlockPos destPipe, Consumer unavailableConsumer, ItemStack stack) { 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 ba9a73f..a14e38c 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 @@ -24,6 +24,7 @@ import org.apache.commons.lang3.tuple.Pair; import java.util.ArrayList; import java.util.List; +import java.util.Stack; import java.util.function.Consumer; public class CraftingModuleItem extends ModuleItem { @@ -136,7 +137,7 @@ public class CraftingModuleItem extends ModuleItem { } @Override - public int getCraftableAmount(ItemStack module, PipeTileEntity tile, Consumer unavailableConsumer, ItemStack stack) { + public int getCraftableAmount(ItemStack module, PipeTileEntity tile, Consumer unavailableConsumer, ItemStack stack, Stack dependencyChain) { PipeNetwork network = PipeNetwork.get(tile.getWorld()); List items = network.getOrderedNetworkItems(tile.getPos()); ItemEqualityType[] equalityTypes = ItemFilter.getEqualityTypes(tile); @@ -147,8 +148,10 @@ public class CraftingModuleItem extends ModuleItem { for (int i = 0; i < output.getSlots(); i++) { ItemStack out = output.getStackInSlot(i); if (!out.isEmpty() && ItemEqualityType.compareItems(out, stack, equalityTypes)) { + // we can craft this item *in general*, so add us to the dependency chain + dependencyChain.push(this); // figure out how many crafting operations we can actually do with the input items we have in the network - int availableCrafts = CraftingTerminalTileEntity.getAvailableCrafts(tile, input.getSlots(), input::getStackInSlot, k -> true, s -> items, unavailableConsumer, equalityTypes); + int availableCrafts = CraftingTerminalTileEntity.getAvailableCrafts(tile, input.getSlots(), input::getStackInSlot, k -> true, s -> items, unavailableConsumer, dependencyChain, equalityTypes); if (availableCrafts > 0) craftable += out.getCount() * availableCrafts; } @@ -159,7 +162,7 @@ public class CraftingModuleItem extends ModuleItem { @Override public ItemStack craft(ItemStack module, PipeTileEntity tile, BlockPos destPipe, Consumer unavailableConsumer, ItemStack stack) { // check if we can craft the required amount of items - int craftableAmount = this.getCraftableAmount(module, tile, unavailableConsumer, stack); + int craftableAmount = this.getCraftableAmount(module, tile, unavailableConsumer, stack, new Stack<>()); if (craftableAmount <= 0) return stack; diff --git a/src/main/java/de/ellpeck/prettypipes/terminal/CraftingTerminalTileEntity.java b/src/main/java/de/ellpeck/prettypipes/terminal/CraftingTerminalTileEntity.java index 61a2ab2..f2ccca5 100644 --- a/src/main/java/de/ellpeck/prettypipes/terminal/CraftingTerminalTileEntity.java +++ b/src/main/java/de/ellpeck/prettypipes/terminal/CraftingTerminalTileEntity.java @@ -5,6 +5,8 @@ import com.google.common.collect.ListMultimap; import de.ellpeck.prettypipes.PrettyPipes; import de.ellpeck.prettypipes.Registry; import de.ellpeck.prettypipes.Utility; +import de.ellpeck.prettypipes.items.IModule; +import de.ellpeck.prettypipes.items.ModuleItem; import de.ellpeck.prettypipes.misc.EquatableItemStack; import de.ellpeck.prettypipes.misc.ItemEqualityType; import de.ellpeck.prettypipes.network.NetworkItem; @@ -87,7 +89,7 @@ public class CraftingTerminalTileEntity extends ItemTerminalTileEntity { if (amount <= 0 && highestAmount <= 0) { PipeTileEntity pipe = this.getConnectedPipe(); if (pipe != null) - amount = PipeNetwork.get(this.world).getCraftableAmount(pipe.getPos(), null, stack, ItemEqualityType.NBT); + amount = PipeNetwork.get(this.world).getCraftableAmount(pipe.getPos(), null, stack, new Stack<>(), ItemEqualityType.NBT); } if (amount > highestAmount) { highestAmount = amount; @@ -117,7 +119,7 @@ public class CraftingTerminalTileEntity extends ItemTerminalTileEntity { int lowestAvailable = getAvailableCrafts(pipe, this.craftItems.getSlots(), i -> ItemHandlerHelper.copyStackWithSize(this.getRequestedCraftItem(i), 1), this::isGhostItem, s -> { NetworkItem item = this.networkItems.get(s); return item != null ? item.getLocations() : Collections.emptyList(); - }, onItemUnavailable(player), ItemEqualityType.NBT); + }, onItemUnavailable(player), new Stack<>(), ItemEqualityType.NBT); if (lowestAvailable > 0) { // if we're limiting the amount, pretend we only have that amount available if (maxAmount < lowestAvailable) @@ -194,7 +196,7 @@ public class CraftingTerminalTileEntity extends ItemTerminalTileEntity { return remain; } - public static int getAvailableCrafts(PipeTileEntity tile, int slots, Function inputFunction, Predicate isGhost, Function> locationsFunction, Consumer unavailableConsumer, ItemEqualityType... equalityTypes) { + public static int getAvailableCrafts(PipeTileEntity tile, int slots, Function inputFunction, Predicate isGhost, Function> locationsFunction, Consumer unavailableConsumer, Stack dependencyChain, ItemEqualityType... equalityTypes) { PipeNetwork network = PipeNetwork.get(tile.getWorld()); // the highest amount we can craft with the items we have int lowestAvailable = Integer.MAX_VALUE; @@ -229,7 +231,7 @@ public class CraftingTerminalTileEntity extends ItemTerminalTileEntity { // check how many craftable items we have and add those on if we need to if (available < lowestAvailable) { - int craftable = network.getCraftableAmount(tile.getPos(), unavailableConsumer, stack.stack, equalityTypes); + int craftable = network.getCraftableAmount(tile.getPos(), unavailableConsumer, stack.stack, dependencyChain, equalityTypes); if (craftable > 0) available += craftable / entry.getValue().intValue(); }