@@ -244,7 +244,10 @@ public void fillCraftingJobBufferFromStorage(CraftingJob craftingJob, Function<I
244244 throw new IllegalStateException ("Re-filling a non-empty crafting job buffer is illegal" );
245245 }
246246 // Determine the ingredients to extract. We can not reuse the ingredientsStorage value from the crafting job, as this may have been modified due to job splitting.
247- Pair <Map <IngredientComponent <?, ?>, List <?>>, Map <IngredientComponent <?, ?>, MissingIngredients <?, ?>>> inputResult = CraftingHelpers .getRecipeInputs (storageGetter , craftingJob .getRecipe (), false , Maps .newIdentityHashMap (), Maps .newIdentityHashMap (), true , craftingJob .getAmount ());
247+ // If this job has dependencies, skip reusable ingredients so that they remain available for other jobs.
248+ // They will be lazily extracted in the update loop once the dependencies have finished.
249+ boolean skipReusableIngredients = !craftingJob .getDependencyCraftingJobs ().isEmpty ();
250+ Pair <Map <IngredientComponent <?, ?>, List <?>>, Map <IngredientComponent <?, ?>, MissingIngredients <?, ?>>> inputResult = CraftingHelpers .getRecipeInputs (storageGetter , craftingJob .getRecipe (), false , Maps .newIdentityHashMap (), Maps .newIdentityHashMap (), true , craftingJob .getAmount (), skipReusableIngredients );
248251 IMixedIngredients buffer = new MixedIngredients (inputResult .getLeft ());
249252 craftingJob .setIngredientsStorageBuffer (CraftingHelpers .compressMixedIngredients (buffer ));
250253 craftingJob .setLastMissingIngredients (inputResult .getRight ());
@@ -457,35 +460,33 @@ public void update(INetwork network, int channel, PartPos targetPos) {
457460 // trigger a crafting job for them if no job is running yet.
458461 // This special case is needed because reusable ingredients are usually durability-based,
459462 // and may be consumed _during_ a bulk crafting job.
460- if (pendingCraftingJob .getLastMissingIngredients ().isEmpty ()) {
461- for (IngredientComponent <?, ?> component : inputs .getRight ().keySet ()) {
462- MissingIngredients <?, ?> missingIngredients = inputs .getRight ().get (component );
463- for (MissingIngredients .Element <?, ?> element : missingIngredients .getElements ()) {
464- if (element .isInputReusable ()) {
465- IIngredientComponentStorage storage = CraftingHelpers .getNetworkStorage (network , channel , component , true );
466- for (MissingIngredients .PrototypedWithRequested alternative : element .getAlternatives ()) {
467- // First check if we can extract it from storage.
468- Object extractedFromStorage = storage .extract (alternative .getRequestedPrototype ().getPrototype (), alternative .getRequestedPrototype ().getCondition (), false );
469- if (!((IIngredientMatcher ) component .getMatcher ()).isEmpty (extractedFromStorage )) {
470- pendingCraftingJob .addToIngredientsStorageBuffer ((IngredientComponent <? super Object , ? extends Object >) component , extractedFromStorage );
471- break ;
472- }
473-
474- // Try to start crafting jobs for each alternative until one of them succeeds.
475- if (CraftingHelpers .isCrafting (craftingNetwork , channel ,
476- alternative .getRequestedPrototype ().getComponent (), alternative .getRequestedPrototype ().getPrototype (), alternative .getRequestedPrototype ().getCondition ())) {
477- // Break loop if we have found an existing job for our dependency
478- // This may occur if a crafting job was triggered in a parallelized job
479- break ;
480- }
481- CraftingJob craftingJob = CraftingHelpers .calculateAndScheduleCraftingJob (network , channel ,
482- alternative .getRequestedPrototype ().getComponent (), alternative .getRequestedPrototype ().getPrototype (), alternative .getRequestedPrototype ().getCondition (), true , true ,
483- CraftingHelpers .getGlobalCraftingJobIdentifier (), null );
484- if (craftingJob != null ) {
485- pendingCraftingJob .addDependency (craftingJob );
486- // Break loop once we have found a valid job
487- break ;
488- }
463+ for (IngredientComponent <?, ?> component : inputs .getRight ().keySet ()) {
464+ MissingIngredients <?, ?> missingIngredients = inputs .getRight ().get (component );
465+ for (MissingIngredients .Element <?, ?> element : missingIngredients .getElements ()) {
466+ if (element .isInputReusable ()) {
467+ IIngredientComponentStorage storage = CraftingHelpers .getNetworkStorage (network , channel , component , true );
468+ for (MissingIngredients .PrototypedWithRequested alternative : element .getAlternatives ()) {
469+ // First check if we can extract it from storage.
470+ Object extractedFromStorage = storage .extract (alternative .getRequestedPrototype ().getPrototype (), alternative .getRequestedPrototype ().getCondition (), false );
471+ if (!((IIngredientMatcher ) component .getMatcher ()).isEmpty (extractedFromStorage )) {
472+ pendingCraftingJob .addToIngredientsStorageBuffer ((IngredientComponent <? super Object , ? extends Object >) component , extractedFromStorage );
473+ break ;
474+ }
475+
476+ // Try to start crafting jobs for each alternative until one of them succeeds.
477+ if (CraftingHelpers .isCrafting (craftingNetwork , channel ,
478+ alternative .getRequestedPrototype ().getComponent (), alternative .getRequestedPrototype ().getPrototype (), alternative .getRequestedPrototype ().getCondition ())) {
479+ // Break loop if we have found an existing job for our dependency
480+ // This may occur if a crafting job was triggered in a parallelized job
481+ break ;
482+ }
483+ CraftingJob craftingJob = CraftingHelpers .calculateAndScheduleCraftingJob (network , channel ,
484+ alternative .getRequestedPrototype ().getComponent (), alternative .getRequestedPrototype ().getPrototype (), alternative .getRequestedPrototype ().getCondition (), true , true ,
485+ CraftingHelpers .getGlobalCraftingJobIdentifier (), null );
486+ if (craftingJob != null ) {
487+ pendingCraftingJob .addDependency (craftingJob );
488+ // Break loop once we have found a valid job
489+ break ;
489490 }
490491 }
491492 }
0 commit comments