fully deliver items of canceled crafting requests so that containers don't get stuck with partial recipes

This commit is contained in:
Ell 2024-11-28 00:02:22 +01:00
parent 704027c3dc
commit 2c8ab9ed07
5 changed files with 42 additions and 20 deletions

View file

@ -277,7 +277,7 @@ public class PipeNetwork extends SavedData implements GraphListener<BlockPos, Ne
this.tileCache.remove(pos);
}
public List<Pair<BlockPos, ItemStack>> getCurrentlyCrafting(BlockPos node, ItemEquality... equalityTypes) {
public List<Pair<BlockPos, ItemStack>> getCurrentlyCrafting(BlockPos node, boolean includeCanceled, ItemEquality... equalityTypes) {
this.startProfile("get_currently_crafting");
List<Pair<BlockPos, ItemStack>> 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<BlockPos, Ne
var pipe = craftingPipes.next();
for (var craft : pipe.activeCrafts) {
var data = craft.getRight();
if (!includeCanceled && data.canceled)
continue;
// add up all the items that should go to the same location
var existing = items.stream()
.filter(s -> s.getLeft().equals(data.resultDestPipe) && ItemEquality.compareItems(s.getRight(), data.resultStackRemain, equalityTypes))
@ -300,8 +302,8 @@ public class PipeNetwork extends SavedData implements GraphListener<BlockPos, Ne
return items;
}
public int getCurrentlyCraftingAmount(BlockPos destNode, ItemStack stack, ItemEquality... equalityTypes) {
return this.getCurrentlyCrafting(destNode).stream()
public int getCurrentlyCraftingAmount(BlockPos destNode, ItemStack stack, boolean includeCanceled, ItemEquality... equalityTypes) {
return this.getCurrentlyCrafting(destNode, includeCanceled).stream()
.filter(p -> p.getLeft().equals(destNode) && ItemEquality.compareItems(p.getRight(), stack, equalityTypes))
.mapToInt(p -> p.getRight().getCount()).sum();
}

View file

@ -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<ItemStack> 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<NetworkLock> ingredientsToRequest, List<ItemStack> 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;
}
}

View file

@ -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;
}

View file

@ -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<ItemStack> getCurrentlyCrafting() {
private List<ItemStack> 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();

View file

@ -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",