Write chunk NBT vanilla reads: flat root, byte section Y, four-bit block palettes

Our region files were not Anvil. Three things stood between them and vanilla's
deserializer, and each is enough on its own:

  * everything was nested under a "Level" compound. Chunk data lived there until
    1.18; SerializableChunkData builds a flat root and never looks for the key.
  * a section's Y was an Int. Vanilla writes putByte and reads getByteOr, so
    every section of ours decodes as index 0 and overwrites the one before it.
  * block palettes were packed at ceil(log2(size)) bits. Strategy's tableswitch
    routes bit counts 1 through 4 to the same four-bit configuration, so a
    palette of 2..16 states is four bits wide on disk. Ours were one to three,
    which makes the long array a quarter of the length vanilla computes, and
    SimpleBitStorage rejects the section outright rather than misreading it.

Biome containers were already right: Strategy has no such floor for them, and a
Global configuration above three bits still stores palette indices, just at its
own width. The suspicion that biomes collapsed on save/load was unfounded --
what let it stand is that every round-trip test in this package set blocks and
asserted blocks, so nothing proved biomes survived. They do now, per cell, for
every palette width a section can hold.

Verified against vanilla rather than against our reading of it:
tools/VanillaChunkFormatCheck.java opens a region file we wrote using vanilla's
RegionFile, NbtIo, Strategy and SimpleBitStorage. Sixteen generated chunks pass.
Reverting either the Y type or the palette floor makes it fail with vanilla's
own message -- "Invalid length given for storage, got: 64 but expected: 256" --
so the check can fail, which is the only reason to trust it passing.

Reading a world the official server generated is what the surface-height parity
capture in CLAUDE.md has always needed, and this is half of it.
This commit is contained in:
Master290 2026-07-27 03:44:48 +03:00
parent 113a59e365
commit e0fdddd887
4 changed files with 437 additions and 54 deletions

View file

@ -73,9 +73,16 @@ java -cp "<out>;$CP" VanillaBlockStateDump > internal/world/block_properties.bin
The 39 jars under `libraries/` are required; the server jar alone will not boot the registry. Bump
the format version in both the Java and `internal/world/block_properties.go` whenever the layout or
a flag's meaning changes. Substring-matching block names is how the light table was wrong before
(`grass_block` matched "grass", `bedrock` matched "bed"); don't reintroduce that shape of guess
anywhere.
a flag's meaning changes.
The same trick verifies output, not just constants. `tools/VanillaChunkFormatCheck.java` opens a
region file we wrote with vanilla's own `RegionFile`, `NbtIo`, `Strategy` and `SimpleBitStorage` and
fails if the root is not flat, a section `Y` is not a byte, or a palette array is not the width
vanilla derives from its palette size. Note the server jar is *signed*, so a helper cannot be
declared inside a `net.minecraft.*` package — reach protected members by reflection instead.
Substring-matching block names is how the light table was wrong before (`grass_block` matched
"grass", `bedrock` matched "bed"); don't reintroduce that shape of guess anywhere.
## Layout