Context
From the July 2026 McRPG quest-system audit (typo'd-id finding adversarially verified: CONFIRMED, severity HIGH downstream). Two McCore "forgiving by design" fallbacks currently absorb server-owner typos with zero observability, producing quests that can never progress and GUI icons that silently render as STONE. Downstream loaders need a way to warn without breaking the intentional custom-content support.
Problem
CustomBlockWrapper(String) (src/main/java/com/diamonddagger590/mccore/util/item/CustomBlockWrapper.java:49-58): when the vanilla registry lookup fails, the string is silently reclassified as a "custom block" identifier (by design, for ItemsAdder/Nexo). CustomEntityWrapper (:40-50) does the same. There is no API to ask "is this id recognized by ANY installed custom-content hook?" — so McRPG's objective loaders cannot distinguish DIMOND_ORE (typo, dead objective) from itemsadder:ruby_ore (legitimate).
ItemPluginType.NONE fallback (ItemPluginType.java:78-87): an unresolvable material name tries base64 decoding and then silently returns STONE — e.g. a typo'd rarity icon in McRPG's board.yml renders as stone with no log output.
Implementation plan
- Add a recognition query to the wrappers (e.g.
boolean isResolvable() / static Optional<ResolutionSource> resolve(String id)) that reports whether the id resolved to a vanilla type or was claimed by an installed custom-content plugin hook — additive API, no behavior change to existing constructors.
- In
ItemPluginType.NONE's fallback path, log a single WARNING naming the unresolvable material string before substituting STONE (consider rate-limiting/dedup so a bad config line doesn't spam every GUI paint — a once-per-string guard is fine).
- Javadoc the intentional fallback semantics on both wrappers and the new query.
- Companion McRPG ticket consumes the new API to warn at quest parse time.
Acceptance criteria
Notes for the implementing session
Additive changes only — downstream plugins construct these wrappers directly. Follow CLAUDE.md conventions.
Context
From the July 2026 McRPG quest-system audit (typo'd-id finding adversarially verified: CONFIRMED, severity HIGH downstream). Two McCore "forgiving by design" fallbacks currently absorb server-owner typos with zero observability, producing quests that can never progress and GUI icons that silently render as STONE. Downstream loaders need a way to warn without breaking the intentional custom-content support.
Problem
CustomBlockWrapper(String)(src/main/java/com/diamonddagger590/mccore/util/item/CustomBlockWrapper.java:49-58): when the vanilla registry lookup fails, the string is silently reclassified as a "custom block" identifier (by design, for ItemsAdder/Nexo).CustomEntityWrapper(:40-50) does the same. There is no API to ask "is this id recognized by ANY installed custom-content hook?" — so McRPG's objective loaders cannot distinguishDIMOND_ORE(typo, dead objective) fromitemsadder:ruby_ore(legitimate).ItemPluginType.NONEfallback (ItemPluginType.java:78-87): an unresolvable material name tries base64 decoding and then silently returns STONE — e.g. a typo'd rarity icon in McRPG'sboard.ymlrenders as stone with no log output.Implementation plan
boolean isResolvable()/static Optional<ResolutionSource> resolve(String id)) that reports whether the id resolved to a vanilla type or was claimed by an installed custom-content plugin hook — additive API, no behavior change to existing constructors.ItemPluginType.NONE's fallback path, log a singleWARNINGnaming the unresolvable material string before substituting STONE (consider rate-limiting/dedup so a bad config line doesn't spam every GUI paint — a once-per-string guard is fine).Acceptance criteria
ItemPluginType.NONEproduce exactly one WARNING per distinct string, naming the string../gradlew testpasses with zero failures.Notes for the implementing session
Additive changes only — downstream plugins construct these wrappers directly. Follow
CLAUDE.mdconventions.