Options > Video Settings... now opens Horizon's graphics screen, as
Sodium's replaces vanilla's video screen. It gains the vanilla rows only
vanilla's screen had (Graphics Preset, Exclusive Fullscreen and its mode,
Menu Background Blur, Texture Filtering, Max Anisotropy) and the extras
that change the picture (Fullbright, Dynamic lights, Hide block-break
particles, still saved in horizon-extras.txt). It drops FOV and View
Bobbing, which stay where vanilla has them (Options, Accessibility).
Horizon Settings drops its second ways into the graphics screen, the
controller screen (Controls has it) and Mods (the Options screen has
it); Extras drops its PvP & HUD link and the PvP preset, which PvP & HUD
opens with. Vanilla's own Video Settings layout stays for
horizon-ctl options video-vanilla and its tests; no menu opens it.
A test walks every menu from Options and checks that each setting and
each page has one way in, and that every row of vanilla's Video
Settings is on the graphics screen.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Graphics settings move their frame, list and key steps into settings_shell, with no change to how they behave,
and Controller Settings is its second user: General, Bindings and Device pages, search, per-row reset and Undo.
A controller notice is one slot per view rather than the split screen's own. A pad-focused options tooltip hangs
from the widget's bottom left, as the pad's hidden pointer sits mid-widget; mouse and keyboard keep vanilla's. A
focus whose widget goes away on the same screen moves beside it.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The bots move to a shared horizon-light label (8 light runners on playhorizon, from 2), and triage command, mojang
republish and nightly build's answer join them. checks' verify and launcher, mod-registry, telemetry-server and the
pack bench run on the desktop's isolated horizon-checks runners, forks included: main's pushes and the pull requests
whose number ends in 0-2 by default (GitHub's pool keeps the others, so both work at once), every one with
SELF_HOSTED_CI=all, none with light (desktop paused) or off (everything back to GitHub).
Jobs with a secret or a token that can push, publish or start workflows stay on GitHub: tests/test_ci_runners.py
pins it. playhorizon's job hook now also drops a checkout's .git past 4 GB: each light runner's held 6822 packs, 50 GB.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Solid beveled panels made the screen read heavy. The plate and the strip
are now the page colour, see-through, with a 1 px edge; groups a lighter
tint on them; buttons, tick boxes and the value stepper flat; a slider a
thin accent track under its value.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The pages are a column of names on the left, under the search field, with
Undo and Done at its foot. The plate shows the open page alone, its
settings in named groups on panels of their own; a search shows every
page's matches under their page. The hovered setting's cost and
description sit in a strip under the plate, and what the page holds
while none is.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
- Undo from the keyboard no longer turns itself back on; Undo keeps
fullscreen (F11, the window manager); a calibration lights Undo.
- The search matches names and descriptions, not values, so a row
stays while its value changes; clearing it or pasting starts the list
over and lets go of the picked tab.
- The scroller is vanilla's thumb, the size Scroll drags by, 6 px wide
as its press column.
- The arrows reach only the rows in view and the next past an edge;
the wheel only scrolls (a controller's D-pad scrolls with it).
- Long names are cut before their control; hover is vanilla's white
edge, without an off-palette colour; the shortcut's caption goes
through the lang table; the title is Graphics.
- One graphics_events in options_ui instead of three copies;
graphics_level is graphics_page.
- screenshot-build saves its cache only when it builds its own branch.
- Docs: the design system's Blocks section names this screen and how
the game draws it; Leaf Culling's place; stale comments.
- Tests: Undo after several changes and with fullscreen changed, the
keyboard's Undo, HDR's working path, Calibrate and the shortcut row,
a 720p window, the scroll after a resize, the wheel's ends, the
search's clear button; the open tab checked against what the list
shows rather than its own rule.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Horizon's Simple, Advanced and HDR graphics screens become one screen
holding vanilla's video options and Horizon's own, built from
Minecraft's own screen patterns in the design system's Blocks look:
the pages as tabs along a beveled panel, a search field that filters
every page as you type, a row per setting with a vanilla kind of
control (a value button, a tick box, a slider with its value on the
track), the hovered setting's description and cost in vanilla's
tooltip under the panel, and Undo and Done along the foot.
Adds screenshot-build.yml, a Linux build for a pull request's
screenshots.
Refs #5705
Co-Authored-By: Claude Opus 5.5 <[email protected]>
GitHub's 20 hosted jobs at a time are shared by every pull request: on 2026-10-31 400+ runs queued and every job
waited 20-25 minutes for work of 0.3-4 minutes. Main's pushes and this repository's own pull requests now run
checks' verify and launcher on playhorizon (label playhorizon-ci, two runners); the bots that run main's own scripts
(pr labels, overlap note, cancel-on-close, claim command, parity-scope) on two small runners there
(playhorizon-light). A fork's pull request stays on ubuntu-latest, and the runners' job-started hook refuses one
whatever its workflow says. SELF_HOSTED_CI=off sends everything back to GitHub's runners.
tools/ci/checks-runners.sh installs the runners (systemd user services pinned to CPUs 4-7 in horizon-ci.slice,
shared cargo home, a build folder per runner outside the checkout); docs/ci-runners.md; tests/test_ci_runners.py pins
the fork rule.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A dedicated server now refuses players' text that holds a hate slur before it
relays it: chat, /msg /tell /w, /me, /say, /teammsg, sign text, anvil names and
book titles. The sender is told in private, logs/chat-filter.log keeps the
original text for operators, and horizon-server's event stream gets a
chat_filtered event instead of chat (so the Discord bridge never forwards it).
The 2nd hit within 10 minutes mutes for 10 minutes, the 3rd bans for 24 hours.
Mutes persist in chat-filter-mutes.json; ops lift them with /unmute <player>
(console: unmute). server.toml's [chat_filter] sets it, on by default.
The new horizon-chat-filter crate holds the settings, the precompiled matcher
for the list (data/slurs.txt, or the owner's words_file) and the escalation.
Text is normalised first: case, accents, look-alike letters, invisible
characters, leetspeak, separators and repeated letters, with care for Niger,
snigger, knight, suspicious and the like.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The same mixed bots on playhorizon (release builds, CPUs 0-3, three rounds):
Horizon's tick is half Pumpkin's at 100 bots, equal at 60, and 1.8 times
longer at 20 (where it generates 63 % more new chunks a second). Idle
memory, start and median join are behind. The report, how to read it, and
the commands to run it again.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
docs/narrator.md: the statuses and hotkey, the voices per platform (flite
needs libflite on Linux, as vanilla), where the code lives, how a screen
records its narration, silent scripted runs with horizon-ctl narration,
and the known differences from vanilla. Linked from the docs index.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A new crate, horizon-anticheat, holds server.toml's [anticheat] settings, each player's violation
levels (they decay every second) and the checks' rules, with no game state. The dedicated server's
hub runs the checks where it handles packets and carries out a flag: send the player back, alert the
console, the log file and online operators, then kick; never a ban. Each check has its own toggle and
thresholds. Without [anticheat] (the default, and the generated server.toml only has a commented
example) the hub holds no anticheat and the server does what vanilla's does.
The first check is timer: vanilla's client ends each tick with ServerboundClientTickEndPacket at the
server's tick rate, so a client further ahead of the wall clock than 300 ms is flagged, with a capped
balance for lag spikes and slow server ticks.
horizon-bots gets --timer F (a sped-up client), tools/anticheat_e2e.py runs a real dedicated server
with legit and cheating bots, and server_bench.py --anticheat measures the cost.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Horizon's own server stays plain: no SMP command, setting or code in the
release. The mod lives in horizon-mods (native/smp); Horizon gains general
server hook points (commands, players, items, menus, interactions) that
any native mod can use. Config and data move to world/horizon-smp/.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Built in behind [smp] in server.toml, off by default: why not a server mod
or a datapack, the commands, the configuration, the data files under
world/horizon-smp/, the cost and the phases.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Names, firing points, sides and cancel contracts from NeoForge's 26.3.x events (no code
copied), a catalog field for the counterpart, how the hooks we have and the PRs in flight
map, a priority list, and the capability/menu shape for mod block entities.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The roadmap: main's (Now at most 8 items) with this layer's native-mod
wording reapplied; the WebAssembly runtime is removed, not being removed.
docs/README.md: main's data pack upgrade line kept.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Horizon's dedicated server, vanilla 26.3 and Pumpkin 0.2.1 (black box) with
the same horizon-bots at 10/50/100 players; numeric targets; everything in
this repo, shared by the integrated server, LAN and --dedicated; parallel
ticking that keeps vanilla's order; the network front, tracker deltas,
off-thread saving; the Horizon fast path; online mode on by default; the
plugin API (with levzzz5154); the plan and the open PRs on the theme.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
🤖 Agent: pr-triage-2 (Ludovic's AI agent, Claude): proven at a717d6d58 in union/pt2-e3 (17 PRs on main cbea22fbb): parity --changed passes but for main's own failures, lan_e2e on both paths, policy read (Mojang rules, supply chain, speed). Merging.
* Add the port ledger: vanilla methods next to the Rust functions that port them
tools/port_ledger.py indexes the decompiled sources and the Rust tree into .local/port-ledger/ledger.json and answers where/what/class/coverage queries both ways, with the gaps where a port isn't wired like vanilla (seam, client, class, callee, stale).
* Document the port ledger
* Port ledger: bytecode calls, wider matching, drift, issue and check
Read the game jar's bytecode for exact call targets, constants and ids, and
resolve Rust calls through the receiver's type. Match more methods: same-named
fns in an impl or file named for the class (the impl type must fit the class),
and callees of known pairs linked through the call graph. Leave trivial methods
out of coverage.
New gap kind drift: a port that never names a sound, particle, item, block,
effect or game event its vanilla method uses, or lacks one of its rare numbers.
Seam gaps on the old in-frame path sort last; maths and geometry callees no
longer make seam or callee gaps.
New commands: issue (the classes, Rust code and gaps a bug report points at),
check (what a branch touches, gaps it opens and closes against its base), diff,
and a searchable offline report.html.
* Document the port ledger's new matching, gaps and commands
* Port ledger: class homes, structural matches and the verdict map
Give every vanilla class its Rust home files, weighed from all its matches.
In those files, match a method to the fn that touches the same fields and
reaches the ports of the same callees. Read tools/port_map/*.tsv, where a
person or agent records a verdict for what nothing else finds (port, inline,
missing, skip with a reason), and list the next unanswered batch with todo.
Count field-only constructors as trivial and fold initializer lambdas into
<clinit> and <init>.
* Map the first three batches: animals, inventory screens, world generation
* Document class homes, structural matches and the verdict map
* Map 13 game-logic batches and add map-check
map-check checks verdict-map files against the last build without
rebuilding, so several mappers can check their own rows at once.
* Map the rest of the game logic: classes with no Rust trace, then method batches
* Map client packet handling, entity renderers and models, block renderers
Also let PORT_LEDGER_NO_MAP build without the verdict map, to measure the
automatic matches on their own.
* Map client rendering, particles, sounds and resources
* map-check: accept full Class#method keys
* Map client screens, toasts, recipe book and world screens
* Add a vanilla-parity skill: start parity fixes from the port ledger
* issue: read registry names, so a mooshroom report finds MushroomCow
* Map the remaining vanilla methods: commands, network, packs, advancements and the last ten
* Follow the furnace code to furnace.rs on main; answer Fox.getBreedOffspring
docs/mods.md is now about content mods (`cargo horizon-mod`, the manifest, the
content fence), native mods, publishing, the official native mods and a short
note on the removed WebAssembly mods. docs/api/mods.md and mods-reference.md
(the code API) are deleted. Other pages, the CLAUDE.md crate table and the
roadmap (five WebAssembly API items removed, others reworded for native mods)
no longer describe the sandbox, the SDK or the WIT.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
tools/fixtures/tall_datapacks/horizon_tall_test is Horizon's own pack
(MIT): an Overworld dimension type of min_y -64, height 2096 (To The
Max's, the highest top vanilla allows) and noise settings that raise
terrain to about y 1900. VanillaChunkGenerationOracle builds each level
at its dimension type's range instead of a fixed -64..320, so
HORIZON_PARITY_DATAPACKS=tools/fixtures/tall_datapacks
tools/test_datapack_worldgen_parity.py compares Horizon's tall generation
with vanilla's: 16 chunks over two seeds, terrain and decorated, the same.
docs/world-height.md describes the model (one LevelShape per level, from
its dimension type, read everywhere), the network path, the checks and
what is left; world-generation.md and the README say packs' dimension
types now apply.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
- docs/datapack-upgrade.md: how to run `horizon-port-pack
upgrade-datapack`, every rewrite and how it is checked, and what is not
rewritten; linked from docs/README.md and the command's help.
- tools/datapack_upgrade_rosetta.py writes vanilla 26.2's own worldgen out
as a pack, upgrades it and compares it with vanilla 26.3's file by file:
registries whose format changed and whose content did not must come out
identical.
- tools/datapack_upgrade_fidelity.py starts vanilla's 26.2 and 26.3
dedicated servers on the same seed, the first with a pack and the second
with its upgrade, force loads the same chunks and compares the saved
blocks; without packs it measures what 26.3 itself changed.
Both need the 26.2 server jar the player downloaded; nothing is fetched.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
🤖 Agent: thank you kacpherek! /pregen is in, off by default: a server turns it on with horizon-pregen=true in server.properties (server.toml [properties]), single player and LAN with --pregen. With it off, the command tree and /help match vanilla. Tested on a dedicated server through horizon-server (on: 1,369 chunks generated and saved), single player on the server thread and in-frame, and 11 harnesses including command_exec.
🤖 Agent: merged after verify passed (hub: website tests 30/30, roadmap tests + sync check, telemetry server 35 tests; local end-to-end run by roadmap-1).
Where to start is playhorizon.dev/hub: the roadmap, the work board, good first
tasks and the forms; roadmap PRs carry their roadmap:<id> label, ideas go to the
suggestion queue and issues are for bugs.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The SDK's tool, in horizon-shader-api: `horizon-shader new <dir> --template
post|sky|material` makes a pack that passes the check, `check <pack>...
[--json]` runs the check the game, the launcher and the registry run and
prints each stage's cost and the pack's SHA-256 or every problem at its
file:line:column, and `pack <dir>` checks then writes the reproducible
.hshader. Golden Hour, the example pack, warms the sky around a low sun and
adds a soft glow and a colour grade, with five options. docs/shaders.md is the
authors' guide.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A Chunky-like command for single player and servers: /pregen start
<radius> [square|circle] [<x> <z>], status, pause, continue and cancel,
with progress (chunks, chunks/s, time left) in the log and to the player
who started it.
The area is swept strip by strip by a band of rows that streaming treats
like a player's area (Streaming::set_band). A row is done once its chunks
are lit and post-processed; the rows behind the band then unload and are
saved, so memory holds only the rows in flight. The band's chunks are
ranked for decoration row by row as they come within reach, so a task
decorates in the same order however its jobs are timed. Between ticks
the server waits on the workers' results and schedules the next jobs at
once instead of once a tick.
docs/api/ gets one page per surface other programs build on (mods,
shaders, agent control, servers, the launcher, data formats), each with an
overview measured from the source, the guide, the generated reference, examples,
its stability, what is not there yet and a changelog, plus the policy every
API follows (docs/api/stability.md): a version per API, semver lines,
experimental / preview / stable, deprecation windows, compatibility tests and
the level of every part today.
The website gets a "Build on Horizon" page (website/docs/apis.md) that
summarises them and links the repository's pages.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A developer of Iris showed that Horizon's shader pack code was written from
Iris's source. This removes it: the horizon-shaderpack crate, Java pack
loading and its render stages, Horizon's own WGSL packs and the example
packs, the Shader Packs screen and its option, the launcher's shader pack
browsing and installing, and the docs about them. Shader packs may come
back later as a clean-room rewrite.
The vanilla renderer and its post-processing (resolution scale, FXAA) are
unchanged. Options files that name a pack load and drop the key; the
launcher reads manifests that list a shader pack, and files in
`shaderpacks/` are never deleted.
Co-Authored-By: Claude Opus 5.5 <[email protected]>