Skip to content

Let insert pre-consumers see what part of an insertion was already accounted for - #1720

Open
rubensworks wants to merge 1 commit into
master-1.21-ltsfrom
fix/insert-pre-consumer-accounting
Open

Let insert pre-consumers see what part of an insertion was already accounted for#1720
rubensworks wants to merge 1 commit into
master-1.21-ltsfrom
fix/insert-pre-consumer-accounting

Conversation

@rubensworks

Copy link
Copy Markdown
Member

Companion of CyclopsMC/IntegratedCrafting#226, which needs this to fix parallel crafting jobs all completing on a single produced output. This PR is the API half; on its own it changes no behaviour.

Problem

Every insert pre-consumer registered on an ingredient channel observes the same insertion, chained by the remaining instance:

for (IIngredientChannelInsertPreConsumer<T> insertPreConsumer : network.getInsertPreConsumers()) {
    ingredient = insertPreConsumer.insert(this.channel, ingredient, simulate);
}

That works for a pre-consumer that consumes part of the insertion, since what it takes is gone from the instance it passes on. It does not work for one that attributes part of the insertion to itself without consuming it, because the instance it passes on is unchanged, so the next pre-consumer attributes that very same instance to itself as well.

Integrated Crafting's crafting job output observer is exactly the second kind: it resolves a job's pending output when the produced ingredient shows up, and then still lets it flow into storage. With several crafting interfaces running parallel jobs for the same output, one produced item resolved the pending output of every one of those jobs at once.

Change

IIngredientChannelInsertPreConsumer now also carries the unaccounted part of an insertion, next to the remaining part:

  • insert(channel, ingredient, unaccounted, simulate) returns a Result(remaining, unaccounted). Consuming reduces both, attributing reduces only the unaccounted part.
  • The single-instance insert(channel, ingredient, simulate) is deprecated. Its default keeps the old behaviour for pre-consumers that have not migrated, and applyAll clamps the unaccounted part to the remaining part so such a pre-consumer can not cause over-accounting.
  • applyAll holds the chaining that was duplicated in IngredientChannelAdapter and IngredientChannelAdapterWrapperSlotted.

INetworkIngredientsChannel additionally accepts an insertion that was already partially accounted for before it reached the channel (insert(ingredient, unaccounted, simulate), defaulting to the plain insert). Integrated Crafting needs this because a crafting interface offers its results to its own jobs before flushing them into the network, and those results must not be accounted for a second time by the channel's pre-consumers.

Testing

  • New TestIngredientChannelInsertPreConsumer covers the chaining: two attributing pre-consumers no longer share one instance, they do split a larger one, a consumed quantity can not be attributed again, and a deprecated pre-consumer can not push the unaccounted quantity above the remaining quantity.
  • ./gradlew build passes.
  • ./gradlew runGameTestServer passes, all 942 tests.
  • Integrated Crafting's game tests (102, including the parallel crafting ones) pass against this build, over 15 runs.

🤖 Generated with Claude Code

https://claude.ai/code/session_01EypmxuPjaJ4cFGh2DvZYbf


Generated by Claude Code

…counted for

All insert pre-consumers of an ingredient channel observe the same insertion,
chained by the remaining instance. A pre-consumer that attributes part of an
insertion to itself without consuming it, such as one that waits for an
ingredient to be produced, therefore left the instance unchanged, after which
the next pre-consumer attributed that very same instance to itself as well.

Integrated Crafting's crafting job output observer works exactly like that, so
with several crafting interfaces running parallel jobs for the same output, one
produced item resolved the pending output of every one of those jobs at once.

IIngredientChannelInsertPreConsumer now takes and returns the unaccounted part
of the insertion next to the remaining part, and applyAll chains both. The
single-instance method is deprecated, and its default keeps the old behaviour
for pre-consumers that have not migrated yet.

INetworkIngredientsChannel additionally accepts an insertion that was already
partially accounted for before it reached the channel, which is needed when a
crafting interface first offers its own results to its own jobs.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EypmxuPjaJ4cFGh2DvZYbf
@coveralls

coveralls commented Sep 4, 2026

Copy link
Copy Markdown

Coverage Status

coverage: 46.997% (+0.06%) from 46.936% — fix/insert-pre-consumer-accounting into master-1.21-lts

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants