diff --git a/src/main/java/de/ellpeck/prettypipes/misc/DirectionSelector.java b/src/main/java/de/ellpeck/prettypipes/misc/DirectionSelector.java index cebaadc..0af8a19 100644 --- a/src/main/java/de/ellpeck/prettypipes/misc/DirectionSelector.java +++ b/src/main/java/de/ellpeck/prettypipes/misc/DirectionSelector.java @@ -13,9 +13,13 @@ import net.minecraft.world.item.ItemStack; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.client.gui.widget.ExtendedButton; +import org.apache.commons.lang3.ArrayUtils; public class DirectionSelector { + private static final Direction[] ALL = ArrayUtils.addAll(Direction.values(), (Direction) null); + + // null means old behavior, which is all directions private Direction direction; private boolean modified; @@ -35,8 +39,8 @@ public class DirectionSelector { @Override public Component getMessage() { var pipe = DirectionSelector.this.pipe; - var dir = DirectionSelector.this.getDirection(); - MutableComponent msg = new TranslatableComponent("dir." + PrettyPipes.ID + "." + (dir != null ? dir.getName() : "none")); + var dir = DirectionSelector.this.direction; + MutableComponent msg = new TranslatableComponent("dir." + PrettyPipes.ID + "." + (dir != null ? dir.getName() : "all")); if (dir != null) { var blockName = pipe.getItemHandler(dir) != null ? pipe.getLevel().getBlockState(pipe.getBlockPos().relative(dir)).getBlock().getName() : null; if (blockName != null) @@ -48,7 +52,10 @@ public class DirectionSelector { } public void onButtonPacket() { - var dir = this.getValidDirection(this.getDirection()); + var dir = this.direction; + do { + dir = DirectionSelector.ALL[(ArrayUtils.indexOf(DirectionSelector.ALL, dir) + 1) % DirectionSelector.ALL.length]; + } while (!this.isDirectionValid(dir)); if (this.direction != dir) { this.direction = dir; this.modified = true; @@ -61,9 +68,8 @@ public class DirectionSelector { this.modified = false; var tag = new CompoundTag(); - var dir = this.getDirection(); - if (dir != null) - tag.putString("direction", dir.getName()); + if (this.direction != null) + tag.putString("direction", this.direction.getName()); this.stack.getOrCreateTag().put("direction_selector", tag); } @@ -74,34 +80,25 @@ public class DirectionSelector { } } - public Direction getDirection() { - // default to the first direction with a container if ours is invalid or unset - if (this.direction == null || !this.isDirectionValid(this.direction)) - return this.getValidDirection(this.direction); - return this.direction; + public Direction[] directions() { + return this.direction != null ? new Direction[]{this.direction} : Direction.values(); + } + + public boolean has(Direction dir) { + return this.direction == null || this.direction == dir; } private boolean isDirectionValid(Direction dir) { + if (dir == null) + return true; if (this.pipe.getItemHandler(dir) == null) return false; return this.pipe.streamModules() .filter(p -> p.getLeft() != this.stack) .map(p -> p.getRight().getDirectionSelector(p.getLeft(), this.pipe)) - // don't use getDirection here because we don't want a stack overflow .noneMatch(p -> p != null && p.direction == dir); } - private Direction getValidDirection(Direction dir) { - if (dir == null) - dir = Direction.UP; - for (var i = 0; i < 6; i++) { - dir = Direction.from3DDataValue(dir.get3DDataValue() + 1); - if (this.isDirectionValid(dir)) - return dir; - } - return null; - } - public interface IDirectionContainer { DirectionSelector getSelector(); diff --git a/src/main/java/de/ellpeck/prettypipes/network/PipeNetwork.java b/src/main/java/de/ellpeck/prettypipes/network/PipeNetwork.java index 8558593..a7c30c8 100644 --- a/src/main/java/de/ellpeck/prettypipes/network/PipeNetwork.java +++ b/src/main/java/de/ellpeck/prettypipes/network/PipeNetwork.java @@ -147,7 +147,7 @@ public class PipeNetwork implements ICapabilitySerializable, GraphL if (!this.world.isLoaded(pipePos)) continue; var pipe = this.getPipe(pipePos); - var dest = pipe.getAvailableDestination(stack, false, preventOversending); + var dest = pipe.getAvailableDestination(Direction.values(), stack, false, preventOversending); if (dest == null || dest.getLeft().equals(startInventory)) continue; var sup = (Function) speed -> itemSupplier.apply(dest.getRight(), speed); diff --git a/src/main/java/de/ellpeck/prettypipes/pipe/PipeBlockEntity.java b/src/main/java/de/ellpeck/prettypipes/pipe/PipeBlockEntity.java index 0316b62..cbfe68c 100644 --- a/src/main/java/de/ellpeck/prettypipes/pipe/PipeBlockEntity.java +++ b/src/main/java/de/ellpeck/prettypipes/pipe/PipeBlockEntity.java @@ -167,7 +167,7 @@ public class PipeBlockEntity extends BlockEntity implements MenuProvider, IPipeC } public Pair getAvailableDestinationOrConnectable(ItemStack stack, boolean force, boolean preventOversending) { - var dest = this.getAvailableDestination(stack, force, preventOversending); + var dest = this.getAvailableDestination(Direction.values(), stack, force, preventOversending); if (dest != null) return dest; // if there's no available destination, try inserting into terminals etc. @@ -185,69 +185,66 @@ public class PipeBlockEntity extends BlockEntity implements MenuProvider, IPipeC return null; } - public Pair getAvailableDestination(ItemStack stack, boolean force, boolean preventOversending) { - for (var dir : Direction.values()) { - var dest = this.getAvailableDestination(dir, stack, force, preventOversending); - if (!dest.isEmpty()) - return Pair.of(this.worldPosition.relative(dir), dest); + public Pair getAvailableDestination(Direction[] directions, ItemStack stack, boolean force, boolean preventOversending) { + if (!this.canWork()) + return null; + for (var dir : directions) { + var handler = this.getItemHandler(dir); + if (handler == null) + continue; + if (!force && this.streamModules().anyMatch(m -> !m.getRight().canAcceptItem(m.getLeft(), this, stack, dir, handler))) + continue; + var remain = ItemHandlerHelper.insertItem(handler, stack, true); + // did we insert anything? + if (remain.getCount() == stack.getCount()) + continue; + var toInsert = stack.copy(); + toInsert.shrink(remain.getCount()); + // limit to the max amount that modules allow us to insert + var maxAmount = this.streamModules().mapToInt(m -> m.getRight().getMaxInsertionAmount(m.getLeft(), this, stack, handler)).min().orElse(Integer.MAX_VALUE); + if (maxAmount < toInsert.getCount()) + toInsert.setCount(maxAmount); + var offset = this.worldPosition.relative(dir); + if (preventOversending || maxAmount < Integer.MAX_VALUE) { + var network = PipeNetwork.get(this.level); + // these are the items that are currently in the pipes, going to this inventory + var onTheWay = network.getItemsOnTheWay(offset, null); + if (onTheWay > 0) { + if (maxAmount < Integer.MAX_VALUE) { + // these are the items on the way, limited to items of the same type as stack + var onTheWaySame = network.getItemsOnTheWay(offset, stack); + // check if any modules are limiting us + if (toInsert.getCount() + onTheWaySame > maxAmount) + toInsert.setCount(maxAmount - onTheWaySame); + } + // totalSpace will be the amount of items that fit into the attached container + var totalSpace = 0; + for (var i = 0; i < handler.getSlots(); i++) { + var copy = stack.copy(); + var maxStackSize = copy.getMaxStackSize(); + // if the container can store more than 64 items in this slot, then it's likely + // a barrel or similar, meaning that the slot limit matters more than the max stack size + var limit = handler.getSlotLimit(i); + if (limit > 64) + maxStackSize = limit; + copy.setCount(maxStackSize); + // 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 + var left = handler.insertItem(i, copy, true); + totalSpace += maxStackSize - left.getCount(); + } + // 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); + } + } + // we return the item that can actually be inserted, NOT the remainder! + if (!toInsert.isEmpty()) + return Pair.of(offset, toInsert); } return null; } - public ItemStack getAvailableDestination(Direction direction, ItemStack stack, boolean force, boolean preventOversending) { - if (!this.canWork()) - return ItemStack.EMPTY; - var handler = this.getItemHandler(direction); - if (handler == null || !force && this.streamModules().anyMatch(m -> !m.getRight().canAcceptItem(m.getLeft(), this, stack, direction, handler))) - return ItemStack.EMPTY; - var remain = ItemHandlerHelper.insertItem(handler, stack, true); - // did we insert anything? - if (remain.getCount() == stack.getCount()) - return ItemStack.EMPTY; - var toInsert = stack.copy(); - toInsert.shrink(remain.getCount()); - // limit to the max amount that modules allow us to insert - var maxAmount = this.streamModules().mapToInt(m -> m.getRight().getMaxInsertionAmount(m.getLeft(), this, stack, handler)).min().orElse(Integer.MAX_VALUE); - if (maxAmount < toInsert.getCount()) - toInsert.setCount(maxAmount); - var offset = this.worldPosition.relative(direction); - if (preventOversending || maxAmount < Integer.MAX_VALUE) { - var network = PipeNetwork.get(this.level); - // these are the items that are currently in the pipes, going to this inventory - var onTheWay = network.getItemsOnTheWay(offset, null); - if (onTheWay > 0) { - if (maxAmount < Integer.MAX_VALUE) { - // these are the items on the way, limited to items of the same type as stack - var onTheWaySame = network.getItemsOnTheWay(offset, stack); - // check if any modules are limiting us - if (toInsert.getCount() + onTheWaySame > maxAmount) - toInsert.setCount(maxAmount - onTheWaySame); - } - // totalSpace will be the amount of items that fit into the attached container - var totalSpace = 0; - for (var i = 0; i < handler.getSlots(); i++) { - var copy = stack.copy(); - var maxStackSize = copy.getMaxStackSize(); - // if the container can store more than 64 items in this slot, then it's likely - // a barrel or similar, meaning that the slot limit matters more than the max stack size - var limit = handler.getSlotLimit(i); - if (limit > 64) - maxStackSize = limit; - copy.setCount(maxStackSize); - // 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 - var left = handler.insertItem(i, copy, true); - totalSpace += maxStackSize - left.getCount(); - } - // 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); - } - } - // we return the item that can actually be inserted, NOT the remainder! - return toInsert; - } - public int getPriority() { return this.priority; } 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 a34bba5..f206d49 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 @@ -75,7 +75,7 @@ public class CraftingModuleItem extends ModuleItem { network.startProfile("crafting_ingredients"); var request = tile.craftIngredientRequests.peek(); var equalityTypes = ItemFilter.getEqualityTypes(tile); - var dest = tile.getAvailableDestination(request.stack, true, true); + var dest = tile.getAvailableDestination(Direction.values(), request.stack, true, true); if (dest != null) { var requestRemain = network.requestExistingItem(request.location, tile.getBlockPos(), dest.getLeft(), request, dest.getRight(), equalityTypes); network.resolveNetworkLock(request); 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 26fa807..03d7088 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 @@ -35,36 +35,35 @@ public class ExtractionModuleItem extends ModuleItem { if (!tile.shouldWorkNow(this.speed) || !tile.canWork()) return; var filter = this.getItemFilter(module, tile); - var dir = this.getDirectionSelector(module, tile).getDirection(); - if (dir == null) - return; - var handler = tile.getItemHandler(dir); - if (handler == null) - return; - - var network = PipeNetwork.get(tile.getLevel()); - for (var j = 0; j < handler.getSlots(); j++) { - var stack = handler.extractItem(j, this.maxExtraction, true); - if (stack.isEmpty()) + var dirSelector = this.getDirectionSelector(module, tile); + for (var dir : dirSelector.directions()) { + var handler = tile.getItemHandler(dir); + if (handler == null) continue; - if (!filter.isAllowed(stack)) - continue; - var remain = network.routeItem(tile.getBlockPos(), tile.getBlockPos().relative(dir), stack, this.preventOversending); - if (remain.getCount() != stack.getCount()) { - handler.extractItem(j, stack.getCount() - remain.getCount(), false); - return; + var network = PipeNetwork.get(tile.getLevel()); + for (var j = 0; j < handler.getSlots(); j++) { + var stack = handler.extractItem(j, this.maxExtraction, true); + if (stack.isEmpty()) + continue; + if (!filter.isAllowed(stack)) + continue; + var remain = network.routeItem(tile.getBlockPos(), tile.getBlockPos().relative(dir), stack, this.preventOversending); + if (remain.getCount() != stack.getCount()) { + handler.extractItem(j, stack.getCount() - remain.getCount(), false); + return; + } } } } @Override public boolean canNetworkSee(ItemStack module, PipeBlockEntity tile, Direction direction, IItemHandler handler) { - return direction != this.getDirectionSelector(module, tile).getDirection(); + return !this.getDirectionSelector(module, tile).has(direction); } @Override public boolean canAcceptItem(ItemStack module, PipeBlockEntity tile, ItemStack stack, Direction direction, IItemHandler destination) { - return direction != this.getDirectionSelector(module, tile).getDirection(); + return !this.getDirectionSelector(module, tile).has(direction); } @Override diff --git a/src/main/java/de/ellpeck/prettypipes/pipe/modules/insertion/FilterModuleItem.java b/src/main/java/de/ellpeck/prettypipes/pipe/modules/insertion/FilterModuleItem.java index bd4eb12..92e470f 100644 --- a/src/main/java/de/ellpeck/prettypipes/pipe/modules/insertion/FilterModuleItem.java +++ b/src/main/java/de/ellpeck/prettypipes/pipe/modules/insertion/FilterModuleItem.java @@ -27,7 +27,7 @@ public class FilterModuleItem extends ModuleItem { @Override public boolean canAcceptItem(ItemStack module, PipeBlockEntity tile, ItemStack stack, Direction direction, IItemHandler destination) { - return this.getDirectionSelector(module, tile).getDirection() != direction || this.getItemFilter(module, tile).isAllowed(stack); + return !this.getDirectionSelector(module, tile).has(direction) || this.getItemFilter(module, tile).isAllowed(stack); } @Override 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 ea305e7..e2f440c 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 @@ -34,10 +34,7 @@ public class RetrievalModuleItem extends ModuleItem { public void tick(ItemStack module, PipeBlockEntity tile) { if (!tile.shouldWorkNow(this.speed) || !tile.canWork()) return; - var dir = this.getDirectionSelector(module, tile).getDirection(); - if (dir == null) - return; - + var directions = this.getDirectionSelector(module, tile).directions(); var network = PipeNetwork.get(tile.getLevel()); var equalityTypes = ItemFilter.getEqualityTypes(tile); // loop through filters to see which items to pull @@ -48,13 +45,13 @@ public class RetrievalModuleItem extends ModuleItem { continue; var copy = filtered.copy(); copy.setCount(this.maxExtraction); - var dest = tile.getAvailableDestination(dir, copy, true, this.preventOversending); - if (dest.isEmpty()) + var dest = tile.getAvailableDestination(directions, copy, true, this.preventOversending); + if (dest.getRight().isEmpty()) continue; - var remain = dest.copy(); + var remain = dest.getRight().copy(); // are we already waiting for crafting results? If so, don't request those again remain.shrink(network.getCurrentlyCraftingAmount(tile.getBlockPos(), copy, equalityTypes)); - if (network.requestItem(tile.getBlockPos(), tile.getBlockPos().relative(dir), remain, equalityTypes).isEmpty()) + if (network.requestItem(tile.getBlockPos(), dest.getLeft(), remain, equalityTypes).isEmpty()) break; } } @@ -62,12 +59,12 @@ public class RetrievalModuleItem extends ModuleItem { @Override public boolean canNetworkSee(ItemStack module, PipeBlockEntity tile, Direction direction, IItemHandler handler) { - return direction != this.getDirectionSelector(module, tile).getDirection(); + return !this.getDirectionSelector(module, tile).has(direction); } @Override public boolean canAcceptItem(ItemStack module, PipeBlockEntity tile, ItemStack stack, Direction direction, IItemHandler destination) { - return direction != this.getDirectionSelector(module, tile).getDirection(); + return !this.getDirectionSelector(module, tile).has(direction); } @Override diff --git a/src/main/resources/assets/prettypipes/lang/en_us.json b/src/main/resources/assets/prettypipes/lang/en_us.json index e1e7c4d..09ce44a 100644 --- a/src/main/resources/assets/prettypipes/lang/en_us.json +++ b/src/main/resources/assets/prettypipes/lang/en_us.json @@ -97,5 +97,5 @@ "dir.prettypipes.east": "East", "dir.prettypipes.south": "South", "dir.prettypipes.west": "West", - "dir.prettypipes.none": "No Side Valid" + "dir.prettypipes.all": "All Sides" } \ No newline at end of file