free_port (7 copies), offline_uuid (4), varint and parse_varint (3 and 2),
dbits (6), fbits (4) and settled (2) move into lab.py; every caller uses
lab's. The other server harnesses keep importing free_port from
test_dedicated_server_parity, which now takes lab's. Imports the moved
code left unused go too.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
vanilla_world_check.py (used by the light harness) defaulted to port 25671, so two parity runs on one machine failed with 'FAILED TO BIND TO PORT'. It now picks a free port unless --port is given. The save round trip, datafix and upgrade_world tools derived their port from the pid or a random number; they ask the OS for a free one like test_dedicated_server_parity does.
Fixes#461
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
tools/vanilla_login.py joins an offline 26.3 server (login and
configuration phases) so the server loads players/data/<uuid>.dat;
vanilla_world_check.py gains 'login NAME SECONDS' and 'sleep S' steps and
disables the whitelist. With it, vanilla loads a Horizon player with its
position, rotation, inventory, selected slot and abilities, and Horizon
reads the file vanilla writes back.
A new world's first spawn becomes its world spawn (no bogus respawn
point), the player UUID is kept across saves, the selected hotbar slot is
restored, and game_rules.dat only holds rules vanilla knows.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Port LightEngine.shapeOccludes / getFaceOcclusionShape (occlusion.nbt) so
slabs, stairs, snow layers, paths etc. block light directionally, and use
ChunkSkyLightSources.isEdgeOccluded for sky sources. Block light now rises
into the section above the highest occupied one.
Block edits on lit chunks are relit in place with vanilla's decrease and
increase passes instead of recomputing the 3x3 chunks (and remeshing every
section of them); edits that race a chunk light job are replayed onto it.
examples/light_parity compares Horizon light with the SkyLight/BlockLight
arrays of worlds saved by the vanilla 26.3 server (0 differences on
villages, outposts and a slab/stair/snow scene; 181 of 113M sky values
differ where vanilla's worldgen light is stale) and checks incremental
relighting against full relights. tools/vanilla_world_check.py runs the
vanilla server headless; tools/anvil_dump.py prints NBT and region chunks.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>