even more fixes!

This commit is contained in:
Ell 2020-10-15 04:15:52 +02:00
parent 27954a9765
commit f38ab16e4d
11 changed files with 178 additions and 144 deletions

View file

@ -10,6 +10,7 @@ import net.minecraft.util.math.BlockPos;
import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandler;
import java.util.List; import java.util.List;
import java.util.function.Predicate;
public interface IModule { public interface IModule {
@ -33,7 +34,9 @@ public interface IModule {
boolean canPipeWork(ItemStack module, PipeTileEntity tile); boolean canPipeWork(ItemStack module, PipeTileEntity tile);
List<ItemStack> getCraftables(ItemStack module, PipeTileEntity tile, boolean onlyReturnPossible); List<ItemStack> getAllCraftables(ItemStack module, PipeTileEntity tile);
ItemStack craft(ItemStack module, PipeTileEntity tile, BlockPos destPipe, BlockPos destInventory, ItemStack stack, ItemEqualityType... equalityTypes); int getCraftableAmount(ItemStack module, PipeTileEntity tile, ItemStack stack, ItemEqualityType... equalityTypes);
ItemStack craft(ItemStack module, PipeTileEntity tile, BlockPos destPipe, ItemStack stack, ItemEqualityType... equalityTypes);
} }

View file

@ -78,12 +78,17 @@ public abstract class ModuleItem extends Item implements IModule {
} }
@Override @Override
public List<ItemStack> getCraftables(ItemStack module, PipeTileEntity tile, boolean onlyReturnPossible) { public List<ItemStack> getAllCraftables(ItemStack module, PipeTileEntity tile) {
return Collections.emptyList(); return Collections.emptyList();
} }
@Override @Override
public ItemStack craft(ItemStack module, PipeTileEntity tile, BlockPos destPipe, BlockPos destInventory, ItemStack stack, ItemEqualityType... equalityTypes) { public int getCraftableAmount(ItemStack module, PipeTileEntity tile, ItemStack stack, ItemEqualityType... equalityTypes) {
return 0;
}
@Override
public ItemStack craft(ItemStack module, PipeTileEntity tile, BlockPos destPipe, ItemStack stack, ItemEqualityType... equalityTypes) {
return stack; return stack;
} }
} }

View file

@ -188,7 +188,7 @@ public class PipeItem implements INBTSerializable<CompoundNBT>, ILiquidContainer
Direction dir = Utility.getDirectionFromOffset(this.destInventory, this.getDestPipe()); Direction dir = Utility.getDirectionFromOffset(this.destInventory, this.getDestPipe());
IPipeConnectable connectable = currPipe.getPipeConnectable(dir); IPipeConnectable connectable = currPipe.getPipeConnectable(dir);
if (connectable != null) if (connectable != null)
return connectable.insertItem(currPipe.getWorld(), currPipe.getPos(), dir, this); return connectable.insertItem(currPipe.getWorld(), currPipe.getPos(), dir, this.stack, false);
IItemHandler handler = currPipe.getItemHandler(dir); IItemHandler handler = currPipe.getItemHandler(dir);
if (handler != null) if (handler != null)
return ItemHandlerHelper.insertItemStacked(handler, this.stack, false); return ItemHandlerHelper.insertItemStacked(handler, this.stack, false);

View file

