Summary: The catalog engine on feature/immutable-challenge-catalog lets rewards differ between first completion and repeats, but a challenge's consumption behaviour and requirement set are fixed across all completions. Any 4.0 challenge that wants to keep items on first completion but consume them on repeat (or otherwise require different items first vs. repeat) is currently inexpressible. This is a needs-decision blocker, not yet committed work.
Why this blocks 4.0
The 4.0 readiness survey flags this as pre-launch blocking because the redesigned challenge set leans on phase-specific economics (e.g. a one-time bootstrap injection that the player keeps, followed by repeatable grinds that consume the same inputs to keep a later challenge budget balanced). The engine already splits rewards per phase (firstCompletionReward vs repeatReward) but does not split consumption or requirements, so these designs cannot be authored today. Until a maintainer picks a direction (engine support vs. content workaround), the affected challenges cannot be finalized in challenges.yml, and the choice shapes both the catalog schema and the YAML authoring conventions.
Current state
On feature/immutable-challenge-catalog:
- A challenge carries a single
completionRequirements list and single properties, but separate firstCompletionReward / repeatReward — so rewards are phase-aware while requirements are not (uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/catalog/ChallengeDefinition.java).
ChallengeProperties is a single consumeItemsOnCompletion boolean for the whole challenge (uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/catalog/ChallengeProperties.java).
- Consumption is decided once, identically for first and repeat completions:
if (!requiredItems.isEmpty() && challenge.properties().consumeItemsOnCompletion()) (uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeExecutor.java:250). There is no per-phase branch.
- The only per-repetition variation is the item amount:
amountForRepetitions(int repetitions) returns (int) Math.floor(progression.operator().apply(amount, progression.increment(), repetitions)), fed the cooldown completion count via collectRequiredItems (uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/catalog/ChallengeRequirements.java:155). ItemAmountProgression scales the count only — it cannot flip takeItems nor swap the matcher/requirement set between first and repeat (ChallengeRequirements.java:160).
- The
CompletionRequirement sealed hierarchy (InventoryItemsRequirement, IslandBlocksRequirement, EntityPresenceRequirement, IslandLevelRequirement) has no notion of a first-vs-repeat profile; there is exactly one requirement list per challenge (ChallengeRequirements.java:27, :66).
- The YAML parser accepts only
consumeItemsOnCompletion under properties and warns on any other key (uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/catalog/yaml/ChallengeCatalogYamlParser.java:236); legacy import maps the old takeItems flag straight onto it (.../bootstrap/LegacyChallengeCatalogImporter.java:248). A grep for any repeatRequirement / firstProfile / requirement-profile concept returns nothing — no such field exists.
Affected designs (from the redesign draft): the draft already expresses several first-vs-repeat reward asymmetries (e.g. a Tier 5 bastion challenge injecting 4 ancient debris on first completion and 2 on repeat), which the engine supports today via separate reward bundles. The case that has no expressible form is a first-vs-repeat consumption/requirement asymmetry on the same input — keeping a required item on first completion but consuming it on repeat (or requiring a different item set per phase). The draft does not yet contain a finalized challenge in this form, but the phase-specific budget economics it relies on point toward needing it; a maintainer decision is required before any such challenge can be authored.
Scope
Option A — engine support (small):
Option B — content workaround (folded into content):
References
- Design draft:
docs/challenge-redesign/uskyblock-v2-challenge-redesign.md (currently untracked / do-not-commit) — see the per-phase reward discussion and the Tier 5 nether challenge entries.
- Key files:
ChallengeDefinition.java, ChallengeProperties.java, ChallengeRequirements.java (:155, :160, :27, :66), ChallengeExecutor.java:250, yaml/ChallengeCatalogYamlParser.java:236, bootstrap/LegacyChallengeCatalogImporter.java:248 (all on feature/immutable-challenge-catalog).
- Related issues: none yet — this depends on the
challenges.yml authoring direction.
Category: engine-code / content-design (contested) · Effort: small if engine, else folded into content · Source: 4.0 readiness survey.
Summary: The catalog engine on
feature/immutable-challenge-cataloglets rewards differ between first completion and repeats, but a challenge's consumption behaviour and requirement set are fixed across all completions. Any 4.0 challenge that wants to keep items on first completion but consume them on repeat (or otherwise require different items first vs. repeat) is currently inexpressible. This is a needs-decision blocker, not yet committed work.Why this blocks 4.0
The 4.0 readiness survey flags this as pre-launch blocking because the redesigned challenge set leans on phase-specific economics (e.g. a one-time bootstrap injection that the player keeps, followed by repeatable grinds that consume the same inputs to keep a later challenge budget balanced). The engine already splits rewards per phase (
firstCompletionRewardvsrepeatReward) but does not split consumption or requirements, so these designs cannot be authored today. Until a maintainer picks a direction (engine support vs. content workaround), the affected challenges cannot be finalized inchallenges.yml, and the choice shapes both the catalog schema and the YAML authoring conventions.Current state
On
feature/immutable-challenge-catalog:completionRequirementslist and singleproperties, but separatefirstCompletionReward/repeatReward— so rewards are phase-aware while requirements are not (uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/catalog/ChallengeDefinition.java).ChallengePropertiesis a singleconsumeItemsOnCompletionboolean for the whole challenge (uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/catalog/ChallengeProperties.java).if (!requiredItems.isEmpty() && challenge.properties().consumeItemsOnCompletion())(uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeExecutor.java:250). There is no per-phase branch.amountForRepetitions(int repetitions)returns(int) Math.floor(progression.operator().apply(amount, progression.increment(), repetitions)), fed the cooldown completion count viacollectRequiredItems(uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/catalog/ChallengeRequirements.java:155).ItemAmountProgressionscales the count only — it cannot fliptakeItemsnor swap the matcher/requirement set between first and repeat (ChallengeRequirements.java:160).CompletionRequirementsealed hierarchy (InventoryItemsRequirement,IslandBlocksRequirement,EntityPresenceRequirement,IslandLevelRequirement) has no notion of a first-vs-repeat profile; there is exactly one requirement list per challenge (ChallengeRequirements.java:27,:66).consumeItemsOnCompletionunder properties and warns on any other key (uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/catalog/yaml/ChallengeCatalogYamlParser.java:236); legacy import maps the oldtakeItemsflag straight onto it (.../bootstrap/LegacyChallengeCatalogImporter.java:248). A grep for anyrepeatRequirement/firstProfile/ requirement-profile concept returns nothing — no such field exists.Affected designs (from the redesign draft): the draft already expresses several first-vs-repeat reward asymmetries (e.g. a Tier 5 bastion challenge injecting 4 ancient debris on first completion and 2 on repeat), which the engine supports today via separate reward bundles. The case that has no expressible form is a first-vs-repeat consumption/requirement asymmetry on the same input — keeping a required item on first completion but consuming it on repeat (or requiring a different item set per phase). The draft does not yet contain a finalized challenge in this form, but the phase-specific budget economics it relies on point toward needing it; a maintainer decision is required before any such challenge can be authored.
Scope
Option A — engine support (small):
consumeItemsOnFirstCompletion/consumeItemsOnRepeat, or makeconsumeItemsOnCompletionphase-aware) and/or a distinct repeat requirement profile to the catalog model.ChallengeExecutoron first-vs-repeat instead of the singleconsumeItemsOnCompletion()check atChallengeExecutor.java:250.ChallengeCatalogYamlParser.java:236) and the legacy importer mapping (LegacyChallengeCatalogImporter.java:248) to read/preserve the new field(s).challenges.ymltemplate comments and the affected challenge entries; add parser tests covering first-keep/repeat-consume.Option B — content workaround (folded into content):
takeItems/consume off) + repeatable (takeItems/consume on)ChallengeDefinitions, wired via unlock requirements.References
docs/challenge-redesign/uskyblock-v2-challenge-redesign.md(currently untracked / do-not-commit) — see the per-phase reward discussion and the Tier 5 nether challenge entries.ChallengeDefinition.java,ChallengeProperties.java,ChallengeRequirements.java(:155,:160,:27,:66),ChallengeExecutor.java:250,yaml/ChallengeCatalogYamlParser.java:236,bootstrap/LegacyChallengeCatalogImporter.java:248(all onfeature/immutable-challenge-catalog).challenges.ymlauthoring direction.Category: engine-code / content-design (contested) · Effort: small if engine, else folded into content · Source: 4.0 readiness survey.