A Minecraft Java Edition server core written in Go
Find a file
Master290 c399070f59 Write biome palettes in the form the client actually reads
Vanilla's SECTION_BIOMES palette strategy switches on the bit count with
`tableswitch {0..3}`: 0 single-valued, 1-3 linear, and everything else falls
through to the global palette. There is no hashmap tier for biomes — that exists
only for block states, whose 0..8 switch we already implement correctly.

We were writing a linear palette all the way up to 7 bits. A section holding 9 or
more distinct biomes therefore went out as a 4-bit indirect container while the
client read it as global: no palette prefix consumed, long array re-read at 7
bits, and every field after it in the chunk payload misaligned. Sections that
straddle the surface and the cave biomes really do carry that many, so this is
reachable in ordinary terrain rather than a corner case.

Checked against the jar rather than recalled: javap -c on Strategy$2 shows the
{0..3} switch with Configuration$Global in the default arm.

The test decodes each container the way the client would and requires it to
consume exactly the bytes we produced, so a misframed container shows up as a
byte count instead of needing a client to notice. Restoring the old threshold
fails the 9-, 20- and 65-biome cases.
2026-07-27 01:28:04 +03:00
cmd Fix terrain streaming and surface spawning 2026-07-21 11:11:19 +03:00
internal Write biome palettes in the form the client actually reads 2026-07-27 01:28:04 +03:00
tools Implement multiplayer persistence and vanilla lighting 2026-07-21 09:21:44 +03:00
world/region Implement multiplayer persistence and vanilla lighting 2026-07-21 09:21:44 +03:00
.gitignore Implement multiplayer persistence and vanilla lighting 2026-07-21 09:21:44 +03:00
chat.md Add structures (ores, flora, desert features, rocks) and wire up generation 2026-06-27 21:08:57 +03:00
go.mod Initial commit: RegionIO Minecraft server core (26.1.2/protocol 775) 2026-06-24 00:32:51 +03:00
Makefile Implement ticketed chunk lifecycle 2026-07-21 10:04:56 +03:00
README.md Fix terrain streaming and surface spawning 2026-07-21 11:11:19 +03:00

RegionIO

A Minecraft Java Edition server core written in Go, targeting version 26.1.2 (protocol 775). RegionIO implements the connection lifecycle (status → login → configuration → play), multiplayer chunk streaming, shared block editing, persistent worlds, and an overworld generator built on the real noise_router final_density tree.

Status

  • Network: full handshake/status/login (offline mode)/configuration/play state machine with zlib compression, keep-alive, and chunk streaming.
  • Registries: 28 synchronized registries + tags, captured verbatim from the 26.1.2 vanilla server and sent during configuration.
  • World: revisioned, concurrency-safe chunk snapshots; memoized level_chunk_with_light frames; ticket-aware bounded LRU cache; shared frame admission limit; Anvil .mca persistence with autosave and seed metadata.
  • Generation: vanilla-derived overworld terrain from the embedded datapack (ImprovedNoise/PerlinNoise/BlendedNoise/NormalNoise + the density function interpreter), 3D multi-noise biomes, surface-rule interpretation, deterministic decoration, and basic template structures.
  • Gameplay: four-player session registry; player join/leave and movement synchronization; chunk-scoped visibility for players and mobs; shared creative block place/break; broadcast chat; and hotbar item→block mapping.
  • Lighting: stored vanilla nibble arrays for sky and block light; horizontal and cross-chunk propagation; incremental updates after edits; persisted SkyLight/BlockLight; load-time border reconciliation; and chunk-scoped light_update broadcasts.
  • Chunk lifecycle: per-client view and prefetch tickets, strict near-first ring streaming, stale-recenter cutoff, explicit client unload packets, and eviction only after the final owner releases a chunk.
  • Safety: duplicate chunk generation is coalesced; corrupt stored chunks are not silently regenerated or overwritten; a world cannot reopen with another seed.

Build & run

go build ./...
go run ./cmd/regionio -seed 12345 -port 25565 -viewdistance 2

The world seed defaults to 0; override it with the -seed flag or the REGIONIO_SEED environment variable. The server listens on 0.0.0.0:25565. Changing the seed for an existing world directory is rejected. The server caps the client-requested chunk radius at 2 by default because cold density-based generation is expensive; raise it with -viewdistance 3 after the surrounding world has been generated and cached.

Testing

go test ./...
go test -race ./internal/network ./internal/server ./internal/world \
  -run 'Test(Integration|BoundaryEdit|PlayerInfo|PlayerRegistry|Concurrent|Incremental|EncodeLight|Cache|Store|Eviction|Region|Ticket|Streamer|LoadSixteen)'
# or run both gates:
make verify

The integration suite exercises four clients across two visibility regions: join, movement, leaving, mob visibility, and local block/light updates. A two-client scenario separately covers shared block edits and chat. Concurrency tests cover simultaneous frame encoding, editing, autosave, cache misses, and session movement/broadcasts. A 16-client lifecycle test exercises overlapping ticket ownership, bounded global frame work, packet output, and cleanup after disconnect. Lighting tests compare the initial flat chunk and a 31x31x31 glowstone propagation volume against fixtures captured from the official vanilla 26.1.2 server. Optional terrain parity diagnostics compare surface heights against /tmp/vanilla_ground.json when that capture is present.

v0.4 scope

RegionIO v0.4 is a small creative multiplayer server core, not a complete vanilla gameplay implementation. Player and mob visibility is chunk-scoped, but there is no interest prioritization or delta-movement compression yet. Lighting matches vanilla's block-state dampening, emission, and face-occlusion properties and reconciles persisted borders when chunks re-enter the live cache. Streaming prioritizes Chebyshev rings and abandons unstarted stale work; an already admitted frame calculation completes atomically rather than being interrupted halfway. Unowned clean chunks remain as an LRU warm cache until capacity pressure evicts them. Structures, placed features, mob AI, authentication, inventory, and survival mechanics remain intentionally partial. The density router is vanilla-derived, while biome/surface/decoration layers still contain approximations and require stricter parity fixtures.

Project layout

cmd/regionio/      entry point (config, listener, graceful shutdown)
internal/
  protocol/        wire primitives: VarInt, framing, compression, packet IDs
  nbt/             NBT encoder/decoder (with modified UTF-8)
  registry/        embedded synchronized registries + tags
  world/           chunk model, level_chunk encoder, cache, generators, biomes
  worldgen/        noise core + density-function interpreter + climate finder
  network/         per-connection state machine (handler/conn/play/login/...)
  server/          shared core: config, status response, profiles

Notes

The vanilla server.jar and its unpacked libraries//versions/ are not included (obtain them from Mojang). The embedded data under internal/ (registries, biome parameters, the overworld datapack) is derived from vanilla reports and is all that is required to build and run.