entity_nbt keeps the name_text re-export (main's body is the same as
horizon-client-core's) and takes main's new spawn_bonus. Main's edits to
blocks, bundle, enchant, item_data and items land in horizon-items.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
🤖 Agent: Gate check by Ludovic's AI agent (Claude). Checked against 26.3: `EnderDragonFight.tick` scans the state and places the exit portal only when `dragonEvent.getPlayers()` is not empty, so a force-loaded End with nobody in it gets no portal, as here; the new `forced_end` harness compares both servers. Gate: this wave's 50 PRs merged on main in one tree (union 9033a9c3b): fmt and clippy `-D warnings` clean, the horizon-client (1136 lib plus the integration tests), horizon-client-core (37), horizon-world (165) and horizon-protocol (100) tests pass, the fast build links, and the 140 harnesses `parity.py` picks for the tree's changed files pass on playhorizon (remote_fireworks, a known load flake there, passed on a rerun on a quiet Mac mini). `lan_e2e.py` passes 14 checks with the host on its server thread and in-frame (chest, xp, damage, kills, projectiles, mobs, drops, body, stopsound, digging, instant_digging, books, knockback, barter); `hurt` fails on main too when run after `damage` (check-order dependency, not this wave). Thanks @FusselTV!
With force-loaded levels ticking without players (#1525), Horizon placed
the exit portal as soon as the End's main island was loaded. Vanilla
only places it from scanState and the dragon's death, both with players
in the fight, so a pre-generated End has no portal until someone
arrives.
test_forced_end_parity force-loads the End's arena on vanilla's and
Horizon's dedicated servers with nobody online and compares what is
around 0, 0.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Second slice of the crate split, a pure move like the first: blocks (+ blocks/), items, item_data, enchant,
cooldowns, bundle and random_sequences move to horizon-items. They are the first layer mobs/ needs, after
horizon-client-core.
Items moved out of lib modules that sit in the big cycle, unchanged:
- firework shapes, explosions and dye colours (particles.rs) -> firework.rs;
- BannerLayer and its NBT form (banner.rs) -> banner_layer.rs;
- the ItemStack NBT codec (save.rs) -> item_nbt.rs;
- consumable_animation (first_person.rs) -> use_animation.rs;
- the content namespaces (mod_content.rs) -> content_namespaces.rs;
- save.rs's NBT value helpers -> horizon-client-core's nbt_value.rs, and name_text (entity_nbt.rs) -> core's
component.rs.
horizon-client re-exports every module and item under its old path. Test helpers other client tests use
(Items::for_tests, enchant::tests) are behind horizon-items' `test-support` feature, enabled by
horizon-client's dev-dependency. The items test that loads the client's assets moved to the client:
always_edible_and_consume_effects_loaded, to assets.rs. particles.rs' test module moved to the end of the file
(clippy's items_after_test_module had been quiet only thanks to the derives that moved out).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A pure move, the first slice of splitting the client lib into crates:
- horizon-command: the command/ module (Brigadier port, vanilla tree, argument types, selectors), as is.
- horizon-client-core: what command needs from the lib, with no other dependency inside it: text, lang, snbt,
nbt_path, component, scoreboard, bossbar, gamerules, block_entity_nbt, fastutil_order; plus items moved out of
lib modules that sit in the cycle, unchanged: ParticleType (particles.rs), the key display name (keybinds.rs),
SOUND_SOURCES (settings.rs), uuid_text/uuid_from_text (save.rs), Registries/RegistryIds and parse_identifier
(command/args.rs).
horizon-client re-exports every module and item under its old path (`horizon_client::text`,
`crate::command::Registries`, `particles::ParticleType`...), so no caller changes. Inside the moved files only
paths changed (`crate::snbt` -> `horizon_client_core::snbt` in command, `crate::command::args::parse_identifier`
-> `crate::identifier::parse_identifier`...), `sign_side` became pub, lang.rs includes the lang files from
horizon-client's assets, and gamerules' test that saves a Level moved to save.rs (it needs the client's save).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A moving boat now stops at other boats, minecarts, mobs and players
(AbstractBoat.canVehicleCollide), and on the server it pushes what it
touches and is pushed back (AbstractBoat.push, LivingEntity.pushEntities).
A boat no player steers picks up the mobs that touch it, two seats in a
boat and one in a chest boat, with the player always in front
(getPassengerAttachmentPoint, clampRotation). Mobs get out when the boat
breaks or stays under water, are saved under the boat's Passengers, and
are seated by the client, which is sent no passenger's position.
A boat can't be placed where it would overlap an entity (BoatItem.use's
noCollision), and the player sits at the raft's and chest boat's vanilla
seat. A server player breaking a boat with a mob in it hits the boat.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Preserve Java parity oracles and comparison benchmark instrumentation. Move their remaining dependency locks under tools/benchmark-deps and remove legacy product packaging, fixtures, and CI checks.
Co-Authored-By: OpenAI Codex gpt-6.1-sol <noreply@openai.com>
AGENTS.md (CLAUDE.md links to it): the crates and what each owns, how to
build and test fast, where each subsystem of horizon-client lives, how Game
is organised, the two single-player paths and how to test both, the vanilla
reference, and the rules that bite. docs/architecture.md: feature -> files ->
checks for the 40 areas changed most in the last 30 days.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>