The in-memory chunk+frame cache no longer grows unbounded as players
explore. An LRU policy (doubly-linked list + index map, O(1) per op)
evicts least-recently-used chunks when the cache exceeds MaxCachedChunks,
dropping both the chunk and its cached frame. Dirty chunks are skipped
until the autosave flushes them, so no edit is ever lost to eviction.
- world/cache.go: maxChunks field + order/index LRU bookkeeping; touch
(move-to-front) on every chunkAt/Frame/SetBlock hit; evictIfNeeded on
miss; NewCacheWithLimit constructor (0 = unbounded, backward-compat).
Dirty chunks are bumped to MRU and left in place rather than doing
region I/O under the cache mutex.
- server/server.go: Config.MaxCachedChunks (default 1024); New wires it
into NewCacheWithLimit when a world dir is set.
- cmd/regionio/main.go: -maxcache flag.
- Tests: limit cap, LRU ordering (touched chunk survives), both-maps
drop, dirty-keep, reload-on-access, and edits-survive-eviction+reload
(end-to-end via the store).
The world now survives restarts: chunks load from disk (read-through
cache) and player edits persist via async autosave + a final SaveAll on
shutdown. RegionIO finally does region I/O.
- world/regionfile.go: Anvil .mca container — 8192-byte header
(offset + timestamp tables), 4096-byte sectors, zlib chunk records.
- world/compress.go: zlib deflate/inflate for chunk payloads.
- world/store.go: chunk <-> Level-nested NBT (per-section
block_states/biomes palettes, WORLD_SURFACE heightmap, DataVersion
4790, yPos -4) via the existing nbt package; Store opens one
RegionFile per region with proper floor-division coords.
- world/state_names.go: id->name bridge from the embedded blocks.json
report so network int-IDs round-trip through the disk named palette.
- world/encode.go: GetBiome read accessor for serialization.
- world/cache.go: read-through (disk then generation), dirty tracking,
StartAutosave (returns a done channel so the saver exits before
Close), SaveAll, NewCacheWithStore.
- server.go + main.go: Config.WorldDir (default "world"), -world flag,
autosave loop every 30s, SaveAll + store Close on signal.
- Tests: region round-trip/absent/overwrite, chunk NBT round-trip,
end-to-end save-reload, negative chunk coords, autosave persistence.
Replaces the biome-blind fillVanillaColumn heuristics with a full
interpreter for the overworld surface_rule tree (already embedded in
overworld.json): block/sequence/condition/bandlands rules plus all 11
condition tests (biome, steep, hole, water, temperature, y_above,
stone_depth, noise_threshold, not, vertical_gradient,
above_preliminary_surface).
- worldgen/blockids.go: name(+Properties)→network-ID table for surface
blocks (grass/sand/terracotta/mycelium/podzol/coarse_dirt/sandstone/
calcite/snow/ice/...), with snowy property variants.
- worldgen/surface.go: rule-tree parser + interpreter + SurfaceContext;
LoadOverworldSurfaceRule caches the seed-independent tree.
- loader.go: OverworldDensity.SurfaceRule() exposes the parsed tree.
- biome_lookup.go: BiomeNameAt returns the biome name for biome tests.
- vanilla.go: samples the 2D climate + biome before column fill, threads
the rule tree and biome name into fillVanillaColumn, and applies it
top-down with stone as the default for non-matching (deeper) blocks.
The above_preliminary_surface gate uses an inclusive bound so the top
solid block reaches the biome dispatch.
- Performance: one per-column RNG and a reused SurfaceContext keep the
overhead to ~+13ms/chunk (71ms vs 58ms baseline), within the gate.
- Chunk stores per-section biome arrays (64 cells/section); flat generators
keep the uniform single-valued fallback.
- New writeBiomePalette uses min 1 bpe and direct at registry width (65 biomes).
- Climate sampler splits 2D axes (sampled once per column) from 3D depth
(per cell), keeping per-cell cost to a single density-function compute.
- Full biome parameter table (surface + underground twins + lush/dripstone/
deep_dark caves) with depth as a true range, not a binary layer.
- fillBiomes3D fills the 1536 cells/chunk in parallel; <0.3ms overhead vs
baseline chunk gen (benchmark-verified).
- Tests: cave-biome resolution, per-cell variation, flat-world regression,
registry-range validity, plus chunk-gen and per-cell benchmarks.