- Studio scoreboards recover while saved biome reads are pending
- Combined environment queries retain mantle cave overrides
- World changes refresh rows and genuine failures retain their cause
- Keep Studio board refreshes alive while saved biome data loads
- Sample mantle-aware biome environments and clear prior world values
- Report permanent failures once per display context
- Localize loading states and verify recovery and Jigsaw transitions
- Clump seeds mix the generator seed and attempt index before sampling
- Deposit plans share immutable seeds across preparation workers
- Probability checks cover generator independence and adjacent clumps across batch boundaries
- Mark generation modes closed only after every stage finishes cleanup
- Retain manager loop and cleanup executor ownership until their existing shutdown waits succeed
- Propagate manager shutdown timeouts and interruption so resource release remains blocked
- Track unpublished runtimes by identity while resource state changes during cleanup
- Verify failed joins, interrupted waits, stage retries, and changing resource hashes
- Keep coral tips attached to the fan silhouette
- Preserve large leaf weights and disable zero threshold ores
- Reuse formation palette sources across each object
- Keep writers until cancelled components actually finish
- Retain incomplete runtime and target ownership for retries
- Gate storage release on completed service drains and saves
- Keep component cancellation separate from actual completion before releasing writers and deduplication claims
- Reject cancelled queued component claims before they can start writing
- Retain failed runtime assemblies and unpublished runtimes for shutdown retry
- Gate storage and data release on completed runtime cleanup
- Cover cancellation, shared writers, interrupted waits, and failed shutdown retries
- Formation resolution shares one base palette source per object
- Strata reuse one seeded source per occupied band
- Mixed palette tests preserve block choices across negative bands and reversed traversal
- Fan coral tips follow the existing top of each occupied column
- Large secondary leaf weights preserve their authored proportions
- Zero ore thresholds skip noise sampling and block generation
- Regressions cover fan silhouettes, weighted leaf choices, and ore cutoffs
- Deposit preparation retains at most 32 clumps between ordered placement passes
- Large deposit counts retain parallel preparation and stable per-clump seeds
- Overlap tests cover every attempt across preparation windows
- Deposit tests isolate platform block conversion from cached registry fixtures
- Keep scaling geometry and volume in one locked snapshot
- Skip unsupported block orientations and their tile data
- Replace smart bore executor scaffolding with ordered loops
- Sea surface decorators respect engine and output ceilings in every placement mode
- Clipped sea stacks retain their top palette
- Tests cover short outputs negative bases and engine ceilings
- Multi-palette tests verify shared random sources match fresh per-block sources
- Sea surface decorators respect engine and output ceilings in every placement mode
- Clipped sea stacks retain their top palette
- Tests cover short outputs negative bases and engine ceilings
- Multi-palette tests verify shared random sources match fresh per-block sources
- Branch tip accents occupy the first free outward cell beyond their leaf cluster
- Existing wood leaves and accents retain their positions
- Tests cover opposite branch directions and repeated placement
- Branch tip accents occupy the first free outward cell beyond their leaf cluster
- Existing wood leaves and accents retain their positions
- Tests cover opposite branch directions and repeated placement
- Clumps prepare in parallel and place in dimension region biome order
- Placement evaluates host rules against preceding deposits
- Each clump uses independent deterministic random state
- Configured attempt counts are sampled once per chunk
- Block traversal reuses cursor coordinates
- Tests cover reversed worker completion and generation context cleanup
- Clumps prepare in parallel and place in dimension region biome order
- Placement evaluates host rules against preceding deposits
- Each clump uses independent deterministic random state
- Configured attempt counts are sampled once per chunk
- Block traversal reuses cursor coordinates
- Tests cover reversed worker completion and generation context cleanup
- Biome and carving children share compact rarity selection
- Weighted choices preserve alternating insertion order
- Rarity totals use long counts without expanded lists
- Natural child selection preserves its existing noise calls
- Differential tests cover normal and extreme rarity values
- Downstream route lengths are evaluated once per routing grid
- Footprint construction sorts primitive column keys without a temporary tree
- Footprint lookups use primitive keys and preserve immutable ordered views
- Closed cave components keep one ordered flood-fill membership set
- Surface pools and rivers share their layer construction
- Regression tests cover routing limits, cycles, coordinate bounds, and footprint ordering
- Failed planner drains retain mantle and generation data for retry
- Detached runtime cleanup retains its target until runtime teardown succeeds
- Terrain caches clear after hydrology shutdown completes
- Hydrology close drains active tile plans and column composition before returning
- Queued tile plans cancel without waiting for their executor to start them
- Closed caches reject new tile and column demand
- Shutdown tests cover background plans, queued demand, active composition, and recursive close
- Concurrent replacement requests report busy before waiting for the manager lock
- Replacement staging reports localized phases and elapsed time
- Player progress messages use entity scheduling
- Pack copies flush completed files after traversal
- Replacement admission and progress tests cover scheduling and cleanup
- Language editor tests use a local catalog response
- Dune and Strata add dunes and layered bands
- Wood and Marble add warped grain and mineral veins
- Gabor and Scales add oriented waves and overlapping scallops
- Chladni and Kaleidoscope add nodal lines and mirrored motifs
- Menger Sponge and Circuit add recursive voids and connected traces
- New styles use the shared scale and full seeds
- Tests cover tile seams, volume variation, bounds, and octaves
- Existing worlds retain generated terrain across generator updates
- New terrain blends at generation boundaries
- Cold generation and Studio startup improvements are integrated
- Terrain sampling validates active generator bounds and noise
- Cold startup and hydrology changes integrate with terrain history
- Flat authoring worlds skip native features under the history write guards
- Native decoration checks retain recorded structure and terrain ownership
- Automatic build revisions replace manual source seals
- Flat authoring studios skip terrain and native structure preparation
- Normal Studio entry prepares the exact hydrology column asynchronously
- Hydrology prefetch admits the complete frontier before stale queued work
- Concurrent hydrology loads avoid cache monitor contention
- Cave density tasks drain failures before releasing chunk state
- Terrain and interpolation queries reuse exact bounded samples
- Pregeneration counts requested chunks directly from its bounds
- World-local pack epochs preserve generated chunks across restart-only updates
- Kernel catalogs and source seals retain executable generation behavior across jar changes
- Crash-safe ownership, boundary, registry, semantic, and mantle records survive activation changes
- New terrain blends lower surfaces and inverted ceilings against frozen historical boundaries
- Cave, object, structure, biome, and hydrology work respects activation ownership
- Find commands merge recorded facts with eligible active predictions for biomes, regions, structures, objects, and rivers
- Bukkit, Fabric, Forge, and NeoForge route generation through retained runtime scopes
- Shutdown ordering preserves class-loader resources until world and service cleanup finishes
- Tests cover activation chains, failure recovery, retained registries, bounded lookup, and transition geometry
- Seekable ZIP output removes redundant data descriptors without changing entry contents
- Compaction validates entry size and CRC before replacing the artifact
- Tests cover metadata preservation, deterministic output, corrupt payloads, and duplicate entries
- 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.
Surface rivers gain a drowned inlet at the mouth, a spring pond and an
inland terminal pond, a configurable erosion profile (thalweg fraction,
blend curve, bed noise, smoothing) and a per-area shore biome width;
banks lose freeboard and inset for a single sink. Underground courses
accept tributaries, coastal grottos can be admitted as standalone sea
caves, and a region or biome can confine the rivers born in it. Tile
planning forks its ring work through HydrologyForkJoin. Pack validation,
the schema, the probes and the tests follow.
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.
A dimension can now list staticObjects: an object key, a world position, a
fixed rotation and scale, block edits and an optional bore or smart bore.
The layer compiles once per dimension and stamps its blocks into every
newly generated chunk it covers, later entries winning overlaps. Pack
validation, the schema, the export closure and the object transforms
(origin-anchored scaling, tile rotation) cover the new fields.
- 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
- Filter excluded biomes, regions, spawners, loot tables, jigsaw pieces and structures out of every pool through CompatPools and cascade empty pools to the container
- Evaluate each object placement per object from the .iob palette header, honouring chance-1 edit rules and reporting every missing palette key
- Treat edit find lists and marker mark lists as match-only
- Exclude jigsaw pieces on missing palette keys, drop them from pools and exclude structures whose start pool is gone
- Drop custom biome spawns whose entity is missing before the datapack JSON is written
- Skip excluded placements in the object, floating object, tree and locator paths while keeping the per-chunk RNG draws unchanged
- Keep the engine focus biome and region null when the gate excluded them
- 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
A pregeneration now generates in multicore mode: the matter stage runs
on the calling thread so its mantle window fans out across the burst
pool while biome and terrain run alongside, components are claimed
through the in-flight map so overlapping windows join instead of
blocking, and each region's chunks are ordered in stride-4 lattices so
consecutive chunks never share a window. Hydrology tiles for the whole
area are planned ahead nearest the centre first on a dedicated planning
pool, and the ring around every needed tile stays planned as the front
moves. Height bounds at grid corners are shared between threads and
from planning into generation, the sole engine of a pack is answered
from a snapshot instead of the registry lock, composed chunk keys are
mixed, cached tiles are answered in place, the burst pool grows to two
workers per core for the run, and large chunk-worker pools admit up to
256 requests.
Planning failures used to escape into the chunk system and crash the
server. The tile cache now catches them, logs the failure in full and
publishes an empty tile so terrain keeps generating. A natural height
that is not finite is no longer memoized, and its error names the
region, biome, fluid height, overlay, every interpolator's bounds and
generator heights, and the cached and fresh values for the column.