allow other crafts to happen while a craft is waiting to be able to insert its result items

This commit is contained in:
Ell 2024-12-04 19:35:34 +01:00
parent b2630a1c51
commit c28100ad9f
2 changed files with 71 additions and 42 deletions

View file

@ -22,6 +22,7 @@ public class ActiveCraft implements INBTSerializable<CompoundTag> {
public BlockPos resultDestPipe; public BlockPos resultDestPipe;
public ItemStack resultStackRemain; public ItemStack resultStackRemain;
public boolean inProgress; public boolean inProgress;
public boolean resultFound;
// 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. // 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 boolean canceled;
@ -48,6 +49,7 @@ public class ActiveCraft implements INBTSerializable<CompoundTag> {
ret.putLong("result_dest_pipe", this.resultDestPipe.asLong()); ret.putLong("result_dest_pipe", this.resultDestPipe.asLong());
ret.put("result_stack_remain", this.resultStackRemain.saveOptional(provider)); ret.put("result_stack_remain", this.resultStackRemain.saveOptional(provider));
ret.putBoolean("in_progress", this.inProgress); ret.putBoolean("in_progress", this.inProgress);
ret.putBoolean("result_found", this.resultFound);
ret.putBoolean("canceled", this.canceled); ret.putBoolean("canceled", this.canceled);
return ret; return ret;
} }
@ -61,6 +63,7 @@ public class ActiveCraft implements INBTSerializable<CompoundTag> {
this.resultDestPipe = BlockPos.of(nbt.getLong("result_dest_pipe")); this.resultDestPipe = BlockPos.of(nbt.getLong("result_dest_pipe"));
this.resultStackRemain = ItemStack.parseOptional(provider, nbt.getCompound("result_stack_remain")); this.resultStackRemain = ItemStack.parseOptional(provider, nbt.getCompound("result_stack_remain"));
this.inProgress = nbt.getBoolean("in_progress"); this.inProgress = nbt.getBoolean("in_progress");
this.resultFound = nbt.getBoolean("result_found");
this.canceled = nbt.getBoolean("canceled"); this.canceled = nbt.getBoolean("canceled");
} }
@ -74,6 +77,7 @@ public class ActiveCraft implements INBTSerializable<CompoundTag> {
", resultDestPipe=" + this.resultDestPipe + ", resultDestPipe=" + this.resultDestPipe +
", resultStackRemain=" + this.resultStackRemain + ", resultStackRemain=" + this.resultStackRemain +
", inProgress=" + this.inProgress + ", inProgress=" + this.inProgress +
", resultFound=" + this.resultFound +
", canceled=" + this.canceled + '}'; ", canceled=" + this.canceled + '}';
} }

View file

