Compare commits

...
Author SHA1 Message Date
Horizon agent 79cfbfc950 Merge remote-tracking branch 'origin/main' into split/horizon-ctl-crate
# Conflicts:
#	tools/test_friends_integration_parity.py
2026-11-09 20:31:47 +01:00
Horizon agent a82091736e Merge remote-tracking branch 'origin/main' into split/horizon-ctl-crate
# Conflicts:
#	.github/workflows/ci.yml
#	.github/workflows/game-build.yml
#	crates/horizon-client-lib/Cargo.toml
#	tools/ci/build-musl.sh
2026-11-09 18:57:38 +01:00
Horizon agentandClaude Opus 5.5 40637018fa Cargo.lock: the horizon-ctl package
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 15:38:53 +01:00
Horizon agentandClaude Opus 5.5 c48cdddd66 horizon-ctl: its own platform crate (layer plan M6)
The horizon-ctl binary and its MCP server leave horizon-client-lib for
crates/horizon-ctl, a platform crate on the client lib's control socket.
horizon-client-lib no longer depends on horizon-mcp. Pure move: the
sources are unchanged; build commands now name -p horizon-ctl.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 15:13:46 +01:00
48 changed files with 78 additions and 51 deletions

No files matched your search

+1 -1
View File
@@ -221,7 +221,7 @@ jobs:
Write-Output "Using $($clang.Source)"
& $clang.Source --version
- name: Build the game for native Windows ARM64 (the official game, as game-build.yml ships it)
run: cargo build --release --locked --target aarch64-pc-windows-msvc -p horizon-official --bin horizon-official -p horizon-client-lib --bin horizon-ctl -p horizon-prepare --bin horizon-prepare -p horizon-server --bin horizon-server
run: cargo build --release --locked --target aarch64-pc-windows-msvc -p horizon-official --bin horizon-official -p horizon-ctl --bin horizon-ctl -p horizon-prepare --bin horizon-prepare -p horizon-server --bin horizon-server
- name: Check the game's PE machine
run: python tools/check_pe_arch.py arm64 target/aarch64-pc-windows-msvc/release/horizon-official.exe target/aarch64-pc-windows-msvc/release/horizon-ctl.exe target/aarch64-pc-windows-msvc/release/horizon-prepare.exe target/aarch64-pc-windows-msvc/release/horizon-server.exe
- name: Check game DLL imports
+1 -1
View File
@@ -170,7 +170,7 @@ jobs:
run: sudo apt-get update && sudo apt-get install -y --no-install-recommends libasound2-dev libudev-dev
- name: Build the official game, horizon-ctl, horizon-prepare and horizon-server
if: ${{ !matrix.musl }}
run: cargo build --release --locked ${{ matrix.target && format('--target {0}', matrix.target) || '' }} -p horizon-official --bin horizon-official -p horizon-client-lib --bin horizon-ctl -p horizon-prepare --bin horizon-prepare -p horizon-server --bin horizon-server
run: cargo build --release --locked ${{ matrix.target && format('--target {0}', matrix.target) || '' }} -p horizon-official --bin horizon-official -p horizon-ctl --bin horizon-ctl -p horizon-prepare --bin horizon-prepare -p horizon-server --bin horizon-server
- name: The official game is the game players get, under its name
# horizon-official: horizon-client's game with Horizon's own parts plugged in (docs/layers.md, "How a
# Horizon crate plugs in"). Everything below, the launcher and players know it as horizon-client.
+3 -2
View File
@@ -54,7 +54,8 @@ Game workspace (root `Cargo.toml`); `launcher/` and `crates/horizon-telemetry-se
| 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-client-lib` | Reusable client systems, the control socket, 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-ctl` | `horizon-ctl`, the CLI over the control socket, and its MCP server (platform): `commands.rs` is the command table ([docs/agent-control.md](docs/agent-control.md)) |
| `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`...) |
@@ -184,7 +185,7 @@ state stays separate from the library tests. This compiles gameplay twice for ex
| 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](docs/agent-control.md)) |
| Agent control | L: `control.rs` (socket), `crates/horizon-ctl/`; G: `control.rs`, `agent.rs`, `events.rs`, `ui_control.rs` ([docs/agent-control.md](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` |
Generated
+11 -1
View File
@@ -1532,7 +1532,6 @@ dependencies = [
"horizon-hdr",
"horizon-hooks",
"horizon-items",
"horizon-mcp",
"horizon-mods",
"horizon-narrator",
"horizon-optifine",
@@ -1650,6 +1649,17 @@ dependencies = [
"ureq",
]
[[package]]
name = "horizon-ctl"
version = "0.1.0"
dependencies = [
"horizon-client-lib",
"horizon-core",
"horizon-mcp",
"horizon-threads",
"serde_json",
]
[[package]]
name = "horizon-dualsense"
version = "0.1.0"
+2
View File
@@ -13,6 +13,8 @@ members = [
"crates/horizon-client-core",
"crates/horizon-client-input",
"crates/horizon-client-render",
# horizon-ctl and its MCP server (platform).
"crates/horizon-ctl",
"crates/horizon-cosmetics",
"crates/horizon-command",
"crates/horizon-items",
-6
View File
@@ -22,8 +22,6 @@ horizon-items = { path = "../horizon-items" }
horizon-core = { path = "../horizon-core" }
# Extension points for the crates above the engine (docs/layers.md, "How a Horizon crate plugs in").
horizon-hooks = { path = "../horizon-hooks" }
# `horizon-ctl mcp`: the Model Context Protocol, shared with the launcher and the server.
horizon-mcp = { path = "../horizon-mcp" }
# The server thread ahead of the workers (MinecraftServer.spin's Thread.setPriority).
horizon-optifine = { path = "../horizon-optifine" }
horizon-threads = { path = "../horizon-threads" }
@@ -136,10 +134,6 @@ horizon-items = { path = "../horizon-items", features = ["test-support"] }
# Every WGSL shader translated as wgpu's DirectX 12 backend does (gfx.rs tests).
naga = { version = "30.0.1", features = ["wgsl-in", "hlsl-out", "msl-out", "spv-out"] }
[[bin]]
name = "horizon-ctl"
path = "../horizon-client/src/bin/horizon-ctl/main.rs"
[[example]]
name = "chunk_load_bench"
path = "../horizon-client/examples/chunk_load_bench.rs"
+20
View File
@@ -0,0 +1,20 @@
[package]
name = "horizon-ctl"
version = "0.1.0"
edition.workspace = true
license.workspace = true
rust-version.workspace = true
description = "horizon-ctl: play and script a running game through its control socket, and its MCP server (platform, docs/layers.md)"
[dependencies]
# The control socket's client side (`control::connect`) and the game's folders (`logging`). No default
# features: the game's own build chooses them, and Cargo unifies them when both are built together.
horizon-client-lib = { path = "../horizon-client-lib", default-features = false }
horizon-core = { path = "../horizon-core" }
# `horizon-ctl mcp`: the Model Context Protocol, shared with the launcher and the server.
horizon-mcp = { path = "../horizon-mcp" }
horizon-threads = { path = "../horizon-threads" }
serde_json = "1.0.151"
[lints]
workspace = true
@@ -714,7 +714,7 @@ pub fn markdown() -> String {
let cell = |s: &str| s.replace('|', "\\|");
let mut out = String::from(
"<!-- Generated by `horizon-ctl help --markdown` from the command table in \
crates/horizon-client/src/bin/horizon-ctl/commands.rs: edit the table, then regenerate. -->\n\
crates/horizon-ctl/src/commands.rs: edit the table, then regenerate. -->\n\
# horizon-ctl commands\n\n\
Every command `horizon-ctl` takes, its MCP tool in `horizon-ctl mcp` (the launcher's \
`horizon-launcher mcp` offers the same tools as `game_<tool>`, all but `launch`) and its \
+1 -1
View File
@@ -20,7 +20,7 @@ The command lists are generated, so they can't drift:
| Surface | Where | Transport |
| --- | --- | --- |
| Game control socket | `horizon-client --control` / `--control-socket PATH`, or Agent Control on in Horizon Settings > AI Agent (`crates/horizon-client/src/control.rs`; commands in `src/game/control.rs`, `agent.rs`, `ui_control.rs`, `saves_control.rs` and friends) | text line in, one JSON line out; Unix socket, or localhost TCP and a token where there is none |
| `horizon-ctl` | `crates/horizon-client/src/bin/horizon-ctl/` | CLI over the socket; one table of commands (`commands.rs`) gives the help, the argument checks, the MCP tools and the reference |
| `horizon-ctl` | `crates/horizon-ctl/src/` | CLI over the socket; one table of commands (`commands.rs`) gives the help, the argument checks, the MCP tools and the reference |
| `horizon-ctl mcp` | same | MCP over stdio, one tool per command of the table |
| Launcher CLI | `launcher/src/cli.rs` | `horizon-launcher <command> [--json]` |
| Launcher MCP | `launcher/src/mcp.rs`, `cli_tools.rs`, `game_tools.rs` | `horizon-launcher mcp` (stdio): every CLI command as a tool, the session tools, and the game's tools as `game_*` |
+1 -1
View File
@@ -41,7 +41,7 @@ A reference page is written by code from the source it describes, and a test fai
| Page | Generated from | Update it with |
| --- | --- | --- |
| [server-reference.md](server-reference.md) | `horizon-server`'s help, `config::TEMPLATE`, `api::ROUTES` | `HORIZON_WRITE_DOCS=1 cargo test -p horizon-server reference` |
| [horizon-ctl-commands.md](../horizon-ctl-commands.md) | the command table in `crates/horizon-client/src/bin/horizon-ctl/commands.rs` | `horizon-ctl help --markdown > docs/horizon-ctl-commands.md` |
| [horizon-ctl-commands.md](../horizon-ctl-commands.md) | the command table in `crates/horizon-ctl/src/commands.rs` | `horizon-ctl help --markdown > docs/horizon-ctl-commands.md` |
| [launcher-commands.md](../launcher-commands.md) | `launcher/src/cli.rs` | `HORIZON_WRITE_DOCS=1 cargo test --manifest-path launcher/Cargo.toml the_launcher_reference` |
| [launch-reference.md](launch-reference.md) | `crates/horizon-client/src/game/launch_api.rs` | `HORIZON_WRITE_DOCS=1 cargo test -p horizon-client --lib launch_api` |
+2 -2
View File
@@ -19,7 +19,7 @@ serves the same commands as MCP tools. The launcher's MCP server offers them too
## Guide
1. Build `horizon-ctl` (`cargo build --profile fast -p horizon-client-lib --bin horizon-ctl`), then
1. Build `horizon-ctl` (`cargo build --profile fast -p horizon-ctl`), then
`horizon-ctl --socket $PWD/ctl.sock launch --world W --creative --wait --resources <prepared files>`.
2. `horizon-ctl --socket … state`, `keys`, `turn`, `command`, `screenshot`, `quit`.
3. For an agent: `horizon-ctl mcp`, or the launcher's `horizon-launcher mcp` with `agent-config` to connect a client
@@ -28,7 +28,7 @@ serves the same commands as MCP tools. The launcher's MCP server offers them too
## Reference
[horizon-ctl-commands.md](../horizon-ctl-commands.md), generated from the command table in
`crates/horizon-client/src/bin/horizon-ctl/commands.rs`: every command, its MCP tool and its arguments.
`crates/horizon-ctl/src/commands.rs`: every command, its MCP tool and its arguments.
## Examples
+1 -1
View File
@@ -32,7 +32,7 @@ command above to inspect the selection rather than relying on historical counts.
| 3 | World save and load (163) | `L/save.rs`, `G/saving.rs`, `G/persist.rs` (entities), `L/entity_nbt.rs`, `K/block_entity_nbt.rs`, `W/region.rs`, `W/nbt.rs` | save_roundtrip, world_reopen, world, datafix |
| 4 | World generation (153) | `W/worldgen.rs`, `W/worldgen/` (`generator*.rs`, `feature_graph.rs`, `structure/`, `placement/`), `L/vanillagen.rs` | chunk_generation, worldgen, server_world_gen, world_spawn, feature_graph, feature_placement, decoration and the other worldgen harnesses |
| 5 | Multiplayer client, packets in (145) | `G/remote.rs` (`fn handle_packet`, `fn tick_remote`), `G/remote_*.rs`, `L/net.rs` | dedicated_server, server_entities, lan_e2e (all) |
| 6 | Agent control, horizon-ctl (145) | `L/control.rs`, `L/bin/horizon-ctl/`, `G/control.rs`, `G/agent.rs`, `G/events.rs`, `G/ui_control.rs` | `python3 tools/agent_control_e2e.py`; `cargo test -p horizon-client-lib --bin horizon-ctl` |
| 6 | Agent control, horizon-ctl (145) | `L/control.rs`, `crates/horizon-ctl/`, `G/control.rs`, `G/agent.rs`, `G/events.rs`, `G/ui_control.rs` | `python3 tools/agent_control_e2e.py`; `cargo test -p horizon-ctl` |
| 7 | CI and release (134) | `.github/workflows/` (`ci.yml`, `parity.yml`, `release.yml`, `launcher.yml`), `tools/ci/`, `tools/parity.py`, `tools/pr_ready.py` | `python3 -m unittest discover -s tests`; actionlint (`.github/actionlint.yaml`) |
| 8 | LAN host: connections, play state, tracking (133) | `L/lan/` (`conn.rs`, `hub.rs` + `hub/`, `chunks.rs`, `entity.rs`, `tracking.rs`, `guest.rs`, `playerdata.rs`), `G/lan.rs` | lan, lan_e2e (all), `cargo test -p horizon-client --test lan_bot` |
| 9 | Renderer core (132) | `R/gfx.rs` (`Renderer::new`, `Renderer::render`), `R/gfx/` (cull, occlusion, translucency, upload, timing, lod) | client_graphics, culling_rays, translucency; `horizon-client --benchmark standard` |
+1 -1
View File
@@ -46,7 +46,7 @@ The report is the [benchmark report format](benchmark-report.md): startup to the
## Reproduce it
You need Horizon built (`cargo build --release -p horizon-client -p horizon-client-lib --bins`) and its resources prepared from your own copy of 26.3 (which also provides `.local/minecraft/26.3`, the vanilla client the driver starts), Java 25 with `javac`, and Python 3.10 or newer.
You need Horizon built (`cargo build --release -p horizon-client -p horizon-ctl --bins`) and its resources prepared from your own copy of 26.3 (which also provides `.local/minecraft/26.3`, the vanilla client the driver starts), Java 25 with `javac`, and Python 3.10 or newer.
```sh
python3 tools/perf_bench.py --game horizon --label horizon-mine
+1 -1
View File
@@ -131,7 +131,7 @@ It runs only in frames drawn flat (Metal past `flat::MIN_SECTIONS` sections in v
`tools/graphics_bench.py` opens a fresh creative world (seed 1234) on a virtual screen and flies the camera along four fixed 192-block paths, over a village, a forest, the ocean and a mountain, at render distances 8, 16 and 32, one game per distance. Each flight takes 12 seconds and reports average FPS, 1% lows, frame-time percentiles, CPU time per frame (frame time minus waits for the GPU, the display and the limiter), the split of that CPU time (world update, ticks, frame preparation, renderer) for all frames and for the slowest 1%, and GPU time per frame from timestamp queries.
```sh
cargo build --release -p horizon-client -p horizon-client-lib --bins
cargo build --release -p horizon-client -p horizon-ctl --bins
python3 tools/graphics_bench.py --label mine # lavapipe on vscreen: CPU-side numbers
python3 tools/graphics_bench.py --label mine-gpu --offscreen # the desktop's RTX 4080
python3 tools/graphics_bench.py --compare baseline-4080 mine-gpu # markdown table
+1 -1
View File
@@ -1,4 +1,4 @@
<!-- Generated by `horizon-ctl help --markdown` from the command table in crates/horizon-client/src/bin/horizon-ctl/commands.rs: edit the table, then regenerate. -->
<!-- Generated by `horizon-ctl help --markdown` from the command table in crates/horizon-ctl/src/commands.rs: edit the table, then regenerate. -->
# horizon-ctl commands
Every command `horizon-ctl` takes, its MCP tool in `horizon-ctl mcp` (the launcher's `horizon-launcher mcp` offers the same tools as `game_<tool>`, all but `launch`) and its arguments. Positional arguments come first, in order; `--flags` after them. `horizon-ctl help --game` lists the game's own commands, test hooks included. Design rules and the full inventory: [agent-control.md](agent-control.md).
+1 -1
View File
@@ -289,7 +289,7 @@ local socket; under control, losing window focus does not pause the game or
release held keys, so a script can play while you use other windows.
```sh
cargo build --release -p horizon-client -p horizon-client-lib --bins
cargo build --release -p horizon-client -p horizon-ctl --bins
C=target/release/horizon-ctl
$C launch --world Survival --seed 5 --wait # start the game, open or create the world, wait for it
$C state # player, world, screen, crosshair target
+1 -1
View File
@@ -17,7 +17,7 @@ the Java exporters used by the game.
```powershell
rustup target add aarch64-pc-windows-msvc
cargo build --release --locked --target aarch64-pc-windows-msvc `
-p horizon-client -p horizon-client-lib --bin horizon-client --bin horizon-ctl `
-p horizon-client --bin horizon-client -p horizon-ctl --bin horizon-ctl `
-p horizon-prepare --bin horizon-prepare -p horizon-server --bin horizon-server
```
+1 -1
View File
@@ -1158,7 +1158,7 @@ def main():
if args.bin_dir:
bins = Path(args.bin_dir).resolve()
else:
subprocess.run(['cargo', 'build', '--locked', '--profile', 'fast', '-p', 'horizon-client', '-p', 'horizon-client-lib', '--bins'],
subprocess.run(['cargo', 'build', '--locked', '--profile', 'fast', '-p', 'horizon-client', '-p', 'horizon-ctl', '--bins'],
cwd=ROOT, check=True)
meta = json.loads(subprocess.run(['cargo', 'metadata', '--format-version', '1', '--no-deps'], cwd=ROOT,
capture_output=True, text=True, check=True).stdout)
+1 -1
View File
@@ -34,7 +34,7 @@ Checks:
Each server runs in a fresh folder with fresh HORIZON_HOME and XDG folders (lab.game_env), on a free port,
in a flat world (creative unless the check says otherwise: the bots fly). Build first:
cargo build --profile fast -p horizon-client -p horizon-client-lib --bin horizon-client --bin horizon-ctl
cargo build --profile fast -p horizon-client -p horizon-ctl --bin horizon-client --bin horizon-ctl
cargo build --profile fast -p horizon-bots
"""
import argparse
+1 -1
View File
@@ -97,7 +97,7 @@ def main():
for binary in (client, ctl_path):
if not binary.exists():
raise Failed(f'{binary} is missing; build it (cargo build --profile fast -p horizon-client '
'-p horizon-client-lib --bins) or pass --bin-dir')
'-p horizon-ctl --bins) or pass --bin-dir')
resources = Path(args.resources).resolve()
if not resources.exists():
raise Failed(f'{resources} is missing; run tools/lab.py prepare')
+1 -1
View File
@@ -15,7 +15,7 @@ export RUSTFLAGS='-C target-feature=-crt-static'
target=x86_64-unknown-linux-musl
bin="target/$target/release"
cargo build --release --locked --target "$target" \
-p horizon-official --bin horizon-official -p horizon-client-lib --bin horizon-ctl \
-p horizon-official --bin horizon-official -p horizon-ctl --bin horizon-ctl \
-p horizon-prepare --bin horizon-prepare -p horizon-server --bin horizon-server
# The official game (horizon-client's with Horizon's own parts, docs/layers.md) is what players
# get, under the game's name.
+1 -1
View File
@@ -258,7 +258,7 @@ def main():
if args.bin_dir:
bins = Path(args.bin_dir).resolve()
else:
subprocess.run(['cargo', 'build', '--locked', '--profile', 'fast', '-p', 'horizon-client', '-p', 'horizon-client-lib', '--bins'],
subprocess.run(['cargo', 'build', '--locked', '--profile', 'fast', '-p', 'horizon-client', '-p', 'horizon-ctl', '--bins'],
cwd=ROOT, check=True)
meta = json.loads(subprocess.run(['cargo', 'metadata', '--format-version', '1', '--no-deps'], cwd=ROOT,
capture_output=True, text=True, check=True).stdout)
+1 -1
View File
@@ -170,7 +170,7 @@ def main():
return
ctl = Path(args.build).resolve() / "horizon-ctl"
if not ctl.exists():
sys.exit(f"{ctl} missing: cargo build --release -p horizon-client -p horizon-client-lib --bins")
sys.exit(f"{ctl} missing: cargo build --release -p horizon-client -p horizon-ctl --bins")
cwd = ROOT / ".local/graphics-bench"
shutil.rmtree(cwd / "saves" / WORLD, ignore_errors=True)
cwd.mkdir(parents=True, exist_ok=True)
+1 -1
View File
@@ -7364,7 +7364,7 @@ def main():
if args.bin_dir:
bins = Path(args.bin_dir).resolve()
else:
subprocess.run(['cargo', 'build', '--locked', '--profile', 'fast', '-p', 'horizon-client', '-p', 'horizon-client-lib',
subprocess.run(['cargo', 'build', '--locked', '--profile', 'fast', '-p', 'horizon-client', '-p', 'horizon-ctl',
'--bin', 'horizon-client', '--bin', 'horizon-ctl'],
cwd=ROOT, check=True)
meta = json.loads(subprocess.run(['cargo', 'metadata', '--format-version', '1', '--no-deps'], cwd=ROOT,
+1 -1
View File
@@ -33,6 +33,7 @@
"cargo-horizon-mod": "platform",
"horizon-anticheat": "platform",
"horizon-chat-filter": "platform",
"horizon-ctl": "platform",
"horizon-dualsense": "platform",
"horizon-game": "platform",
"horizon-hdr": "platform",
@@ -99,7 +100,6 @@
"horizon-client-lib -> horizon-bench",
"horizon-client-lib -> horizon-chat-filter",
"horizon-client-lib -> horizon-hdr",
"horizon-client-lib -> horizon-mcp",
"horizon-client-lib -> horizon-mods",
"horizon-client-lib -> horizon-optifine",
"horizon-client-lib -> horizon-shader-api",
+1 -1
View File
@@ -42,7 +42,7 @@ def close(g):
def build():
subprocess.run(['cargo', 'build', '--locked', '--profile', 'fast', '-p', 'horizon-client', '-p', 'horizon-client-lib',
subprocess.run(['cargo', 'build', '--locked', '--profile', 'fast', '-p', 'horizon-client', '-p', 'horizon-client-lib', '-p', 'horizon-ctl',
'--bin', 'horizon-client', '--bin', 'horizon-ctl', '--example', 'old_world_fixture'], cwd=lan.ROOT, check=True)
meta = json.loads(subprocess.run(['cargo', 'metadata', '--format-version', '1', '--no-deps'], cwd=lan.ROOT,
capture_output=True, text=True, check=True).stdout)
+1 -1
View File
@@ -3,7 +3,7 @@
tarball for one of your own Linux or macOS machines. The resources are Mojang
assets: keep the archive in ignored .local/ and never publish or commit it.
cargo build --release -p horizon-client -p horizon-client-lib --bins
cargo build --release -p horizon-client -p horizon-ctl --bins
python3 tools/package_native_client.py
"""
import argparse
+1 -1
View File
@@ -66,7 +66,7 @@ Cases:
it, and Undo shows once the pack is picked.
- extras_shell_edges: on Extras, which has no page list, down from the search field lands on the first row, not Done;
a row the right stick leaves mostly hidden scrolls back into view when A presses it, and A changes it.
Needs built fast binaries (`cargo build --profile fast -p horizon-client -p horizon-client-lib --bins`)
Needs built fast binaries (`cargo build --profile fast -p horizon-client -p horizon-ctl --bins`)
and prepared resources in .local/horizon-client/26.3. Exit status 0 when every case passes.
"""
import argparse
+1 -1
View File
@@ -16,7 +16,7 @@ Cases:
- gameplay_drop: Q in play throws one and Ctrl+Q the rest; the pad's drop button tapped and held must too.
- screenshot: key.screenshot bound to the pad takes a screenshot as F2 does.
Needs built fast binaries (`cargo build --profile fast -p horizon-client -p horizon-client-lib --bins`)
Needs built fast binaries (`cargo build --profile fast -p horizon-client -p horizon-ctl --bins`)
and prepared resources in .local/horizon-client/26.3. Exit status 0 when every case matches.
"""
import argparse
+1 -1
View File
@@ -19,7 +19,7 @@ console` attaches through a pipe, runs two commands and shows what they log.
Everything runs in a fresh temporary folder with fresh HORIZON_HOME and XDG folders and no audio. Logs go
to --out. Build first:
cargo build --profile fast -p horizon-client -p horizon-client-lib --bins -p horizon-bots -p horizon-server
cargo build --profile fast -p horizon-client -p horizon-ctl --bins -p horizon-bots -p horizon-server
"""
import argparse
import http.client
+1 -1
View File
@@ -512,7 +512,7 @@ def main():
if args.bin_dir:
bins = Path(args.bin_dir).resolve()
else:
subprocess.run(['cargo', 'build', '--locked', '--profile', 'fast', '-p', 'horizon-client', '-p', 'horizon-client-lib', '--bins'],
subprocess.run(['cargo', 'build', '--locked', '--profile', 'fast', '-p', 'horizon-client', '-p', 'horizon-ctl', '--bins'],
cwd=ROOT, check=True)
bins = ROOT / 'target/fast'
out = Path(args.out)
+1 -1
View File
@@ -11,7 +11,7 @@ A real Horizon client (horizon-ctl, offscreen) with LOD Distance 32 joins a dedi
Each server and game runs in fresh folders with fresh HORIZON_HOME and XDG folders (lab.game_env), on a free
port. Build first:
cargo build --profile fast -p horizon-client -p horizon-client-lib --bin horizon-client --bin horizon-ctl
cargo build --profile fast -p horizon-client -p horizon-ctl --bin horizon-client --bin horizon-ctl
"""
import argparse
import os
+1 -1
View File
@@ -16,7 +16,7 @@ ops.json); at level 2 the admins' commands must do nothing.
The game and the server run with fresh HORIZON_HOME, launcher and XDG folders and without audio. Logs go to --out.
Build first:
cargo build --profile fast -p horizon-client -p horizon-client-lib --bins
cargo build --profile fast -p horizon-client -p horizon-ctl --bins
cargo build --profile fast -p horizon-bots
"""
import argparse
+1 -1
View File
@@ -14,7 +14,7 @@ again as a spectator. Ops, spectating, sees Pat's.
The server and the games run in fresh folders with fresh HORIZON_HOME and XDG folders (lab.game_env), on a free
port. Build first:
cargo build --profile fast -p horizon-client -p horizon-client-lib --bin horizon-client --bin horizon-ctl
cargo build --profile fast -p horizon-client -p horizon-ctl --bin horizon-client --bin horizon-ctl
"""
import argparse
import os
+1 -1
View File
@@ -202,7 +202,7 @@ def signal_saves(build):
def main():
subprocess.run(['cargo', 'build', '--profile', 'fast', '-p', 'horizon-client', '-p', 'horizon-client-lib', '--bin', 'horizon-client', '--bin', 'horizon-ctl'], cwd=lab.ROOT, check=True)
subprocess.run(['cargo', 'build', '--profile', 'fast', '-p', 'horizon-client', '-p', 'horizon-ctl', '--bin', 'horizon-client', '--bin', 'horizon-ctl'], cwd=lab.ROOT, check=True)
build = lab.LOCAL / 'dedicated-crash-save'
shutil.rmtree(build, ignore_errors=True)
build.mkdir(parents=True)
+1 -1
View File
@@ -68,7 +68,7 @@ SEED = '7'
# horizon-mod-api-gen generates Rust from tools/native-hook-fragments/ (BUILT_FROM_TOOLS).
NO_BINARY = ('tools/', 'tests/', '.github/')
BUILT_FROM_TOOLS = ('tools/native-hook-fragments/',)
BUILD = ['cargo', 'build', '--locked', '--profile', 'fast', '-p', 'horizon-client', '-p', 'horizon-client-lib', '--bins']
BUILD = ['cargo', 'build', '--locked', '--profile', 'fast', '-p', 'horizon-client', '-p', 'horizon-ctl', '--bins']
# 🤖 Agent: Where the overworld scenes are built, high above seed 7's spawn, so terrain below hardly shows.
X, Y, Z = 8, 160, 8
+1 -1
View File
@@ -17,7 +17,7 @@ from integration_env import suite_lock
if __name__ == '__main__':
# The official executable: joining a friend is Play with Friends' hook, which horizon-client's
# own executable doesn't register (docs/layers.md, "How a Horizon crate plugs in").
subprocess.run(['cargo', 'build', '--locked', '--profile', 'fast', '-p', 'horizon-official', '-p', 'horizon-client-lib',
subprocess.run(['cargo', 'build', '--locked', '--profile', 'fast', '-p', 'horizon-official', '-p', 'horizon-ctl',
'-p', 'horizon-relay', '--bin', 'horizon-official', '--bin', 'horizon-ctl',
'--bin', 'horizon-relay'], cwd=lab.ROOT, check=True)
metadata = json.loads(subprocess.check_output(
+1 -1
View File
@@ -80,7 +80,7 @@ def check_thrown(host, guest, out):
def main():
subprocess.run(['cargo', 'build', '--locked', '--profile', 'fast', '-p', 'horizon-client', '-p', 'horizon-client-lib',
subprocess.run(['cargo', 'build', '--locked', '--profile', 'fast', '-p', 'horizon-client', '-p', 'horizon-ctl',
'--bin', 'horizon-client', '--bin', 'horizon-ctl'], cwd=lab.ROOT, check=True)
metadata = json.loads(subprocess.check_output(
['cargo', 'metadata', '--format-version', '1', '--no-deps'], cwd=lab.ROOT, text=True))
+1 -1
View File
@@ -11,7 +11,7 @@ import lan_e2e as lan
def main():
subprocess.run(['cargo', 'build', '--locked', '--profile', 'fast', '-p', 'horizon-client', '-p', 'horizon-client-lib',
subprocess.run(['cargo', 'build', '--locked', '--profile', 'fast', '-p', 'horizon-client', '-p', 'horizon-ctl',
'--bin', 'horizon-client', '--bin', 'horizon-ctl'], cwd=lab.ROOT, check=True)
metadata = json.loads(subprocess.check_output(
['cargo', 'metadata', '--format-version', '1', '--no-deps'], cwd=lab.ROOT, text=True))
+1 -1
View File
@@ -44,7 +44,7 @@ def main():
args = parser.parse_args()
bin_dir = Path(args.bin_dir).resolve() if args.bin_dir else None
if bin_dir is None:
subprocess.run(['cargo', 'build', '--locked', '--profile', 'fast', '-p', 'horizon-client', '-p', 'horizon-client-lib', '--bins'], cwd=ROOT, check=True)
subprocess.run(['cargo', 'build', '--locked', '--profile', 'fast', '-p', 'horizon-client', '-p', 'horizon-ctl', '--bins'], cwd=ROOT, check=True)
bin_dir = ROOT / os.environ.get('CARGO_TARGET_DIR', 'target') / 'fast'
shutil.rmtree(RUN, ignore_errors=True)
RUN.mkdir(parents=True)
+1 -1
View File
@@ -665,7 +665,7 @@ def main():
else:
bin_dir = Path(args.bin_dir).resolve() if args.bin_dir else None
if bin_dir is None:
subprocess.run(['cargo', 'build', '--locked', '--profile', 'fast', '-p', 'horizon-client', '-p', 'horizon-client-lib', '--bins'], cwd=ROOT, check=True)
subprocess.run(['cargo', 'build', '--locked', '--profile', 'fast', '-p', 'horizon-client', '-p', 'horizon-ctl', '--bins'], cwd=ROOT, check=True)
bin_dir = ROOT / os.environ.get('CARGO_TARGET_DIR', 'target') / 'fast'
h = horizon_resave(v0, RUN / 'h', bin_dir)
print('comparing', v0, 'with', h)
+1 -1
View File
@@ -88,7 +88,7 @@ def main():
import lab
import lan_e2e as lan
subprocess.run(['cargo', 'build', '--locked', '--profile', 'fast', '-p', 'horizon-client', '-p', 'horizon-client-lib',
subprocess.run(['cargo', 'build', '--locked', '--profile', 'fast', '-p', 'horizon-client', '-p', 'horizon-ctl',
'--bin', 'horizon-client', '--bin', 'horizon-ctl'], cwd=lab.ROOT, check=True)
metadata = json.loads(subprocess.check_output(
['cargo', 'metadata', '--format-version', '1', '--no-deps'], cwd=lab.ROOT, text=True))
+1 -1
View File
@@ -75,7 +75,7 @@ def main():
args = parser.parse_args()
bin_dir = Path(args.bin_dir).resolve() if args.bin_dir else None
if bin_dir is None:
subprocess.run(['cargo', 'build', '--locked', '--profile', 'fast', '-p', 'horizon-client', '-p', 'horizon-client-lib', '--bins'], cwd=ROOT, check=True)
subprocess.run(['cargo', 'build', '--locked', '--profile', 'fast', '-p', 'horizon-client', '-p', 'horizon-ctl', '--bins'], cwd=ROOT, check=True)
bin_dir = ROOT / os.environ.get('CARGO_TARGET_DIR', 'target') / 'fast'
shutil.rmtree(RUN, ignore_errors=True)
RUN.mkdir(parents=True)
+1 -1
View File
@@ -54,7 +54,7 @@ def main():
args = parser.parse_args()
bin_dir = Path(args.bin_dir).resolve() if args.bin_dir else None
if bin_dir is None:
subprocess.run(['cargo', 'build', '--locked', '--profile', 'fast', '-p', 'horizon-client', '-p', 'horizon-client-lib', '--bins'], cwd=ROOT, check=True)
subprocess.run(['cargo', 'build', '--locked', '--profile', 'fast', '-p', 'horizon-client', '-p', 'horizon-ctl', '--bins'], cwd=ROOT, check=True)
bin_dir = ROOT / os.environ.get('CARGO_TARGET_DIR', 'target') / 'fast'
shutil.rmtree(RUN, ignore_errors=True)
RUN.mkdir(parents=True)
+2 -2
View File
@@ -1,7 +1,7 @@
//! Repository tasks, run with `cargo run -p xtask -- TASK`.
//!
//! `package BINARY OUTDIR`: a playable Horizon folder with the game binary, horizon-ctl,
//! horizon-prepare and horizon-server (built beside it: cargo build --release -p horizon-client -p horizon-client-lib
//! horizon-prepare and horizon-server (built beside it: cargo build --release -p horizon-client -p horizon-ctl
//! --bins -p horizon-prepare -p horizon-server), the exporters horizon-prepare compiles, its sources (the launcher compares
//! them to its own), and PLAY.txt. It holds none of Minecraft's files: players prepare those
//! from their own copy. .github/workflows/release.yml makes the release folders with it.
@@ -297,7 +297,7 @@ fn copy_beside(program: &Path, tools: &[&str], out: &Path) -> Result<(), String>
.join(program_name(program, tool));
if !path.is_file() {
return Err(format!(
"{} is missing; build it too: cargo build --release -p horizon-client -p horizon-client-lib --bins -p horizon-prepare -p horizon-server",
"{} is missing; build it too: cargo build --release -p horizon-client -p horizon-ctl --bins -p horizon-prepare -p horizon-server",
path.display()
));
}