- Every registrant is evaluated on load (IrisData.preprocessObject ->
IrisRegistrant.evaluateCompat) by a cached per-class reflective walker over the
annotated key fields; the verdict is stored on the registrant and pool sites filter
with isCompatExcluded(). Block keys resolve through the live registry, the legacy
rename table, IrisDimension.blockFallbacks and the entry backup, in that order.
- Unit of exclusion is the compat unit that composes the missing content (registrant
or object placement). A referencing unit drops the reference; an emptied required
pool excludes the container (CompatPools cascade through regions, biomes, dimension,
spawners, loot tables, jigsaw pools and structures). A cascade that reaches the
dimension is a blocking validation error and world creation is refused.
- Object placements are evaluated per object from the .iob palette header: an object
is excluded from a placement's pool unless a chance-1 type-replace (edit rule
matching the key) or a fallback covers the key. edit find lists and marker mark
lists are match-only. Missing palette keys stay MissingBlockState placeholders
(air everywhere, real air nativeHandle) so a chance-1 edit rule can still rewrite
them at placement time.
- Approved decisions: exclude the composing unit; console-only reporting; no version
fields on packs and no cross-version pre-check (authors build on their version,
older servers gate at load).
- IrisDimension.blockFallbacks (base key -> full block state) applies to every
palette, decorator, deposit, replace rule and object in the pack.
- IrisBlockData.backup is revived on every platform (it was dead on Bukkit because
B.getState returned air).
- The legacy rename table now lives in LegacyBlockRenames and is applied identically
on Bukkit and the mod loaders.
Operator surface
- Boot listing per pack after the validation lines (IrisWorldGeneratorResolver on
Bukkit, ModdedStartup on modded), grouped by key, capped at three subjects per key.
- Validation summary line on /iris pack validate and /iris pack status, findings
persisted in PackValidationResult through PackValidationCache.
- One summary line per world engine when its pack has findings.
- /iris pack compat [pack] (alias cp) on Bukkit and modded, uncapped, from the
persisted validation so no pack is reloaded; catalog keys in all 17 locales.
Verification on the branch
- Full build green in the .compatwt worktree; modded adapters compile.
- Golden hash unchanged on Paper 26.2, seed 1337, radius 8.
- Live boots on Paper 26.1.2 and 26.2: the stock Overworld lists 6 unavailable keys
on 26.1.2 and none on 26.2; the world creates and generates without the excluded
content on 26.1.2.
Integration on top of master (df34f328e..fc3a26dd9)
- Conflicts: PackValidator keeps both import sets (JSONObject for static object
validation plus the compat and loader types); RiverPolicyResolver.State.apply takes
the confinement scope and the pack data (confined rivers and gate-filtered river
biome selections); IrisRiverPolicy keeps shoreBiomeWidth and confined next to
compatBiomes.
- Static objects honour the gate. The per-object palette evaluation moved out of
IrisObjectPlacement into the shared IrisObjectCompat helper; IrisStaticObject
.evaluateCompat mirrors a one-object placement, records findings with subject type
"static object" and the object key (DROPPED for uncovered palette keys, EXCLUDED
for a missing edit replace palette), IrisStaticObjectLayer.compile skips gated
entries instead of failing, and PackValidator.gateContent asks every dimension for
its static objects (IrisDimension.evaluateStaticObjectsCompat) so the boot listing
is complete. CompatWalker treats IrisStaticObject like IrisObjectPlacement: never
descended, so a static object's edit palette excludes only that entry, never the
dimension. Covered by IrisStaticObjectCompatTest.
- The modded compat and cp subcommands run inside ModdedCommandTree.localized like
the rest of the pack tree and are documented in the modded help; the parity test
asserts both.
- Locale keys stay in core/src/main/resources/languages: master's on-demand download
reads those files from the repository and the build only keeps them out of the jar,
so the compat keys sit next to the debugdump keys in the same form.
- Placeholder audit of master's new code: the only native casts added are the
isFaceSturdy fallbacks in IrisSpeleothems and ModdedDecoratorHooks, both behind
B.isAir guards, and MissingBlockState.nativeHandle is the real air anyway;
IrisObjectTransforms only asks B.isAir; decorators resolve palettes through
IrisBlockData.getBlockData, which never yields a placeholder. No new guards needed.
- core/purity-allowlist.txt gains IrisSpeleothems: 5053a644c split the Bukkit
isFaceSturdy fallback out of the already allowlisted DecoratorCore without moving
the allowlist entry, so master's own build failed the Bukkit purity ratchet.
- CompatTestPlatform states now answer isAir, isSolid, isFluid and materialKey like a
real adapter: B caches the first registries it sees per JVM, so an interned mock
air that never said isAir leaked into the core.compat tests once the static layer
ran under that platform.
Gate commands on the merged tree
- ./gradlew build (default VolmLib composite, ../VolmLib at 7b8029e): BUILD SUCCESSFUL;
core 3499 (8 skipped) tests, bukkit plugin 343 tests, nms v26_2_R1 255 (1 skipped) tests,
probe 78 tests, buildSrc 10 tests, 0 failures.
- cd adapters/fabric && ../../gradlew compileJava: BUILD SUCCESSFUL (:compileJava executed)
- cd adapters/forge && ../../gradlew compileJava: BUILD SUCCESSFUL (:compileJava executed)
- cd adapters/neoforge && ../../gradlew compileJava: BUILD SUCCESSFUL (:compileJava executed)
- cd adapters/forge && ../../gradlew test --tests IrisModdedCommandParityTest --tests
ModdedLanguageCommandsTest: BUILD SUCCESSFUL, 11 tests, 0 failures.
/iris language opens a locale menu and sets the language for the caller
or, for a gamemaster, the server default; /iris debugdump writes a
diagnostic report and optionally uploads it. Neither needs iris.all, so
a plain player can reach them. Every modded command now executes inside
a language audience scope, and the Bukkit dispatcher opens one around
execution, tab completion and help. Permissions, message keys and the
shipped locales follow.
Locales are fetched from the Iris repository at runtime into
languages/downloaded and cached against the revision the jar was built
from; the artifact ships only a manifest of the available locales.
IrisLanguage gains a player language service, per-audience snapshots and
an in-game message editor that writes locale overrides. The Bukkit
artifact verifier now fails when any locale file is embedded, and the
modded shadow jars drop the Bukkit-only switcher and editor classes.
Dripstone and sulfur spikes are placed as oriented, thickness-graded
columns by the surface and ceiling decorators through a shared
IrisSpeleothems helper, replacing the ad hoc dripstone fixups, and the
stacking path is unified for both directions. The perfection modifier
renormalizes a spike whose support a pool replaced, dropping the
unsupported run and re-tipping what remains. Surface sturdiness is asked
per face now, so a downward spike tests the ceiling it hangs from.
A height or biome query from the tick thread no longer blocks on a cold
hydrology plan: it answers from the natural streams and asks the
planning pool for the tiles meanwhile. A new world prefetches the tiles
around spawn when the generator is injected, and the hydrology pool gets
full parallelism instead of a third. Also stops the shared corner-bounds
cache from pinning a non-finite sample and fences its two stamp reads.
Vanilla structure and feature placement now runs through the bounded
worldgen access with a protected-position predicate, so a jigsaw piece
or an imported feature can read a static object's blocks but never
overwrite them, and never schedules a tick or block entity there.
Dimensions without static objects keep the plain level as before.
- Force-load every registrant and placement during pack validation and persist the findings with the Minecraft version in the validation cache
- Turn an excluded dimension into a blocking validation error and suppress content-key warnings the gate already reported
- Print the capped per-key listing after the validation lines on Bukkit and modded, ordered excluded, dropped, substituted
- Log one summary line per world engine from the published validation result
- Add /iris pack compat on Bukkit and modded with help and locale keys for every shipped language
- Add the ContentGate, CompatWalker, PackCompatReport and finding types under core.compat
- Resolve block keys through the live registry, the legacy rename table, dimension blockFallbacks and the entry backup on every platform
- Move the legacy rename table into LegacyBlockRenames so Bukkit and the mod loaders apply it identically
- Evaluate every registrant on load from IrisData.preprocessObject and store the verdict on IrisRegistrant
- Add IrisDimension.blockFallbacks as a plain object property
- Keep missing palette keys as MissingBlockState placeholders so a chance-1 edit rule can still rewrite them
- Guard the modded rotator, merger and face fixer against non-modded states
- Source the legacy potion effect aliases from the gate so the Bukkit-typed table stays unloaded on modded
Brings master's Sentry removal, bound platform classification, Vision
entity toggle, release version and generation context binding onto the
rivers rework while keeping the hydrology system master had removed.
Hydrology files master deleted are restored from the branch, master's
non-hydrology edits are kept, and the modded adapter builds drop the
Sentry dependency with master.
Also removes the ridge_tunnel find selector: no course publishes ridge
bores any more, so it could never return a result.
- channel.springWidthRatio / springLength open every surface river in a pool that shrinks where the ground falls away
- Banks settings keep structural invariants only; authoring bounds stay in the validator
- Feature searches walk tiles outward and stop early; find and goto report progress per ring
- Replace the river package with the hydrology planner, footprint compiler, cave containment and runtime
- Add the hydrology pack schema, validator, probes and tests
- Wire hydrology into IrisComplex, actuators, mantle, Vision and commands
- Resolve first-generation engine binding from authoritative published level context.
- Validate generator identity and recover canonical Overworld binding from stale snapshots.
- Add shared loader regression tests and their Mockito test dependency.
- Publish and remove dynamic levels through host lifecycle methods when available.
- Attach hybrid host level data before engine binding and publication.
- Preserve native loader behavior when host extensions are absent.
- Remove automatic error reporting and server-identifying attachments.
- Remove Sentry dependencies, release tooling, settings, and test commands.
- Keep failures operator-visible through local stack traces and logging.