Files
horizon/.claude/skills/vanilla-parity/SKILL.md
T
rdbtCVSandClaude Opus 5.5 23f8bd4fed Remove the deprecated in-frame single-player path
Single player only runs on its server thread now. --in-frame and
--no-server-thread print a notice, and HORIZON_SERVER_THREAD is ignored.
This deletes the code that only the in-frame path reached: the window's
world loader and local player tick, its portal travel, the loading screen
and ring-by-ring streaming, and the in-frame LAN host (the host player in
the hub, its models of the guests, the reserved uuid). The world-upgrade
progress screen with its Cancel button moves to the server-thread start.
Tools, the harnesses and the docs no longer use the in-frame path.

Closes #6473

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-02 09:30:14 +00:00

3.9 KiB


name: vanilla-parity description: Fix a Horizon bug or gap so it behaves 1:1 like vanilla 26.3, starting from the port ledger (tools/port_ledger.py) instead of grepping. Use for any issue, Discord report or PR that makes Horizon match vanilla: "X doesn't work like in Java", a missing sound, particle, animation, mob behaviour, block rule, screen or packet.

Vanilla parity with the port ledger

The port ledger pairs every vanilla method with the Rust fn that ports it (or says it is missing, or needs no port) and lists where a port isn't wired like vanilla. Ask it first; grep only for what it can't answer. Full reference: docs/port-ledger.md.

0. Have a fresh ledger

python3 tools/port_ledger.py build          # ~20 s; again after pulling main

It needs the vanilla jar (the launcher's versions/26.3/26.3.jar, or --jar) and/or the lab's decompiled sources (python3 tools/lab.py decompile, or --sources DIR). If build says it has no vanilla code, run the lab first; don't guess vanilla from memory.

1. From the report to the code

python3 tools/port_ledger.py issue 3236                      # a GitHub issue number
python3 tools/port_ledger.py issue "mooshroom stays red after lightning"   # or the report's text

It ranks the vanilla classes the report names and lists, per class, its Rust home files, where each method is ported, and the known gaps (missing rows from the verdict map, seam/client/drift gaps). Often the cause is already written there ("Type is not saved"). Then drill in:

python3 tools/port_ledger.py where MushroomCow.readAdditionalSaveData   # ports, callers, callees, gaps
python3 tools/port_ledger.py class MushroomCow                          # every method: where, or missing
python3 tools/port_ledger.py what crates/horizon-client/src/mobs/farm.rs:120   # which vanilla method a fn ports

A ledger answer is a lead, not a verdict: about 1 in 12 map rows is wrong. Read the vanilla method (path and line are in the output) and the Rust fn before changing anything.

2. Port it the vanilla way

  • Translate the vanilla method, don't reinvent it: same order of operations, same constants, the same random draws in the same order (horizon_core::random), Java Math through horizon_core::jmath.
  • Open the fn's doc with the vanilla method it ports: /// `MushroomCow.readAdditionalSaveData`: .... That one line is what makes the next agent find it.
  • Fix the path players run: single player is a client of the integrated server, so server logic lives in game/lan*.rs and src/lan/, and what only the client's copy shows (particles, local sounds, hand animation) must be reached from game/remote*.rs.
  • Look at the neighbours the ledger lists for the same class: a client or seam gap next to your fix is usually the same bug on the other path.

3. Before the PR

python3 tools/port_ledger.py check --base origin/main

It lists the ports your branch touches with their open gaps, citations to add, stale citations, and (against the base) the gaps the branch closes and opens. Close what belongs to your fix, cite what you ported, leave no new stale citation. If you ported a method the verdict map called missing, change its row in tools/port_map/*.tsv to port with the fn (file.rs::Owner::fn) and run python3 tools/port_ledger.py map-check tools/port_map/<file>.tsv.

Then the usual: the harness for the area (docs/architecture.md), cargo check/tests per AGENTS.md, and a small PR that says which vanilla method it now matches.

Finding work

python3 tools/port_ledger.py gaps --kind seam      # ported on two paths, wired on one: the best leads
python3 tools/port_ledger.py gaps --kind client    # client-only effects the server path never reaches
python3 tools/port_ledger.py gaps --kind drift     # a port missing a sound, particle, item or constant
rg -n "player:" tools/port_map/*.tsv               # missing behaviour a player would see