@ -70,55 +70,80 @@ public class CraftingModuleItem extends ModuleItem {
return; return;
var slot = tile.getModuleSlot(module); var slot = tile.getModuleSlot(module);
var network = PipeNetwork.get(tile.getLevel()); var network = PipeNetwork.get(tile.getLevel());
var crafts = tile.getActiveCrafts(); var foundMainCraft = false;
if (!crafts.isEmpty()) { var crafts = tile.getActiveCrafts().iterator();
var craft = crafts.getFirst(); while (crafts.hasNext()) {
if (craft.moduleSlot == slot) { var craft = crafts.next();
// handle main crafting, which only one recipe (in the whole pipe!) should be able to do at a time so that items between recipes don't mix
if (!foundMainCraft) {
// process crafting ingredient requests
if (!craft.ingredientsToRequest.isEmpty()) { if (!craft.ingredientsToRequest.isEmpty()) {
// process crafting ingredient requests if (craft.moduleSlot == slot) {
network.startProfile("crafting_ingredients"); network.startProfile("crafting_ingredients");
var lock = craft.ingredientsToRequest.getFirst(); var lock = craft.ingredientsToRequest.getFirst();
var equalityTypes = ItemFilter.getEqualityTypes(tile);
var dest = tile.getAvailableDestination(Direction.values(), lock.stack, true, true);
if (dest != null) {
// if we're ensuring the correct item order and the item is already on the way, don't do anything yet
if (!module.get(Contents.TYPE).ensureItemOrder || network.getPipeItemsOnTheWay(dest.getLeft()).findAny().isEmpty()) {
network.requestExistingItem(lock.location, tile.getBlockPos(), dest.getLeft(), lock, dest.getRight(), equalityTypes);
network.resolveNetworkLock(lock);
craft.ingredientsToRequest.remove(lock);
craft.travelingIngredients.add(lock.stack.copy());
craft.inProgress = true;
}
}
network.endProfile();
} else if (craft.travelingIngredients.isEmpty()) {
if (craft.resultStackRemain.isEmpty()) {
// the result stack is empty from the start if this was a partial craft whose results shouldn't be delivered anywhere
// (ie someone requested 3 sticks with ensureItemOrder, but the recipe always makes 4, so the 4th recipe has no destination)
crafts.remove(craft);
} else {
// pull requested crafting results from the network once they are stored
network.startProfile("crafting_results");
var items = network.getOrderedNetworkItems(tile.getBlockPos());
var equalityTypes = ItemFilter.getEqualityTypes(tile); var equalityTypes = ItemFilter.getEqualityTypes(tile);
var destPipe = network.getPipe(craft.resultDestPipe); var dest = tile.getAvailableDestination(Direction.values(), lock.stack, true, true);
if (destPipe != null) { if (dest != null) {
var dest = destPipe.getAvailableDestinationOrConnectable(craft.resultStackRemain, true, true); // if we're ensuring the correct item order and the item is already on the way, don't do anything yet
if (dest != null) { if (!module.get(Contents.TYPE).ensureItemOrder || craft.travelingIngredients.isEmpty()) {
for (var item : items) { network.requestExistingItem(lock.location, tile.getBlockPos(), dest.getLeft(), lock, dest.getRight(), equalityTypes);
var requestRemain = network.requestExistingItem(item, craft.resultDestPipe, dest.getLeft(), null, dest.getRight(), equalityTypes); network.resolveNetworkLock(lock);
craft.resultStackRemain.shrink(dest.getRight().getCount() - requestRemain.getCount()); craft.ingredientsToRequest.remove(lock);
if (craft.resultStackRemain.isEmpty()) { craft.travelingIngredients.add(lock.stack.copy());
crafts.remove(craft); craft.inProgress = true;
break;
}
}
} }
} }
network.endProfile(); network.endProfile();
} }
foundMainCraft = true;
} else if (!craft.resultFound && craft.travelingIngredients.isEmpty()) {
if (craft.moduleSlot == slot) {
// check whether the crafting results have arrived in storage
if (craft.resultStackRemain.isEmpty()) {
// the result stack is empty from the start if this was a partial craft whose results shouldn't be delivered anywhere
// (ie someone requested 3 sticks with ensureItemOrder, but the recipe always makes 4, so the 4th recipe has no destination)
crafts.remove();
} else {
// check if the result is in storage
var items = network.getOrderedNetworkItems(tile.getBlockPos());
var equalityTypes = ItemFilter.getEqualityTypes(tile);
network.startProfile("check_crafting_results");
var remain = craft.resultStackRemain.copy();
for (var item : items) {
remain.shrink(item.getItemAmount(tile.getLevel(), remain, equalityTypes) - network.getLockedAmount(item.getPos(), remain, null, equalityTypes));
if (remain.isEmpty())
break;
}
craft.resultFound = remain.isEmpty();
network.endProfile();
}
}
foundMainCraft = true;
} }
} }
// pull requested crafting results from the network once they are stored
if (craft.resultFound && craft.moduleSlot == slot) {
var items = network.getOrderedNetworkItems(tile.getBlockPos());
var equalityTypes = ItemFilter.getEqualityTypes(tile);
network.startProfile("pull_crafting_results");
var destPipe = network.getPipe(craft.resultDestPipe);
if (destPipe != null) {
var dest = destPipe.getAvailableDestinationOrConnectable(craft.resultStackRemain, true, true);
if (dest != null) {
for (var item : items) {
var requestRemain = network.requestExistingItem(item, craft.resultDestPipe, dest.getLeft(), null, dest.getRight(), equalityTypes);
craft.resultStackRemain.shrink(dest.getRight().getCount() - requestRemain.getCount());
if (craft.resultStackRemain.isEmpty()) {
crafts.remove();
break;
}
}
}
}
network.endProfile();
}
} }
} }
@ -234,7 +259,7 @@ public class CraftingModuleItem extends ModuleItem {
} }
} }
if (craft.travelingIngredients.isEmpty() && craft.ingredientsToRequest.isEmpty()) { if (craft.ingredientsToRequest.isEmpty() && craft.travelingIngredients.isEmpty()) {
if (contents.emitRedstone) { if (contents.emitRedstone) {
tile.redstoneTicks = 5; tile.redstoneTicks = 5;
tile.getLevel().updateNeighborsAt(tile.getBlockPos(), tile.getBlockState().getBlock()); tile.getLevel().updateNeighborsAt(tile.getBlockPos(), tile.getBlockState().getBlock());