What the dedicated server does today (measured against vanilla 26.3), the horizon-server supervisor and
its packaging, server.toml, the CLI and TUI, the web panel, backups and updates, the control API and MCP,
the bot benchmark plan against vanilla and Paper, the working version for 2026-10-23, and the PRs that
build it (#551 to #556).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
docs/modpacks.md: how any pack (ATM10 down to small Fabric packs) gets to
Horizon: import (.mrpack, CurseForge zip or instance, Prism, packwiz),
inventory and classification, dependency order, mechanical carry-over of
data and assets, one agent per mod for code with a per-mod harness against
a dev-only NeoForge/Fabric oracle, and a coverage report. Also the mod API
gaps against 0.1, the registries 0.2 design (template blocks through the
overlay root), licence handling, how "10x" is measured against NeoForge,
and the scope for 2026-10-23.
docs/modpacks/atm10-mods.csv: ATM10's 495 jars from the pack's own
crash_assistant modlist (2026-10-15), with Modrinth metadata looked up by
hash: class, API tier, licence, sides. Metadata only.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
docs/mods.md: the sandboxed WebAssembly runtime, capabilities, hooks, budgets,
authoring, versions, multiplayer and distribution, with measured hook costs.
docs/research/java-mod-compat.md: why Fabric/NeoForge jars cannot run, data
import, which mods to port natively first, a porting guide outline.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
What the launcher, the game socket, horizon-ctl and the two MCP servers
can do today, and one model for what comes next: shared names and JSON
shapes, a widget tree with actions by id, options get/set, waits, an
event stream, the launcher's MCP proxying the game, errors with a kind,
and the safety rules.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
One versioned JSON report for every benchmark Horizon writes (the game's
--benchmark, the launcher's measurements, tools/perf_bench.py): the local log
a player can attach and, with consent, what the telemetry upload sends.
Summaries over repeats (mean, stdev, 95% CI) and fixed-edge frame-time
histograms, never raw frame streams; no host, user or path in uploads.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tools/perf_bench.py runs Horizon, the vanilla 26.3 client and vanilla with
Sodium, Lithium, FerriteCore and ImmediatelyFast through the same steps:
fresh world (seed 1234, creative) per render distance, start to title, start
to in-world, then per scene teleport, chunk load, settle and a fixed 192-block
flight. Every frame time is kept and one function computes average FPS, 1% and
0.1% lows, p50/p95/p99/p99.9 and a frame-time histogram for every game; RSS is
sampled from outside the process for every game. One options.txt (vanilla's
keys, Fancy preset values with a Custom preset so the render distance holds)
is written for all of them.
Vanilla is driven by a dev-only Fabric mod (mods/horizon/src/bench) compiled
against the user's own client jar: it creates the world with
WorldOpenFlows.createFreshLevel, teleports with /tp and places the player on
the path every frame as horizon-ctl fly does. Nothing of the game is
redistributed and the performance mods are fetched from Modrinth with the
hashes pinned in packs/mods.lock.json.
Horizon side: `fly ... PITCH raw` also replies with every frame time, and
--offscreen drives frames from the event loop, so a window nobody sees (a
locked macOS session) still renders.
docs/benchmark.md describes what is measured, how fairness is kept, the
caveats and how to reproduce it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
horizon-telemetry, shared by the launcher, the game and the ingest server:
- consent.json in the game folder: four switches, all off until the player
answers, a consent version that re-asks when what is collected changes, the
answer's time, and a random install ID made at the first yes.
- Payloads: perf summaries (percentiles + 14 frame-time buckets from a
fixed-size Timings recorder), crash and bug reports, and benchmark reports
carried as docs/benchmark-report.md defines them; size caps per kind.
- A scrubber for user folders, user names, e-mail and IP addresses, UUIDs and
caller-known private terms.
- The outbox: only allowed kinds get in, daily caps, 200 items / 2 MiB.
- zstd batches with bounded decoding; the uploader re-reads the consent and
drops withdrawn items before connecting, backs off and caps batches a day.
- tests/consent_gating.rs: a local mock server sees zero connections with the
consent missing, outdated or withdrawn.
No server is set (DEFAULT_ENDPOINT is None): nothing is sent yet.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
An Extras section in Horizon's Options holds optional additions saved in
horizon-extras.txt beside options.txt. Zoom divides the field-of-view
target vanilla's Camera.tickFov eases toward (the spyglass path), with a
wheel-adjustable level and lower mouse sensitivity; scoping keeps the
spyglass view. The FPS counter (with minimum and 1% low) and the keystroke
overlay (WASD, space, mouse buttons with clicks per second) draw in the
HUD layer, hidden with F1. docs/extras.md describes all the extras.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
links.json gains a website key; the launcher shows a quiet Website link under
Join Discord and lists it in the links CLI command and MCP tool.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The Horizon options shell's Video section now holds the graphics settings:
a Simple / Advanced switch (remembered in horizon-graphics.txt), then the
level's rows, each with its frame-time cost and one-line description
(ui_theme::described_row). Horizon settings draw as switches, sliders or
value buttons like vanilla options. The Classic style keeps the Video
Settings buttons to the same screens. Main's menu blur and the world's
resolution-scale pass are separate (post.wgsl, world_post.wgsl).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
At render distance 32 the single section arena grew past the 4 GiB buffer
limit and the renderer panicked. Sections now live in pages of at most
256 MiB (or the device's buffer limit); draws keep their order and bind each
page once per run of consecutive draws in it, so translucent sections stay
back to front. docs/graphics.md describes the settings, the benchmark and
what changed; graphics_bench.py --compare prints a before/after table and
keeps each game's log.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Options open as the launcher's Settings page: a sidebar with the sliding
selection (Video, Audio, Controls, Accessibility, Language, Chat, Interface)
and rows with a switch, slider or value button per option
(options_horizon.rs; new sections or rows slot into SECTIONS). Key binds,
the language list and resource packs open vanilla's pages. Interface holds
Menu style (Horizon / Classic). The pause menu hides the in-game HUD over the
blurred world. Scripted and frame-limited runs default to Classic, so the
harnesses see vanilla's screens.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Removed (each unreferenced by code, workflows, tests or living docs; no harness
dependency record names any of them, and parity.py --list still finds all 281):
- 22 one-off write-ups of the Java-pack experiments in docs/: adaptive-terrain,
client-graphics-smoke, compact-headers, core-performance, culling-empty,
culling-rays, debounce-queue, dispatch-retry, foreground-first,
graphics-api-comparison, heap-budget, mac-first-test, optimization-plan,
playable-validation, quad-reuse, server-graphics-context, shader-world-smoke,
terrain-measurements, terrain-position, terrain-read-wait, tick-membership,
worker-pacing. Their findings are folded into one paragraph of java-packs.md.
- 24 benchmarks/ observation dumps only those write-ups linked (client graphics,
culling, queues, heap, Mac Vulkan, shader worlds, software identity, and the
unlinked rust-core, rust-worldgen-2026-10-05, rust-native-client and
rust-cuboid-model-decoding runs), plus 12 unlinked files inside kept
report folders. The scoped-parity reports the living docs cite stay.
- debug/: one server log from a chunk investigation.
- The manual macos-shader-research and macos-vulkan-research workflows.
- tools/logs/latest.log, an empty log committed by accident (now ignored).
Kept: research-lock.json (parity.py, packaging, the launcher and datafix read
it), the Java-pack how-tos (vulkan, collectors, profiling, process-memory,
tick-state) and tools/test_client_graphics.py (ci.yml runs it).
README: leads with what Horizon is and "Download the launcher" (the
launcher-v* releases; the launcher updates itself), then build from source
for developers. Direct game downloads and PLAY.txt steps for players are gone;
the launcher has its own section with two screenshots. The roadmap merges the
known differences, the final checks and the plans after parity, under the
"Roadmap" heading the launcher's What's next page reads. The parity table and
its 100%-of-what-the-harnesses-compare note are unchanged.
docs/README.md indexes what remains: build and run, parity (status and
workflow), world generation, world data and simulation, the old Java track.
Links to the removed pages and README anchors are fixed.
packaging/PLAY.txt now speaks to players who came through the launcher and
points anyone with a bare archive to it, keeping the manual steps short.
The launcher's README link points at main instead of the launcher branch.
.gitignore: tools/logs/ and .DS_Store. No code behaviour changes; the compiler
and clippy flag no unused code and the tree has no stale TODOs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>