Skip to content

Add crafting plan progress and duration estimation API - #211

Merged
rubensworks merged 18 commits into
master-1.21-ltsfrom
feature/craftingplan-progress-api
Sep 4, 2026
Merged

Add crafting plan progress and duration estimation API#211
rubensworks merged 18 commits into
master-1.21-ltsfrom
feature/craftingplan-progress-api

Conversation

@rubensworks

@rubensworks rubensworks commented Aug 31, 2026

Copy link
Copy Markdown
Member

Part of the work towards #145 (showing estimated/remaining time and completion percentage for crafting jobs).

This is the API groundwork only: it adds the fields that the gui will later render, and the plumbing to keep them alive across (de)serialization and plan flattening. Nothing is computed or displayed yet, so this change is inert on its own.

Added

  • ITerminalCraftingPlan#getCraftingQuantityTotal(): the number of crafting operations of a job, including the ones that finished already. getCraftingQuantity() keeps its current meaning (the operations that still have to happen), so total - remaining gives the completion of a job.
  • ITerminalCraftingPlan#getEstimatedTickDurationTotal() and #getEstimatedTickDurationRemaining(): estimations, as opposed to getTickDuration(), which is the time a job has been running already. -1 means unknown.
  • The same estimation methods on ITerminalCraftingPlanFlat, plus getCraftingQuantityTotal() and getCraftingQuantityRemaining(), which are aggregated over all jobs of a plan during flattening.

These are regular interface methods rather than default ones, so implementations outside of this repository have to implement them. The existing constructors of TerminalCraftingPlanStatic, TerminalCraftingPlanFlatStatic and TerminalCraftingPlanCraftingJobDependencyGraph are kept next to the new ones.

Notes

  • Flattening sums the quantities over the job tree, skipping jobs that were already visited (jobs can have multiple dependents due to job splitting) and jobs with an invalid status (their crafting quantity refers to missing ingredients, not to crafting operations). The existing deduplication check is extracted into isPlanHandled so that both traversals share it.
  • The new NBT entries are always written, but are read leniently with fallbacks (craftingQuantity and -1), so plans serialized by an older version still load.
  • Since the values are not filled in yet, everything reports "unknown" for now: craftingQuantityTotal equals craftingQuantity, and both estimations are -1.
  • This adds the first src/test/java sources of this repository, covering the flattening aggregation (nested jobs, jobs shared through job splitting, and invalid jobs).

Heads-up: I could not build this locally, as all org.cyclops dependencies resolve to GitHub Packages, which returns 401 in my environment. The changed files parse cleanly, but compilation and the new unit tests are only verified by CI here.

Next steps for #145 are measuring per-recipe crafting durations in IntegratedCrafting (CyclopsMC/IntegratedCrafting#220), filling in these values in TerminalStorageTabIngredientCraftingHandlerCraftingNetwork, and rendering them in the crafting plan and crafting jobs guis.

🤖 Generated with Claude Code

https://claude.ai/code/session_0186zEXrjMNMVXQC7wcoSiMR

Adds the total crafting quantity and the estimated total and remaining
tick durations to crafting plans, together with their (de)serialization
and aggregation during plan flattening.

These values are not filled in or displayed yet, so everything reports
an unknown value for now.

Refs #145

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0186zEXrjMNMVXQC7wcoSiMR
Estimates the duration of a crafting plan by walking its dependency
graph: a job takes the measured duration of its recipe times its amount,
plus the longest estimation of the jobs it depends on, as dependencies
have to finish first, while dependencies of the same job are crafted
simultaneously. Running jobs subtract the time that their current
crafting operation has been going on already.

The crafting plan guis show the estimated total duration before a job is
started, and the estimated remaining duration while it is running. The
crafting jobs gui additionally shows the percentage of crafting
operations that are finished.

Refs #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
The progress and remaining duration that were added to the crafting job
list are drawn in a second column, which the status and duration of the
first column ran into: at half scale "Status: Queueing" and
"Duration: 0:00:00" are both wider than the 40 pixels that separated the
two columns, so their last characters were overwritten.

