Bare ground under a decorator preview was dimmed, which made the block
under each decoration look lit up. It now shows at its own brightness;
the sprites alone mark where the decorator places.
Plants whose model stacks several sprites, like the firefly bush with
its glowing fireflies, now draw every layer in order instead of only
the particle texture.
Model used: Claude Opus 5.5
Decorator previews used the dark "nothing here" colour around and
between their sprites. They now show the biome's top surface layer
there: through the see-through parts of each sprite, and dimmed where
the decorator places nothing or places air. Hovering a bare spot says
the decorator places nothing there.
Model used: Claude Opus 5.5
Decorators now draw their plant sprite on each block instead of its
average colour, which only suits stacked ground layers.
The Overview tab lists every decorator and block palette snippet with
how often biomes use it. Picking one opens it where the first biome
places it; its rows open each other use. Snippet files no biome uses yet
are listed too. Snippet names keep their folders, so two snippets with
the same file name in different folders stay apart.
Model used: Claude Opus 5.5
Each decorator of a biome is now listed and previewed next to its layers,
walls and slabs. The preview shows where the decorator places, using the
same seed as the generator, and which block it picks there. Notes explain
what it leaves out: the part it decorates, competition with other
decorators, stacking and height.
Palettes that come from a snippet file show the snippet name, read from
the biome file since snippets are copied in when the pack loads.
Model used: Claude Opus 5.5
The Here tab listed palettes only for the biome you stand on. The other
biomes in your region, including child biomes nested under their parent,
showed just their name, so a child like Grassland Hills had no way to
reach its wall blocks from there. Every biome in the region now lists its
palettes under it, indented with the biome.
Model used: Claude Opus 5.5
Carving rock behind cliff faces with noise didn't give mountains the
look it was meant to, so it comes out again: the noiseCarving biome
setting, its mantle component and the NOISE_CARVED flag.
This reverts 8c39f9a01 and 8a1c7ac99.
Model used: Claude Opus 5.5
Noise carving ran inside the cave carving pass, which visits every
chunk within cave range of the chunk being generated, and it looked up
the biome and height of every column in all of them. Opening a studio
froze the server for about 35 seconds on its first chunk, even for
packs that don't use noise carving.
It now has its own mantle component that runs last and only for the
chunk being generated, and it does nothing when no biome in the pack
uses it. A fresh studio's spawn chunk is ready in about 1.4 seconds
again.
Model used: Claude Opus 5.5
Iris terrain is one height per column, so mountains could never lean
out over the ground below. Biomes can now set noiseCarving, which
removes rock behind cliff faces and slopes wherever a 3D noise drops
under a threshold. The hollows open up into overhangs, arches through
ridges and ragged cliffs instead of hiding inside the mountain.
Gentle ground keeps a crust of rock so trees and grass keep their
footing, carving fades out toward the biome's borders, and nothing is
carved at or below sea level. The carved blocks go through the normal
carve pass, so they get cave walls, floors, ceilings and decoration.
Model used: Claude Opus 5.5
The single before picture wasn't pulling its weight. The toolbar
buttons, the C shortcut and the swipe and changes overlays are gone
until there's a better way to compare pack versions.
Model used: Claude Opus 5.5
Palettes listed only a biome's surface layers. They now include sea
layers, cave ceiling layers, and wall and slab blocks, each previewed
with the noise and random source the generator uses for that kind.
Wall and slab blocks also change with height, so their preview is drawn
at sea level and says so.
The Here tab names the parent of a child biome and lists the region's
biomes with their children nested under them, marking where you stand.
Model used: Claude Opus 5.5
The height view spread its colours over the whole world height, so a
mountain range and the plains next to it got nearly the same colour.
The legend now measures the visible heights (1st to 99th percentile,
rounded to 8 blocks) and fits the gradient to that range, with sea level
kept as the water/land split.
The map also re-finds its own world after a reload instead of whichever
Iris world is active, now that the active world prefers the open studio.
Model used: Claude Opus 5.5
Long biome names now shorten instead of pushing the percentages out of
the legend, and biomes that share a display name show their key. The
highlight edge tints instead of drawing solid white, which turned
biomes scattered pixel by pixel into noise.
Model used: Claude Opus 5.5
/iris std noise listed the generators of whichever Iris world Bukkit
listed first. A normal Iris world runs on its own copy of the pack from
when it was created, so generators added to the pack since (like a new
generators/2026 folder) were missing while you worked in the studio.
The noise commands now use the world you stand in, and otherwise the
open studio before any other Iris world. After a hotload the explorer
stays on the world it was opened for.
Model used: Claude Opus 5.5
Highlight a biome or region (legend click, right-click, or H under the
cursor) to fade everything else and outline it; Esc clears it. A live
legend beside the map lists the biomes or regions in view with their
share of the screen.
The hover card now answers at once from the drawn tiles and then adds
height, sea level, land or sea, slope, cave biome and the Minecraft
biome; Shift adds keys and files.
After a refresh or hotload, C compares with the map from before: a
draggable before/now divider, or a view that fades out everything that
stayed the same and says how much changed.
Shading (S) adds hillshade relief to every view and Borders (B) outlines
the regions. Tiles now remember what each pixel shows, so all of this
restyles without rendering again.
Model used: Claude Opus 5.5
The map drew every visible tile to the window on its own, hundreds of
scaled images per paint, and since tiles are no longer cached in the
display server each of those was uploaded again on every frame, which
made dragging and zooming lag. The tiles are now put together in memory
once, only when tiles or the view change, and drawn as a single image
like the palette view does.
Model used: Claude Opus 5.5
Opening the map crashed Xwayland inside Mesa's Intel driver, which took
the server, the game client and every other X window down with it.
Map tiles and noise frames were left for Java2D to copy into textures
inside the display server, hundreds of them for one map. They are now
drawn straight from memory again, like before the render rework.
Model used: Claude Opus 5.5
FlatLaf grows fonts and its own controls to the screen's DPI, but the
sizes the studio set itself stayed fixed, so on a 192 DPI screen text
was cut off and overlapped. Every padding, row height, column, card and
legend now grows with the same scale or follows the font, the windows
open at a scaled size that still fits the screen, and the theme is
installed before any window builds its controls. Long status text now
shortens with an ellipsis instead of pushing the rest of the bar away.
Model used: Claude Opus 5.5
/iris std map now opens a single window with a grouped list of views
(world, biome layers, generation load and the new Palettes view), each
with a number or letter key. The palette explorer lives in that window
instead of its own: double-click or right-click a spot on the map to see
its palettes, and switching views keeps both looking at the same place.
/iris std pal still works and opens the map straight on its palettes.
The map draws much faster. Tiles are cached per power-of-two zoom level
so zooming reuses them, coarser and finer tiles already in the cache
stand in while new ones render, renders start the moment you drag or
zoom, and tiles that are still on screen keep rendering instead of being
thrown away. The noise explorer keeps one worker pool instead of making
threads for every frame and skips work for frames that were replaced.
Pointer coordinates now live in a status bar, so moving the mouse no
longer redraws the whole map.
Model used: Claude Opus 5.5
FlatLaf is loaded at runtime through slimjar like the other libraries.
Every studio window now opens with FlatLaf's dark look tuned to the
IntelliJ New UI colours, and shares a small kit of controls: a flat
toolbar, toolbar buttons and tabs, search boxes, a status bar and the
rounded cards drawn over maps.
Model used: Claude Opus 5.5
With focusRegion set the world only generates that region, but find
checked the dimension's region list, which the focus region does not
have to be part of, so everything in it was reported as missing.
Model used: Claude Opus 5.5
Find biome, structure and object only checked the biomes a region lists
directly, so a biome that only appears as another biome's child was
reported as not being in any region.
Model used: Claude Opus 5.5
Textures were looked up by the block state with only the properties the
pack set, so a plain grass_block never matched its snowy=false variant
and fell back to its map colour. The lookup now uses the full state.
Model used: Claude Opus 5.5
The explorer only reloaded the map for textures once a layer was already
showing. Now that the Minecraft jar is cached, textures can finish while
the first layer is still loading, which left that layer on map colours
until another layer was picked.
Model used: Claude Opus 5.5
Every tinted block used one fixed plains green, so biomes with their own
grass colour looked nothing like the game. Tints now follow Minecraft's
own rules: its block tint table, the grass, foliage and dry foliage
colour maps from the client jar, vanilla biome colour overrides, the
dark forest and swamp grass modifiers with an exact copy of the swamp
noise, and the client's 5x5 biome blend. Custom biomes use the colours
Iris writes into their data pack, and the variant is picked per chunk
the same way Iris generates them.
Plants have no top face, so they now show their average colour instead
of their side-on sprite tiled into stripes.
Model used: Claude Opus 5.5
While dragging or zooming, the map stood still until the mouse paused,
then restarted from a blocky draft. The last finished frame is now moved
and scaled with the view straight away, and a new frame starts as soon
as the previous one is done, sized from how fast the last frame drew so
cheap views come out sharp immediately.
Budgets are now measured in drawn pixels, so a frame where the layer is
missing everywhere no longer breaks the refinement step.
Model used: Claude Opus 5.5
The explorer read the persistent world instead of the studio world the
player was in, and left out the studio focus region, so it showed the
wrong palettes. It now uses the player's own world, lists the focus
region first and opens on the surface biome centred on the player.
Blocks are sampled once per whole block and drawn at full resolution
without smoothing, so textures look like they do in game. The view and
depth controls use styled buttons instead of the default Swing widgets.
Model used: Claude Opus 5.5
Biomes are 3D, so the biome at a player's position underground isn't the
surface biome above it. The Here tab now lists the region, the surface
biome and, when different, the biome at the player's position, each with
its layers, followed by the region's other biomes. It updates as the player
moves but no longer changes the selection, and biomes without a key no
longer crash it.
Model used: Claude Opus 5.5
Block textures come from the Minecraft client jar, downloaded once from
Mojang and cached under plugins/Iris/cache. Each block shows its tinted top
face: texture pixels when zoomed in, the texture's average colour when
zoomed out, and the map colour when no texture is available.
The sidebar now has two tabs. Here follows the player who opened it and
shows their region, the biome they stand in with its layers, and the
region's other biomes, opening each new biome they walk into. Overview is a
searchable tree of region, biome group, biome and layer.
Model used: Claude Opus 5.5
/iris studio palette (alias pal) opens the explorer on the biome you stand
in, listing each biome's palette layers instead of noise styles. The map
shows the blocks the layer places, the raw noise, or both, and a side panel
shows which noise values the layer produces, which value range each block
owns, and how its real share of the ground compares to its weight.
World generation and the preview now sample layers through the same
IrisBiome methods, so the preview matches what the world places.
Model used: Claude Opus 5.5
axialFracturing on a style only changed how that style fractures its
parent, so setting it on a style like IRIS changed nothing. It now also
makes the style's own built-in fractures axial. A fracture the pack
adds keeps its own axialFracturing setting.
Model used: Claude Opus 5.5
Default fracturing pushed every sample by one value along the (1, -1)
diagonal, so heavily fractured styles such as FRACTAL_SMOKE and the
IRIS family formed straight 45 degree edges. It still takes a single
fracture sample, but the push direction now turns with that sample's
value. That costs a few multiplications per fracture level: 0% on
FRACTAL_SMOKE and FRACTAL_WATER, 4% on IRIS_DOUBLE.
axialFracturing read its second offset from the same noise with
swapped coordinates, which mirrors the warp across x = z. Each axis
now samples a far, uncorrelated part of the fracture noise instead.
Both change terrain for fractured styles, so existing worlds will show
seams at the border to newly generated chunks.
Model used: Claude Opus 5.5
Snippet discovery only followed a field's raw type, so element types of
KList, KMap and arrays were never visited. Snippets that only appear in
collections, such as decorator, deposit and tree, got no schema and no
workspace mapping.
Model used: Claude Opus 5.5
Brings over v4's Noise Explorer and Vision viewers: a tiled, cancellable
renderer, viewport math, palettes, player and entity markers, and
click-to-teleport.
On Wayland desktops whose Xwayland window manager does not reparent
windows (niri, sway, Hyprland), Java's X11 toolkit waits for a reparent
that never comes, so it keeps its guessed window size and insets and
leaves most of the window white. Iris now sets
_JAVA_AWT_WM_NONREPARENTING natively before opening its first window
when the desktop needs it. GNOME and KDE are left alone because Java
already recognises their window managers.
All Iris windows, including the pregen view, now come from GuiHost, and
the studio commands report a headless server instead of failing.
Model used: Claude Opus 5.5
Paper still provides Adventure at runtime. Every Adventure method Iris calls has the same signature in 4.17 and 5.2.0, so older servers keep working.
Model used: Claude Opus 5.5
The heap gate and the engine service's keep-alive scaling read heap usage
right after the last collection instead of the moment's usage, which G1
lets climb near the maximum on a healthy heap. The plate budget now comes
from a measured 38 MB per plate on a 1088 block world instead of an
estimate that assumed 136 MB there, and is enforced as is rather than at
twice its value. Pregen evicts only the least recently used plates down to
the budget instead of every idle one, so it no longer reloads the plates
it is still generating around.
Model used: Claude Opus 5.5
Ported from Iris v4's mantle backpressure. Before each chunk the
pregenerator now:
- evicts idle tectonic plates and waits while more plates are loaded
than the heap-scaled budget allows (pregen.maxResidentTectonicPlates)
- pauses between 92% and 82% heap, requesting a GC because a paused
pregen allocates too little for the collector to run on its own; if
the heap stays full, the JVM's diagnostic GC runs at most once a
minute, which also works with -XX:+DisableExplicitGC
Both waits give up after pregen.mantleBackpressureTimeoutMs so a stuck
heap cannot hang the pregen. Unlike v4, a reclaim starts anywhere above
82% instead of only at 92%, since a pregen waiting at 89% otherwise
never triggers one.
Outside pregen, the engine service shortens the mantle keep-alive as
the heap fills and trims studio worlds once the heap is critical.
The mantle itself:
- concurrent requests for a plate that is still loading share one load
instead of each holding an IO thread
- plate retries stop once the mantle is closed or the thread is
interrupted, instead of recursing forever
- trim(0, 0) evicts plates idle for 500 ms instead of 4 s
Model used: Claude Opus 5.5
An exception on the pregen thread ended the thread without shutting the
job down, so it kept reporting 0 chunks per second forever and blocked
starting another pregen. A failure is now logged and the job is closed.
Model used: Claude Opus 5.5
Every mantle chunk allocated a coroutine mutex for all 256 possible flag
ordinals up front, about 66 KB of locks per chunk, although only a few
flags are ever raised under a lock. During a pregen those locks took
well over a gigabyte of heap and ran 3 GB servers out of memory. Each
lock is now created when its flag is first raised.
Model used: Claude Opus 5.5
26.3 changed the chunk generator, biome source and structure placement
APIs, so it gets its own v26_3_R1 binding, compiled against the 26.3
dev bundle. v26_1_R1 keeps covering 26.1.2 and 26.2.
Binding changes against v26_1_R1:
- noise, surface and carvers run through a single buildTerrain stage
- the biome source hands out itself as the BiomeResolver
- structures are generated with a climate sampler, and starts are
looked up per chunk instead of per section
- structure set salt and frequency come from the spreading placement
- biome colors are read from Vector3f attributes
Data pack format 121 with DataFixerV2603:
- biome mob spawns and creature spawn probability move into the
natural_mob_spawns and creature_world_gen_spawn_probability attributes
(26.3 silently ignores the old fields)
- the bed rule's "explodes" becomes "destroy_on_use", and straw beds get
the same rule, matching vanilla
Model used: Claude Opus 5.5
Older servers such as Paper 1.20.1 cannot read the Java 25 classes of
the 26.x binding and logged a conversion error for each of them on
shutdown. Bindings for other versions are never used, so they are not
loaded at all.
Model used: Claude Opus 5.5
Studio worlds live in the "iris" world folder, which on 26.x is inside
the level's dimensions folder rather than in the world container.
Model used: Claude Opus 5.5
Paper 26.1.2 caches block data that names every state without the parsed
states BlockData#merge needs, so replacing blocks inside objects threw
on every placement. Such block data replaces the base completely, so
B.merge returns it directly.
Model used: Claude Opus 5.5
26.1 requires has_ender_dragon_fight in dimension types and reads data
packs before any plugin runs, so a pack written on 1.21 stopped the
server from starting. 1.21 ignores the field, so it is now always
written.
Model used: Claude Opus 5.5
Adds the v26_1_R1 binding, which covers both versions. 26.x servers are
not obfuscated and need Java 25, so the build moves to Gradle 9.5.1 and
paperweight-userdev 2.0.0-beta.21, and the binding compiles against the
26.1.2 dev bundle with a Java 25 toolchain while everything else stays on
Java 21.
On 26.x every world is a dimension inside the main level, so the binding
provides DimensionWorldStorage:
- world folders resolve to <level>/dimensions/<namespace>/<key>
- data packs go to the level's datapacks folder
- Iris data in a pre-26.1 world folder is moved into the dimension
before Paper imports the world and deletes the old folder
- "main=true" swaps the world in as the level's overworld instead of
changing level-name
Also:
- INMS compares 1.x and 26.x versions in release order
- data pack formats 101 (26.1.2) and 107 (26.2), declared with
min_format/max_format from format 82 on
- dimension types get the fields 26.1 added
- the Java safeguard accepts Java 25
Model used: Claude Opus 5.5
Minecraft 26.1 moved every world into its level's dimensions folder, so
Iris can no longer assume <world container>/<world name>. World folders,
data pack folders and moving Iris data out of an old layout now go
through WorldStorage, which the NMS binding provides. Every binding so
far uses LegacyWorldStorage, so behaviour is unchanged.
Code that already holds a loaded World uses World#getWorldFolder, which
is correct for both layouts.
Model used: Claude Opus 5.5
Core now compiles against paper-api instead of spigot-api. PaperLib is
replaced by Paper's native async chunk and teleport API, and the Spigot
fallbacks (Medieval pregen method, sync chunk loading) are removed.
Adventure is no longer bundled and relocated: Paper ships it and every
CommandSender is an Audience, so the BukkitAudiences wrapper and ShadeFix
go away.
Iris now refuses to enable on servers without the Paper API, with a clear
message instead of failing later at runtime.
Model used: Claude Opus 5.5