Commit graph

110 commits

Author SHA1 Message Date
Master290
e33370a049 Add dynamic chunk lighting engine (vertical sky light + emissive blocks) 2026-06-27 21:21:31 +03:00
Master290
09a694daf5 Add gravity and player-seeking AI to zombies 2026-06-27 21:16:39 +03:00
Master290
7af0acd3a3 Add basic entity tracking, mob spawning and syncing 2026-06-27 21:13:20 +03:00
Master290
7e285e8068 Add structures (ores, flora, desert features, rocks) and wire up generation 2026-06-27 21:08:57 +03:00
Master290
65a7445a78 LRU chunk eviction (bounded cache, default 1024 chunks / ~200MB)
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).
2026-06-25 13:56:06 +03:00
Master290
d7c80a8858 Background predictive chunk streaming
Chunk generation and sending no longer block the read loop. The read
loop pushes a non-blocking recenter request and stays free to handle
movement, chat, and keep-alive acks immediately; a per-connection
streamer goroutine generates chunks in a worker pool and sends them
serially under the write mutex.

- network/streamer.go: per-connection streamer. spiralOrder emits
  chunks centre-outward; parallelSend fans Cache.Frame across a worker
  pool (Cache.Frame is already goroutine-safe), parallelGenerate warms
  a one-ring predictive border so movement finds ready chunks; the
  loaded-set is owned solely by the streamer.
- network/play.go: beginPlay launches the streamer and pushes an
  initial recenter instead of the old blocking streamAround;
  onPlayerMove now just calls requestRecenter (non-blocking).
- network/handler.go: ctx (connection lifetime) + streamer field; the
  streamer stops when the read loop ends (cancel on serve exit).
- network/configuration.go: client view_distance is saved (clamped
  2..16) and drives the streamer radius.
- Tests: spiral order (centre-first, ring structure) and the
  non-blocking recenter guarantee the read loop relies on.
2026-06-25 00:54:57 +03:00
Master290
d1cc29bb60 Chunk persistence to Anvil .mca region files
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.
2026-06-25 00:40:14 +03:00
Master290
4dcf938a85 Biome-aware surface rules from the vanilla rule tree
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.
2026-06-24 19:44:07 +03:00
Master290
d3142e7687 3D per-cell biomes (4x4x4) with surface/underground/cave layers
- 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.
2026-06-24 01:04:01 +03:00
Master290
a7bb9496ae Initial commit: RegionIO Minecraft server core (26.1.2/protocol 775)
Vanilla-faithful overworld generator (final_density + multi-noise biomes),
full connection lifecycle (status/login/configuration/play), chunk streaming,
creative block editing, and the protocol/nbt/registry infrastructure.
2026-06-24 00:32:51 +03:00