The clean-room structure oracle saved, for each start of a mod world, the
blocks of its box and every position around it that differs from the no-mod
world of the same seed. tools/test_structure_blocks_parity.py generates the
same chunks in full with Horizon twice (26.3 alone, and with the mods carried
by horizon-port-pack as players' packs are) and compares: a position counts
only where Horizon's no-mod world equals the oracle's (1.21.1 and 26.3 differ
elsewhere), and a mismatch is reported by its no-mod, expected and Horizon
blocks, so a missing processor rule reads as one line.
Better Dungeons (3 seeds, 96 complete starts): every structure is listed as
known, with the reason: the placeholder processors, the biome modifier and the
mod's own structure types are not implemented yet.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Include End crystals in attack-only object hit-testing using their network entity IDs. Add a real-mouse LAN regression for survival and creative, reach, block occlusion, passing item use, and explosion damage.
Co-Authored-By: OpenCode GPT-6.1 <noreply@openai.com>
Sounds can't be observed playing without an audio device, so the control
status counts each stopped selection, as it counts the sounds heard.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Clean-room (spec-yungsapi.md §2, §3, §5; no mod source read; the legacy
files were deleted unread). horizon-port-pack's new `yung` module carries
`yungsapi:yung_jigsaw` structures and `yungsapi:yung_single_element` pool
elements as the mods write them, so players' packs reach the YUNG draws of
the jigsaw assembler. Fields whose behaviour the specification leaves open
(adapt_noise, max_y/min_y, enhanced terrain, element conditions, modifiers,
priorities, depths, ignore_bounds) are counted as lost by name. YUNG's
other structure, placement and processor types go to the general code
(unsupported or dropped) until the specification covers them.
Deleted: legacy_structure_mods/yung.rs, horizon-world's structure/yung.rs,
the `horizon:yungsapi` keys and `horizon:disables`, which nothing writes
now. Two test initializers of the removed field (enhanced_terrain.rs,
piece_limited.rs) were removed by line from the compiler's error positions.
The layout harness now carries the mods through `horizon-port-pack carry`:
82 of 84 Better Dungeons starts match the oracle piece for piece, as before.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Each step waited a fixed 2.5 s. When the machine is loaded the vanilla server stalls for longer than that (CI on
#1571 and #1585: after Bob's trip to the Nether, vanilla's `tp Bob 4.5 -60 0.5` from the console ran a step late),
so its packets were filed under the next step and the transcripts differed although both servers sent the same.
A step now ends once the server has done its work:
- the console's own `time query gametime` comes back, so the step's console commands have run (the console runs
its queue in order);
- LocatorBarClient's new `sync NAME` runs `time query gametime` as that player and waits for the reply (not
recorded), so that player's commands have run and every packet sent before the reply is recorded;
- the server's game time has advanced STEP_TICKS (40) more ticks, then each player sends its position reminder
and syncs once more.
game_time() moves out of settle() in test_dedicated_server_parity.py so both use it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
/random reset * in the ticking group counted 12 sequences in vanilla against Horizon's 11 on one CI run (#1585).
Locally 1 oracle run in 24 did the same, and its extra sequence was minecraft:entities/bat. Before the setup's
gamerules (spawn_mobs and mob_drops off), the oracle ticks until the entities around the player have loaded, a
number of ticks that depends on the machine; mobs spawn meanwhile, and a bat that died then rolled its loot table.
Once mob_drops is off no mob death rolls one (LivingEntity.shouldDropLoot), so the setup now ends with an
unrecorded /random reset *: every run starts the script with no sequence, and the later count holds only what the
corpus itself rolled.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Read Git's pre-push ref updates and inspect the full reachable history of each non-deleted local object ID. Ignore unrelated refs while rejecting private artifacts in deleted files, merge-only paths, and stored history masked by local replacements.
Add regression coverage for branches, tags, raw revisions, multiple updates, deletion-only pushes, and artifact detection.
Co-Authored-By: OpenCode gpt-6.1-sol <noreply@openai.com>
Clean-room, from spec-yungsapi.md §2.1 and §3.1 (no mod source read).
A `yungsapi:yung_jigsaw` structure lays out with the jigsaw assembler and
YUNG's draws: the start pool's file entries shuffled, then the rotation,
then a weighted pick in the shuffled order; each jigsaw's target pool is
drawn by weight from its shuffled entries without replacement, an element
whose `name` already has `max_count` pieces skipped at no other draw.
`yungsapi:yung_single_element` places what a single element places; its
pool entry carries the name and limit.
tools/test_structure_layout_parity.py --profile betterdungeons reads the
mod's own data from its jar into an overlay of the 26.3 resources and
compares the mod world's pieces: 82 of 84 Better Dungeons starts match
piece for piece (60 small, 11 skeleton, 11 zombie dungeons, up to 790
pieces); the other 2 sit in 26.3's sulfur_caves, which 1.21.1 lacks.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Reuse stop_riding before applying a player teleport destination so the riding tick cannot return the player to the vehicle. Add vanilla command parity and both-mode LAN regressions for mounted teleports.
Co-Authored-By: OpenCode gpt-6.1-sol <noreply@openai.com>
Preserve the Hero effect captured by the guest's merchant session and cover discounted prices and payments for both single-player modes.
Fixes#1365
Co-Authored-By: OpenCode (gpt-6.1-sol) <noreply@openai.com>
Notify connected players of the display IDs forgotten by /recipe take.
Discard queued additions for recipes the player no longer knows.
Add LAN regression coverage for both single-player paths.
Co-Authored-By: OpenCode agentrouter/gpt-6.1-sol <noreply@opencode.ai>
Decode source/event selection flags, including 26.3 UI source 10, and route them to Audio.stop_sounds. Compare all 36 native Java codec selections and round-trip their bytes; reject invalid sources and truncated packets.
Co-Authored-By: Codex (gpt-6.1-sol) <noreply@openai.com>
Move the spectator-travel check before the existing villagers check so it merges cleanly with the newly added falling check on main.
Co-Authored-By: OpenCode agentrouter/gpt-6.1-sol <noreply@openai.com>
Assign mob-fired projectiles IDs when they are added and recognize shulker bullet spawns on remote clients. Extend the live LAN checks for both hosting modes.
Co-Authored-By: OpenCode (agentrouter/gpt-6.1-sol) <noreply@opencode.ai>
Apply metadata, lifetime and position/transform interpolation; render wrapped/aligned text, background, opacity, shadows, brightness and see-through flags. Upload dynamic font glyphs and expose actual emitted vertices for end-to-end checks. Verify 108 matrices with the native client renderer and exercise a real Java-server/Rust-client fixture.
Co-Authored-By: Codex (gpt-6.1-sol) <noreply@openai.com>
A dialog's text inputs are edit boxes (labelled above, CommonLayouts.
labeledElement; width, max length and initial value from the dialog) and
its boolean inputs are checkboxes with their label. A click focuses a box
or toggles a box, Tab and Shift+Tab move between the text inputs, the
keys, shortcuts and typed text go to the focused one. What they hold
fills the command templates and custom actions' payloads.
With this, AuthMe's register and login dialogs work: players type their
password and join instead of being kicked after 30 s.
horizon-ctl's `type` types into the focused input of an open dialog (the
first one when none is), in configuration too. server_e2e's dialog check
now types a number and ticks a box, and checks the command the template
makes of them and the payload of a custom action.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The clean-room structure oracle saved, for 31 starts of vanilla structures
(villages, outposts, trial chambers, shipwrecks, ruined portals, desert
pyramids over seeds 1234, 2 and 42), the no-mod world's pieces. A new
structure_pieces probe lists the starts a chunk owns, piece by piece, and
tools/test_structure_layout_parity.py compares them with those saves.
22 of the 31 match piece for piece (every village and outpost that 26.3
still places there, and the horizontal boxes of the code-built pieces).
The other 9 differ between 1.21.1 and 26.3 themselves: 26.3 vanilla's own
pieces there (VanillaChunkGenerationOracle scan) equal Horizon's for all 18
starts that differ from 1.21.1. No vanilla jigsaw fix is needed.
Templates now keep the id they were loaded under, so a piece names its
element.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Forward landing block-write events to notify_written so unsupported crops break, drop their items, and synchronize to clients. Add LAN regression coverage for the host and guest in both hosting paths.
Co-Authored-By: OpenCode GPT-6.1-sol <noreply@openai.com>
Add a native Java oracle for the actual Display/TextDisplay accessors and encoded metadata, with 513 combinations of flags, opacity, billboard mode and transforms. Preserve styled text and partial updates.
Co-Authored-By: Codex (gpt-6.1-sol) <noreply@openai.com>
A server's open_screen title is a text component, and container screens
draw it as AbstractContainerScreen does: in the label grey, under the
component's own colours, bold, italics and fonts, with the § codes a
literal holds. Horizon flattened it to a plain string, so a plugin's
gold and bold "Server Selector" menu showed in plain grey (#1645).
Chests, hoppers, dispensers, droppers, brewing stands and the other
workstations now draw the server's title. Before, the workstations
ignored it and showed their default name.
horizon-ctl's `screen` reports the title span by span (text, colour,
bold, italic). server_e2e's new `titles` check names a chest on the
vanilla server with a styled CustomName, opens it, and checks the title.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A server's show_dialog (configuration and play) opens vanilla's
DialogScreen instead of being dropped: the header with the title and the
warning button, the message bodies in a scrolling column, the action
buttons packed into columns (MultiButtonDialogScreen) or side by side in
the footer (notice, confirmation). A button runs its click event: a
custom action goes back as custom_click_action, a command runs (in play;
in configuration vanilla only warns), show_dialog opens another dialog,
copy_to_clipboard copies. after_action closes the screen, leaves it, or
opens the WaitingForResponseScreen. The warning button opens the
"custom screen" warning, whose Disconnect leaves the server. clear_dialog
closes it, and so do the level loading screen and a disconnect. The world
and HUD blur behind it as behind any in-game screen.
Inputs come next; here they are not drawn and keep their initial values.
tools/server_e2e.py is a new harness: a vanilla 26.3 dedicated server and
one Horizon client. Its dialog check shows a dialog with /dialog show,
clicks a command button (the server's trigger), a custom action (the
server's debug log shows its payload) and a wait_for_response one, and
clears a dialog with /dialog clear.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Restore the current game mode's spectator flag when remote_teleport creates a replacement player body. Add an end-to-end wall traversal regression for Nether travel and return, covering the integrated-server host, LAN guest and in-frame host.
Fixes#1299
Co-Authored-By: OpenCode agentrouter/gpt-6.1-sol <noreply@openai.com>
PrimedTnt keeps Entity's NO_OP InterpolationHandler and ticks on a client
too: a position packet puts it there at once, its own tick moves it on
(gravity, collisions, bounces, drag) and burns the fuse down, and a client
discards it when the fuse runs out. Horizon interpolated it towards each
update instead, so it trailed about two ticks behind the server.
lan_e2e's falling check now drops primed TNT too and checks that the
guest has it exactly where its fall from rest puts it for the fuse the
server sent.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A server sends an item's and a falling block's position only every 20 ticks.
As a client (multiplayer, a LAN guest, single player on its server thread)
Horizon moved them only when a position arrived, three steps towards it, so a
dropped item or falling sand hung in the air and then jumped down once a
second (#1568).
Vanilla runs ItemEntity.tick and FallingBlockEntity.tick on the client too
(gravity, collisions, drag), takes their motion from AddEntity
(recreateFromPacket) and SetEntityMotion (Entity.lerpMotion), and snaps them to
each position packet: neither overrides Entity's NO_OP InterpolationHandler.
The client now does the same, with the same ticks single player in-frame uses;
only the server removes them or places the block.
lan_e2e --check falling: the guest samples both every 2 ticks over 16 ticks.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The new home-leak test rejects scripts that set HORIZON_NO_AUDIO by hand; this one, added on main
since, did.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
GitHub's "Latest release" is the newest game release, so new players download the game's archive, which
does not start on its own (#1647). Making a launcher release the latest instead would break every
installed horizon-server, install.sh and install.ps1: they ask for releases/latest and expect the game's
archives, and a server that can't update can't fetch a fix either. So the game stays the latest and says
where to go:
- The notes open with "Want to play? Download the Horizon launcher, not the files below", linking
playhorizon.dev and the launcher releases. It is raw HTML on one line, which GitHub renders and the
launcher's notes view and one-line summary skip (pulldown-cmark HTML events), so launchers already
installed don't tell players to download themselves. The game footer that said the same at the bottom
goes. The site's Releases page leaves the block out.
- release.yml gives each archive a label ("Game files the launcher installs: Linux (...)", "Dedicated
server for Linux (...)"), which GitHub shows instead of the file name. Everything that downloads
matches the asset's name, which is unchanged.
Fixes#1647
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A mounted mob answered "Found no elements matching Passengers": the command
built the entity with the flat serializer, so `Passengers` was never in the
tag, even though the game had the relationship and saving a world kept it.
Persistence already writes the tree (`Game::mob_tree_nbt`, which also carries
the leash), and vanilla's command path uses the same one, so the command reads
it now.
Fixes#1519.
Co-Authored-By: Hermes Agent (Nous Research) <noreply@nousresearch.com>
decorated_region compiles its oracle into chunk-generation-parity; when it
passed while chunk_generation was still running, the trim deleted
chunk_generation's dumps mid-run (FileNotFoundError on
*-987654321987-full.txt in CI on #1569, #1571 and #1584).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>