From 63975d9ca87ce0e5b580e0397215dd376de83fe0 Mon Sep 17 00:00:00 2001 From: Malte Langkabel Date: Fri, 21 Aug 2026 22:13:21 +0200 Subject: [PATCH] let the input chips stand for the buffers too The output chips stopped testing the unlock state last commit; the input ones were left doing it, on a comment that had outlived its design -- buffers have been sized for the selected recipe alone for some time, not unioned over every recipe of the building's type. With the summary and the dialog now offering only recipes the player can run, the test is dead for a miner, smelter or assembler: step 4 unlocks a recipe only if it produces something unlocked, and step 2 has then already unlocked its inputs. It could still fire for a reprocessing plant, whose inputs no traversal propagates -- and firing is the bad case, not the good one. It would empty the input section of a plant that is running, while the summary directly above went on naming the material it eats. Both sections now say the same thing: one chip per buffer the building has. Whether a buffer exists is a fact about the building rather than about the player's progression, and one they cannot fill yet reads 0, which is what it holds. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01Ne3mejABZoLWKLh8fgpM3x --- docs/requirements.md | 2 +- src/ui/selection/BufferedBuildingContent.cpp | 13 ++++++------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/docs/requirements.md b/docs/requirements.md index 529b6c4..f3e1536 100644 --- a/docs/requirements.md +++ b/docs/requirements.md @@ -652,7 +652,7 @@ The panel shows exactly one **content** at a time, picked from the catalog in RE Input and output chips form separately captioned sections (REQ-UI-SELECTION-CARD). A section lists a chip for **every item the building's cycle involves**, whether or not the buffer currently holds any: an empty buffer reads `0` rather than its chip disappearing, so the card keeps one shape while the building runs. A section left with no chips at all is not shown. The production section (REQ-UI-PRODUCTION-PROGRESS) sits **between them**, so the card reads in the direction the materials flow: what goes in, what is being made of it, what has come out. For a selected construction site the buffer sections are omitted (REQ-BLD-SITE-CONFIG). - **Only buffers the building really has are listed, and all of them.** The output chips follow the recipe summary above them: one chip per item of the groups the summary states, which are the groups the building can actually be handed (REQ-UI-RECIPE-SUMMARY, REQ-LOCK-OUTPUT-POOL). No further per-item test is applied on top, and none is wanted — an item can only reach an output buffer by being yielded by a group the building was picking from, so a chip suppressed for being locked would not be hiding a locked item, it would be misreporting a buffer the building is filling. The input chips are the selected recipe's inputs, which an unlocked recipe's always are (REQ-LOCK-IMPLICIT step 2 adds the inputs of every recipe that produces something unlocked). + **Only buffers the building really has are listed, and all of them.** The output chips follow the recipe summary above them: one chip per item of the groups the summary states, which are the groups the building can actually be handed (REQ-UI-RECIPE-SUMMARY, REQ-LOCK-OUTPUT-POOL). The input chips follow the same principle: one per input of the selected recipe, which is one per input buffer, since selecting a recipe sizes the buffers for it alone (REQ-MAT-INPUT-BUFFER). **Neither section applies a per-item unlock test on top of that**, and neither should. Whether a buffer exists is a fact about the building, not about the player's progression: a chip suppressed for naming a locked item would not be hiding something the player must not see, it would be hiding a buffer the building actually has — on the output side one it may be filling, on the input side one it is waiting on. A buffer for an item the player cannot produce yet simply reads `0`, which is what it holds. A building with no recipe selected has no buffers at all, so both sections are absent, and a Miner's input section likewise (REQ-BLD-MINER: a miner recipe consumes nothing). - REQ-UI-RECIPE-SUMMARY: Below the recipe/schematic selection control, a building running a recipe or schematic shows a one-line **recipe summary**: each input item's icon on its colored square (REQ-UI-ITEM-ICON) with its per-cycle amount and the inputs separated by `+`, an arrow, then what the recipe produces, and the cycle time in seconds. The output side lists each item of an output group with its icon and per-cycle amount, the items within a group separated by `+` as the inputs are — they are produced together — and the **groups separated by `/`**, since only one of them happens (REQ-MAT-OUTPUT-GROUP). A recipe with a single group therefore reads exactly as before, and a Reprocessing Plant's reads as the alternatives it is rather than as one combined yield. **Only groups the player could be handed are stated.** A group holding any locked item is left out whole, exactly as the pool leaves it out when picking (REQ-LOCK-OUTPUT-POOL) — a summary that advertised it would promise a yield the building will never produce, and would disagree with the output buffers beneath it, which list unlocked items only (REQ-UI-SINGLE-SELECTION). A Reprocessing Plant therefore states three alternatives where its recipe lists four and the fourth is still locked. Unlike the pool, the test applies to a single-group recipe too: the pool exempts those so that a building whose one output nothing yet demands still produces, which is a rule about what to run, not about what to state. A recipe left with no group at all would have nothing to draw, but none can be selected, adopted, or applied from a blueprint (REQ-LOCK-UI-RECIPE, REQ-BLD-AUTO-RECIPE, REQ-LOCK-UI-BLUEPRINT), so no building holds one. It restates what the building will do without opening the selection dialog, and it is the panel's only display of the cycle time. Each input and output icon names an item and explains it on hover or click, together with the amount beside it (REQ-UI-ITEM-VALUE-TOOLTIP) — so the summary is also where the player follows a recipe's inputs back to what makes them, without the item having to be in a buffer to be asked about. For a Shipyard the summary is built from the schematic's materials and production time including the placed modules' contributions (REQ-BLD-SHIPYARD, REQ-MOD-STAT-CALC), matching the buffers beneath it. A building with no recipe or schematic selected shows no summary — including an auto-recipe building that has yet to select one (REQ-BLD-AUTO-RECIPE), which shows none until it does and keeps it from then on, so the card does not resize in step with the building's status (REQ-UI-SELECTION-STATUS, REQ-UI-SELECTION-PANEL). diff --git a/src/ui/selection/BufferedBuildingContent.cpp b/src/ui/selection/BufferedBuildingContent.cpp index 18013ec..8d028c4 100644 --- a/src/ui/selection/BufferedBuildingContent.cpp +++ b/src/ui/selection/BufferedBuildingContent.cpp @@ -150,15 +150,14 @@ std::vector BufferedBuildingContent::buildInputEntries( buffered[entry.first.id] = entry.second; } + // One chip per input buffer the building has, which is one per input of the selected + // recipe: selecting it sized the buffers for that recipe alone (REQ-MAT-INPUT-BUFFER). + // No unlock test, as on the output side -- whether a buffer exists is a fact about + // the building, not about the player's progression. A buffer for something they + // cannot make yet simply reads 0 until they can, which is what it holds. std::vector entries; - for (const std::string& itemId : - collectItemIds(buffered, cycle.perCycleInputs)) + for (const std::string& itemId : collectItemIds(buffered, cycle.perCycleInputs)) { - // An auto-recipe building's buffers are sized over every recipe of its type, - // including recipes still locked, so those entries are left out here - // (REQ-UI-SINGLE-SELECTION, REQ-LOCK-UI-RECIPE). - if (!getContext().sim->isItemUnlocked(itemId)) { continue; } - ItemChipRow::Entry chip; chip.itemId = itemId; chip.countText = QString::number(lookUp(buffered, itemId));