@ -188,37 +188,36 @@ public class PipeNetwork implements ICapabilitySerializable<CompoundNBT>, GraphL
ItemStack remain = stack.copy(); ItemStack remain = stack.copy();
// check existing items // check existing items
for (NetworkLocation location : this.getOrderedNetworkItems(destPipe)) { for (NetworkLocation location : this.getOrderedNetworkItems(destPipe)) {
remain = this.requestExistingItem(location, destPipe, destInventory, remain, equalityTypes); remain = this.requestExistingItem(location, destPipe, destInventory, null, remain, equalityTypes);
if (remain.isEmpty()) if (remain.isEmpty())
return remain; return remain;
} }
// check craftable items // check craftable items
return this.requestCraftedItem(destPipe, destInventory, remain, equalityTypes); return this.requestCraftedItem(destPipe, remain, equalityTypes);
} }
public ItemStack requestCraftedItem(BlockPos destPipe, BlockPos destInventory, ItemStack stack, ItemEqualityType... equalityTypes) { public ItemStack requestCraftedItem(BlockPos destPipe, ItemStack stack, ItemEqualityType... equalityTypes) {
for (Pair<BlockPos, ItemStack> craftable : this.getOrderedCraftables(destPipe, true)) { for (Pair<BlockPos, ItemStack> craftable : this.getAllCraftables(destPipe)) {
if (!ItemEqualityType.compareItems(stack, craftable.getRight(), equalityTypes)) if (!ItemEqualityType.compareItems(stack, craftable.getRight(), equalityTypes))
continue; continue;
PipeTileEntity pipe = this.getPipe(craftable.getLeft()); PipeTileEntity pipe = this.getPipe(craftable.getLeft());
if (pipe == null) if (pipe == null)
continue; continue;
stack = pipe.craft(destPipe, destInventory, stack, equalityTypes); stack = pipe.craft(destPipe, stack, equalityTypes);
if (stack.isEmpty()) if (stack.isEmpty())
break; break;
} }
return stack; return stack;
} }
public ItemStack requestExistingItem(NetworkLocation location, BlockPos destPipe, BlockPos destInventory, ItemStack stack, ItemEqualityType... equalityTypes) { public ItemStack requestExistingItem(NetworkLocation location, BlockPos destPipe, BlockPos destInventory, NetworkLock ignoredLock, ItemStack stack, ItemEqualityType... equalityTypes) {
if (location.getPos().equals(destInventory)) if (location.getPos().equals(destInventory))
return stack; return stack;
// make sure we don't pull any locked items // make sure we don't pull any locked items
int amount = location.getItemAmount(this.world, stack, equalityTypes); int amount = location.getItemAmount(this.world, stack, equalityTypes);
if (amount <= 0) if (amount <= 0)
return stack; return stack;
// we ignore locks on the destination inventory, since we're probably the ones trying to solve those locks amount -= this.getLockedAmount(location.getPos(), stack, ignoredLock, equalityTypes);
amount -= this.getLockedAmount(location.getPos(), stack, destInventory, equalityTypes);
if (amount <= 0) if (amount <= 0)
return stack; return stack;
ItemStack remain = stack.copy(); ItemStack remain = stack.copy();
@ -249,25 +248,36 @@ public class PipeNetwork implements ICapabilitySerializable<CompoundNBT>, GraphL
return tile; return tile;
} }
public List<Pair<BlockPos, ItemStack>> getOrderedCraftables(BlockPos node, boolean onlyReturnPossible) { public List<Pair<BlockPos, ItemStack>> getAllCraftables(BlockPos node) {
if (!this.isNode(node)) if (!this.isNode(node))
return Collections.emptyList(); return Collections.emptyList();
this.startProfile("get_craftables"); this.startProfile("get_all_craftables");
List<Pair<BlockPos, ItemStack>> craftables = new ArrayList<>(); List<Pair<BlockPos, ItemStack>> craftables = new ArrayList<>();
for (BlockPos dest : this.getOrderedNetworkNodes(node)) { 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)) if (!this.world.isBlockLoaded(dest))
continue; continue;
PipeTileEntity pipe = this.getPipe(dest); PipeTileEntity pipe = this.getPipe(dest);
for (ItemStack stack : pipe.getCraftables(onlyReturnPossible)) for (ItemStack stack : pipe.getAllCraftables())
craftables.add(Pair.of(pipe.getPos(), stack)); craftables.add(Pair.of(pipe.getPos(), stack));
} }
this.endProfile(); this.endProfile();
return craftables; return craftables;
} }
public int getCraftableAmount(BlockPos node, ItemStack stack, ItemEqualityType... equalityTypes) {
int total = 0;
for (Pair<BlockPos, ItemStack> pair : this.getAllCraftables(node)) {
if (!ItemEqualityType.compareItems(pair.getRight(), stack, equalityTypes))
continue;
if (!this.world.isBlockLoaded(pair.getLeft()))
continue;
PipeTileEntity pipe = this.getPipe(pair.getLeft());
if (pipe != null)
total += pipe.getCraftableAmount(stack, equalityTypes);
}
return total;
}
public List<NetworkLocation> getOrderedNetworkItems(BlockPos node) { public List<NetworkLocation> getOrderedNetworkItems(BlockPos node) {
if (!this.isNode(node)) if (!this.isNode(node))
return Collections.emptyList(); return Collections.emptyList();
@ -307,9 +317,9 @@ public class PipeNetwork implements ICapabilitySerializable<CompoundNBT>, GraphL
return this.networkLocks.get(pos); return this.networkLocks.get(pos);
} }
public int getLockedAmount(BlockPos pos, ItemStack stack, BlockPos ignoredLock, ItemEqualityType... equalityTypes) { public int getLockedAmount(BlockPos pos, ItemStack stack, NetworkLock ignoredLock, ItemEqualityType... equalityTypes) {
return this.getNetworkLocks(pos).stream() return this.getNetworkLocks(pos).stream()
.filter(l -> ItemEqualityType.compareItems(l.stack, stack, equalityTypes) && (ignoredLock == null || !ignoredLock.equals(l.location.getPos()))) .filter(l -> !l.equals(ignoredLock) && ItemEqualityType.compareItems(l.stack, stack, equalityTypes))
.mapToInt(l -> l.stack.getCount()).sum(); .mapToInt(l -> l.stack.getCount()).sum();
} }

View file