Widen both columns to fit their longest strings, the "Pending
Dependencies" status and a two-digit hour duration.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016gX5ZToD5ApLBXQkKW2QGj
The longest status, "Pending Dependencies", is the one that nested jobs
spend most of their time in, and it ended right against the progress
column next to it. Widen the status column so the two are separated.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016gX5ZToD5ApLBXQkKW2QGj
The crafting job terminal listed the status, size, channel, duration,
progress and remaining time as six separate pieces of text per job.
Replace the duration, progress and remaining time with a progress bar
that carries all three: the time the job has been running on the left,
how far it has come in the middle, and what is left on the right.
The labelled values, along with the total estimate and the owner, now
show up in a tooltip when hovering a job.

An estimate that is not known yet was left out entirely, which made it
indistinguishable from a job that had no line to show. Show a question
mark for it instead, for any job that is not in an error state.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016gX5ZToD5ApLBXQkKW2QGj
…aftingplan-progress-api

# Conflicts:
#	gradle.properties
The crafting jobs gui was still on the overload that master deprecated
when it gained a tooltip component parameter.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016gX5ZToD5ApLBXQkKW2QGj
Hovering a craftable in the storage terminal now says how long one
crafting operation of it is expected to take.

The client had no notion of recipe durations, and asking for a whole
crafting plan per hovered item would be far too expensive. The duration
of a single operation is only a lookup in the crafting network though,
so the server can attach it to the crafting option it already sends.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016gX5ZToD5ApLBXQkKW2QGj
Every line was plain white, which made the tooltip a wall of text to
read through. Give the status the same color that the plan guis paint it
in, dim the labels so that the durations stand out from them, put the
remaining time in a color of its own, and push the values that are only
occasionally interesting to the back.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016gX5ZToD5ApLBXQkKW2QGj
The numbers inside the bar sat on a track that was close in brightness
to the line behind it. Give the bar a border and a darker track, so that
the times and the percentage read over both the track and the fill.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016gX5ZToD5ApLBXQkKW2QGj
The operations of a job are added to the estimation of its dependencies.
An unknown duration for them counted as zero, so a job on a crafting
interface that had never crafted anything reported the duration of its
dependencies as if that were the whole answer.

Report an unknown estimation instead, which the guis already show as a
question mark. Unknown dependencies keep being skipped: they only lower
a maximum that the other dependencies can still win.

The recipe duration is now passed in rather than looked up, so that the
estimation itself can be tested without a crafting network, instead of
through the network being absent.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016gX5ZToD5ApLBXQkKW2QGj
The question mark on its own does not say whether the estimate is
missing, zero, or broken. Hovering it now explains that the crafting
interfaces have not crafted these recipes before.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016gX5ZToD5ApLBXQkKW2QGj
Make getEstimatedTickDuration a regular interface method, deprecate the
constructor that does not take a duration, and drop a comment that does
not carry its weight.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016gX5ZToD5ApLBXQkKW2QGj
Crafting interfaces only measure how long a recipe takes to produce its
outputs after being started. Regular crafting recipes are done within the
tick they are started in, so they measure as taking no time at all, and
their average drags every other recipe on the interface to zero as well.
Multiplied by the operations of a job, that reported a plan for 100 chests
as taking no time, and left the remaining time of a running job at zero.

An interface performs at most one operation per update though, so no recipe
can go faster than that. Take the update interval as a lower bound.

The durations are also no longer formatted as H:mm:ss throughout, which
rounded everything below a minute away. Seconds are shown with the decimals
that are meaningful at their magnitude, minutes as m:ss, and only durations
of an hour and over as H:mm:ss.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016gX5ZToD5ApLBXQkKW2QGj
Recipes that are crafted within the tick they are started in were measured
as taking no time, which was worked around here by taking the crafting
interface update interval as a lower bound.

CyclopsMC/IntegratedCrafting#223 moved that bound to where the numbers come
from, where it also knows that non-blocking interfaces start as many
operations as their target accepts, and that an interface can be configured
to update less often than the configured minimum.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016gX5ZToD5ApLBXQkKW2QGj
@rubensworks
rubensworks merged commit 599072a into master-1.21-lts Sep 4, 2026
3 checks passed
@rubensworks
rubensworks deleted the feature/craftingplan-progress-api branch September 4, 2026 17:45
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