The official Zoom mod (mods/official/zoom) does what the extra did. The extra's zoom, its key and wheel hooks and its Extras rows go; the camera keeps a mod's zoom (render.set-zoom). A player who had zoom on gets the mod installed and turned on at the first start, with the starting zoom, smooth zoom and slower turning carried into its storage and a changed key into horizon-mods.txt, and one chat line. horizon-extras.txt keeps the old keys. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
8.8 KiB
Horizon extras
Optional conveniences built into the client: fullbright, dynamic lights, a minimap, auto-reconnect, Mouse Tweaks-style inventory controls and inventory sorting. Every one is off by default: a fresh install looks and behaves exactly like vanilla 26.3, and turning an extra off again restores vanilla's behaviour completely.
Where they live
| Part | Code |
|---|---|
| Settings, parsing and saving | crates/horizon-client/src/extras.rs |
| FPS and click counters (for mods) | extras.rs (pure logic, unit tested) |
| Dynamic lights: item glow, nearest sources | crates/horizon-client/src/dynamic_light.rs (unit tested), game/dynamic_lights.rs, terrain.wgsl and entity.wgsl (dynamic_block_light) |
| HUD drawing (minimap frame, corner stacking) | crates/horizon-client/src/extras_hud.rs |
| Minimap colours, tiles and image | crates/horizon-client/src/minimap.rs |
| Reconnect policy and backoff | crates/horizon-client/src/reconnect.rs |
| Game glue (input hooks, per-frame update) | crates/horizon-client/src/game/extras.rs |
| Mouse Tweaks-style controls, sort buttons | crates/horizon-client/src/game/tweaks.rs |
| Sort order and its clicks | crates/horizon-client/src/inv_sort.rs (pure, unit tested) |
| The settings page | options_ui.rs (Page::Extras): Options → Horizon Settings... → Extras... |
The settings are grouped by extra, under a header each, two buttons to a row as
vanilla's options lists are, and each says what it does in its tooltip. An
extra's own settings (its key, corner, size...) are greyed out while its switch
is off (Item::parent).
game.rs only gets one-line hooks (key, wheel, mouse, frame, HUD), so the
extras stay out of the way of other input and options work.
Options storage
horizon-extras.txt beside options.txt, in the same key:value format as
horizon-graphics.txt. options.txt is untouched, so a vanilla client can share
the folder. Unknown or broken lines fall back to the defaults.
Extras' keys (the sort key) are Horizon settings stored in that file and bound on
the Extras page, not in vanilla's Key Binds screen: Horizon has no Horizon category
in Controls, and adding one would put a non-vanilla mapping into options.txt.
The extras
Fullbright (fullbright, default off)
- Displays blocks and entities with a fully bright lightmap, including in dark caves.
- Turning it off restores the normal lightmap using the current brightness, time of day and effects. The brightness slider keeps its normal range.
Dynamic lights (dynamicLights, default off)
- A light source held by a player or mob (main or off hand), dropped as an item, or an entity on fire lights the blocks, entities and hand around it, as dynamic-light mods do. Not in vanilla; the idea is ported, not a mod's code (issue #814).
- An item glows like its block's default state (
getLightEmission): torches 14, lanterns, glowstone, sea lanterns and jack o'lanterns 15, soul torches 10, a redstone torch 7; a lava bucket 15. An entity on fire gives 15. - Client-only, at render time: the light engine, meshes, saves and other players never see it.
Each frame the game picks the 16 sources nearest the camera (within 96 blocks,
dynamic_light::select); terrain.wgsl and entity.wgsl raise each vertex's block light to the source's level minus its distance in blocks when that is brighter, then light it through the lightmap as usual. The light doesn't stop at walls. - Off: nothing is gathered and the shaders' loop runs zero times (the count is 0), so it costs nothing measurable (numbers in the pull request, #814).
Moved to the mod browser
The FPS counter, Keystrokes and Zoom are official mods now (mods/official/, mods.md),
with the same look and options. On the first start after the update, a player who had one on gets the mod installed
from Horizon's registry and turned on, with their corner and options carried over (Zoom's key too, into
horizon-mods.txt, when it wasn't Z), and reads one line in the chat ("Zoom moved to the mod browser: installed for
you"). The install is checked like the launcher's (size,
SHA-256, signature, manifest); if it fails (offline), the next start tries again. horizon-extras.txt keeps the old
keys and lists what was done in movedToMods. Code: crates/horizon-client/src/moved_extras.rs,
game/moved_extras.rs.
Minimap (minimap, default off)
- A corner map (top right by default), square or round, small/medium/large, zoom 0.5 to 4 blocks per pixel, rotating with the player or north up, with the player arrow (vanilla's map decoration sprite).
- Colours are vanilla's
MapColorper block, as map items use, with the map item's height shading and water-depth dithering. - Underground, in the Nether and under any roof, it maps the floor around the player's height instead of the top block, so caves read sensibly.
- Cost: one cached 16x16 tile per loaded chunk (packed map colour and height). Tiles are filled nearest first and refreshed when blocks change, within a time budget of 0.3 ms a frame; composing the 128x128 image is a few thousand lookups, done only when the view moved or a tile changed, and uploaded into a dedicated atlas slot. With the minimap off nothing runs.
Auto-reconnect (autoReconnect, default off)
- On the "Connection lost" screen after a multiplayer connection drops, a countdown "Reconnecting in N s" with a Cancel button, then a new connection to the same address.
- Backoff 5, 10, 20, 40, 60 s; at most 5 attempts, then it stops. The count only resets after staying connected for a minute, so a server that drops players at once never causes an endless loop.
- Never after a kick, a ban, a whitelist or version refusal, a duplicate login, an online-mode refusal (no account signed in), or a session refusal from the account's login (invalid session, banned from playing online, multiplayer disabled, the server failing to verify the username). Unreachable session servers, on either side, are retried with the same backoff.
- Online-mode servers: the retry joins with the account the game signed in
with, held in memory for the whole run (
auth::current()); nothing is written to disk.
Mouse Tweaks controls (mouseTweaks, default off; mouseTweaksWheel, default on)
In the player inventory and chest-like containers (chests, barrels, ender chests, shulker boxes, hoppers, dispensers), in singleplayer and on servers:
- Right-drag holding a stack: one item goes into each slot entered, at once (slots holding another item, or full, are skipped).
- Left-drag holding a stack: each slot entered that holds the same item is gathered into the hand, when it all fits. This takes over only while vanilla's drag covers one slot, so a left-drag across empty slots still splits the stack as vanilla does.
- Shift + left-drag: every slot entered is quick-moved (with a stack in hand, only the slots of its item).
- The wheel over a slot, with an empty hand (
mouseTweaksWheel): down moves one item to the other side (container and inventory, or hotbar and main inventory: to a stack of it with room, else the first empty slot, as quick-move picks), up brings one of the same item back.
Every action is ordinary slot clicks (ContainerClick on a server), so a
vanilla server sees nothing unusual. With the extra off, the hooks return at
once and the screens click exactly as vanilla's (tools/test_menu_click_parity.py
and the container screen tests are unchanged).
Sorting (sort, default off; sortKey, unbound)
- A small button right of the container's title (chests, barrels, ender chests, shulker boxes) and one right of the "Inventory" line (the main inventory; the hotbar is left alone). The key, when bound on the Extras page, sorts the part under the cursor (the container when over no slot).
- Partial stacks of one item merge, then the stacks go in creative tab order (the search tab's), then by name; full stacks before the partial one, empty slots last. It needs an empty hand.
- Done with ordinary left clicks planned by
inv_sort::plan, so a vanilla server accepts it; a unit test replays the planned clicks through the menu engine on random chests.
Shared rules
- All extras are hidden with F1 and drawn in the HUD layer: under screens, over the world, like vanilla's HUD. Extras in the top left corner give way to the debug screen (F3), which shows the FPS anyway.
- Corners stack: extras placed in the same corner stack downward (top corners) or upward (bottom corners) in the order minimap, then mods' panels. The top right corner starts below the status effect icons.
Perf budget
Off: a flag check per frame per extra (no allocations, no world access). On: the minimap stays under 0.3 ms of CPU per frame (tile budget) plus a 64 KiB texture upload when its image changes.