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 ItemStack resultStackRemain;
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.
public boolean canceled;
@ -48,6 +49,7 @@ public class ActiveCraft implements INBTSerializable<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("result_found", this.resultFound);
ret.putBoolean("canceled", this.canceled);
return ret;
}
@ -61,6 +63,7 @@ public class ActiveCraft implements INBTSerializable<CompoundTag> {
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.resultFound = nbt.getBoolean("result_found");
this.canceled = nbt.getBoolean("canceled");
}
@ -74,6 +77,7 @@ public class ActiveCraft implements INBTSerializable<CompoundTag> {
", resultDestPipe=" + this.resultDestPipe +
", resultStackRemain=" + this.resultStackRemain +
", inProgress=" + this.inProgress +
", resultFound=" + this.resultFound +
", canceled=" + this.canceled + '}';
}

View file

@ -70,19 +70,23 @@ public class CraftingModuleItem extends ModuleItem {
return;
var slot = tile.getModuleSlot(module);
var network = PipeNetwork.get(tile.getLevel());
var crafts = tile.getActiveCrafts();
if (!crafts.isEmpty()) {
var craft = crafts.getFirst();
if (craft.moduleSlot == slot) {
if (!craft.ingredientsToRequest.isEmpty()) {
var foundMainCraft = false;
var crafts = tile.getActiveCrafts().iterator();
while (crafts.hasNext()) {
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.moduleSlot == slot) {
network.startProfile("crafting_ingredients");
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()) {
if (!module.get(Contents.TYPE).ensureItemOrder || craft.travelingIngredients.isEmpty()) {
network.requestExistingItem(lock.location, tile.getBlockPos(), dest.getLeft(), lock, dest.getRight(), equalityTypes);
network.resolveNetworkLock(lock);
craft.ingredientsToRequest.remove(lock);
@ -91,16 +95,39 @@ public class CraftingModuleItem extends ModuleItem {
}
}
network.endProfile();
} else if (craft.travelingIngredients.isEmpty()) {
}
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(craft);
crafts.remove();
} else {
// pull requested crafting results from the network once they are stored
network.startProfile("crafting_results");
// 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);
@ -109,7 +136,7 @@ public class CraftingModuleItem extends ModuleItem {
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(craft);
crafts.remove();
break;
}
}
@ -119,8 +146,6 @@ public class CraftingModuleItem extends ModuleItem {
}
}
}
}
}
@Override
public List<ItemStack> getAllCraftables(ItemStack module, PipeBlockEntity tile) {
@ -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) {
tile.redstoneTicks = 5;
tile.getLevel().updateNeighborsAt(tile.getBlockPos(), tile.getBlockState().getBlock());