Expose crafting job progress and measured recipe durations - #220
Expose crafting job progress and measured recipe durations#220rubensworks wants to merge 7 commits into
Conversation
Crafting jobs now remember the amount they started with, so that the part of a job that was crafted already can be derived. Crafting interfaces measure how long each crafting operation takes, and expose a smoothed duration per recipe. This allows the duration of crafting jobs to be estimated, which is not possible otherwise, as the time that a machine needs for a recipe is unknown upfront. Refs CyclopsMC/IntegratedTerminals#145 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0186zEXrjMNMVXQC7wcoSiMR
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0186zEXrjMNMVXQC7wcoSiMR
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0186zEXrjMNMVXQC7wcoSiMR
|
Status on the checks:
Happy to add more coverage if you would rather see that number stay flat. Generated by Claude Code |
Makes the current tick overridable in the crafting job handler, so that measuring the duration of crafting operations can be tested without a running server. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0186zEXrjMNMVXQC7wcoSiMR
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0186zEXrjMNMVXQC7wcoSiMR
|
Correcting my previous comment: I claimed game test coverage does not feed into coveralls. That is wrong —
So the branch adds 88 relevant lines, of which the push run counts ~20 as covered. That is what the -0.9% is. Two caveats on those numbers. The two runs for the same commit disagree by 45 lines, and that divergence is not new — on the #218 branch the push build reported 2967 and the merge build 2982 for the same work — so some of this is run-to-run variance in what the game test run records. And the comparison coveralls picked is the push build against the push base, which is the like-for-like one, so I am treating the decrease as real rather than as an artifact. What I have added since: unit tests driving a full crafting operation through the handler with a controlled clock (start tick recorded, duration measured, amount decremented, parallel operations, cleanup), and one that measured durations survive a serialization round trip. What stays uncovered by unit tests: Generated by Claude Code |
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0186zEXrjMNMVXQC7wcoSiMR
The measured durations were stored per recipe and serialized with the crafting interface. As the number of recipes that an interface can craft is unbounded (attuned interfaces expose all recipes of their target, and reconfigured interfaces leave behind entries for old recipes), and part states are also stored in the item when a part is broken, this could grow the crafting interface indefinitely. Recipe-specific durations are now kept in memory only, in a bounded least-recently-used cache, and only the average duration over all recipes is serialized. After loading, estimations start from that average, and become recipe-specific again as soon as recipes are crafted. Measurements are also forgotten once they become too old, so that estimations follow changes to the network, such as machines becoming faster. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0186zEXrjMNMVXQC7wcoSiMR
Groundwork for CyclopsMC/IntegratedTerminals#145, which asks for the estimated/remaining time and the completion percentage of crafting jobs in the crafting terminal. Neither can be derived from what is exposed today:
amountis decremented while crafting and finished jobs are removed from the network, so the part of a job that is done is not recoverable.Crafting job progress
CraftingJobnow also keeps the amount it started with, next to the amount that still has to be crafted:CraftingJob#getAmountTotal(), maintained when jobs are split over multiple interfaces (CraftingHelpers#splitCraftingJobs) and when jobs are merged (CraftingJobDependencyGraph#mergeCraftingJobs), and serialized. Jobs from an older world load with the total set to their remaining amount.Recipe durations
CraftingJobHandlerrecords the tick at which each crafting operation is inserted into its target, and measures the duration once that operation's outputs come back in. Durations are smoothed with a running average (weight0.25), as machine speeds can vary.These measurements are kept by
RecipeDurationStatistics, which is deliberately bounded:craftingInterfaceRecipeDurationEntries(default 32) recipes. The number of recipes a crafting interface can craft is unbounded — an attuned interface exposes every recipe of its target machine, and reconfiguring a regular interface leaves entries for recipes it no longer exposes — and part states are also written into the item when a part is broken, so serializing them per recipe would grow both the world and the dropped item indefinitely.craftingInterfaceRecipeDurationMaxAge(default 24000 ticks, one in-game day). A player who speeds up their network would otherwise keep seeing estimations from the old setup for recipes that are not crafted often. An outdated measurement is replaced rather than smoothed into, so the new duration takes effect immediately.This is exposed as:
ICraftingInterface#getEstimatedRecipeDuration(recipe): the measured duration of one crafting operation of a recipe in that interface.ICraftingInterface#getCraftingJobEntryStartTick(craftingJobId): when the oldest running operation of a job started, so that the remaining time of a running operation can be shown.ICraftingNetwork#getEstimatedRecipeDuration(channel, recipe): averaged over the interfaces that expose the recipe and have measured it.All of these return
-1when nothing was measured yet, and the new methods on the API interfaces aredefault, so implementations outside of this repository keep compiling.Also,
CraftingNetwork#getCurrentTickmoved toCraftingHelpers#getCurrentTick, as the crafting job handler needs it too.Tests
Heads-up: I could not build or run this locally, as all
org.cyclopsdependencies resolve to GitHub Packages, which returns 401 in my environment. Compilation, the unit tests and the game tests are verified by CI here.