From 2c8ab9ed07aa39c6398dd687ec28701ed017d975 Mon Sep 17 00:00:00 2001 From: Ellpeck Date: Thu, 28 Nov 2024 00:02:22 +0100 Subject: [PATCH] fully deliver items of canceled crafting requests so that containers don't get stuck with partial recipes --- .../prettypipes/network/PipeNetwork.java | 8 ++++--- .../modules/craft/CraftingModuleItem.java | 24 +++++++++++++++---- .../retrieval/RetrievalModuleItem.java | 2 +- .../terminal/ItemTerminalBlockEntity.java | 22 ++++++++++------- .../assets/prettypipes/lang/en_us.json | 6 ++--- 5 files changed, 42 insertions(+), 20 deletions(-) diff --git a/src/main/java/de/ellpeck/prettypipes/network/PipeNetwork.java b/src/main/java/de/ellpeck/prettypipes/network/PipeNetwork.java index e851c9b..31fb23a 100644 --- a/src/main/java/de/ellpeck/prettypipes/network/PipeNetwork.java +++ b/src/main/java/de/ellpeck/prettypipes/network/PipeNetwork.java @@ -277,7 +277,7 @@ public class PipeNetwork extends SavedData implements GraphListener> getCurrentlyCrafting(BlockPos node, ItemEquality... equalityTypes) { + public List> getCurrentlyCrafting(BlockPos node, boolean includeCanceled, ItemEquality... equalityTypes) { this.startProfile("get_currently_crafting"); List> items = new ArrayList<>(); var craftingPipes = this.getAllCraftables(node).stream().map(c -> this.getPipe(c.getLeft())).distinct().iterator(); @@ -285,6 +285,8 @@ public class PipeNetwork extends SavedData implements GraphListener s.getLeft().equals(data.resultDestPipe) && ItemEquality.compareItems(s.getRight(), data.resultStackRemain, equalityTypes)) @@ -300,8 +302,8 @@ public class PipeNetwork extends SavedData implements GraphListener p.getLeft().equals(destNode) && ItemEquality.compareItems(p.getRight(), stack, equalityTypes)) .mapToInt(p -> p.getRight().getCount()).sum(); } 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 e8af9fb..ac1daed 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 @@ -95,6 +95,7 @@ public class CraftingModuleItem extends ModuleItem { var requestRemain = network.requestExistingItem(lock.location, tile.getBlockPos(), dest.getLeft(), lock, dest.getRight(), equalityTypes); network.resolveNetworkLock(lock); craftData.ingredientsToRequest.remove(lock); + craftData.inProgress = true; var traveling = lock.stack.copy(); traveling.shrink(requestRemain.getCount()); @@ -222,10 +223,12 @@ public class CraftingModuleItem extends ModuleItem { var slot = tile.getModuleSlot(module); var equalityTypes = ItemFilter.getEqualityTypes(tile); var matchingCraft = tile.activeCrafts.stream() - .filter(c -> c.getLeft() == slot && c.getRight().isMatchingIngredient(stack, equalityTypes)) + .filter(c -> c.getLeft() == slot && !c.getRight().getTravelingIngredient(stack, equalityTypes).isEmpty()) .findAny().orElse(null); if (matchingCraft != null) { - matchingCraft.getRight().travelingIngredients.removeIf(s -> ItemEquality.compareItems(stack, s, equalityTypes)); + var data = matchingCraft.getRight(); + data.travelingIngredients.remove(data.getTravelingIngredient(stack, equalityTypes)); + if (module.get(Contents.TYPE).insertSingles) { var handler = tile.getItemHandler(direction); if (handler != null) { @@ -237,6 +240,10 @@ public class CraftingModuleItem extends ModuleItem { } } } + + // if we canceled the request and all input items are delivered (ie the machine actually got what it expected), remove it from the queue + if (data.canceled && data.travelingIngredients.size() <= 0 && data.ingredientsToRequest.size() <= 0) + tile.activeCrafts.remove(matchingCraft); } return stack; } @@ -276,6 +283,9 @@ public class CraftingModuleItem extends ModuleItem { public List travelingIngredients; public BlockPos resultDestPipe; public ItemStack resultStackRemain; + public boolean inProgress; + // we only remove canceled requests from the queue once their items are fully delivered to the crafting location, so that unfinished recipes don't get stuck in crafters etc. + public boolean canceled; public ActiveCraft(List ingredientsToRequest, List travelingIngredients, BlockPos resultDestPipe, ItemStack resultStackRemain) { this.ingredientsToRequest = ingredientsToRequest; @@ -295,6 +305,8 @@ public class CraftingModuleItem extends ModuleItem { ret.put("traveling_ingredients", Utility.serializeAll(this.travelingIngredients, s -> (CompoundTag) s.save(provider, new CompoundTag()))); ret.putLong("result_dest_pipe", this.resultDestPipe.asLong()); ret.put("result_stack_remain", this.resultStackRemain.saveOptional(provider)); + ret.putBoolean("in_progress", this.inProgress); + ret.putBoolean("canceled", this.canceled); return ret; } @@ -304,14 +316,16 @@ public class CraftingModuleItem extends ModuleItem { this.travelingIngredients = Utility.deserializeAll(nbt.getList("traveling_ingredients", Tag.TAG_COMPOUND), t -> ItemStack.parse(provider, t).orElseThrow()); this.resultDestPipe = BlockPos.of(nbt.getLong("result_dest_pipe")); this.resultStackRemain = ItemStack.parseOptional(provider, nbt.getCompound("result_stack_remain")); + this.inProgress = nbt.getBoolean("in_progress"); + this.canceled = nbt.getBoolean("canceled"); } - public boolean isMatchingIngredient(ItemStack stack, ItemEquality... equalityTypes) { + public ItemStack getTravelingIngredient(ItemStack stack, ItemEquality... equalityTypes) { for (var traveling : this.travelingIngredients) { if (ItemEquality.compareItems(stack, traveling, equalityTypes)) - return true; + return traveling; } - return false; + return ItemStack.EMPTY; } } 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 02d338d..b58f191 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 @@ -52,7 +52,7 @@ public class RetrievalModuleItem extends ModuleItem { continue; 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)); + remain.shrink(network.getCurrentlyCraftingAmount(tile.getBlockPos(), copy, true, equalityTypes)); if (network.requestItem(tile.getBlockPos(), dest.getLeft(), remain, equalityTypes).isEmpty()) break; } diff --git a/src/main/java/de/ellpeck/prettypipes/terminal/ItemTerminalBlockEntity.java b/src/main/java/de/ellpeck/prettypipes/terminal/ItemTerminalBlockEntity.java index 55330f1..6c20dd0 100644 --- a/src/main/java/de/ellpeck/prettypipes/terminal/ItemTerminalBlockEntity.java +++ b/src/main/java/de/ellpeck/prettypipes/terminal/ItemTerminalBlockEntity.java @@ -136,7 +136,7 @@ public class ItemTerminalBlockEntity extends BlockEntity implements IPipeConnect if (playersToSync.length > 0) { var clientItems = this.networkItems.values().stream().map(NetworkItem::asStack).collect(Collectors.toList()); var clientCraftables = PipeNetwork.get(this.level).getAllCraftables(pipe.getBlockPos()).stream().map(Pair::getRight).collect(Collectors.toList()); - var currentlyCrafting = this.getCurrentlyCrafting().stream().sorted(Comparator.comparingInt(ItemStack::getCount).reversed()).collect(Collectors.toList()); + var currentlyCrafting = this.getCurrentlyCrafting(false).stream().sorted(Comparator.comparingInt(ItemStack::getCount).reversed()).collect(Collectors.toList()); for (var player : playersToSync) { if (!(player.containerMenu instanceof ItemTerminalContainer container)) continue; @@ -200,12 +200,12 @@ public class ItemTerminalBlockEntity extends BlockEntity implements IPipeConnect return items; } - private List getCurrentlyCrafting() { + private List getCurrentlyCrafting(boolean includeCanceled) { var network = PipeNetwork.get(this.level); var pipe = this.getConnectedPipe(); if (pipe == null) return Collections.emptyList(); - var crafting = network.getCurrentlyCrafting(pipe.getBlockPos()); + var crafting = network.getCurrentlyCrafting(pipe.getBlockPos(), includeCanceled); return crafting.stream().map(Pair::getRight).collect(Collectors.toList()); } @@ -217,11 +217,17 @@ public class ItemTerminalBlockEntity extends BlockEntity implements IPipeConnect for (var craftable : network.getAllCraftables(pipe.getBlockPos())) { var otherPipe = network.getPipe(craftable.getLeft()); if (otherPipe != null) { - for (var craft : otherPipe.activeCrafts) { - for (var lock : craft.getRight().ingredientsToRequest) - network.resolveNetworkLock(lock); - } - otherPipe.activeCrafts.clear(); + otherPipe.activeCrafts.removeIf(c -> { + var data = c.getRight(); + if (data.inProgress) { + data.canceled = true; + return false; + } else { + for (var lock : data.ingredientsToRequest) + network.resolveNetworkLock(lock); + return true; + } + }); } } var lookingPlayers = this.getLookingPlayers(); diff --git a/src/main/resources/assets/prettypipes/lang/en_us.json b/src/main/resources/assets/prettypipes/lang/en_us.json index 0069344..8911144 100644 --- a/src/main/resources/assets/prettypipes/lang/en_us.json +++ b/src/main/resources/assets/prettypipes/lang/en_us.json @@ -68,10 +68,10 @@ "info.prettypipes.blacklist.description": "Items in filter slots are disallowed", "info.prettypipes.insert_singles_on": "\u00A72S", "info.prettypipes.insert_singles_off": "\u00A74\u00A7mS", - "info.prettypipes.insert_singles.description": "Whether items should be inserted one at a time, rather than as a stack\nRecommended for use with the Crafter", + "info.prettypipes.insert_singles.description": "Whether items should be inserted one at a time, rather than as a stack\n\u00A7oRecommended for use with the Crafter", "info.prettypipes.ensure_item_order_on": "\u00A72O", "info.prettypipes.ensure_item_order_off": "\u00A74\u00A7mO", - "info.prettypipes.ensure_item_order.description": "Whether the module should wait for items to be inserted in the order they appear in the input slots\nRecommended for use with the Crafter", + "info.prettypipes.ensure_item_order.description": "Whether the module should wait for items to be inserted in the order they appear in the input slots\n\u00A7oRecommended for use with the Crafter", "info.prettypipes.shift": "Hold Shift for info", "info.prettypipes.populate": "P", "info.prettypipes.populate.description": "Populate filter slots with items from adjacent inventories", @@ -94,7 +94,7 @@ "info.prettypipes.energy": "%s / %s FE", "info.prettypipes.crafting": "Awaiting", "info.prettypipes.cancel_all": "Cancel", - "info.prettypipes.cancel_all.desc": "Stops waiting for current crafting outputs\nDoesn't remove inputs from blocks", + "info.prettypipes.cancel_all.desc": "Stops waiting for current crafting outputs\nOngoing crafting operations are still completed", "info.prettypipes.no_pipe_connected": "The terminal needs to be connected to a pipe network", "info.prettypipes.too_many_pipes_connected": "The terminal can only be connected to a single pipe at a time", "dir.prettypipes.up": "Up",