Update the fidelity notes for the surface pass

The gap list described a surface pipeline that no longer exists: no subsurface
banding, surfaceDepth pinned at zero, six unsupported noises, no deepslate.
What is left is smaller and more specific — carvers, ore veins,
PerlinSimplexNoise, and the two SurfaceSystem extensions that run outside the
rule tree.

Also records the two things that are now compile-time errors rather than silent
wrong output: a surface rule naming a block the ID table does not have, and the
rule tree being used without a seed.
This commit is contained in:
Master290 2026-07-27 02:32:05 +03:00
parent 3a255b52e1
commit 4db7638377

View file

@ -101,35 +101,34 @@ with trilinear interpolation, the climate/biome finder, and the chunk wire encod
Ported from the decompiled source and checked by behaviour rather than by bytes — faithful as far as
we can tell, but no vanilla capture confirms them: the aquifer (`worldgen/aquifer.go`, the whole of
`Aquifer.NoiseBasedAquifer` bar `shouldScheduleFluidUpdate`), the surface-rule interpreter
(`worldgen/surface.go`), and the column pass in `world/vanilla.go` that mirrors `SurfaceSystem`.
(`worldgen/surface.go`, every condition the overworld tree uses), the badlands clay bands
(`worldgen/bandlands.go`), and the column pass in `world/vanilla.go` that mirrors `SurfaceSystem`.
The whole `noise_router` is parsed. `preliminary_surface_level` is reachable through
`od.PreliminarySurfaceLevelAt`, which quart-aligns and memoises across chunks the way `NoiseChunk`
does; the `vein_*` keys are parsed but nothing reads them yet.
The rule tree is **seed-bound**: `od.SurfaceRule()` returns a `*SurfaceRuleSet` compiled against the
world's `RandomState`, because `noise_threshold` and `vertical_gradient` cannot work without it. Get
a context from `NewContext`, call `BeginColumn` per column, then `Apply` per block.
Two things a surface rule cannot do silently: name a block that is not in `worldgen/blockids.go`
(that is a parse error now — it used to resolve to 0 and get dropped, which is how deepslate went
missing from the whole world), and be added without the world's height bounds (anchors resolve at
parse time).
Known gaps, roughly in order of how visible they are:
- **`above_preliminary_surface` is wrong**, so there is no subsurface banding: every land column is
one grass block directly on stone, no dirt, no sandstone under sand. Vanilla is
`blockY >= preliminarySurfaceLevel + surfaceDepth - 8` with the level bilinearly interpolated from
the four corners of the 16-block cell; we compare against the actual top block, which gates the
whole biome surface subtree to a single block per column. `gendump` prints this. The router value
it needs is already available.
- **`surfaceDepth` is always 0.** Vanilla is `surfaceNoise*2.75 + 3 + rand*0.25`, so the dirt band is
three-ish blocks deep; ours is one. This is the other half of the missing banding, and it also
neuters every `add_surface_depth`/`surface_depth_multiplier` term in the rule tree.
- **Several surface-rule conditions are stubs**: `hole` is hardcoded false (vanilla is
`surfaceDepth <= 0`), `steep` is never assigned, the `minecraft:surface` noise is a per-column
random draw rather than the real noise, `surface_secondary` is not sampled at all (so
`secondary_depth_range` is ignored), and 6 of the 7 `noise_threshold` noises are unsupported so
calcite, ice, packed ice, powder snow, swamp water and gravel patches never appear. `bandlands` is
a 4-colour cycle rather than the 192-band array.
- **`vertical_gradient` ignores absolute anchors**, reading only `above_bottom`. The bedrock floor
works because its anchors are `above_bottom`; the deepslate rule's are `absolute` 0..8, so both
collapse to y=-64 and **no deepslate is ever placed**`gendump`'s deep-layer line reads
`deepslate=0` everywhere.
- **No carvers and no ore veins.** Caves come only from the density router; `configured_carver` is
not extracted and the `OreVeinifier` over the parsed `vein_*` keys is not written.
- **No `PerlinSimplexNoise`**, so two corners of `Biome.coldEnoughToSnow` are missing: the height
adjustment that cools a column above sea level + 17, and the `frozen` temperature modifier that
warms patches of frozen ocean. Base temperatures are real (`worldgen/biome_temperature.go`,
extracted from the jar's 65 biome JSONs). The overworld tree reaches `minecraft:temperature` from
exactly one rule — whether a hole in a frozen ocean floor ices over — so neither omission is
visible; snowy peaks come from biome selection, not from this condition.
- **`erodedBadlandsExtension` and `frozenOceanExtension` are not ported.** `SurfaceSystem` runs both
outside the rule tree, for eroded badlands spires and frozen-ocean icebergs.
- **Decoration is hand-written heuristics**, not the vanilla feature system: oak trees only and
without a biome check (so oaks grow in deserts), ores that cannot generate below y≈0 because they
only replace stone and never deepslate, and no grass, flowers, lakes or springs.
@ -138,14 +137,16 @@ Known gaps, roughly in order of how visible they are:
`make verify` is the gate, but most generator defects are invisible to it — they show up as terrain
that looks wrong. `cmd/gendump` exists for that: biome distribution, top surface blocks, subsurface
banding, deep-layer composition, the bedrock band, the underground fluid census, and an ASCII
cross-section, with no client involved. Add an assertion to it whenever you fix a class of defect;
the bedrock-band check is the model — it prints per-layer counts and fails loudly on any air or
water in the floor. The fluid census is the same shape: it prints water as a share of the open
volume under inland chunks (3.8% now, 100% before the aquifer) and fails if caves flood again.
banding, deep-layer composition, the bedrock band, the underground fluid census, the badlands clay
bands, and an ASCII cross-section, with no client involved. Add an assertion to it whenever you fix
a class of defect; the bedrock-band check is the model — it prints per-layer counts and fails loudly
on any air or water in the floor. The fluid census is the same shape: it prints water as a share of
the open volume under inland chunks (3.8% now, 100% before the aquifer) and fails if caves flood
again.
Anything gendump can assert on, prefer to also assert in a test — `TestCavesAreDry` and
`TestNoFluidUnderBedrock` in `internal/world` are gendump checks that run under `make verify`.
Anything gendump can assert on, prefer to also assert in a test. `internal/world` carries four that
started as gendump checks and run under `make verify`: `TestCavesAreDry`, `TestNoFluidUnderBedrock`,
`TestGrassColumnsHaveDirt`, `TestDeepslateLayer`.
`go test -race` needs cgo and a C toolchain; on a Windows box without gcc, `make test-race` cannot
run at all.