🤖 Agent: merging: the launcher's portable Rust 1.99.1 (pinned SHA-256 components, own data dir); proven by a real isolated rust install + crate build on the Mac mini and the launcher tests.
horizon-launcher native-build FOLDER --trust-native-code compiles mixin bundles (a folder with a
horizon-mixin.toml, or an unpacked .hnmod from the registry) into a game of their own:
- the Horizon commit the mods pin (all must agree; else the installed version's), its source from
GitHub by commit (Nightlies keep theirs as nightly-source/ tags);
- horizon-mixins at the commit the mods were tested with, built once with the launcher's Rust;
- horizon-mixins apply, then the release's cargo build, with the portable toolchain;
- installed as native-<commit>-<key>, played by the Native mods instance.
Based on native-mixins-1's unmerged work; docs/native-mods.md describes it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Native mods compile the game on the player's computer (levzzz5154: many native mods per build). The
launcher now downloads the official rustc, cargo and rust-std components of Rust 1.99.1 (plus
rust-mingw on Windows, the windows-gnu host that needs no Visual Studio) from static.rust-lang.org,
each pinned by SHA-256, into <launcher data>/rust/, and runs them with its own CARGO_HOME. No rustup,
nothing installed on the system. `horizon-launcher rust status|install|remove`.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The nightly release names its commit, and now also attaches horizon-source.tar.gz (git archive of that
commit, made from git objects in pick and signed with the builds) and tags the commit
nightly-source/<date>-<short>. The dated release and the nightly/build-* branch are pruned after 7 days;
the tag is not, so native mods pinned to a Nightly's commit keep building.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
🤖 Agent: verify passed at 0f565f4e4. Move only: parse_entries/parse_costs/SpawnCost go from mobs/spawn_selection.rs to biome.rs (re-exported), cutting biome -> mobs (step A of the cycle plan). pr_ready --quick green (1315 tests). Ready to merge once parity is green.
The bullet fell through to the item billboard and showed the whole spark texture. Vanilla ShulkerBulletRenderer draws the tumbling bullet model plus a 1.5x translucent copy at full block light.
Mobs only drew the cramming random and never took damage, so a crowd was never thinned. Vanilla's LivingEntity.pushEntities hurts a mob by 6 on a quarter of the ticks while max_entity_cramming or more non-riding entities are pushable around it.
The merchant's random sequences (the salts that keep its offers stable) were
written with the result dropped, so a failed write rerolled every trade on
the next load with nothing in the log. Log it like the other save paths.
Co-Authored-By: Hermes Agent (Nous Research) <noreply@nousresearch.com>
name_tags cloned every named mob's custom name each frame and dropped the tag
afterwards when the mob was beyond 64 blocks. Test the distance first, so the
copy happens only for a mob the frame can show.
Co-Authored-By: Hermes Agent (Nous Research) <noreply@nousresearch.com>
The panel list is painted every frame the inventory is open. An unclipped
name was cloned per panel and the icon key was a fresh format! per panel; the
name is borrowed and the key is built in one buffer now.
Co-Authored-By: Hermes Agent (Nous Research) <noreply@nousresearch.com>
The row made the short sprite name (format! or to_owned) and then wrapped it
in format!("gui/sprites/{sprite}") for the atlas. Build the full key in the
match arm and hand it straight to sprite_scaled.
Co-Authored-By: Hermes Agent (Nous Research) <noreply@nousresearch.com>
tab_headers() builds a header per tab without the item lists, and the caller
then cloned the selected one again: three Strings copied every frame the
screen is open. Borrow it instead.
Co-Authored-By: Hermes Agent (Nous Research) <noreply@nousresearch.com>
draw_slot_item needs neither ownership nor &mut self: it reads the carried
stack only for a drag. Taking `&Option<ItemStack>` and &self drops the copy
every caller made, including the two the creative hotbar made per slot each
frame (and one clone per hovered slot becomes a clone only when hovered).
Co-Authored-By: Hermes Agent (Nous Research) <noreply@nousresearch.com>
paint() runs for every drawn HUD call each frame and made a fresh String per
sprite to look it up in the atlas: sprite.to_string() for a mob_effect and
format!("gui/sprites/{sprite}") otherwise. One buffer outside the loop keeps
the same keys without the allocation.
Co-Authored-By: Hermes Agent (Nous Research) <noreply@nousresearch.com>
os.symlink needs Developer Mode or an elevated token on Windows, so the test
errored with WinError 1314 instead of exercising own_reports. Skip it there
and keep it on hosts that can link.
Co-Authored-By: Hermes Agent (Nous Research) <noreply@nousresearch.com>
python() returned shutil.which("python3"), which on Git for Windows is the
Microsoft Store stub (prints "Python", exits 49): every tool it launched
failed before its first line. Probe python3, python and py and keep the first
that is Python 3, once per process.
Co-Authored-By: Hermes Agent (Nous Research) <noreply@nousresearch.com>
named_logs only matched a Posix absolute path (`see /...log`), so on Windows
horizon-prepare's "see C:\...\export.log" matched nothing and its javac
errors were never shown. The pattern now takes either form.
Co-Authored-By: Hermes Agent (Nous Research) <noreply@nousresearch.com>
narrow() and its graph key files by Posix path (`crates/a/src/used.rs`), so
a fixture built from str(relative_to) on Windows produced backslashes and all
seven tests errored in setUp. as_posix() in the fixture matches the tool.
Co-Authored-By: Hermes Agent (Nous Research) <noreply@nousresearch.com>
Name tags faced the player's own look, so in the front view (F5 twice) every name and hologram read mirrored. They now face the camera, turned round in that view, like Camera.rotation().
Every with_level built every chest and hopper cart's signal through item lookups. tick_scheduled calls it once per scheduled tick, so freshly generated forests (thousands of leaf ticks) next to mineshaft chest carts spent a large share of the server tick there. detector_rail_signal now counts the cart it reads.
The charge read the rider's own last move, which a rider never sends, so on horseback it had no speed and hit nothing. ServerPlayer.getKnownSpeed gives a rider its vehicle's movement.
Shadows used the entity fragment shader, which discards alpha under 0.1, so they vanished at block light 7 and below and faded out a few blocks away. rendertype_entity_shadow.fsh has no cutout.
Every spawning pass built a new 289-per-player candidate Vec and a new
dedup set. Keep both in a scratch struct on the game and clear them between
passes, so their capacity survives. The first pass and the thunder pass use
the same buffers.
Co-Authored-By: OpenCode <noreply@opencode.ai>
Streaming walked every loaded column and every proto chunk on each update to
drop the ones that had fallen out of range. The sweep now runs at once when
the view moves and every eighth tick otherwise; unloads can wait 400 ms
without changing what is visible or generated.
Co-Authored-By: OpenCode <noreply@opencode.ai>
The list of ticking block entities was cloned into a new Vec on every tick,
even when no slot had been freed and nothing had been added. Keep it behind an
Arc and clone the Arc instead; promotions and sweeps use Arc::make_mut, so the
list is copied only when it actually changes.
Also skip the block lookup in tick_spawner: the caller only reaches it for a
BlockEntity::Spawner, and changing the block removes or replaces that entity.
Co-Authored-By: OpenCode <noreply@opencode.ai>
A hopper on its 8-tick cooldown looked up its block and compared the state
name every tick, then returned without moving. Advance the cooldown first and
only resolve the block when it is due to move. The sweep that drops hoppers
whose block entity is gone can run once a second; a hopper that ticks still
checks its own block.
Co-Authored-By: OpenCode <noreply@opencode.ai>