Skip to content

Add an at-least / ignore-extra-components item matcher for challenge hand-ins #149

Description

@minoneer

Summary: Inventory hand-in matching only does strict, full-component equality (ExactItemcandidate.isSimilar(item.create())). The catalog needs a third item matcher that accepts an item by base type while ignoring extra data components (or by matching only a subset of required components, e.g. an enchantment at level ≥ N), so component-rich vanilla items can be handed in.

Why this blocks 4.0

This is the last pure-engine gap on the 4.0 readiness survey. Several redesigned Tier 6 challenges require the player to possess items that, in real play, always carry extra data components the YAML prototype can't predict (food with per-flower suspicious_stew_effects, a forged netherite tool, or gear carrying enchantments and other meta). Because ExactItem.matches requires the candidate to be isSimilar to a fixed prototype, any real-world variation in components causes the hand-in to fail, making those challenges effectively impossible to complete. The any-of and #tag matchers landed and cover "any of a fixed set" / "any member of a material tag", but neither expresses "this base item with at least these components, ignore the rest."

Current state (on feature/immutable-challenge-catalog)

  • ItemMatcher is a sealed interface permitting only ExactItem, ItemTag, AnyOfItems — no at-least/subset variant. uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/catalog/ChallengeRequirements.java:94
  • ExactItem.matches is strict full-component equality: return candidate.isSimilar(item.create());. ChallengeRequirements.java:104-106 (the isSimilar call is on line 105)
  • ItemStackSpec.create() returns prototype.clone(), a full ItemStack carrying all meta/components, so isSimilar compares the complete component set, not just the base type. uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/gameobject/ItemStackSpec.java:23-25
  • The YAML parser accepts a plain item id (→ ExactItem), a #tag (→ ItemTag), or a YAML list (→ AnyOfItems). There is no matchMode / minimum / ignore-components / stored_enchantments handling for item requirements (the item requirement parser only knows item / amount / progression). uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/catalog/yaml/ChallengeCatalogYamlParser.java:420-438 (the minimum / ignore substrings that do appear are all unrelated to item-component matching: the IslandLevelRequirement minimum at lines 390-391, the rank gate's minimumCompletedChallenges at lines 379/382, a block-data comment at line 472, and a caught-exception name at line 528)
  • Matchers are consumed during completion in ChallengeExecutor via the ItemRequirementSpec.matches dispatch: spec.matches(item) at uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeExecutor.java:615 and required.getKey().matches(item) at :642
  • Affected redesigned challenges (design draft, untracked at docs/challenge-redesign/uskyblock-v2-challenge-redesign.md):
    • 6.5 topchef — requires suspicious_stew (carries per-flower effect components). Draft lines 517-522
    • 6.7 netheritesmith — requires netherite_upgrade_smithing_template + netherite_ingot, the inputs consumed to forge netherite gear. Draft lines 530-534
    • 6.8 warmaster — requires gear at a target enchantment, e.g. diamond_sword[enchantments={sharpness:4}], diamond_chestplate[enchantments={protection:4}], bow[enchantments={power:4}]. Draft lines 536-540

Scope

  • Add a new ItemMatcher variant to the sealed interface in ChallengeRequirements.java that matches an item by base type while ignoring components not explicitly specified (an "at-least" / subset match), including the ability to require an enchantment at level ≥ N.
  • Implement matches(ItemStack) for the new variant without relying on isSimilar (compare base type + only the specified components/enchantments, allowing the candidate to carry additional components).
  • Extend ChallengeCatalogYamlParser to parse the new matcher syntax for item requirements (e.g. a matchMode/minimum/ignore-components key or a stored_enchantments-style spec) and route it through parseItemMatcher; add it to the relevant warnUnknownKeys allowlists.
  • Add parser/diagnostic coverage in ChallengeCatalogYamlParserTest and matcher unit coverage (candidate with extra components passes; missing required component or too-low enchant level fails).
  • Wire the three at-risk challenges (topchef, netheritesmith, warmaster) in challenges.yml to the new matcher.
  • Document the new matcher syntax alongside the existing #tag / any-of documentation.
  • Fallback (only if the matcher slips 4.0): feature-flag or strip components on just those three challenges so they degrade to base-type hand-ins — this preserves progression but loses the teaching value of the component requirement.

References

Category: engine-code · Effort: medium · Source: 4.0 readiness survey.

Metadata

Metadata

Assignees

No one assigned

    Labels

    4.0Targeted for the 4.0 release (challenge system rework)enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions