Files
horizon-airdef/CONTRIBUTING.md
T
Ludovic Marie 48c85fa19f Add tools/pr_ready.py, CONTRIBUTING.md and a pull request template
pr_ready is the one self-check to run before asking for review: from the
files a branch changes it runs rustfmt, clippy with warnings denied, the
tests of the touched crates (mapped through cargo metadata), the launcher's
own workspace when it is affected, the tokens.css check, the Cargo.lock
rule, the Python tests and the public-tree check, and the vanilla harnesses
the change can affect, picked by tools/parity.py exactly as CI's parity job
picks them. It runs locally or on a fleet machine through ~/fleet/rbuild;
on the Mac mini the harnesses use the parity runner's own workspace and
scripts. It prints one Markdown block for the pull request body and exits
non-zero on any failure.

tools/parity.py gains --changed-files for copies without Git history, and
tools/ci/vanilla-data.sh accepts the preparation key from outside.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 01:13:39 +02:00

4.4 KiB

Contributing to Horizon

Thanks for helping. Horizon is Minecraft: Java Edition 26.3 rewritten in Rust, and the one rule that shapes everything is that it plays exactly like vanilla. This page is the short version of how we work; questions are welcome on Discord.

Build it

You need Rust (stable), Python 3.10+, JDK 25, and on Linux the ALSA and udev headers (libasound2-dev libudev-dev). Horizon never downloads the game: it prepares its resources from your own copy of Minecraft 26.3, as described in Build from source.

cargo run --release -p horizon-prepare -- --prepare --server-jar ~/Downloads/server.jar
cargo run --release -p horizon-client

The launcher is its own Cargo workspace in launcher/ (cd launcher && cargo run; on NixOS, nix-shell first).

Vanilla first

Wherever vanilla has a feature, vanilla is the specification, down to the order of random calls. "Parity" here means Horizon gives the same results as the pinned 26.3 client and server for the same inputs, checked by a harness: a tools/test_*_parity.py script that runs a small Java oracle against the real game and a Rust probe against Horizon, and compares their outputs. There are about 290 of them.

  • Read the vanilla code before writing Horizon's. tools/rea_vanilla.py queries the pinned game bytecode: python3 tools/rea_vanilla.py method net.minecraft.world.level.block.DispenserBlock dispenseFrom. Say in your pull request which vanilla classes and methods you followed.
  • Gameplay changes come with a harness, new or extended, so the next change can't silently break them. The parity workflow shows how harnesses run; copy a nearby one.
  • Horizon's own features (the launcher, the new menus) follow the design system and are off by default wherever they would change the vanilla look.
  • Everything players run is Rust. Python and Java are fine for dev tools and harness drivers in tools/, never for player-facing code.

Never commit game files, decompiled source or prepared resources (.local/): tools/check_public_tree.py rejects them (git config core.hooksPath .githooks runs it before every commit).

Before asking for review

Run the self-check and paste the block it prints into your pull request:

python3 tools/pr_ready.py --base upstream/main   # or origin/main if you work on the main repository

It looks at what your branch changes and runs what matters: rustfmt, clippy with warnings denied, the tests of the crates you touched (and the launcher's), generated files, Cargo.lock, the Python tests, and the vanilla harnesses your change can affect. Without the vanilla data on your machine it lists those harnesses instead; CI runs them. --quick skips the harnesses. It exits non-zero when something fails.

Pull requests

  • Small. One change per pull request, under about 500 lines of code where you can; split bigger work into pieces that each make sense alone. Small pull requests get reviewed and merged the same day.
  • Fill in the template: what and why, the vanilla reference, the pr_ready block, screenshots for anything you can see.
  • Tick "Allow edits by maintainers". When something small is left (a lint, a rebase, a nit) we push the fixup ourselves instead of sending it back to you; only design questions come back.
  • Labels (we set them if you can't): feature when players get something new (it appears under "New" in the release notes), skip-release when players see no change (tooling, docs, tests), nothing for a fix. release-now is for crash fixes that shouldn't wait. pr_ready suggests one.

Every merge to main is released automatically (release flow), so main always stays playable.

Parity checks on forks

The verify check (formatting, lints, tests) runs on every pull request. The parity check runs the affected harnesses on a maintainer's machine, which holds the game files, so it never runs a fork's code on its own: a maintainer reads your change, then adds the run-parity label, which runs it once on your current commit. After new pushes, we add it again.

Talk to us

Discord for questions and ideas, issues for bugs. If you want to take something on, say so in its issue so nobody else starts the same work.