horizon
AGENTS.md8k starsChanged 10 days agoMITView on GitHub
Minecraft: Java Edition 26.3 rewritten in Rust (wgpu). Vanilla is the specification wherever it has the feature. Read CONTRIBUTING.md once; this page tells you where things are. Feature → files → harness for the most-changed areas: docs/architecture.md. - Never commit Mojang's files: game jars, assets, decompiled source, prepared resources (.local/). tools/check_public_tree.py rejects them; git config core.hooksPath .githooks runs it on commit. - Keep your runs away from real player data. Any game or launcher you start gets fresh mktemp -d…
Trending
More talk lately.about the whole repository
Who's talking about ludovic111/horizon
- A Hacker News story“Minecraft: Java Edition 26.3 rewritten from scratch in Rust”Hacker News · Oct 26, 2026 · 2 points
- A Hacker News story“Minecraft Java 26.3 was decompiled and rewritten in Rust”Hacker News · Oct 16, 2026 · 2 points
- KookaStudio/KookaPictura“fix(render): crash-safe Windows GPU backend chain (DX12 -> Vulkan -> CPU)”GitHub · Oct 31, 2026
- alexgaoth/awesome-reverse-engineered“Nightly refresh 2026-10-28”GitHub · Oct 28, 2026
- horizon-rust/horizon“Fix sweep attacks never triggering, and make them hit nearby entities like vanilla”GitHub · Oct 27, 2026
The biggest 5 of 39 mentions linking to the repository that our crawl found. Each line is their own headline.
See all 39
Talked about on GitHub and Hacker News (39 times).
On GitHub · 37
- Oct 31, 2026fix(render): crash-safe Windows GPU backend chain (DX12 -> Vulkan -> CPU) — KookaStudio/KookaPictura0 reactions · 1 comment
- Oct 28, 2026Nightly refresh 2026-10-28 — alexgaoth/awesome-reverse-engineered0 reactions
- Oct 27, 2026Fix sweep attacks never triggering, and make them hit nearby entities like vanilla — horizon-rust/horizon0 reactions
- Oct 27, 2026Nightly builds: an opt-in pre-release built each night from the proven union branches — horizon-rust/horizon0 reactions · 2 comments
- Oct 26, 2026Release notes: "Known issues" are cut off — horizon-rust/horizon0 reactions · 2 comments
32 more on GitHub
- Oct 26, 2026Scout 2026-10-26: 10 reports CrashSleuth said nothing about — Holo795/CrashSleuth0 reactions · 1 comment
- Oct 25, 2026[regression] Support other Languages — horizon-rust/horizon0 reactions · 4 comments
- Oct 25, 2026GUI Scale is clamped to 2 after restarting under Hyprland; preserved correctly with XWayland — horizon-rust/horizon0 reactions · 1 comment
- Oct 25, 2026Add e2e_check 0.1.0 — horizon-rust/horizon-mods0 reactions · 1 comment
- Oct 25, 2026add horizon — GoldenStack/dayssincelastrustmcserver0 reactions
- Oct 24, 2026feat(launcher-ui): paginate and virtualize instance Content Workspace — horizon-rust/horizon0 reactions
- Oct 24, 2026feat(launcher-ui): paginate Content browsing with a View selector — horizon-rust/horizon0 reactions
- Oct 24, 2026feat(launcher-ui): display real instance modpack and content icons — horizon-rust/horizon0 reactions
- Oct 24, 2026feat(launcher): resolve real instance and content artwork — horizon-rust/horizon0 reactions
- Oct 24, 2026feat(launcher-ui): make Content cards easier to scan — horizon-rust/horizon0 reactions
- Oct 24, 2026feat(launcher-ui): select launch instances from the original Home page — horizon-rust/horizon0 reactions
- Oct 24, 2026feat(launcher-ui): create instances from the sidebar plus button — horizon-rust/horizon0 reactions
- Oct 24, 2026feat(launcher-ui): add instance Worlds Files and Logs tabs — horizon-rust/horizon0 reactions
- Oct 24, 2026feat(launcher-ui): manage instance content from its workspace — horizon-rust/horizon0 reactions
- Oct 24, 2026feat(launcher-ui): add the instance Content Workspace — horizon-rust/horizon0 reactions
- Oct 24, 2026feat(launcher-ui): add Release Radar and prominent sponsorship — horizon-rust/horizon0 reactions
- Oct 24, 2026feat(launcher-ui): group Versions into Installed and Available — horizon-rust/horizon0 reactions
- Oct 24, 2026feat(launcher-ui): organize complete Settings into icon sections — horizon-rust/horizon0 reactions
- Oct 24, 2026feat(launcher-ui): simplify Content navigation and filter popovers — horizon-rust/horizon0 reactions
- Oct 24, 2026feat(launcher): add isolated instance profiles — horizon-rust/horizon0 reactions · 2 comments
- Oct 24, 2026fix(launcher): bound content checks across browser searches — horizon-rust/horizon0 reactions
- Oct 24, 2026[Project]: Horizon — Minecraft Java 26.3 rewritten in Rust · native client — kaixinbaba/awesome-rea0 reactions
- Oct 23, 2026Prepare: Netty's native transports are optional, as in the game (Prism Launcher on macOS) — horizon-rust/horizon0 reactions
- Oct 23, 2026Launcher: the command reference is the same on Windows (unblocks launcher@0.2.2) — horizon-rust/horizon0 reactions
- Oct 23, 2026Prepare fails on Prism Launcher installs — Prism never downloads the netty kqueue native jar — horizon-rust/horizon0 reactions · 3 comments
- Oct 23, 2026Releases: one channel, every release is the latest once its checks pass — horizon-rust/horizon0 reactions
- Oct 23, 2026someone made a new one — GoldenStack/dayssincelastrustmcserver0 reactions
- Oct 23, 2026Beds: respawning checks the bed and stands up beside it, else the world spawn — horizon-rust/horizon0 reactions
- Oct 19, 2026Launcher and horizon-server update: install only releases whose signed checksums match — horizon-rust/horizon0 reactions · 3 comments
- Oct 18, 2026Specialize constant surface material-rule branches — horizon-rust/horizon0 reactions · 1 comment
- Oct 18, 2026Specialize constant surface material-rule branches — rdbtCVS/horizon0 reactions
- Oct 17, 2026Launcher: Windows tests pass again (releases blocked since launcher-v0.4.0) — horizon-rust/horizon0 reactions
On Hacker News · 2
- Oct 26, 2026Minecraft: Java Edition 26.3 rewritten from scratch in Rust2 points
- Oct 16, 2026Minecraft Java 26.3 was decompiled and rewritten in Rust2 points · 3 comments
Where files are headingNew AGENTS.md files have more rules about keeping secrets out of the code, and fewer about code style.
Of the AGENTS.md files we read, the 31,774 first seen in the last six months, against the older ones: the kind of rule that gained most share, and the kind that lost most. About files like this in general, not this one, and an estimate, since a kind is a pattern in the words.
In this repositoryOne other file it gives its agents.
- vanilla-paritySkill
The file
We split this AGENTS.md into the rules it gives an agent
9 rules. About 0 are common, 6 are distinctive, and 3 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈6
Distinctive · estimate
This author's own choices. Worth a look.
3
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 35
No hardcoded user-facing strings: Keep UI translation-ready from the start.
- Distinctive: line 83
Test observable behavior, not words in docs, comments or source.
- Distinctive: line 84
Use independent expected values or a vanilla oracle.
- Distinctive: line 85
Test outcomes, not only calls to stubs.
- Distinctive: line 87
Avoid pinning implementation details.
- Distinctive: line 89
Never delete parity harnesses or tests that pin vanilla behaviour: they are the spec.
- Very specific: line 125
Run and drive the game (starts the horizon-client beside horizon-ctl.
- Very specific: line 132
Start parity work from the port ledger, not grep: python3 tools/port_ledger.py issue N (or where Class.method, what file:line), and check …
- Distinctive: line 205
Test the server thread when you touch player-facing gameplay:
≈ “Common” is an estimate: at least 1 in 5 of the 40,246 AGENTS.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Horizon: a map for agents
Minecraft: Java Edition 26.3 rewritten in Rust (wgpu). Vanilla is the specification wherever it has the feature. Read CONTRIBUTING.md once; this page tells you where things are. Feature → files → harness for the most-changed areas: docs/architecture.md.
Rules that bite
- Never commit Mojang's files: game jars, assets, decompiled source, prepared resources (
.local/).tools/check_public_tree.pyrejects them;git config core.hooksPath .githooksruns it on commit. - Keep your runs away from real player data. Any game or launcher you start gets fresh
mktemp -dfolders inHORIZON_HOME(logs, crash reports, telemetry consent, recordings; not saves),HORIZON_LAUNCHER_HOME,XDG_DATA_HOMEandXDG_CONFIG_HOME, plusHORIZON_LAUNCHER_NO_SELF_UPDATE=1andHORIZON_NO_AUDIO=1. Saves,options.txtand caches go in the game folder, by default the working directory: start the game from a scratch folder with--game-dirpointing at it, or they land in the repo root, hidden by.gitignore. For the launcher,HORIZON_LAUNCHER_TRASH,HORIZON_LAUNCHER_CLIPBOARDandHORIZON_LAUNCHER_DESKTOPpointing into the scratch home. Never write to~/.local/share/{applications,horizon,horizon-launcher}or~/.local/bin. - Mark what an agent posts. A PR body starts with a line naming the person whose agent opened it and
the tool:
> 🤖 Opened by <login>'s AI agent (<tool, model>), not by <login> personally., where<login>is the GitHub account the PR is opened from (gh api user --jq .login). Issues say "Filed by", reviews "Review by". Every comment starts with🤖 Agent:. Write only as the person you work for: the lines on this page that name Ludovic are for his own agents (accountludovic111), never for anyone else's. - Attribution. Commits end with a
Co-Authored-By:line for the agent that wrote them, and PR bodies with that agent's own "Generated with" line. Example, Ludovic's agents (Claude Code onludovic111): first line> 🤖 Opened by Ludovic's AI agent (Claude), not by Ludovic himself., commitsCo-Authored-By: Claude <model> <noreply@anthropic.com>, last line🤖 Generated with [Claude Code](https://claude.com/claude-code). - Everything players run is Rust. Python/Java only for dev tools and harness drivers in
tools/. - Horizon-only features follow docs/design-system.md and are off by default where they would change the vanilla look.
- Small PRs (< ~500 lines). Labels:
feature(players get something new),skip-release(they see no change), none for a fix. Agents never addrelease-now: the maintainer decides it. Merges ship in batches of 5, or after 6 hours (docs/release-flow.md). - Contributors first:
gh pr list --state open --search <area>before you start; never duplicate theirs. - No hardcoded user-facing strings. Keep UI translation-ready from the start. In the launcher (
launcher/), wrap visible text withtr("...")ortrf("... {arg} ...", &[("arg", &val)])fromcrate::i18ninstead of raw string literals orformat!. In the game, use translation keys (Text::tr,lang::get), never hardcoded English strings. - Claim before you start: comment
/claimon the issue (no issue yet: open one, then claim it). An assigned issue is taken, and so is one labelledin progress(claimed on Discord): pick another./unclaimwhen you stop; a claim with no open PR linking it is released after 5 days. The issues free to claim, without reading threads:gh issue list --search 'is:open no:assignee -label:"in progress" -label:tracker -label:proposal -label:"not claimable" -linked:pr' - Controllers reach what registers. Draw controls with a registering helper (
ui::button,settings_shell::foot_button);graphics_style::buttonandscreen_draw::buttononly paint, and registering one part of a screen ends its crosshair, so register all of it.
Crates
Game workspace (root Cargo.toml); launcher/ and crates/horizon-telemetry-server are separate workspaces.
| Crate | Owns |
horizon-client | Gameplay library (src/lib.rs: game.rs + game/, entry.rs) and thin executable (src/main.rs). Also the dedicated server (--dedicated). Re-exports horizon-client-lib for existing mod paths. |
horizon-client-lib | Reusable client systems, horizon-ctl, probes and their tests. Its manifest points to the existing sources under crates/horizon-client/; the library root is src/client_lib.rs. It never depends on gameplay. |
horizon-items | Blocks and items below gameplay: blocks.rs (block facts), items.rs, item_data.rs (components), enchant.rs, cooldowns.rs, bundle.rs, item_nbt.rs. Re-exported as horizon_client::items... |
horizon-command | Command parsing (Brigadier): the vanilla tree, argument types, selectors, suggestions, the tree's network form. Re-exported as horizon_client::command |
horizon-client-core | The client lib's bottom layer: text.rs, lang.rs, snbt.rs, nbt_path.rs, component.rs, scoreboard.rs, bossbar.rs, gamerules.rs, block_entity_nbt.rs, registry/particle/sound tables. Re-exported under the old paths (horizon_client::text...) |
horizon-client-input | Key bindings and key names, toggle keys, mouse options, controller settings and glyphs, the clipboard, window options (keybinds.rs, gamepad.rs, mouse.rs, window.rs...). Re-exported under the old paths |
horizon-client-render | The client's world data, rendering and screens (chunks, meshing, light, streaming, gfx, HUD, menus, settings), modules that horizon-client re-exports under the same paths. Nothing in it reaches gameplay |
horizon-world | Vanilla world data with no gameplay loop: NBT, regions, chunks, datafix/, worldgen/, level/ (server-side block behaviour, ticks, redstone), entity physics, items, effects, food, damage |
horizon-core | Simulation primitives: Java Randoms, jmath (HotSpot-exact Math), positions, noise, density, paletted storage, version.rs (the pinned version) |
horizon-protocol | Network protocol 777: codecs, framing, encryption, packets/{handshake,status,login,configuration,play}.rs, entity_data.rs |
horizon-assets | Resource decoding: block-state and item models, baking, atlases |
horizon-prepare | Builds .local/horizon-client/26.3 from the player's own Minecraft install (runs the Java exporters) |
horizon-server | horizon-server: server.toml, CLI, supervisor of the headless game (docs/hosting.md) |
horizon-server-files | server.properties, eula, ops/whitelist/bans, usercache |
horizon-anticheat | The dedicated server's anticheat, off by default: [anticheat] settings, violation levels, the checks' rules; the hub runs them (lan/anticheat.rs) (docs/anticheat.md) |
horizon-cosmetics | Cosmetic items Horizon clients draw on players (off by default): the item format, bones and animations (docs/cosmetics.md) |
horizon-friends, horizon-relay | Play with Friends: invite codes, encrypted tunnel, the relay (docs/play-with-friends.md) |
horizon-mods, cargo-horizon-mod | Content mods (.hmod: manifest, content fence, no code), the registry index and .hpack, and cargo horizon-mod (new, build, run, check, registry) (docs/mods.md). Code mods are native, built by the launcher (docs/native-mods.md) |
horizon-port-pack | Porting Java modpacks (docs/modpacks.md) |
horizon-optifine | OptiFine-format pack files below every feature that reads them: .properties, the name/range/block matchers, paths and optifine/ folders, and custom entity models (cem/: .jem/.jpm parsing and baking) |
horizon-polytone | Polytone-format pack files (assets/*/polytone/), read clean-room from the public wiki: targets, biome and dimension modifiers and their environment attribute layers (#11486) |
horizon-shader-api | Horizon's own WGSL shader packs (docs/api/shaders.md): horizon-shaders.toml, the .hshader package; shared by the game, the launcher and the registry |
horizon-shaders | Shader packs (the shaders/ folder format), rebuilt clean-room from a written spec of the format; no wgpu |
horizon-theme | Design tokens and fonts for the launcher, the game's own menus and the website |
horizon-telemetry, horizon-telemetry-server, horizon-bench | Opt-in data collection, its ingest server, the benchmark report format |
horizon-dualsense, horizon-threads, horizon-release-sign, horizon-bots, xtask | DualSense output, thread priorities, signed release checksums, load-test bots, repo tasks |
launcher/ | GPUI launcher: main.rs (UI), backend.rs (installs, updates), cli.rs, mcp.rs, *_page.rs |
Other top-level folders: tools/ (harnesses and dev scripts), tests/ (Python unit tests: python3 -m
unittest discover -s tests), mods/horizon/src/test/java/dev/horizonlab/parity/ (Java oracles),
docs/, .github/workflows/. The website (playhorizon.dev) is the private horizon-rust/horizon-site: its build
reads README.md, launcher/links.json, docs/api/, roadmap/roadmap.json and crates/horizon-theme/tokens.css from main.
Write tests with signal
- Test observable behavior, not words in docs, comments or source. Keep checks for machine-consumed contracts.
- Use independent expected values or a vanilla oracle; do not derive the answer from the code under test.
- Test outcomes, not only calls to stubs. Use mocks to isolate behavior, not as the behavior itself.
- Skip tests of trivial constants, derives and getters, or behavior already covered by another test.
- Avoid pinning implementation details; a harmless refactor should not break a behavior test.
- Make slow tests faster without removing cases or weakening their coverage.
- Never delete parity harnesses or tests that pin vanilla behaviour: they are the spec.
Build and test fast
python3 tools/pr_ready.py # the self-check: fmt, clippy -D warnings, touched crates' tests, harnesses; paste its block in the PR
python3 tools/pr_ready.py --quick # same without harnesses
cargo test -p horizon-client -p horizon-client-lib --lib --bins --tests # skips the examples (pr_ready does this); `--doc` separately
cargo test -p horizon-client-lib --lib mod_content::tests:: -- --ignored # the slow content-root tests, #[ignore]d; pr_ready runs them when mod content, assets, blocks or items change
cargo build --profile fast -p horizon-client # optimized, quick to link: use it to play or run lan_e2e
python3 tools/parity.py --changed origin/main # the harnesses your branch can affect (CI's parity job)
python3 tools/parity.py --changed-files paths.txt --list # which harnesses cover these files, without running them
python3 tools/parity.py mob_ai sculk # named harnesses
python3 tools/lan_e2e.py --check chest # two real games over LAN (server-thread host)
python3 tools/agent_control_e2e.py # horizon-ctl / MCP end to end- Harnesses and the game need the vanilla data in
.local/(minecraft/,horizon-client/26.3,datagen/,tools/): see docs/parity-workflow.md. Without it, pr_ready lists the harnesses for CI. - A harness =
tools/test_<name>_parity.py+ a Java oracle (mods/horizon/src/test/java/dev/horizonlab/parity/Vanilla*Oracle.java)- a Rust probe:
crates/<crate>/examples/<name>_{probe,fixture}.rs(mostly horizon-world and horizon-client), or the game binary with a fixture env var (game/dispense_fixture.rs,game/sculk_fixture.rs,game/command_harness.rs,game/net_harness.rs). Copy a nearby harness for a new one.
- a Rust probe:
- Developing a native mod? Run
horizon-launcher settings native-profile devonce.devbuilds the game crate unoptimized: a mod edit rebuilds about 6× faster than withperformance, while game logic runs up to about twice as slow. Use it while developing, not for playing;performancestays the default for players and releases (docs/native-mods.md). - Probes build into
.local/parity-target/; harnesses find binaries vialab.cargo_target(), nevertarget/. - Harness selection uses Cargo dep-info and reachable-code narrowing (
tools/parity_reach.py).horizon-client-libbuilds the control tool and client probes without gameplay; their dep-info excludesgame.rsandgame/, so gameplay edits do not rebuild or select those probes. Source paths remain incrates/horizon-client/. Measure actual harness selection on refreshed records withtools/parity.py --changed-files paths.txt --list; historical counts are not a guarantee. - Rust integration tests:
crates/horizon-client/tests/(lan_bot.rs,generation_saves.rs,streaming_meshes.rs). - Linux needs
libasound2-dev libudev-dev;--no-default-featuresdrops audio, controllers,discord,friendsandheartbeat(the server build). - Run and drive the game (starts the
horizon-clientbesidehorizon-ctl; other arguments go to the game):target/fast/horizon-ctl --socket $PWD/ctl.sock launch --world W --creative --offscreen --wait --resources $PWD/.local/horizon-client/26.3, thenhorizon-ctl --socket … state|keys|turn|command|screenshot|quit(docs/horizon-ctl-commands.md).
Vanilla reference
- Start parity work from the port ledger, not grep:
python3 tools/port_ledger.py issue N(orwhere Class.method,what file:line), andcheck --base origin/mainbefore the PR. How: .claude/skills/vanilla-parity/SKILL.md, docs/port-ledger.md. - Decompiled sources:
.local/minecraft/26.3/sources/{client,server}/(python3 tools/lab.py decompile). - Bytecode queries (callers through lambdas, every overload):
python3 tools/rea_vanilla.py method net.minecraft.world.level.block.DispenserBlock dispenseFrom(docs/decompilation-status.md). - A harness runs the oracle against the real 26.3 jars and the Rust probe on the same inputs, then compares
their JSON. Oracle runs are cached by
tools/parity_shim.py;--freshreruns them. - Mirror vanilla's
Mathcalls withhorizon_core::jmath, and vanilla's RNG withhorizon_core::random: random draws must happen in vanilla's order.
horizon-client: where things live
L: = lib (crates/horizon-client/src/, or crates/horizon-client-render/src/ for the modules that crate holds, under
the same horizon_client::<module> paths), G: = gameplay (crates/horizon-client/src/game/), also in the lib in normal builds.
Gameplay keeps its horizon_client::<module> imports through a self-crate alias. The executable
contains only the allocator, mod API marker and a call to entry::main. For unit tests, the lib
excludes entry and game, and the executable test target owns game so its process-wide test
state stays separate from the library tests. This compiles gameplay twice for executable tests.
| Subsystem | Files |
| Game loop, tick, frame | game.rs: fn run, fn tick, fn tick_world, fn render; G: window_handler.rs (impl ApplicationHandler for Game: window_event, about_to_wait); L: clock.rs, spans.rs; horizon-client-input/src/window.rs |
| Rendering | L: gfx.rs (Renderer::new, Renderer::render), gfx/ (cull, occlusion, translucency, upload, timing, lod, weather, stars, end_sky), *.wgsl, particles.rs, block_entity_render.rs, item_render.rs, fog.rs, clouds.rs, camera.rs, first_person.rs; G: render_tick.rs, item_draw.rs, screen_backgrounds.rs (panorama, menu blur, border wall) |
| Chunks, streaming, light | L: streaming.rs (worker pool: generate, light, mesh), world.rs, chunk.rs, chunk_map.rs, light.rs, mesher.rs + mesher/, vanillagen.rs (binds horizon-world's generator), lod.rs + lod/, server_terrain.rs (a server's kept chunks), bluemap.rs + bluemap_detect.rs (far terrain from its web map), ticket_levels.rs; G: world_loading.rs, world_entry.rs, postprocess.rs; game.rs fn update_world |
| World generation | crates/horizon-world/src/worldgen/ (generator*.rs, feature_graph.rs, structure/, carver/) |
| Block behaviour | crates/horizon-world/src/level/ (mod.rs, tick.rs, hooks.rs, redstone.rs, place.rs, interact.rs); game.rs fn tick_blocks, fn process_level_events |
| Mobs | L: mobs.rs (types), mobs/ (ai.rs, goals.rs, brain.rs, *_brain.rs, nav.rs, path.rs, species.rs, spawning.rs, render.rs, anim.rs); G: creatures.rs (ticking, spawning, mob events), one file per mob family (dragon.rs, wither.rs, villagers.rs, piglins.rs, golems.rs...), natural_spawning.rs |
| Other entities | L: entities.rs, projectiles.rs, arrows.rs; G: boats.rs, minecarts.rs, mounts.rs, armor_stands.rs, paintings.rs, frames.rs, fireworks.rs, tnt.rs, explosion.rs |
| Player actions | game.rs (fn use_hand, fn tick_mining, fn break_block); G: item_actions.rs (fn use_item), melee.rs (fn attack), hand.rs, combat.rs, consume.rs, using_item.rs (an item in use, tick by tick), potions.rs, shield.rs, crossbow.rs, trident.rs, fishing.rs; L: motion.rs + motion/ (movement), collisions.rs; crate horizon-items: items.rs, item_data.rs, enchant.rs, blocks.rs |
| Inventory and containers | L: menu.rs (AbstractContainerMenu.clicked), container_screen.rs, containers.rs, creative.rs, crafting.rs, recipe_book*.rs, stations.rs, merchant.rs; game.rs fn menu_ops, fn click_inventory; G: stations.rs, trading.rs, recipe_book.rs, machines.rs, inventory_input.rs (keys and clicks over a container), inventory_slots.rs (slot layout and drawing) |
| Commands | parse: crate horizon-command (args.rs, selector.rs, tree_*.rs, vanilla.rs); run: G: commands.rs (dispatch) + commands/*.rs (admin, execute, items, players, world_cmds...); L: scoreboard_cmd.rs, data_cmd.rs; horizon-client-core: nbt_path.rs, scoreboard.rs; G: functions.rs, command_blocks.rs |
| UI screens | Screen enum in game.rs; L: title.rs + title/, options_ui.rs, multiplayer.rs, pack_screen.rs, graphics_ui.rs, screen_draw.rs, ui.rs (widgets), hud.rs, hud_layout.rs, hud_overlays.rs, chat.rs, tab_list.rs; G: startup_menu.rs, loading_screen.rs (the loading screen, the pre-game App), screens.rs (pause, death), options.rs, lan_screen.rs, chat.rs, sign_edit.rs, books.rs, creative_screen.rs |
| Multiplayer client | L: net.rs (network thread); G: remote.rs (fn handle_packet, fn tick_remote), remote_*.rs (mob data, objects, projectiles, vehicles, stations) |
| LAN host / server side | L: lan/ (conn.rs handshake + login threads, hub.rs + hub/ play state, chunks.rs, entity.rs, tracking.rs, guest.rs, playerdata.rs); G: lan.rs (LanHost), lan_actions.rs (fn as_guest, fn tick_guests), lan_*.rs per feature, lan_entities.rs (tracked entities) |
| Integrated server | G: integrated.rs (the server thread), levels.rs (one level per dimension, fn tick_server), server_travel.rs |
| Dedicated server | G: dedicated.rs, dedicated/status.rs; crates horizon-server-files, horizon-server, horizon-anticheat (L: lan/anticheat.rs) |
| Save and load | L: save.rs (level.dat, regions, playerdata), entity_nbt.rs, options_file.rs; horizon-client-core/src/block_entity_nbt.rs; G: saving.rs, persist.rs (entities), world_session.rs (opening and closing a world); crates/horizon-world/src/{region.rs,nbt.rs,datafix/} |
| Input | game.rs fn window_event; G: play_keys.rs (fn key_pressed), play_input.rs (fn play_mouse, toggled keys, the hotbar wheel); crate horizon-client-input (keybinds.rs, keymapping.rs, key_names.rs, mouse.rs, input.rs, interaction_input.rs, gamepad.rs, clipboard.rs); L: osk.rs; G: pad.rs, pad_menu.rs, pad_craft.rs, pointer_capture.rs (mouse look, pointer grab) |
| Audio | L: audio.rs (mixer), sound_engine.rs, sound_events.rs, music.rs, ambience.rs; G: music.rs, subtitle_hud.rs |
| Resource packs | L: packs.rs + packs/, pack_screen.rs, atlas_sources.rs, sprites.rs, mipmap.rs, model_library.rs, font.rs, mobs/cem.rs + mobs/cem_anim.rs (OptiFine/EMF entity models and their animations); horizon-client-core/src/lang.rs; crates horizon-assets, horizon-optifine; G: packs.rs |
| Agent control | L: control.rs (socket), bin/horizon-ctl/; G: control.rs, agent.rs, events.rs, ui_control.rs (docs/agent-control.md) |
| Mods | crate horizon-mods; G: mods.rs; L: mod_content.rs, mod_list.rs |
| Horizon extras, settings | L: extras.rs, graphics.rs, settings.rs, minimap.rs; G: extras.rs, tweaks.rs, options.rs |
How Game is organised
struct Game(game.rs) holds everything. Its methods are spread over many files: game.rs keeps the core (tick, render, input, inventory, world open/close) and eachgame/<feature>.rsadds animpl Game<'_>block for one feature, with its own state types. Fields stay private to the gameplay module and its descendants. Gameplay tests run in the gameplay library, separate from reusable-library tests.- Find a feature's code:
grep -rn "fn tick_<thing>\|fn <verb>_<thing>" crates/horizon-client/src/game*; the file is usuallygame/<thing>s.rs. Who calls it: grep the name in game.rs'sfn tick/fn tick_world. - Fields that say which mode runs:
remote(this window is a client of a server: multiplayer, LAN guest, or single player on its server thread),lan(LanHost: this world is open to the network),integrated(the window's own server thread),serving(thisGameis that server thread),options.dedicated.fn tickreturnstick_remote()whenremoteis set; a server ticks its levels (fn tick_world). - A server's players run through the shared gameplay code:
as_guestswaps the guest's state (position, inventory, mode, mining, item use) intoGamefor one call (game/lan_actions.rs), andlevels.rsswaps whole dimensions in the same way. Changes reach clients through the block log, level events and the entity tracker (lan/tracking.rs,game/lan_entities.rs). - Shared read-only data:
Resources(res: blocks, items, recipes, mob types, biomes) andPackResources(pack), both in game.rs, their methods ingame/resource_tables.rs.
Single player runs on a server thread
game/integrated.rs runs a second Game (serving) on a "Server thread" with one level per dimension;
the window joins it as a client through memory (remote), exactly as a LAN guest or a dedicated server's
player does (#1514). A window's Game never ticks a world itself: the old in-frame path is gone
(--in-frame and --no-server-thread only print a notice; HORIZON_SERVER_THREAD is ignored).
Open [server-thread] issues list the gaps left.
Single player, LAN guests and dedicated servers all run the server code, so a fix there serves all three. Test the server thread when you touch player-facing gameplay:
cargo run --profile fast -p horizon-client -- --resources .local/horizon-client/26.3 --world T # server thread
python3 tools/lan_e2e.py --check <name> # host on its server thread, guest is a server client
python3 tools/parity.py dedicated_server server_entities server_player_damageDocs worth knowing
docs/parity-workflow.md (runner, gate, shards, scopes) · docs/native-client.md (options, controls, horizon-ctl) · docs/server-levels.md (levels per dimension) · docs/rust-parity.md (what is ported) · docs/known-issues.md · docs/release-flow.md · docs/README.md (index).
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

