Commit Graph

7 Commits

Author SHA1 Message Date
rdbtCVS 0d1736da8f Make startup and world-loading execution roles explicit
Separate client, integrated-server and dedicated-server roles from connection state. Use roles for startup, presentation work and server dimension loading while preserving in-frame client simulation.

Co-Authored-By: OpenAI Codex (GPT-6.1) <noreply@openai.com>
2026-10-24 23:53:00 +01:00
Ludovic Marie a4a101ca9c Single player runs on its server thread by default again; --in-frame is the opt-out
#1428 made the in-frame world the default while a server's players lagged
behind it (signs, books, totems, keep_inventory and the other [server-thread]
issues). With the fixes of this stack a scripted single player session (walk,
mine, place, inventory, combat, eating, boats, minecarts, chests, furnaces,
beds, chat, signs, books, totems, keep_inventory, fishing, maps, saving and
reopening) gives the same results on the server thread as in the frame.

`--in-frame`, `--no-server-thread` or HORIZON_SERVER_THREAD=0 runs the world
in the frame; `--server-thread` still works. LAN guests, dedicated servers and
the command harness are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 23:30:14 +02:00
Ludovic Marie 6049012b52 Single player runs in the frame by default again; the server thread is opt-in
Players on the Alpha channel report single player as broken since v0.2.1
(#1265 made the integrated server thread the default again). On v0.2.11's
server thread, placed signs open no editor (#1380), held books don't open
(#1366), a totem doesn't save its holder (#1292) and death keeps the
inventory with keep_inventory off (#1284); the in-frame world and Stable
v0.2.0 do all four right. About 45 more [server-thread] issues are open.

`--server-thread` or HORIZON_SERVER_THREAD=1 turns it on, as before #1114;
`--no-server-thread` and HORIZON_SERVER_THREAD=0 still work. LAN guests and
dedicated servers are untouched. Temporary until the server thread reaches
parity (FEATURES 4zg).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 10:54:42 +02:00
Ludovic Marie 2ced9a451d Server players respawn at their point in the Nether (anchors, spawnpoint)
A server's player (a LAN guest, and since the server thread the single
player too) always respawned in the Overworld. Its respawn anchor was
dropped when its action ended, and its save kept only an Overworld point.

- The guest keeps a respawn point outside the Overworld (respawn_elsewhere,
  saved as the player's `respawn`) and has it in place while it acts, so an
  anchor it uses is its own.
- guest_respawn respawns it in that point's level, waits there for the
  chunks, then resolves the point through its block
  (findRespawnAndUseSpawnBlock): beside the anchor, using a charge, or the
  world spawn and block.minecraft.spawn.not_valid when the block is gone.
- `spawnpoint` in another level than the Overworld sets a forced point there
  (SetSpawnCommand) instead of Overworld coordinates, and a forced point that
  is no anchor holds where a player fits (isPossibleToRespawnInThis), in the
  window's own game too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 15:32:24 +02:00
Ludovic Marie 86fdc72069 Server players go through End gateways
handle_server_portal ignored End gateways, so on a server (dedicated, or
single player's server thread) no player could use one: the in-frame game's
gateway code moved only its own player.

A gateway that is not cooling down now takes a server player at once
(EndGatewayBlock.entityInside, triggerCooldown, setAsInsidePortal), within
the End, keeping its motion and look (Relative.DELTA and ROTATION). An exact
exit is reached straight away; otherwise the player waits at the destination
while it loads, and the exit is found or built there (the in-frame
resolve_gateway, shared through gateway_job).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 15:32:24 +02:00
Ludovic Marie 9fe228cd1e Server commands run in their source's level (execute in, execute at)
On a server (dedicated, or single player's server thread) each dimension is
its own level, but a command ran in whichever level was in place. So a guest
in the Nether running `execute in minecraft:overworld run setblock ...` got
"That position is not loaded", and `execute at <a player in another level>`
used the wrong level's blocks.

with_source now puts the source's level in place for the command
(CommandSourceStack.getLevel), as as_target already does for a player in
another level, and puts the old one back after. `execute at` takes the
entity's level (withLevel(entity.level())), and a player's level is the
guest's own (target_level) even while another level is in place.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 15:32:24 +02:00
Ludovic Marie bd36508c29 lan_e2e levels: players in their own levels on the server thread; design note
A new `levels` check (--server-thread) runs the host and a guest in different
dimensions: execute in ... tp, mobs ticking in two levels at once with unique
ids, rejoin and save/reload with the guest in the Nether, death there, the
host through a Nether portal alone, the guest through an End portal and the
exit portal alone. All of it already works on the server thread.

docs/server-levels.md says how the server's levels map onto vanilla's, what
the dedicated server and the server thread share, the cost of an extra level
and what's left. docs/server.md no longer says players can't change dimension.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 15:32:24 +02:00