* native health: also cargo check, and mark the mods whose own code doesn't compile
The daily check only applied the mods, so versions that apply but don't
compile on the newest Nightly (eatinganimation's ItemRenderState, hitbox_plus's
module path, carryblock's removed Dim::min_y...) weren't marked broken_on,
while every player's build leaves them out.
After the apply pass, the mods that apply are checked together (cargo check,
with Horizon's `mods` feature) in rounds: each round's errors are traced to the
mod whose helper or support module holds them (scripts/native_trace.py, the
launcher's rule), those mods and the ones needing them leave, and the rest
compile again. An error of the kind two mods cause together (a name defined
twice...) is checked again with that mod alone, so a pair is never marked.
Mods that use an API the launcher prepares ([api], trait_method) aren't
compiled here. Dependencies and horizon-mixins come from the Actions cache.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* native health: trace helpers whose signature holds an array type, mask each file once
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* native health: an error in the call horizon-mixins generates for a helper is the helper's mod's
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---------
Co-authored-by: Horizon agent <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
The first daily run (42099210086) marked horizon_physics broken for an
E_OVERWRITE_CONFLICT with another mod: a pair conflict, not a mod that
fails on the Nightly. Each mod refused in the full set is now applied
again with only the mods it needs, and is broken on that Horizon only if
horizon-mixins still refuses it.
Co-authored-by: Horizon agent <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
Players' native builds broke on mods made for an older Horizon (targets moved
by the crate split, a support module refused by a glob) and the whole build
failed. scripts/native_compat.py applies mods as the launcher builds them:
- check (pull requests): each new native-mod version on the newest Nightly
with the 20 most downloaded native mods, horizon-mixins apply then cargo
check, and its support modules' (file, name) against every registry mod's.
- health (daily, native-compat.yml): every native mod's newest version on the
newest Nightly; the ones horizon-mixins refuses go to the native-health
release, and publish marks them `broken_on` in index.json so the launcher
warns before an install.
The PR job runs main's script with a read-only token; the submission's build
scripts run under that token only.
Co-authored-by: Horizon agent <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
rdbt (operator, #mod-chat 11-05): the centred 'Vanished: only operators see
you' line covers the view. It is now an action bar line refreshed once a
second; unvanishing sends an empty action bar instead of clearing titles.
proof.py checks the action bar and that nothing shows mid-screen.
Co-authored-by: Horizon agent <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
glue.rs's VERSION still read 0.34.0 after #261 (0.35.0). proof.py's claims mode checks the version line and counts errors from the server's Done on (the engine logs one "No key layers" error while loading the world).
Co-authored-by: Horizon agent <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
* /ledger minted: say "partial" only when the end read stops short of the six hours
The official audit.log is ~9 MB (~1.8 MB a day), so a 1 MiB end read
covers the six hours; the note now depends on whether the lines read
reached back past the window's start, not on the file's size.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* proof.py: config.json now has a reports section
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---------
Co-authored-by: Horizon agent <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
Registry v2 backfill (docs/design/registry-v2.md): categories and tags for
each entry, descriptions extended where they were short or unformatted, and
every icon stored in icons/<id>.png (creators' own icons mirrored, the
missing ones drawn). No owners, versions or keys change.
Co-authored-by: Horizon agent <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
* SMP 0.35.0: claims stop griefing from outside, chat pings
Claims: blocks placed (or fire, buckets, spawn eggs) against a claim's
border from outside, dispensers acting into a claim, lava lighting a
claim's blocks from outside, projectiles of non-members (buttons, targets,
chorus, pots, TNT, crystals, pearls, potions, animals, frames), animals,
frames and stands used by non-members, frames and animals hit by blasts
are all kept. Trust lookups no longer allocate.
Chat pings (jaszka's ask): naming an online player in chat, or /msg to
them, plays the experience orb sound to them alone (3 s apart, never the
sender), /pingsound on|off.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* SMP 0.35.0: rustfmt; the chat queue's module has plain comments
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* SMP 0.35.0: the dispenser hook binds its facing as a parameter
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* SMP 0.35.0: no attribute on the impact helper
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* SMP 0.35.0: README for the claims' new guards and chat pings
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* SMP: log each chat ping on the server
One info line per ping (at most one each 3 s per player), so bots and ops can see pings work.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* SMP: test on eaa7da4, the Horizon the minimap uses
Native mods on the newest hooks (359) must share one Horizon for the together check; r9.1 (52882c1) descends from eaa7da4 with the same hooks.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* SMP: end crystals always guarded in claims; proof SMP_PROOF=claims
A snowball or a punch from someone not trusted no longer sets off a crystal in a claim, even in worlds whose config.json lists protected entities from before. proof.py's claims mode runs two bots on a dedicated server: blocks and fire against the border, dispensers' water and arrows, a crystal, a pearl, TNT by animals and a frame, shears, and the chat pings.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* SMP README: end crystals always guarded
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---------
Co-authored-by: Horizon agent <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
Registry v2 backfill (docs/design/registry-v2.md): categories and tags for
each entry, descriptions extended where they were short or unformatted, and
every icon stored in icons/<id>.png (creators' own icons mirrored, the
missing ones drawn). No owners, versions or keys change.
Co-authored-by: Horizon agent <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
Registry v2 backfill (docs/design/registry-v2.md): categories and tags for
each entry, descriptions extended where they were short or unformatted, and
every icon stored in icons/<id>.png (creators' own icons mirrored, the
missing ones drawn). No owners, versions or keys change.
Co-authored-by: Horizon agent <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
Registry v2 backfill (docs/design/registry-v2.md): categories and tags for
each entry, descriptions extended where they were short or unformatted, and
every icon stored in icons/<id>.png (creators' own icons mirrored, the
missing ones drawn). No owners, versions or keys change.
Co-authored-by: Horizon agent <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
Registry v2 backfill (docs/design/registry-v2.md): categories and tags for
each entry, descriptions extended where they were short or unformatted, and
every icon stored in icons/<id>.png (creators' own icons mirrored, the
missing ones drawn). No owners, versions or keys change.
Co-authored-by: Horizon agent <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
Registry v2 backfill (docs/design/registry-v2.md): categories and tags for
each entry, descriptions extended where they were short or unformatted, and
every icon stored in icons/<id>.png (creators' own icons mirrored, the
missing ones drawn). No owners, versions or keys change.
Co-authored-by: Horizon agent <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
Registry v2 backfill (docs/design/registry-v2.md): categories and tags for
each entry, descriptions extended where they were short or unformatted, and
every icon stored in icons/<id>.png (creators' own icons mirrored, the
missing ones drawn). No owners, versions or keys change.
Co-authored-by: Horizon agent <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
Registry v2 backfill (docs/design/registry-v2.md): categories and tags for
each entry, descriptions extended where they were short or unformatted, and
every icon stored in icons/<id>.png (creators' own icons mirrored, the
missing ones drawn). No owners, versions or keys change.
Co-authored-by: Horizon agent <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
Registry v2 lists no repository-linked entries: each of these shader packs
becomes a pinned version of its newest GitHub release's .hshader (staged
as <sha256>.hshader), with the page from the repository's
horizon-registry.toml written into the entry, categories, tags and an icon.
Co-authored-by: Horizon agent <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
Registry v2 backfill (docs/design/registry-v2.md): categories and tags for
each entry, descriptions extended where they were short or unformatted, and
every icon stored in icons/<id>.png (creators' own icons mirrored, the
missing ones drawn). No owners, versions or keys change.
Co-authored-by: Horizon agent <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
* registry: mark Create for Horizon as an unofficial port
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* icons: scale customhud's icon to 64x64 (the registry now needs 64 to 1024 px)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---------
Co-authored-by: Horizon agent <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
latest_nightly() chose the newest nightly-source tag by comparing the ref
string, so two tags on the same date were ordered by their short SHA and it
could return an earlier build (2026-11-04-67dad0d over the newer
2026-11-04-3fb4c31, both on 2026-11-04). Pick the newest by the tag's date
and break a same-date tie by the tagged commit's own date.
cargo(action="build") named --bin horizon-ctl under -p horizon-client, but
horizon-ctl is a bin of horizon-client-lib (its path is the client's
src/bin), so the build failed with "no bin target named horizon-ctl in
horizon-client package" (only check worked). Build the ctl under its own
package: -p horizon-client-lib --bin horizon-ctl.
Closes#220Closes#222
Co-authored-by: makscoder <[email protected]>
Daybreak, a Horizon shader pack listed from the releases of
hildlabs/horizon-shaders, with its icon.
Co-authored-by: Claude Opus 5.5 <[email protected]>
* Add spider_man (native mod)
* spider_man: add owner_ids
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* spider_man: pin 0.2.0 by hash instead of following the repository's releases
A native mod's code runs unsandboxed and every version is read by a reviewer before it is listed (README). An entry with repo = … would take later releases with no review. The page fields come from the repository's horizon-registry.toml at v0.2.0.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---------
Co-authored-by: wyddy7 <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: Horizon agent <[email protected]>
The launcher only loads icons from the registry's GitHub Pages and the Modrinth and CurseForge CDNs, so the raw.githubusercontent.com link showed no icon.
Co-authored-by: umbx-dot <[email protected]>
Submitted by @tomasmendes01 through the form.
Submission: -p-AKjDZoFl_Kou4es3JCbFL84AL8_02MDTCf4ZsUoY
Co-authored-by: tomasmendes01 <[email protected]>
Submitted by @tomasmendes01 through the form.
Submission: T6p3r_WvUBM66p1RumW8TjWkXawwML_QUuN9_pda2LE
Co-authored-by: tomasmendes01 <[email protected]>
* Add dynamic_fps_for_rust 0.1.0
Submitted by @Lyvt-Dev through the form.
Submission: MAyCnE4TcnIo3B05CCph3VzW4RMBdFYO_0S76ynJA-M
Co-authored-by: Lyvt-Dev <[email protected]>
* dynamic_fps_for_rust: describe what 0.1.0 does
The page listed Dynamic FPS's toast pausing and battery HUD and toasts, which this build doesn't have. It now names the caps it sets, the JSON config file, and that it has no settings screen.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---------
Co-authored-by: Lyvt-Dev <[email protected]>
Co-authored-by: Horizon agent <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
* Add connected_textures 0.1.2
Submitted by @tariksabanuz through the form.
Submission: 8z1xdnIhXYT7sDm0v6CCif30RGP2lYOLB6q2V6C9ef8
Co-authored-by: tariksabanuz <[email protected]>
* connected_textures: icon from raw.githubusercontent.com (the blob page is HTML, not the image)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---------
Co-authored-by: tariksabanuz <[email protected]>
Co-authored-by: Horizon agent <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
* Add chat_animation 0.1.0
Submitted by @tariksabanuz through the form.
Submission: gypApON8d6DU7sdJ81St9xAxOONKxb_edS-LUEh95yQ
Co-authored-by: tariksabanuz <[email protected]>
* chat_animation: icon from raw.githubusercontent.com (the blob page is HTML, not the image)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---------
Co-authored-by: tariksabanuz <[email protected]>
Co-authored-by: Horizon agent <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
* Update horizon_physics 0.18.0
Submitted by @tariksabanuz through the form.
Submission: dUwtD3FcOST_rD7zK-b-0LW83RvCQatWATzx8eZplT0
Co-authored-by: tariksabanuz <[email protected]>
* horizon_physics: keep the hosted icon, and say it is a clean-room project not made by PhysicsMod's author
The new icon was a GitHub blob page (HTML) of a 250 KB animated preview; the entry's own icons/horizon_physics.png stays. The summary and description keep the 0.15.1 page's statement that it holds none of PhysicsMod's code or assets.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---------
Co-authored-by: tariksabanuz <[email protected]>
Co-authored-by: Horizon agent <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
* Update mod_menu 0.3.3
Submitted by @tariksabanuz through the form.
Submission: l0GzXMA1DQh20OewDGgMOQvMM_CnMnPSnV7Imjga354
Co-authored-by: tariksabanuz <[email protected]>
* mod_menu: icon from raw.githubusercontent.com (the blob page is HTML, not the image)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---------
Co-authored-by: tariksabanuz <[email protected]>
Co-authored-by: Horizon agent <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
- /rtp: rtp_max_distance 5000 -> 10000, rtp_cooldown_seconds 1800 -> 300
(defaults; the official config.json has no rtp_* keys, so they apply).
Same safety: no water, lava or void, chunks loaded with forceload.
- /report <player> <reason> for everyone: a reason is required, one report
per player every reports.cooldown_seconds (120). Appended to reports.log,
told at once to the level-3 operators on, logged in the server log; an
operator who joins later hears how many came in the last 24 hours.
/reports [page] lists them for operators. (No Kira route exists for
messages to Discord; Kira only takes the market/economy pages.)
- /ledger for level-3 operators: audit.log already records every coin
movement before it happens; /ledger [page], /ledger <player> [page] and
/ledger minted (coins made and destroyed per hour, last 6 h) read the
end of it (1 MB) when asked, nothing on the tick. Economy::adjust lines
now carry flow: minted|burned so the hourly count is exact.
- utc_minute and tail() moved to smp_store for both.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Filled by horizon's tools/registry_backfill_owner_ids.py (horizon#9688): every owner login resolved and
matched the IDs the submission form recorded; nothing was left alone.
Co-authored-by: Horizon agent <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
* Remove SMP daily coin cap on sales and payments
Co-Authored-By: Codex gpt-6.1-sol <[email protected]>
* Remove SMP daily per-item sale limit
Co-Authored-By: Codex gpt-6.1-sol <[email protected]>
* Allow immediate resale of SMP market purchases
Co-Authored-By: Codex gpt-6.1-sol <[email protected]>
* SMP 0.33.0: a 20% price floor carries what the daily caps did
With no daily sale caps, the market's moving price is what bounds a farm:
- min_factor 0.6 -> 0.2 (a config still on the old default gets 0.2 at load)
- an item's depth is at most 50 items a 1% (was up to 400), so the cheap
items farms make reach the floor within 10,000 sold; a family takes its
step from its cheapest member, so every member does
- tests: 10,000 of any item sold a minute at a time end at the floor and
bring under half their base value (diamond 21%, wheat 44%), and the price
comes back within a day; buying and selling straight back (no resale
delay) never earns, for every item traded both ways, 5 amounts, from a
fresh price, the floor and the cap (495 round trips)
- proof: 1,000 wheat sold over four minutes, 250 a minute, the price lower
after each sale
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* SMP proof: the cobblestone stack's comment for the new depth
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---------
Co-authored-by: Codex gpt-6.1-sol <[email protected]>
Co-authored-by: Ludovic Marie <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
* smp: /rtp (/wild) to a random safe spot 500-5000 blocks from the spawn, 30 min cooldown
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* smp: /rtp draws until enough points fall inside a close border
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* smp: /rtp undo as a struct; rustfmt
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* smp: /rtp proof (2 clients, flat world) and SMP_PROOF=rtp tick cost on a normal world; per-/rtp read cost in the log
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* smp: proof checks the /rtp landing with execute ... run say (block tags aside)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---------
Co-authored-by: Claude Opus 5.5 <[email protected]>
Submitted by @ImmortalWhisper through the form.
Submission: 765YnzbfBhAVyZAv1UoXeiUShV3tjRRGT3C-A3VjDIg
Co-authored-by: ImmortalWhisper <[email protected]>
Submitted by @tomasmendes01 through the form.
Submission: QMPtuLy0qMsJH6Y0KP2iDIvzdYTpPS0FOLtPdmcSYd8
Co-authored-by: tomasmendes01 <[email protected]>
Submitted by @tomasmendes01 through the form.
Submission: XSR34WRLB30OrdD_82S40jKedlhtfgeaXXKyxlVPyis
Co-authored-by: tomasmendes01 <[email protected]>
Submitted by @eltanschauung through the form.
Submission: kwCxRPKxqLPLNKKKt1Y3GT_vcpxGHQAPWgryPVRQq2s
Co-authored-by: eltanschauung <[email protected]>
* Add Visuality (visuality_horizon) 1.0.0, a native mod
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* visuality_horizon: 1.0.1 instead of 1.0.0 (reproducible stored package, lighter tick)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* visuality_horizon: 1.0.2 instead of 1.0.1 (bundle holds only .rs and .toml files)
---------
Co-authored-by: Claude Opus 5.5 <[email protected]>
* Add Held Item Info native mod listing
MIT source, pinned build and initial game validation are published in the linked repository.
Co-Authored-By: Codex <[email protected]>
* Pin Held Item Info 0.1.0 for per-version review
Co-Authored-By: Codex <[email protected]>
---------
Co-authored-by: Codex <[email protected]>
Co-authored-by: AltMugen <[email protected]>
Submitted by @repositorykreml1n through the form.
Submission: jEsjBlLxuH_fH0gi0d1ZaAgPL2A5TB4NH7laEwo_zpY
Co-authored-by: repositorykreml1n <[email protected]>
Preserve upstream defaults and existing settings. Include the supplied screenshot, settings regression checks, and the native tool pins and split control-target support needed to validate this renderer integration.
Co-Authored-By: Codex <[email protected]>
An operator of level 3 leaves the Tab list and world of every player below
level 3 (in any game mode), with no join or leave messages for them;
operators still see them. A subtitle stays on screen the whole time. Vanished
players aren't counted online, don't hold the night up, aren't announced
AFK, and can't be reached by name (/tpa, /trade, /coinflip, /playtime).
Kept in vanish.json. Needs horizon#7003 (native_hide_player).
Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: Ludovic Marie <[email protected]>
Operators of level 3 turn parts of the SMP off while the server runs,
by name or all at once (land protection only by name). A part off refuses
its commands and menu clicks and its timed work waits; nothing held is
lost. Kept in switches.json across restarts, logged and audited.
Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: Ludovic Marie <[email protected]>
The sidebar keeps the player's own block (name, balance, playtime, online)
and the address. /baltop still ranks the richest. board.top is ignored.
Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: Ludovic Marie <[email protected]>
* Update chatheads 0.1.1
Submitted by @Domanffe through the form.
Submission: m9iIfQyNTA6ee66EpcsIdlIFDTgx3mIakQro02chGVU
Co-authored-by: Domanffe <[email protected]>
* chatheads: fix the doubled icon URL and restore the name ChatHeads
The submission form pasted the icon URL twice and lowercased the name; the
in-game name is still ChatHeads.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---------
Co-authored-by: Domanffe <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
Add the author's approved project page, icon and verified Minisign signature. Request maintainer staging because the web form rejects the submission origin.
Co-authored-by: GPT-6.1 Sol <[email protected]>
* Add customhud (Beautiful Day Counter), a native mod
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* customhud: list version 1.6.0 explicitly instead of repo
Every version of a native mod is reviewed, so the entry names its file
and SHA-256 rather than following the repository's releases.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---------
Co-authored-by: Claude Opus 5.5 <[email protected]>
/spawn teleported to one fixed point, which on the anarchy server can sit in
a lava cast. After the tp it now runs vanilla's spreadplayers around the
spawn point with places.spawn_radius (default 250, like the live server's
respawn_radius), which picks a random column that is not fluid, fire or
magma and has solid ground, retrying until one is found. Warps, homes, /back
and /tpa are unchanged. Radius 0 keeps the exact point.
Refs #144
Co-authored-by: Claude Sonnet 5.5 <[email protected]>
Submitted by @VanishingTacos through the form.
Submission: MV28vLDz8HAq_j0ApAE1yIC4BXlLuoDRF8RWnRBpWkg
Co-authored-by: VanishingTacos <[email protected]>
Submitted by @repositorykreml1n through the form.
Submission: 9rPRCH2NULh3Iy5kRA1ctwN9shoKNDOc0jW7uTbaeNo
Co-authored-by: repositorykreml1n <[email protected]>
* Revert "Add crossversion 0.7.1 (#180)"
This reverts commit 7645804495: the listing
comes down while the mod's account handling is reviewed with its author.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* revoked: turn installed crossversion 0.7.1 copies off
Removing the entry stops new installs only; the revocation also turns
copies players already installed off, with the reason shown to them.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Keep the crossversion listing; the revocation alone takes 0.7.1 down
The registry refuses removing a listing ("take its files down in revoked.toml instead").
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---------
Co-authored-by: Claude Opus 5.5 <[email protected]>
* voicechat-server: proximity voice chat on Horizon's own server
A native server mod (voicechat_server 1.0.0): the server half for voice chat
clients that speak Simple Voice Chat 2.6.x's protocol, such as azetech's
Complex Voice Chat. The handshake rides Horizon's mod messages on voicechat:
channel names; voices go over UDP through the server, sealed per player with
AES-128-GCM, to the players nearby in the same dimension or in the speaker's
group. A player without a voice client is never sent anything, and the UDP
port opens only when the first voice client asks.
The relay is a bundle crate (horizon-mixins 0.6.0): every native mod now pins
horizon-mixins d9c83d7, since native.py builds them with one, and package
includes a bundle's crates.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* voicechat-server: replay-proof re-authentication; packages carry LICENSE
- A secret belongs to the first address that authenticates with it: an
Authenticate copied and sent from another address is refused however long
the client was quiet (the 5 s move rule is gone). Exact replays are dropped
too: the last 64 control packets' nonces per player, and a 64-wide window
on voice packets' sequence numbers.
- A client the server stops hearing for 10 keep-alives gets a fresh secret
over the game connection (Complex Voice Chat 2.1.0 reconnects on any
voicechat:secret), keeping its group; the old key then opens nothing. So
a NAT that rebinds recovers without a rejoin (2.1.0 never re-sends
Authenticate after its ack, so the old move rule never helped it).
- Secret requests: one answer a second a player (more requests meanwhile
get one answer), the snapshot replaces what still waited. Group and state
changes 2 a second (burst 10). At most 512 messages wait per player.
- Client pings aren't echoed (the server never pings; SVC's server doesn't
echo either), and the relay thread never spins on a socket error.
- The glue lists the players on a message only when the sender is new, not
on every voice chat message.
- native.py package puts native/<mod>/LICENSE into the .hnmod as
mixins/<id>/LICENSE (Horizon's bundle reader accepts LICENSE* there); the
CI check requires it. Every native mod's package now carries its licence.
Tests: a_replayed_handshake_after_a_silence_moves_nothing,
a_client_the_server_stops_hearing_gets_a_fresh_secret,
repeated_secret_requests_and_group_changes_stay_bounded.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---------
Co-authored-by: Claude Opus 5.5 <[email protected]>
rdbt's ask: /ah refused anything that wasn't a plain item. A listing now
carries the whole stack (enchantments, name, damage, lore, a shulker box's
or a bundle's contents, every component) as the game writes it in player
files (ItemStack.CODEC NBT, hex), through listing, purchase, auction win,
mail and returns, saved in economy.json in the same step as the money.
Given back with native_give_stack; what doesn't fit waits in the mail.
Taken only when it reads back equal; not market charts, nor stacks over
32 KiB of data. Creative players are still refused. Listings and mail from
0.30 (no `stack`) load unchanged and give plain items as before.
Co-authored-by: Claude Opus 5.5 <[email protected]>
* Add Motion Blur (native mod, levzzz5154/horizon-motion-blur)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* motion_blur: the registry's current entry format
source and a [[versions]] entry instead of repo; the file is in the
staging release as <sha256>.hnmod, as the submission form puts it.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---------
Co-authored-by: Claude Opus 5.5 <[email protected]>
rdbt: the zone around 0 0 should apply in the Nether and the End too.
Claims there are refused and dropped at start in every dimension.
Co-authored-by: Claude Opus 5.5 <[email protected]>
Operators asked for the land near spawn to be free for all: no one may
claim a chunk that touches the zone, and claims already there are dropped
at start, each logged. Off by default (0).
Co-authored-by: Claude Opus 5.5 <[email protected]>
* smp: simplify the economy, drop the tax code
No more VAT on auction sales, weekly land and wealth taxes, /taxes and
/eco taxes, tax on market trades or teleport fees. The Treasury stays
(fees and house edges in, operators' grants out) with /treasury, now in
its own small module. Old taxes/tax_percent/fees config keys are ignored
and owed land tax is forgiven.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* smp: remove the Treasury, the bank, jobs and futures, and every fee
Operators make money with /eco give <player> <amount> <reason> (everyone
reads it) and take it with /eco take. The auction listing fee and the
coinflip/lottery fee are gone. The casino's pot gets its float once, made
for it, then keeps the house edge.
A world from before this gets its bank savings and open futures margins
back at the first start; the Treasury, insurance fund, contracts and land
tax owed are dropped.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* smp: keep the casino's float mark in economy.json
The "pot got its float" flag lived in casino.json while the money went to
economy.json, so a lost or unreadable casino.json, or a crash between the
two saves, made up to 20,000 again on the next start. The mark now sits in
the economy's ext, written in the same file as the pot.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---------
Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: Ludovic Marie <[email protected]>
/invsee on yourself stays refused (it would move stacks into the same
inventory); your own ender chest is a second container, so /endersee works.
Asked by bunchy7s (operator) on Discord.
Co-authored-by: Claude Opus 5.5 <[email protected]>
A book from before 0.29 quotes its history in the old mid of buy and sell
(diamond 250); the one price is 200. Scaled once at load (the book now
records its bases), so charts, 1 h/24 h moves, the news and the futures'
TWAP see no cliff; open futures positions get the same ratio on their
entry, so none gains or loses by it. Each minute's band opens at the
loaded price rather than at the base.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Ludovic: the market's buy and sell prices didn't make sense (diamond bought
for 400 and sold for 100, two numbers everywhere). Each item now has one
price, the geometric mean of the old pair (diamond 200, iron 15, wheat 2),
shown in /worth, /market, /shop, the chart maps and market.json (`price`;
`buy`/`sell` repeat it on the sides the market trades).
- A trade of N is priced along the curve it moves (each unit moves the log
price by 1%/depth): buying N and selling them back returns exactly what
was paid less the tax, for 1, 64 or past the band. Rounding goes against
the trader (up when buying, down when selling).
- Prices move as trades happen; all trades together move an item at most
5% a minute: past that a purchase is cut short and a sale keeps the
rest (flat pricing at the edge would let slow buying plus a flat dump
earn). At the 0.6/1.6 factor bounds the rest goes at the bound.
- Items linked by recipes share one moving price, a block moving it as its
9 ingots do; the vanilla-recipe test checks every item at the worst
drift too, and finds a block sold for its ingots once unlinked.
- The tax is its own receipt line ("Tax 2%: -12 coins. You get 583
coins."). Daily sell limits unchanged.
- A config with two prices gets one at load, logged ("one price now").
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A player whose net casino winnings today reach casino.daily_win_cap
(10,000, same as the loss cap) is refused new bets until 00:00 UTC, with
a message saying why. The round that crosses the cap is paid in full; a
blackjack double inside a hand already dealt is still allowed.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Selling up to the cap on alts and paying it all to a main bypassed the daily sell
limit (reported by pointofpressure). A /pay now checks the receiver's remaining
daily_sell_coins and is refused past it; a payment made counts toward it. Trades
and auction sales are unaffected.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
/casino opens a lobby menu; each game is a chest menu a stock client plays,
animated at most 5 pictures a second per open menu and only while a round
moves, with sounds, titles, the action bar, a boss bar for crash, fireworks
and a line for everyone on a jackpot.
- European roulette (2.70% edge), slots with a published paytable (94.2%
paid back), one shared crash round (96%), blackjack S17 3:2 (~1% edge).
- Draws by the server (ChaCha20 keyed from the system) before the
animation. Bet limits, a daily loss cap a player, a cooldown.
- Bets are held, then settled once through settle_pool into the casino's
pot (capped, never minted); hourly the pot above its float goes to the
Treasury (casino_profit), below it the Treasury tops it up (casino_float).
- Closing the menu or leaving never loses a round.
- casino.json: the day's ledger, wins, totals. proof_casino.py plays every
game on a real server with two clients.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Four contracts a day from farm, mine and mob produce; a delivery of 64 plain items
pays the market's sell price +30%, never over 90% of its ask (rechecked at
delivery), from the Treasury. 8 deliveries a contract, 2 a player a day, at most
10% of the Treasury a day, survival/adventure only.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
/eco stats: the supply and where it sits, what the server made and destroyed
today (new per-kind flows in economy.json), the day's taxes, Gini and top-10
share. At 00:00 UTC everyone reads the day before; 60 daily snapshots kept in
ext.report. web/economy.json once a minute, written off the tick thread, with
every Treasury movement and the tax code, for /hub.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Deposits wait in the `bank` pool; interest 0.1% a day on up to 10,000 coins,
paid at 00:00 UTC from the Treasury on the day's lowest amount (no
deposit-before-midnight trick), at most 5% of the Treasury a night, pro rata.
At most 25,000 saved. The wealth tax counts savings. No loans.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Teleports cost a fee (home 5, warp 10, back 10, tpa 10, spawn free), checked when
the command runs and paid to the Treasury when the teleport happens; one called off
costs nothing and keeps /back and the cooldown. The daily reward waits for 10
minutes of play that day (moving or commands), so alts that only log in get
nothing. Proof: fees and delay off to keep its sums; config_keys gets `auction`.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Players sell to players: fixed-price listings or timed auctions, browsed
in a chest menu by category (or a search), cheapest a unit first.
- Listing fee 1% (min 1 coin) and 5% VAT on each sale go to the Treasury.
- Listed items leave the inventory at once; unsold ones, auction wins and
what didn't fit come back by mail (/ah claim, or the menu's mail page).
- A purchase is one step under the SMP's lock: the listing leaves first,
so of two buyers at once the second finds it gone.
- Bids are held in the `auction` pool; the outbid get theirs back at once;
a bid in the last 60 s moves the end back to 60 s; offline sellers are
paid and get a note when they're back.
- Listings, bids, mail and notes are written in economy.json with the
money (ext.auction): a crash can't split items from coins.
- Plain items only until native_give_stack is stamped.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Every tax, fee and house edge now goes into a Treasury pool kept in
economy.json with the balances; operators pay only from it, with a reason
everyone sees (/treasury pay, logged as `grant`). /eco give, /eco set and
/eco give * are gone: nobody can make money, operators included. /eco take
moves a cheat's gains into the Treasury.
- smp_economy: system pools (`pools`: treasury, insurance, casino...),
to_pool / from_pool / pool_move / settle_pool, each one audit line; the
Treasury's income and spending by kind (today, all time) and its last 50
movements; `ext` for other parts' state written in the same step as the
money. award()'s fee goes to the Treasury.
- smp_tax: the tax code (VAT 5% for the auction house, land tax 5 coins a
week per chunk past 4, wealth tax 1/2/3% above 50k/250k/1M a week),
collected on Monday 00:00 UTC (an O(1) check each second), unpaid land tax
owed and blocking new claims; /treasury, /treasury log, /eco taxes,
/eco taxes pay.
- proof: funds players from a seeded Treasury instead of /eco give, and
checks /treasury, /treasury log, /eco taxes and the refusals.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Review fix by Ludovic's AI agent (Claude): the nose guns and beams blow up
blocks when blasting is on (off by default), and the ship is kept in the
world's folder (astral_cruiser/ship.json).
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Submitted by @repositorykreml1n through the form.
Submission: aXw6Cm5ItBnfJZ5XYEO0w5xfcjfLs6I5Vvv5h9vqr6M
Co-authored-by: repositorykreml1n <[email protected]>
Submitted by @repositorykreml1n through the form.
Submission: CCBrVRl_Te6V2LQUa8oSqf6mTpFOgWk62yydwskMFw4
Co-authored-by: repositorykreml1n <[email protected]>
"Settings → Game → Native mods (experimental)" no longer exists. The launcher builds
native mods from the Mods page (Build on the native build row); the game lists and
toggles them under Options → Mods. Prose only: no sha256, file or version changes.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
rdbt (Team moderator) reported /nick abuse on the official server. Nicknames now:
- show as ~name in chat, the Tab list and the sidebar;
- are compared case-insensitively, with _ dropped and look-alikes folded (0/o, 1/i/l, 3/e...);
- are refused when equal to, or containing, a known player's name (economy accounts, usercache.json), an
operator's, a Team member's (nicks.protected) or another player's nickname, or when they read as a reserved
word (server, console, admin, mod, owner, staff, op, horizon, kira, notch, mojang, herobrine...);
- need nicks.min_playtime_minutes (60) of play first, operators excepted; the chat filter and cooldown stay;
- that break these rules are taken off at start, each logged.
/pay, /tpa, /trade, /playtime, /tpaccept, /tpdeny and /eco take a nickname where they take a player's name;
/nick alone says how to take it off. The proof covers each rule end to end.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Title "Horizon SMP": the player's name (their nickname if set), balance,
playtime and the players online; then the three richest; then the
server's address (board.footer, play.playhorizon.dev). The ranking is still
built once for everyone, on a balance change or every refresh_seconds; the
players' own lines are looked at on the same refresh_seconds and sent only
where they changed (and to newcomers). 0.13's untouched defaults (Richest
players, top 10) move to the new ones. Feedback from rdbt (Team moderator).
Co-Authored-By: Claude Opus 5.5 <[email protected]>
/nick <name> and /nick off for players, /nick <player> <name|off> and
/realname <nick> for operators. The nickname shows in chat and the Tab list
(horizon API 62: native_set_nickname), the hover keeps the real name, and
the log, the anticheat and Discord keep the real one. Rules: 3-16 letters,
digits or _; never a known player's name, an operator's or another
player's nickname; through the chat filter (native_text_allowed); a
10-minute cooldown. Saved in world/horizon-smp/nicks.json.
Also: the redundant 'eco give * <amount>' literal is gone (the engine left
it out: '*' isn't a command word; <player:word> takes it).
Co-Authored-By: Claude Opus 5.5 <[email protected]>
MOD-POLICY gets the licence rule reviewers already follow: a new project or
a new version needs source under a permissive licence (MIT, MIT-0, BSD,
0BSD, Apache-2.0, ISC, zlib, Unlicense, CC0) or a written grant to the
Horizon reviewers. classic_zoom, distant_horizons, fly_speed and serverify,
listed before, stay as they are until their next version.
The README no longer promises owner updates without a review: every version
of a native mod runs with the player's account permissions, so a reviewer
reads it first.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The description started with the form's paste instructions; the version
was "panorama-1.0.0" (the pack's own version is 1.0.0); the launcher reads
icons from icons/<id>.png.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The entry's icon URL pointed at the repository's old name; the launcher
reads icons from icons/<id>.png.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
- /shop: the market as a 6-row chest menu: categories (config.json `shop`), a click buys one, a shift-click 64,
a click on a stack of yours sells it, "Sell all"; balance, today's limit and help in the bottom row. Through the
market's own rules; items move by the console's clear/give, measured before and after.
- Market: buy always dearer than sell (else the sale closes), no recipe chain makes a sold item for less than it
sells (smp_recipes, Bellman-Ford over the recipes; the tests walk every vanilla recipe when the data is there),
daily limits per player (2,000 coins, 640 of each item, market.json), checked arithmetic, item ids validated.
- 56 default prices in 7 categories; a config still holding the 18 old defaults gets the new ones.
- /money give|take|set (= /eco), /eco give * <amount> for everyone on; recipients are told; all logged.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A new presence module, looked at once a second: a player's first join is
announced and they read the welcome and the rules; each player gets a
daily reward (logged as daily_reward); a player who doesn't move, turn
or run a command for afk_minutes, or types /afk, leaves the sleep count
(native_sleep_ignored) until they move; and a player runs at most
spam_commands SMP commands in spam_seconds. All in config.json's
presence section.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
/back returns to where the player died or where their last teleport took
them from, with the same warmup and cooldown. /playtime reads the time
played that places already counts. /claim show draws the chunk's border
with dust particles for 10 s, to that player only, coloured by whose
land it is.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The sidebar lists the top 10 balances and the player's own rank and
balance; it is built again when a balance changed (at most every 5 s) or
every minute, and sent only to the players whose lines changed. /sidebar
off hides it, kept in board.json. The Tab list shows the server's name,
its TPS and the players on, every 5 s. An idle tick now costs a counter:
the SMP's work runs once a second, or each tick only while a teleport
warms up, a trade is open or a command's changes wait to be written.
On hooks API 43 (native_sidebar, native_tab_list, native_tick_stats). 0.9.0.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The owner retires it: 0.1.1 needs an old launcher inventory feed and the game's own Mods screen now does the same job.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
On Horizon's API 22 hook points: a fluid or fire never spreads into a
claim from land of another owner (or of a player they don't trust), a
piston never pushes or pulls blocks into one, explosions spare claimed
blocks whoever lit them, buckets are guarded where they fill or empty, and
the claim's frames, armor stands, paintings, vehicles and animals
(`claims.protected_entities`) take no blows from untrusted players. The
spread and piston hooks read the open claims without allocating and never
wait on the SMP's lock. The proof adds a world_guard step on the dedicated
server, with controls outside the claim; the claims step no longer fails
when grass spreads onto its dirt. 0.8.0.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A player claims the chunk they stand in; only they, the players they
trust and operators break or right click blocks there
(native_destroy_block, native_right_click_block), told on the action
bar (native_action_bar, API 16). Chunks a player may hold grow with
the time played, counted by places. claims.json, written atomically.
Proved on a dedicated server: a lever, a dirt block and a placement
refused to Steve in Alex's chunk, then allowed once trusted.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
#3996's block entities took API 15 on main: horizon#4610's hooks are 16.
say() polls for the command's answer instead of a fixed 1.5 s, which a
busy machine outran.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Teleports wait a warmup that a move or a hit calls off, then run vanilla's
tp as the server (native_run_command, API 15), so they cross levels.
Homes grow with the time played here, counted by the mod. places.json
holds the spawn, warps, homes and time played, written atomically.
Proved on a dedicated server with two clients: home from the Nether,
called off by a move and by damage, /tpa, warps, operators only.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A sync_data on every server tick, even with nothing appended, cost about
2.8 ms of MSPT with 55 bots on the Mac mini.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The server buys and sells vanilla items at config.json's market prices
(a starting list the owner edits): plain items only, players in
survival or adventure mode only. Items move first, then money, both in
the audit log; a sale the log refuses gives the items back, a purchase
checks money and room first. Needs hook points API 9 (the acting
player's items). config.json is written again when a version adds keys.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The official server's SMP, opt-in: not listed in the registry, built only
into the official server's engine. Balances by UUID in
world/horizon-smp/economy.json (written atomically, at most once a tick),
an audit line per change written before it, config.json with defaults.
Hooks only Horizon's hook points (API 8: server commands and players).
Co-Authored-By: Claude Opus 5.5 <[email protected]>
0.3.0 is the WebAssembly mod rewritten as a mixin bundle, so the entry
turns native-mod once (docs/native-mods.md). Its two .hmod versions stay
as they are. The bundle itself is not in staging yet.
The entry points at raw.githubusercontent.com, which the launcher refuses: it
fetches project images only from Modrinth's and CurseForge's CDNs and this
registry's Pages (launcher/src/browser/images.rs, HOSTS). So Blockscope has
shown no icon in the launcher's Mods page while every registry icon does.
icons/blockscope.png is the mod's own 256x256 RGBA icon, the size the other
icons here use, and the entry now names the Pages URL the publish workflow
serves it from (publish.yml copies icons/ to the site root).
Checked: https://horizon-rust.github.io/horizon-mods/icons/biomecompass.png
answers 200 image/png, while icons/blockscope.png and icons/zoom.png (a mod
with no file here) answer 404, so the URL is live only once the file is.
Co-Authored-By: Hermes Agent (Nous Research) <[email protected]>
The entries pointed at raw.githubusercontent.com, which playhorizon.dev's
img-src and the launcher don't load. The same 256x256 PNGs now live in
icons/, as coords_hud's does.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The WebAssembly SDK's example mod, ported to a horizon-mixins bundle in
native/coords-hud: the position and facing box in the top left, /where and
/coords, and a Shown setting that /coords now keeps. The time of day line is
gone: the hook points don't give the game's clock yet. Tested on Nightly
4baa571, alone and with the five other native mods; the proof drives the
built game.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The four official entries switch from `mod` to `native-mod`, each with a
2.0.0 `.hnmod` built from native/<name>/ and pinned to Nightly 6f8c7a0
(nightly-source/2026-10-28-6f8c7a0), the first Nightly with the native
hook points v1 and the on/off from Options > Mods. Their 1.0.0 `.hmod`
stays published; the index lists only 2.0.0, and the launcher keeps a
player's installed `.hmod` until a native build has the mod. Settings
carry over: the same files and keys.
Recipes stays on 8f91683 (hook points v2) until a Nightly ships them.
native.py now builds mods pinned to different commits on the pin of the
mods that need the most hook points, as the launcher does, so `together`
checks the whole set without --horizon.
Co-authored-by: Claude Opus 5.5 <[email protected]>
* Recipes as a native mod (native/recipes, hooks 2)
Horizon's official Recipes viewer, ported from the WebAssembly mod to a
horizon-mixins bundle on the native hook points, API 2: the item panel
beside container screens, search (#tag, @namespace), recipes and uses per
station, + to fill the crafting grid, and "Click gives items" in creative.
It keeps the WebAssembly mod's setting file (give) and keys
(key.recipes.recipe, key.recipes.uses), and rests when turned off in
Options > Mods.
The viewer is runtime.rs (also the crate's library, with its tests); the
game's tables and panel events go through glue.rs, a second module.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Native mods: pin all five to Horizon 8f91683 (hook points v2)
Zoom, FPS Counter, Keystrokes, Minimap and Recipes all name the commit
they were tested on: main after horizon-rust/horizon#3435, which brought
hook points v2 (the item panel and recipe tables). One commit for all of
them, so the `together` job builds the set without --horizon. The four
older mods still need only hooks 1.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---------
Co-authored-by: Claude Opus 5.5 <[email protected]>
Each official mod checks `native_on` (horizon-rust/horizon#3346) first in its
HUD, minimap, key, wheel and zoom hooks, so turning it off in Options > Mods
takes effect at once; the launcher's next build leaves it out. Pinned to
Horizon 01d0f45, which has the helper.
Co-authored-by: Claude Opus 5.5 <[email protected]>
Horizon's own native mods (zoom, fps-overlay, keystrokes, minimap) were one
repo each; they now live here under native/<name>/ with their history.
native/tools/native.py builds, packages and proves any of them, alone or
together; native.yml checks each changed folder (fmt, clippy, tests, the
.hnmod, the game with it applied), every mod together, and every Monday all
of them on the newest Nightly. Pinned to Horizon 1149c92 (hook points v1).
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Port of Horizon's official WebAssembly mod to a horizon-mixins bundle,
keeping its settings files. Unit tests, a .hnmod packager, a native
check against Horizon by commit and an offscreen proof (tools/).
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Port of Horizon's official WebAssembly mod to a horizon-mixins bundle,
keeping its settings files. Unit tests, a .hnmod packager, a native
check against Horizon by commit and an offscreen proof (tools/).
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Port of Horizon's official WebAssembly mod to a horizon-mixins bundle,
keeping its settings files. Unit tests, a .hnmod packager, a native
check against Horizon by commit and an offscreen proof (tools/).
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Port of Horizon's official WebAssembly mod to a horizon-mixins bundle,
keeping its settings files. Unit tests, a .hnmod packager, a native
check against Horizon by commit and an offscreen proof (tools/).
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Third-party projects are made and owned by their authors, not by the
Horizon project; listing is not endorsement. Authors confirm their right to
publish (ports included), and rights holders get a takedown form.
Co-authored-by: Claude Opus 5.5 <[email protected]>
The repositories moved from ludovic111 to horizon-rust. GitHub redirects the
repository URLs, but not GitHub Pages: the index now lives at
https://horizon-rust.github.io/horizon-mods/. The build passes --site so icon
URLs use the new address without waiting for a new cargo-horizon-mod.
Co-authored-by: Claude Opus 5.5 <[email protected]>
Ludovic asked for his top three contributors by merged pull requests: kacpherek, rdbtCVS and Online5277.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Ludovic's decision (2026-10-27): the three trusted contributors approve submissions; /.github/ and revoked.toml
stay his.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
🤖 Agent: merging (as #4–#7, the official mods). The registry check passes with the checker moved to main (0c7f6b7f0), the file is byte-identical to #2446's build, and the mod's e2e passes in all five modes on main.
publish.yml runs every hour as well as on merges. It sums GitHub's
download_count of each version's release asset into the project's
`downloads` field of index.json, which the launcher and playhorizon.dev/mods
show.
publish and check keep `files/` in the Actions cache, so CI doesn't fetch
every release asset again on each run (each fetch counts as a download).
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The FPS counter and Keystrokes extras as mods, built from Horizon's main
at 5bcc87983 (mods/official/fps-overlay, mods/official/keystrokes).
Co-Authored-By: Claude Opus 5.5 <[email protected]>
- mods/coords_hud.toml: the SDK's example mod, MIT, built from
crates/horizon-mod-sdk/examples/coords-hud in Horizon.
- check.yml: a pull request's changes, each new file's checks and a trial
run in the sandbox, the index it would publish (cargo horizon-mod from
Horizon at HORIZON_REV).
- publish.yml: on main, new versions become releases, index.json and the
icons go to GitHub Pages.
- cleanup.yml: staging copies nobody needs, weekly.
- CODEOWNERS, the report form, the pull request template, revoked.toml.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-25 15:01:10 +01:00
378 changed files with 39681 additions and 9 deletions
**Updates** come the same way: the form adds a version to your entry. Only an entry's `owners` publish its updates
without a reviewer's extra look. A published file never changes: publish a new version.
**Updates** come the same way: the form adds a version to your entry, and a reviewer reads it before it is
published. Only an entry's `owners` can add versions, and every version of a native mod is reviewed, owner or
not: its code runs with the player's account permissions. A published file never changes: publish a new version.
**Signing** is optional and recommended: put your [minisign](https://jedisct1.github.io/minisign/) public key in your
entry, and every later version must be signed with it, so nobody else can publish an update in your name.
## Report
Something wrong with a project? [Report it](../../issues/new?template=report.yml). A project that does harm is taken
Something wrong with a project? [Report it](../../issues/new?template=report.yml). Your work published without your
permission? [Ask for a takedown](../../issues/new?template=takedown.yml) ([mod policy](MOD-POLICY.md)). A project that does harm is taken
down in [`revoked.toml`](revoked.toml): the launcher then refuses it and turns installed copies off, telling players
why.
@@ -50,11 +66,33 @@ why.
| `.github/workflows/check.yml` | A pull request's checks |
| `.github/workflows/publish.yml` | On merge: releases, then `index.json` on Pages |
| `.github/workflows/cleanup.yml` | Weekly: staging files nobody needs any more |
| `.github/workflows/native-compat.yml` | Native mods on the newest Nightly, as the launcher builds them: a pull request's new version applied and compiled with the most downloaded native mods, its module names against every mod's; daily, every mod's newest version, the ones that don't apply marked `broken_on` in the index (`scripts/native_compat.py`) |
| `.github/workflows/native.yml` | Horizon's native mods: each changed one's tests, `.hnmod` and game check, all of them together, and weekly on the newest Nightly |
| `native/<name>/` | Horizon's own native mods (Zoom, FPS Counter, Keystrokes, Minimap, Recipes, Coordinates HUD): the source of their `.hnmod` files |
| `native/tools/` | Shared by them: apply on Horizon, check, build, package, prove (`native/tools/native.py`) |
| `scripts/` | What the workflows share |
The format of the entries and of `index.json` is
[docs/api/mod-index.md](https://github.com/ludovic111/horizon/blob/main/docs/api/mod-index.md) in Horizon's repository;
[docs/api/mod-index.md](https://github.com/horizon-rust/horizon/blob/main/docs/api/mod-index.md) in Horizon's repository;
the checks are `cargo horizon-mod check` and `cargo horizon-mod registry`, from Horizon at the commit in the
repository variable `HORIZON_REV` (else `main`).
The index: `https://ludovic111.github.io/horizon-mods/index.json`.
The index: `https://horizon-rust.github.io/horizon-mods/index.json`.
## Horizon's native mods
`native/<name>/` holds the source of Horizon's official mods, as
[horizon-mixins](https://github.com/horizon-rust/horizon-mixins) bundles on Horizon's native hook points
([docs/native-mods.md](https://github.com/horizon-rust/horizon/blob/main/docs/native-mods.md)). Each folder keeps the
history of the repository it came from. A mod builds on any Horizon whose hook points are at least the version its
`compatibility.json` names; `horizon_revision` is the commit it was last tested on. `smp` and `voicechat-server`
are server mods, built into the official server's engine (see their READMEs).
```sh
python3 native/tools/native.py check zoom # apply on the tested Horizon and cargo check the game
python3 native/tools/native.py check all # every native mod together
python3 native/tools/native.py package all # native/target/<id>-<version>.hnmod, for a registry entry
Loaded 100 of 378 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.