On a server that doesn't offer horizon:lod (any vanilla, Paper or Spigot
server), every chunk it sends is kept as its far-terrain summary, on
disk per server, world and dimension (server-terrain/<server>/<hashed
seed>/<namespace>/<level>/, Anvil region files), and drawn beyond the
server's view distance on this visit and later ones: a server never
sends its seed, so the client draws what it was sent. A chunk the client
forgets (ForgetLevelChunk, or a moved or resized storage) is observed
one last time first. A server's offer (horizon:lod) still comes first,
and a friend's world keeps nothing (its code changes at every share),
nor a splitscreen guest's (the player's own world, its other guests
writing the same folder).
The far terrain is rebuilt when the level changes; a proxy's next server
comes through reconfiguration. Cells wider than 128 chunks aren't
searched for kept chunks, and a failed write is logged once.
tools/server_lod_e2e.py's server without an offer now expects these kept
chunks (source "server-terrain").
server_terrain lives in horizon-client-render beside lod and streaming.
The launcher leaves server-terrain/ out when it duplicates an instance:
it is a cache, rebuilt as the instance plays.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
old_world_e2e asked horizon-client-lib for the horizon-client binary, which
only horizon-client has; three e2e docstrings, the agent-control guide and
xtask's comment still built horizon-ctl from horizon-client.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Review fixes (kacpherek on #4947):
- a refused, lost, timed-out or unreadable tile comes back as no columns,
and Lod asks for it again 2 s later instead of keeping it empty;
- sampling threads queue their requests and the game thread sends them
each tick with its other packets, so they no longer take the
connection's writer; requests queued when the far terrain ends are
dropped with their slots;
- docs and the e2e: horizon-lod-distance is off unless set.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The last step: a Horizon client of a dedicated server or of a LAN world
(not of its own server thread, which hands its generator over directly)
draws far terrain when the server offers it. Its far terrain's samplers
each send one tile request and wait for the reply, which the network
thread hands straight to them (lod_net::Inbox), keeping to the server's
limits (requests waiting, tiles a second) so a well-behaved client is never
refused. LOD Distance stops at the server's distance. A new dimension, a
reconfiguration or a disconnect cancels the waiting samplers at once.
tools/server_lod_e2e.py checks it on a real dedicated server: with
horizon-lod-distance=16, a client with LOD Distance 32 gets the server's
far terrain, capped at 16 chunks, and draws far tiles; with 0, none.
Co-Authored-By: Claude Opus 5.5 <[email protected]>