@ -12,8 +12,8 @@ public interface IPipeConnectable {
ConnectionType getConnectionType(World world, BlockPos pipePos, Direction direction); ConnectionType getConnectionType(World world, BlockPos pipePos, Direction direction);
default ItemStack insertItem(World world, BlockPos pipePos, Direction direction, PipeItem item) { default ItemStack insertItem(World world, BlockPos pipePos, Direction direction, ItemStack stack, boolean simulate) {
return item.stack; return stack;
} }
default boolean allowsModules(World world, BlockPos pipePos, Direction direction) { default boolean allowsModules(World world, BlockPos pipePos, Direction direction) {

View file

@ -63,7 +63,7 @@ public class PipeTileEntity extends TileEntity implements INamedContainerProvide
} }
}; };
public final Queue<NetworkLock> craftIngredientRequests = new ArrayDeque<>(); public final Queue<NetworkLock> craftIngredientRequests = new ArrayDeque<>();
public final List<Triple<BlockPos, BlockPos, ItemStack>> craftResultRequests = new ArrayList<>(); public final List<Pair<BlockPos, ItemStack>> craftResultRequests = new ArrayList<>();
public PressurizerTileEntity pressurizer; public PressurizerTileEntity pressurizer;
public int moduleDropCheck; public int moduleDropCheck;
protected List<PipeItem> items; protected List<PipeItem> items;
@ -84,10 +84,9 @@ public class PipeTileEntity extends TileEntity implements INamedContainerProvide
compound.putInt("module_drop_check", this.moduleDropCheck); compound.putInt("module_drop_check", this.moduleDropCheck);
compound.put("requests", Utility.serializeAll(this.craftIngredientRequests)); compound.put("requests", Utility.serializeAll(this.craftIngredientRequests));
ListNBT results = new ListNBT(); ListNBT results = new ListNBT();
for (Triple<BlockPos, BlockPos, ItemStack> triple : this.craftResultRequests) { for (Pair<BlockPos, ItemStack> triple : this.craftResultRequests) {
CompoundNBT nbt = new CompoundNBT(); CompoundNBT nbt = new CompoundNBT();
nbt.putLong("dest_pipe", triple.getLeft().toLong()); nbt.putLong("dest_pipe", triple.getLeft().toLong());
nbt.putLong("dest_inv", triple.getMiddle().toLong());
nbt.put("item", triple.getRight().serializeNBT()); nbt.put("item", triple.getRight().serializeNBT());
results.add(nbt); results.add(nbt);
} }
@ -105,9 +104,8 @@ public class PipeTileEntity extends TileEntity implements INamedContainerProvide
ListNBT results = compound.getList("craft_results", NBT.TAG_COMPOUND); ListNBT results = compound.getList("craft_results", NBT.TAG_COMPOUND);
for (int i = 0; i < results.size(); i++) { for (int i = 0; i < results.size(); i++) {
CompoundNBT nbt = results.getCompound(i); CompoundNBT nbt = results.getCompound(i);
this.craftResultRequests.add(Triple.of( this.craftResultRequests.add(Pair.of(
BlockPos.fromLong(nbt.getLong("dest_pipe")), BlockPos.fromLong(nbt.getLong("dest_pipe")),
BlockPos.fromLong(nbt.getLong("dest_inv")),
ItemStack.read(nbt.getCompound("item")))); ItemStack.read(nbt.getCompound("item"))));
} }
super.read(state, compound); super.read(state, compound);
@ -260,17 +258,23 @@ public class PipeTileEntity extends TileEntity implements INamedContainerProvide
return this.streamModules().allMatch(m -> m.getRight().canPipeWork(m.getLeft(), this)); return this.streamModules().allMatch(m -> m.getRight().canPipeWork(m.getLeft(), this));
} }
public List<ItemStack> getCraftables(boolean onlyReturnPossible) { public List<ItemStack> getAllCraftables() {
return this.streamModules() return this.streamModules()
.flatMap(m -> m.getRight().getCraftables(m.getLeft(), this, onlyReturnPossible).stream()) .flatMap(m -> m.getRight().getAllCraftables(m.getLeft(), this).stream())
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
public ItemStack craft(BlockPos destPipe, BlockPos destInventory, ItemStack stack, ItemEqualityType... equalityTypes) { public int getCraftableAmount(ItemStack stack, ItemEqualityType... equalityTypes) {
return this.streamModules()
.mapToInt(m -> m.getRight().getCraftableAmount(m.getLeft(), this, stack, equalityTypes))
.sum();
}
public ItemStack craft(BlockPos destPipe, ItemStack stack, ItemEqualityType... equalityTypes) {
Iterator<Pair<ItemStack, IModule>> modules = this.streamModules().iterator(); Iterator<Pair<ItemStack, IModule>> modules = this.streamModules().iterator();
while (modules.hasNext()) { while (modules.hasNext()) {
Pair<ItemStack, IModule> module = modules.next(); Pair<ItemStack, IModule> module = modules.next();
stack = module.getRight().craft(module.getLeft(), this, destPipe, destInventory, stack, equalityTypes); stack = module.getRight().craft(module.getLeft(), this, destPipe, stack, equalityTypes);
if (stack.isEmpty()) if (stack.isEmpty())
break; break;
} }

View file

@ -10,6 +10,7 @@ import de.ellpeck.prettypipes.network.NetworkLocation;
import de.ellpeck.prettypipes.network.NetworkLock; import de.ellpeck.prettypipes.network.NetworkLock;
import de.ellpeck.prettypipes.network.PipeItem; import de.ellpeck.prettypipes.network.PipeItem;
import de.ellpeck.prettypipes.network.PipeNetwork; import de.ellpeck.prettypipes.network.PipeNetwork;
import de.ellpeck.prettypipes.pipe.IPipeConnectable;
import de.ellpeck.prettypipes.pipe.PipeTileEntity; import de.ellpeck.prettypipes.pipe.PipeTileEntity;
import de.ellpeck.prettypipes.pipe.containers.AbstractPipeContainer; import de.ellpeck.prettypipes.pipe.containers.AbstractPipeContainer;
import de.ellpeck.prettypipes.terminal.CraftingTerminalTileEntity; import de.ellpeck.prettypipes.terminal.CraftingTerminalTileEntity;
@ -37,14 +38,12 @@ public class CraftingModuleItem extends ModuleItem {
public final int inputSlots; public final int inputSlots;
public final int outputSlots; public final int outputSlots;
private final int speed; private final int speed;
private final int maxExtraction;
public CraftingModuleItem(String name, ModuleTier tier) { public CraftingModuleItem(String name, ModuleTier tier) {
super(name); super(name);
this.inputSlots = tier.forTier(1, 4, 9); this.inputSlots = tier.forTier(1, 4, 9);
this.outputSlots = tier.forTier(1, 2, 4); this.outputSlots = tier.forTier(1, 2, 4);
this.speed = tier.forTier(20, 10, 5); this.speed = tier.forTier(20, 10, 5);
this.maxExtraction = tier.forTier(1, 16, 32);
} }
@Override @Override
@ -79,15 +78,14 @@ public class CraftingModuleItem extends ModuleItem {
PipeNetwork network = PipeNetwork.get(tile.getWorld()); PipeNetwork network = PipeNetwork.get(tile.getWorld());
// process crafting ingredient requests // process crafting ingredient requests
if (!tile.craftIngredientRequests.isEmpty()) { if (!tile.craftIngredientRequests.isEmpty()) {
NetworkLock request = tile.craftIngredientRequests.remove(); NetworkLock request = tile.craftIngredientRequests.peek();
Pair<BlockPos, ItemStack> dest = tile.getAvailableDestination(request.stack, true, true); Pair<BlockPos, ItemStack> dest = tile.getAvailableDestination(request.stack, true, true);
if (dest != null) { if (dest != null) {
network.requestExistingItem(request.location, tile.getPos(), dest.getLeft(), dest.getRight(), ItemEqualityType.NBT); ItemStack remain = network.requestExistingItem(request.location, tile.getPos(), dest.getLeft(), request, dest.getRight(), ItemEqualityType.NBT);
if (remain.getCount() != request.stack.getCount()) {
network.resolveNetworkLock(request); network.resolveNetworkLock(request);
tile.craftIngredientRequests.remove();
// if we couldn't fit all items into the destination, create another request for the rest // 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()) { if (!remain.isEmpty()) {
NetworkLock remainRequest = new NetworkLock(request.location, remain); NetworkLock remainRequest = new NetworkLock(request.location, remain);
tile.craftIngredientRequests.add(remainRequest); tile.craftIngredientRequests.add(remainRequest);
@ -95,14 +93,34 @@ public class CraftingModuleItem extends ModuleItem {
} }
} }
} }
}
// pull requested crafting results from the network once they are stored // pull requested crafting results from the network once they are stored
if (!tile.craftResultRequests.isEmpty()) { if (!tile.craftResultRequests.isEmpty()) {
List<NetworkLocation> items = network.getOrderedNetworkItems(tile.getPos()); List<NetworkLocation> items = network.getOrderedNetworkItems(tile.getPos());
ItemEqualityType[] equalityTypes = ItemFilter.getEqualityTypes(tile); ItemEqualityType[] equalityTypes = ItemFilter.getEqualityTypes(tile);
for (Triple<BlockPos, BlockPos, ItemStack> request : tile.craftResultRequests) { for (Pair<BlockPos, ItemStack> request : tile.craftResultRequests) {
ItemStack remain = request.getRight().copy(); ItemStack remain = request.getRight().copy();
PipeTileEntity destPipe = network.getPipe(request.getLeft());
if (destPipe != null) {
Pair<BlockPos, ItemStack> dest = destPipe.getAvailableDestination(remain, true, true);
if (dest == null) {
// if there's no available destination, try inserting into terminals etc.
for (Direction dir : Direction.values()) {
IPipeConnectable connectable = destPipe.getPipeConnectable(dir);
if (connectable == null)
continue;
ItemStack connectableRemain = connectable.insertItem(tile.getWorld(), destPipe.getPos(), dir, remain, true);
if (connectableRemain.getCount() != remain.getCount()) {
ItemStack inserted = remain.copy();
inserted.shrink(connectableRemain.getCount());
dest = Pair.of(destPipe.getPos().offset(dir), inserted);
break;
}
}
}
for (NetworkLocation item : items) { for (NetworkLocation item : items) {
remain = network.requestExistingItem(item, request.getLeft(), request.getMiddle(), remain, equalityTypes); ItemStack requestRemain = network.requestExistingItem(item, request.getLeft(), dest.getLeft(), null, dest.getRight(), equalityTypes);
remain.shrink(dest.getRight().getCount() - requestRemain.getCount());
if (remain.isEmpty()) if (remain.isEmpty())
break; break;
} }
@ -110,19 +128,18 @@ public class CraftingModuleItem extends ModuleItem {
tile.craftResultRequests.remove(request); tile.craftResultRequests.remove(request);
// if we couldn't pull everything, log a new request // if we couldn't pull everything, log a new request
if (!remain.isEmpty()) if (!remain.isEmpty())
tile.craftResultRequests.add(Triple.of(request.getLeft(), request.getMiddle(), remain)); tile.craftResultRequests.add(Pair.of(request.getLeft(), remain));
return; return;
} }
} }
} }
} }
}
@Override @Override
public List<ItemStack> getCraftables(ItemStack module, PipeTileEntity tile, boolean onlyReturnPossible) { public List<ItemStack> getAllCraftables(ItemStack module, PipeTileEntity tile) {
ItemStackHandler output = this.getOutput(module);
if (!onlyReturnPossible) {
// if we only need to return the ones we *could* craft, it's easy
List<ItemStack> ret = new ArrayList<>(); List<ItemStack> ret = new ArrayList<>();
ItemStackHandler output = this.getOutput(module);
for (int i = 0; i < output.getSlots(); i++) { for (int i = 0; i < output.getSlots(); i++) {
ItemStack stack = output.getStackInSlot(i); ItemStack stack = output.getStackInSlot(i);
if (!stack.isEmpty()) if (!stack.isEmpty())
@ -131,42 +148,39 @@ public class CraftingModuleItem extends ModuleItem {
return ret; return ret;
} }
@Override
public int getCraftableAmount(ItemStack module, PipeTileEntity tile, ItemStack stack, ItemEqualityType... equalityTypes) {
PipeNetwork network = PipeNetwork.get(tile.getWorld()); PipeNetwork network = PipeNetwork.get(tile.getWorld());
List<NetworkLocation> items = network.getOrderedNetworkItems(tile.getPos()); List<NetworkLocation> items = network.getOrderedNetworkItems(tile.getPos());
List<Pair<BlockPos, ItemStack>> craftables = network.getOrderedCraftables(tile.getPos(), true);
ItemEqualityType[] equalityTypes = ItemFilter.getEqualityTypes(tile);
ItemStackHandler input = this.getInput(module); ItemStackHandler input = this.getInput(module);
List<ItemStack> ret = new ArrayList<>(); int craftable = 0;
ItemStackHandler output = this.getOutput(module);
for (int i = 0; i < output.getSlots(); i++) { for (int i = 0; i < output.getSlots(); i++) {
ItemStack stack = output.getStackInSlot(i); ItemStack out = output.getStackInSlot(i);
if (!stack.isEmpty()) { if (!out.isEmpty() && ItemEqualityType.compareItems(out, stack, equalityTypes)) {
// figure out how many crafting operations we can actually do with the input items we have in the network // 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); int availableCrafts = CraftingTerminalTileEntity.getAvailableCrafts(tile, input.getSlots(), input::getStackInSlot, k -> true, s -> items, null, equalityTypes);
if (availableCrafts > 0) { if (availableCrafts > 0)
ItemStack copy = stack.copy(); craftable += out.getCount() * availableCrafts;
copy.setCount(stack.getCount() * availableCrafts);
ret.add(copy);
} }
} }
} return craftable;
return ret;
} }
@Override @Override
public ItemStack craft(ItemStack module, PipeTileEntity tile, BlockPos destPipe, BlockPos destInventory, ItemStack stack, ItemEqualityType... equalityTypes) { public ItemStack craft(ItemStack module, PipeTileEntity tile, BlockPos destPipe, ItemStack stack, ItemEqualityType... equalityTypes) {
// check if we can craft the required amount of items // check if we can craft the required amount of items
List<ItemStack> craftables = this.getCraftables(module, tile, true); int craftableAmount = this.getCraftableAmount(module, tile, stack, equalityTypes);
int craftableAmount = craftables.stream() if (craftableAmount <= 0)
.filter(c -> ItemEqualityType.compareItems(c, stack, equalityTypes)) return stack;
.mapToInt(ItemStack::getCount).sum();
if (craftableAmount > 0) {
PipeNetwork network = PipeNetwork.get(tile.getWorld()); PipeNetwork network = PipeNetwork.get(tile.getWorld());
List<NetworkLocation> items = network.getOrderedNetworkItems(tile.getPos()); List<NetworkLocation> items = network.getOrderedNetworkItems(tile.getPos());
List<Pair<BlockPos, ItemStack>> allCraftables = network.getOrderedCraftables(tile.getPos(), true);
int resultAmount = this.getResultAmountPerCraft(module, stack, equalityTypes); int resultAmount = this.getResultAmountPerCraft(module, stack, equalityTypes);
int requiredCrafts = MathHelper.ceil(stack.getCount() / (float) resultAmount); int requiredCrafts = MathHelper.ceil(stack.getCount() / (float) resultAmount);
int toCraft = Math.min(craftableAmount, requiredCrafts);
ItemStackHandler input = this.getInput(module); ItemStackHandler input = this.getInput(module);
for (int i = 0; i < input.getSlots(); i++) { for (int i = 0; i < input.getSlots(); i++) {
@ -174,18 +188,18 @@ public class CraftingModuleItem extends ModuleItem {
if (in.isEmpty()) if (in.isEmpty())
continue; continue;
ItemStack copy = in.copy(); ItemStack copy = in.copy();
copy.setCount(in.getCount() * requiredCrafts); copy.setCount(in.getCount() * toCraft);
Pair<List<NetworkLock>, ItemStack> ret = ItemTerminalTileEntity.requestItemLater(tile.getWorld(), destPipe, destInventory, copy, items, allCraftables, equalityTypes); Pair<List<NetworkLock>, ItemStack> ret = ItemTerminalTileEntity.requestItemLater(tile.getWorld(), tile.getPos(), copy, items, equalityTypes);
tile.craftIngredientRequests.addAll(ret.getLeft()); tile.craftIngredientRequests.addAll(ret.getLeft());
tile.craftResultRequests.add(Triple.of(destPipe, destInventory, stack));
} }
ItemStack result = stack.copy();
result.setCount(resultAmount * toCraft);
tile.craftResultRequests.add(Pair.of(destPipe, result));
ItemStack remain = stack.copy(); ItemStack remain = stack.copy();
remain.shrink(craftableAmount); remain.shrink(toCraft);
return remain; return remain;
} else {
return stack;
}
} }
public ItemStackHandler getInput(ItemStack module) { public ItemStackHandler getInput(ItemStack module) {

View file

@ -23,11 +23,10 @@ public class CraftingTerminalBlock extends ItemTerminalBlock {
} }
@Override @Override
public ItemStack insertItem(World world, BlockPos pipePos, Direction direction, PipeItem item) { public ItemStack insertItem(World world, BlockPos pipePos, Direction direction, ItemStack remain, boolean simulate) {
BlockPos pos = pipePos.offset(direction); BlockPos pos = pipePos.offset(direction);
CraftingTerminalTileEntity tile = Utility.getTileEntity(CraftingTerminalTileEntity.class, world, pos); CraftingTerminalTileEntity tile = Utility.getTileEntity(CraftingTerminalTileEntity.class, world, pos);
if (tile != null) { if (tile != null) {
ItemStack remain = item.stack;
int lowestSlot = -1; int lowestSlot = -1;
do { do {
for (int i = 0; i < tile.craftItems.getSlots(); i++) { for (int i = 0; i < tile.craftItems.getSlots(); i++) {
@ -41,15 +40,15 @@ public class CraftingTerminalBlock extends ItemTerminalBlock {
if (lowestSlot >= 0) { if (lowestSlot >= 0) {
ItemStack copy = remain.copy(); ItemStack copy = remain.copy();
copy.setCount(1); copy.setCount(1);
remain.shrink(1 - tile.craftItems.insertItem(lowestSlot, copy, false).getCount()); remain.shrink(1 - tile.craftItems.insertItem(lowestSlot, copy, simulate).getCount());
if (remain.isEmpty()) if (remain.isEmpty())
return ItemStack.EMPTY; return ItemStack.EMPTY;
} }
} }
while (lowestSlot >= 0); while (lowestSlot >= 0);
return ItemHandlerHelper.insertItemStacked(tile.items, remain, false); return ItemHandlerHelper.insertItemStacked(tile.items, remain, simulate);
} }
return item.stack; return remain;
} }
} }

View file

@ -12,6 +12,7 @@ import de.ellpeck.prettypipes.network.NetworkLock;
import de.ellpeck.prettypipes.network.PipeNetwork; import de.ellpeck.prettypipes.network.PipeNetwork;
import de.ellpeck.prettypipes.packets.PacketGhostSlot; import de.ellpeck.prettypipes.packets.PacketGhostSlot;
import de.ellpeck.prettypipes.packets.PacketHandler; import de.ellpeck.prettypipes.packets.PacketHandler;
import de.ellpeck.prettypipes.pipe.PipeTileEntity;
import de.ellpeck.prettypipes.terminal.containers.CraftingTerminalContainer; import de.ellpeck.prettypipes.terminal.containers.CraftingTerminalContainer;
import de.ellpeck.prettypipes.terminal.containers.ItemTerminalContainer; import de.ellpeck.prettypipes.terminal.containers.ItemTerminalContainer;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
@ -100,14 +101,17 @@ public class CraftingTerminalTileEntity extends ItemTerminalTileEntity {
} }
public void requestCraftingItems(PlayerEntity player, int maxAmount) { public void requestCraftingItems(PlayerEntity player, int maxAmount) {
PipeTileEntity pipe = this.getConnectedPipe();
if (pipe == null)
return;
PipeNetwork network = PipeNetwork.get(this.world); PipeNetwork network = PipeNetwork.get(this.world);
network.startProfile("terminal_request_crafting"); network.startProfile("terminal_request_crafting");
this.updateItems(); this.updateItems();
// get the amount of crafts that we can do // get the amount of crafts that we can do
int lowestAvailable = getAvailableCrafts(this.world, this.craftItems.getSlots(), this::getRequestedCraftItem, this::isGhostItem, s -> { int lowestAvailable = getAvailableCrafts(pipe, this.craftItems.getSlots(), this::getRequestedCraftItem, this::isGhostItem, s -> {
NetworkItem item = this.networkItems.get(s); NetworkItem item = this.networkItems.get(s);
return item != null ? item.getLocations() : Collections.emptyList(); return item != null ? item.getLocations() : Collections.emptyList();
}, this.craftables, s -> player.sendMessage(new TranslationTextComponent("info." + PrettyPipes.ID + ".not_found", s.getDisplayName()).setStyle(Style.EMPTY.setFormatting(TextFormatting.RED)), UUID.randomUUID()), ItemEqualityType.NBT); }, s -> player.sendMessage(new TranslationTextComponent("info." + PrettyPipes.ID + ".not_found", s.getDisplayName()).setStyle(Style.EMPTY.setFormatting(TextFormatting.RED)), UUID.randomUUID()), ItemEqualityType.NBT);
if (lowestAvailable > 0) { if (lowestAvailable > 0) {
// if we're limiting the amount, pretend we only have that amount available // if we're limiting the amount, pretend we only have that amount available
if (maxAmount < lowestAvailable) if (maxAmount < lowestAvailable)
@ -148,8 +152,8 @@ public class CraftingTerminalTileEntity extends ItemTerminalTileEntity {
return new CraftingTerminalContainer(Registry.craftingTerminalContainer, window, player, this.pos); return new CraftingTerminalContainer(Registry.craftingTerminalContainer, window, player, this.pos);
} }
public static int getAvailableCrafts(World world, int slots, Function<Integer, ItemStack> inputFunction, Predicate<Integer> isGhost, Function<EquatableItemStack, Collection<NetworkLocation>> locationsFunction, List<Pair<BlockPos, ItemStack>> craftables, Consumer<ItemStack> unavailableConsumer, ItemEqualityType... equalityTypes) { public static int getAvailableCrafts(PipeTileEntity tile, int slots, Function<Integer, ItemStack> inputFunction, Predicate<Integer> isGhost, Function<EquatableItemStack, Collection<NetworkLocation>> locationsFunction, Consumer<ItemStack> unavailableConsumer, ItemEqualityType... equalityTypes) {
PipeNetwork network = PipeNetwork.get(world); PipeNetwork network = PipeNetwork.get(tile.getWorld());
// the highest amount we can craft with the items we have // the highest amount we can craft with the items we have
int lowestAvailable = Integer.MAX_VALUE; int lowestAvailable = Integer.MAX_VALUE;
// this is the amount of items required for each ingredient when crafting ONE // this is the amount of items required for each ingredient when crafting ONE
@ -170,7 +174,7 @@ public class CraftingTerminalTileEntity extends ItemTerminalTileEntity {
// total amount of available items of this type // total amount of available items of this type
int available = 0; int available = 0;
for (NetworkLocation location : locationsFunction.apply(stack)) { for (NetworkLocation location : locationsFunction.apply(stack)) {
int amount = location.getItemAmount(world, stack.stack, equalityTypes); int amount = location.getItemAmount(tile.getWorld(), stack.stack, equalityTypes);
if (amount <= 0) if (amount <= 0)
continue; continue;
amount -= network.getLockedAmount(location.getPos(), stack.stack, null, equalityTypes); amount -= network.getLockedAmount(location.getPos(), stack.stack, null, equalityTypes);
@ -180,11 +184,10 @@ public class CraftingTerminalTileEntity extends ItemTerminalTileEntity {
// we have available for each crafting slot that contains this item // we have available for each crafting slot that contains this item
available /= entry.getValue().intValue(); available /= entry.getValue().intValue();
// check how many craftable items we have and add those on // check how many craftable items we have and add those on if we need to
if (!craftables.isEmpty()) { if (available < lowestAvailable) {
int craftable = craftables.stream().map(Pair::getRight) int craftable = network.getCraftableAmount(tile.getPos(), stack.stack, equalityTypes);
.filter(c -> ItemEqualityType.compareItems(c, stack.stack)) if (craftable > 0)
.mapToInt(ItemStack::getCount).sum();
available += craftable / entry.getValue().intValue(); available += craftable / entry.getValue().intValue();
} }

View file

@ -69,12 +69,12 @@ public class ItemTerminalBlock extends ContainerBlock implements IPipeConnectabl
} }
@Override @Override
public ItemStack insertItem(World world, BlockPos pipePos, Direction direction, PipeItem item) { public ItemStack insertItem(World world, BlockPos pipePos, Direction direction, ItemStack stack, boolean simulate) {
BlockPos pos = pipePos.offset(direction); BlockPos pos = pipePos.offset(direction);
ItemTerminalTileEntity tile = Utility.getTileEntity(ItemTerminalTileEntity.class, world, pos); ItemTerminalTileEntity tile = Utility.getTileEntity(ItemTerminalTileEntity.class, world, pos);
if (tile != null) if (tile != null)
return ItemHandlerHelper.insertItemStacked(tile.items, item.stack, false); return ItemHandlerHelper.insertItemStacked(tile.items, stack, simulate);
return item.stack; return stack;
} }
@Override @Override

View file

@ -52,8 +52,7 @@ public class ItemTerminalTileEntity extends TileEntity implements INamedContaine
return true; return true;
} }
}; };
public Map<EquatableItemStack, NetworkItem> networkItems; protected Map<EquatableItemStack, NetworkItem> networkItems;
public List<Pair<BlockPos, ItemStack>> craftables;
private final Queue<NetworkLock> existingRequests = new ArrayDeque<>(); private final Queue<NetworkLock> existingRequests = new ArrayDeque<>();
protected ItemTerminalTileEntity(TileEntityType<?> tileEntityTypeIn) { protected ItemTerminalTileEntity(TileEntityType<?> tileEntityTypeIn) {
@ -90,7 +89,7 @@ public class ItemTerminalTileEntity extends TileEntity implements INamedContaine
if (!this.existingRequests.isEmpty()) { if (!this.existingRequests.isEmpty()) {
NetworkLock request = this.existingRequests.remove(); NetworkLock request = this.existingRequests.remove();
network.resolveNetworkLock(request); network.resolveNetworkLock(request);
network.requestExistingItem(request.location, pipe.getPos(), this.pos, request.stack, ItemEqualityType.NBT); network.requestExistingItem(request.location, pipe.getPos(), this.pos, request, request.stack, ItemEqualityType.NBT);
update = true; update = true;
} }
} }
@ -124,13 +123,10 @@ public class ItemTerminalTileEntity extends TileEntity implements INamedContaine
PipeTileEntity pipe = this.getConnectedPipe(); PipeTileEntity pipe = this.getConnectedPipe();
if (pipe == null) if (pipe == null)
return; return;
PipeNetwork network = PipeNetwork.get(this.world);
this.networkItems = this.collectItems(); this.networkItems = this.collectItems();
this.craftables = network.getOrderedCraftables(pipe.getPos(), true);
if (playersToSync.length > 0) { if (playersToSync.length > 0) {
// the craftables we display should be displayed even if they can't be crafted!
List<ItemStack> clientCraftables = network.getOrderedCraftables(pipe.getPos(), false).stream().map(Pair::getRight).collect(Collectors.toList());
List<ItemStack> clientItems = this.networkItems.values().stream().map(NetworkItem::asStack).collect(Collectors.toList()); List<ItemStack> clientItems = this.networkItems.values().stream().map(NetworkItem::asStack).collect(Collectors.toList());
List<ItemStack> clientCraftables = PipeNetwork.get(this.world).getAllCraftables(pipe.getPos()).stream().map(Pair::getRight).collect(Collectors.toList());
for (PlayerEntity player : playersToSync) { for (PlayerEntity player : playersToSync) {
if (!(player.openContainer instanceof ItemTerminalContainer)) if (!(player.openContainer instanceof ItemTerminalContainer))
continue; continue;
@ -158,7 +154,7 @@ public class ItemTerminalTileEntity extends TileEntity implements INamedContaine
public int requestItemImpl(ItemStack stack) { public int requestItemImpl(ItemStack stack) {
NetworkItem item = this.networkItems.get(new EquatableItemStack(stack)); NetworkItem item = this.networkItems.get(new EquatableItemStack(stack));
Collection<NetworkLocation> locations = item == null ? Collections.emptyList() : item.getLocations(); Collection<NetworkLocation> locations = item == null ? Collections.emptyList() : item.getLocations();
Pair<List<NetworkLock>, ItemStack> ret = requestItemLater(this.world, this.getConnectedPipe().getPos(), this.pos, stack, locations, this.craftables, ItemEqualityType.NBT); Pair<List<NetworkLock>, ItemStack> ret = requestItemLater(this.world, this.getConnectedPipe().getPos(), stack, locations, ItemEqualityType.NBT);
this.existingRequests.addAll(ret.getLeft()); this.existingRequests.addAll(ret.getLeft());
return stack.getCount() - ret.getRight().getCount(); return stack.getCount() - ret.getRight().getCount();
} }
@ -212,7 +208,7 @@ public class ItemTerminalTileEntity extends TileEntity implements INamedContaine
return new ItemTerminalContainer(Registry.itemTerminalContainer, window, player, this.pos); return new ItemTerminalContainer(Registry.itemTerminalContainer, window, player, this.pos);
} }
public static Pair<List<NetworkLock>, ItemStack> requestItemLater(World world, BlockPos destPipe, BlockPos destInventory, ItemStack stack, Collection<NetworkLocation> locations, List<Pair<BlockPos, ItemStack>> craftables, ItemEqualityType... equalityTypes) { public static Pair<List<NetworkLock>, ItemStack> requestItemLater(World world, BlockPos destPipe, ItemStack stack, Collection<NetworkLocation> locations, ItemEqualityType... equalityTypes) {
List<NetworkLock> requests = new ArrayList<>(); List<NetworkLock> requests = new ArrayList<>();
ItemStack remain = stack.copy(); ItemStack remain = stack.copy();
PipeNetwork network = PipeNetwork.get(world); PipeNetwork network = PipeNetwork.get(world);
@ -221,7 +217,7 @@ public class ItemTerminalTileEntity extends TileEntity implements INamedContaine
int amount = location.getItemAmount(world, stack, ItemEqualityType.NBT); int amount = location.getItemAmount(world, stack, ItemEqualityType.NBT);
if (amount <= 0) if (amount <= 0)
continue; continue;
amount -= network.getLockedAmount(location.getPos(), stack, destInventory, ItemEqualityType.NBT); amount -= network.getLockedAmount(location.getPos(), stack, null, ItemEqualityType.NBT);
if (amount > 0) { if (amount > 0) {
if (remain.getCount() < amount) if (remain.getCount() < amount)
amount = remain.getCount(); amount = remain.getCount();
@ -240,7 +236,7 @@ public class ItemTerminalTileEntity extends TileEntity implements INamedContaine
} }
// check for craftable items // check for craftable items
if (!remain.isEmpty()) if (!remain.isEmpty())
network.requestCraftedItem(destPipe, destInventory, remain, equalityTypes); remain = network.requestCraftedItem(destPipe, remain, equalityTypes);
return Pair.of(requests, remain); return Pair.of(requests, remain);
} }
} }