100 Commits
Author SHA1 Message Date
martipopsandClaude Opus 5.5 ecd3764d93 Settings shell: leaving search gives the keys back, and fixes from reviewing it
Once the search field had the focus it kept the keyboard, so Enter did nothing and letters filtered
the list with the ring on a row. Moving the focus away now ends typing.

A key that moves nothing shows no ring, a row greyed out while focused does nothing, the wheel stops
behind a resource error as `scroll_at` does, and a description too long for the strip ends in an
ellipsis, with room for one more line on Extras.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-06 19:50:14 -05:00
martipopsandClaude Opus 5.5 7f1eef46b2 Settings shell: a screen describes its rows, and Horizon Extras moves onto it
A screen now implements settings_shell::Screen, describing its pages, groups,
rows and values, and Shell does the drawing, clicks, scrolling, the controller's
focus and declared buttons, keys and each row's description. OptionsUi reaches
it through one accessor, so the wheel and a stick's scrolling can't part ways.

Horizon Extras is the first screen on it. Its settings do what they did and are
saved the same way. It gains the shell's look and search, and its descriptions
move from tooltips to the strip, which grows for them.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-06 19:21:17 -05:00
martipopsandClaude Opus 5.5 f8a7a59085 Controllers: Replay Studio's recordings and buttons take the focus
Its rows and buttons only painted, so a pad reached them through the crosshair alone. The D-pad now
walks the recordings to the buttons, the right stick scrolls them, and Done declares its button.

A notch is now one whole row, since nothing clips a row that's partly scrolled off, and the scroll
limit counts the rows that fit, so the last recording can be reached with the mouse too.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-06 18:39:17 -05:00
martipopsandClaude Opus 5.5 c752fee870 Controllers: Play in Background, rumble in splitscreen, the keyboard after a new renderer
Play in Background, off by default and per player, lets the pad keep driving the game while its
window has no focus, and a game the pad is playing doesn't pause on losing focus.

While several play, the router now plays each player's rumble on that player's pad. Rumble no
longer stops when the window loses focus: nothing asked for that, and it's useful to an AFK player.

Starting or leaving splitscreen builds a new renderer, whose atlas has none of what was drawn into
it at run time. Those two paths only forgot the skins, so the on-screen keyboard lost its letters
and rounded corners, and maps were exposed the same way. All renderer swaps now forget the same
things.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-06 17:37:00 -05:00
martipops 37b174ada3 Merge remote-tracking branch 'upstream/main' into fix/pad-read
# Conflicts:
#	crates/horizon-client/src/game.rs
2026-11-06 16:46:14 -05:00
martipopsandClaude Opus 5.5 b0286fb598 Controllers: the bumpers move the selected server
Its arrows are hit-tested inside the icon, where a pad's click on the row never
lands.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-06 10:10:52 -05:00
martipopsandClaude Opus 5.5 cf73e1d25f Merge main
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-06 10:05:53 -05:00
martipopsandClaude Opus 5.5 6e0b26dbc2 Controllers: fixes from reviewing this branch
- Take back the server list's move arrows as targets: they split Tab's stop on
  the list, and the D-pad still couldn't land on them.
- A right stick on Z takes over in every direction, not only its pulled end.
- A pad's toggle-sneak doesn't count as holding, or a rebound key's release could
  leave the player sneaking.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-06 07:22:43 -05:00
martipopsandClaude Opus 5.5 84efc873cf Input: one device letting go of sneak or sprint leaves the other's hold
Releasing Shift while R3 held sneak in hold mode dropped it for both, and so did
the other way round.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-06 06:59:30 -05:00
martipopsandClaude Opus 5.5 a4ffae3402 Controllers: reach the recipe search, suggestions, server arrows, Realms tabs and HUD editor
Each was painted by hand or hit-tested with no target, so a pad couldn't use it:
the recipe book's search box had no keyboard, a command's suggestions couldn't be
picked, a server couldn't be moved, Realms Configure's tabs had no bumpers, and
the HUD editor's footer ended its crosshair.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-06 06:14:06 -05:00
martipopsandClaude Opus 5.5 e41c28a92b Controllers: typing on signs and books, the death screen, and joining
- A book's page and signing title weren't fields, so a pad couldn't write one.
- A sign's keyboard closed on Enter after line 1, and nothing reopened it. Enter
  now keeps it open, and A opens it again.
- A keyboard open over chat stayed over the death screen and took every button.
- B answered the death confirm during the second it's meant to wait.
- A guest who joined with a pad got P1's Controllers off in a new profile, so
  that pad did nothing, on this join and every later one.
- Pad presses in another window could join a player.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-06 05:37:01 -05:00
martipopsandClaude Opus 5.5 1a6fba23c7 Controllers: what reading a real pad got wrong
- An idle pad's trigger rests at -1, which counted as moved past 0.5, so touching
  it took over from the pad in use.
- An analog trigger jumped to full at gilrs' 0.75, so a higher threshold did
  nothing.
- gilrs drops `~` from SDL rows, so sticks on the nine Linux rows with one ran
  backwards, the Switch 2 Pro among them.
- The 8BitDo Ultimate 2 without a row looked up when pushed down, with X and Y
  crossed.
- Rumble reached the pad from an unfocused window, adaptive triggers stayed on
  over books and signs, a stale lightbar stayed after splitscreen, and in_use
  outlived an unplugged pad.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-06 05:11:50 -05:00
martipopsandClaude Opus 5.5 88cddcec82 Tests: pass mob_to_nbt its UUID lookup in entity_nbt's tests too
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-06 03:55:48 -05:00
martipopsandClaude Opus 5.5 3aaa70563e Raids: pass mob_to_nbt its UUID lookup, so main compiles
#10304 gave mob_to_nbt a fifth argument after the raid observation's call to it
was written, and the two merged without a conflict.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-06 03:35:09 -05:00
martipopsandClaude Opus 5.5 b32520088e Controllers: read Bluetooth Xbox pads from their layout, on any firmware
SDL rows match a firmware version exactly, and gilrs' copy has no row for
045e:0b13 at 0x0520. The pad then falls back to gilrs' default mapping: its
right stick is on ABS_Z/ABS_RZ, which nothing read, its triggers on
ABS_GAS/ABS_BRAKE, which that mapping doesn't name, and X and Y stay crossed
because it lists C and Z.

Recognise that layout from what the pad reports, so a new firmware works
without a row.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-06 00:28:36 -05:00
martipopsandClaude Opus 5.5 2cce72df97 Merge upstream/main into controller/buttons-prompts-v2
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-05 15:56:51 -05:00
martipopsandClaude Opus 5.5 9dae50aefd Controllers: bindable actions, prompts over gameplay, and button art
Held mappings are named by an Action rather than read by key, per device, and more actions can be bound: hotbar
slots, fullscreen, toolbars, social and quick actions. Held drop repeats and throws the stack. Readers of the
movement keys see the left stick, and a bumper steps the hotbar through the wheel's gates. Prompts over gameplay
are pad-driven and keep what's behind them, the keyboard opens on every field, and focus follows its widget.
Buttons and the crosshair draw from Horizon's own art, one file per pad family, instead of text labels.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-05 15:37:30 -05:00
martipopsandClaude Opus 5.5 db65974cd8 Controllers: new default buttons
New players get the new layout. A file that bound a button by hand keeps it through the change.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-05 14:40:02 -05:00
martipopsandClaude Opus 5.5 d8781cb9df Splitscreen: a player's pack reload no longer deletes P1's overlay
Fixes #10179.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-05 14:10:42 -05:00
martipopsandClaude Opus 5.5 f513a784f0 Merge upstream/main into fix/pad-e2e-linux: #9946 edited the same file
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-05 13:34:34 -05:00
martipopsandClaude Opus 5.5 7a882e8442 pad_menu_e2e: pass on a fast machine and at 16:9, and say when the window isn't
focus_on looked a widget up before stepping, so a row scrolled out of view
ended the case: it now steps until the row is drawn. optimize_world's job
finished before the case could look on a fast machine: 60000 linked regions
take long enough and cost almost nothing. A tiling compositor sizes the hidden
window too, which fails every case that scrolls, so the harness warns.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-05 11:59:35 -05:00
martipopsandClaude Opus 5.5 7ac3021dfb Show each controller's mapping source and uuid in pad status
A mapping bug report needs to know whether gilrs found an SDL row for a pad
and which id such a row would need. pad status now lists mapping_source
(sdl, driver or none) and uuid (32 hex digits, the id an SDL row starts with).

With splitscreen on, PadRouter holds the gilrs reader, so pad status said
backend:false and listed no controllers, unless the reader was lent to P1.
The router now leaves what it sees for the status of each game that has a
control socket; that list is only built when one is open.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-05 11:53:03 -05:00
martipopsandClaude Opus 5.5 1a7a3678bb Refuse a control socket path too long for a Unix socket up front
A --control-socket path over the system's limit was only found when the
game tried to listen, after loading resources: it logged the raw SUN_LEN
error, wrote a crash report and exited 1, leaving startedCleanly:false so
the next start reset fullscreen. It is a bad command line: exit 2 with a
plain message, before the game folder, options.txt or resources are
touched. horizon-ctl launch refuses it as usage too, without starting a
game or creating a log beside the socket. A .json endpoint is TCP and has
no such limit.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-05 11:45:34 -05:00
martipopsandClaude Opus 5.5 e58ee9c714 Controllers: icon buttons and two checkboxes take the focus, and a screen with no targets fails a test
An icon-only button recorded nothing, so the pad could not reach the pause
menu's Report Bugs, Feedback and Player Reporting icons, or Realms' icons. An
active button with an empty label is now a focus target. So are the
Multiplayer warning's "Do not show again" box and Optimize World's Erase
Cached Data box, which A now ticks.

tools/pad_menu_e2e.py gains every_screen_has_targets, which walks the title's
submenus and every options page and fails on a focus screen with no targets.
Replay Studio is allowlisted because it registers nothing yet. New pause_icon
and erase_checkbox cases press the new targets. The pause menu now has
unlabelled widgets, so splitscreen_e2e's setup scenario reads labels with get.
controller_settings_pad's check for a Navigation page now matches exactly: it
tripped on the General page's Navigation Repeat rows.

docs/controllers.md no longer says every rectangle registers itself or that
both modes reach every screen.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-05 08:46:36 -05:00
martipopsandClaude Opus 5.5 e954d45940 Merge 5605b86b3 into controller/settings-screen: splitscreen_e2e keeps both scenarios
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-05 07:30:56 -05:00
martipopsandClaude Opus 5.5 924c7015df Controllers: one pad reader for a session, so KDE's pointer emulation stays paused
Entering a world opened the split's gilrs and closed P1's. gilrs opens a pad twice
at once, which inotify can merge into one event, and closes it twice apart. KWin
counts those events to pause its emulation, so its count could reach zero while
Horizon still held the pad, and the left stick also moved the mouse.

The router now takes P1's reader and gives it back. Its reader also gets the extra
SDL rows, which it was missing.

Refs #9730

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-05 07:28:34 -05:00
martipopsandClaude Opus 5.5 80fc892f98 AGENTS.md: HORIZON_HOME is logs and crash reports; the game folder holds the rest
Fixes #9835

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-05 05:57:55 -05:00
martipopsandClaude Opus 5.5 7fbd35def9 Render test: smoothness off the 8-bit rounding boundary
0.5 × 255 is 127.5, which drivers can round either way: NVIDIA gives 127. The test
checks that the surface reads back exactly, so 0.75 (191) checks the same thing.

Fixes #9831

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-05 05:55:58 -05:00
martipopsandClaude Opus 5.5 6f682e763e Controllers: X and Y in their places on unmapped Xbox-style Linux pads
The kernel defines BTN_X as BTN_NORTH and BTN_Y as BTN_WEST, and gilrs' default
mapping takes those names literally, so a pad with no SDL row had X and Y crossed.
Sony and Nintendo pads send the same codes by real position and stay as they are.

Closes #9813

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-05 05:21:19 -05:00
martipopsandClaude Opus 5.5 ff0a9f199f horizon-ctl: the pad command's arguments name connection too
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-05 04:06:53 -05:00
martipopsandClaude Opus 5.5 6408c7175f horizon-ctl: the pad command's usage names pad connection
The generated reference has it, so the usage it comes from has to.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-05 04:02:44 -05:00
martipopsandClaude Opus 5.5 b72ddf75c2 Controllers: a settings screen in the graphics style, and one notice per view
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]>
2026-11-05 03:14:31 -05:00
martipopsandClaude Opus 5.5 4828bea53c Controllers: tabs, lists, stick and crosshair reach everything in a menu
The bumpers switch every tabbed screen, and turn the recipe book's pages; its triggers change category.
The right stick only scrolls: the focus stays on its row, no value changes, and nothing scrolls under the
on-screen keyboard. The D-pad walks a list's hidden rows, stops at a list's edge without changing a value, and
a held direction stops at the edge of the slots it's on. The crosshair stays on its target as the screen changes,
A held with the D-pad spreads a stack, and a list's scrollbar says how far its rows moved.

The arrow keys share the focus step, so they walk hidden rows too, and the superflat and single-biome rows
become focus targets for them. Focus on a preset selects it and leaves the share box to a press, as vanilla does.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-05 00:14:05 -05:00
martipopsandClaude Opus 5.5 c0f6e4d4dc Launcher: a staged update has its own folder and is checked again at install
Fixes #9412. Every launcher process deleted and rewrote the one update folder, and the installer
only checked that the payload existed, so a second launcher could leave a partial file to copy over
the launcher.

- Each stage is a `<pid>-<nonce>` folder. Downloads get their name only after the hash check. Each
  process removes its own; stages whose process is gone are cleaned up after an hour, counted from
  the hand-over, because an installer may still be using them.
- The installer checks the archive against the signed SHA-256 again and places the launcher from
  those bytes. The hash travels in an environment variable: the installer is whatever file is in
  place, so the command line stays readable across versions. A window without one can't place.
- Nothing happens when the launcher in place is already that version or newer.
- On Windows a launcher running from the temp folder, however it is spelled, can't replace itself.
- Update no longer stops hosted servers. The new window doesn't stop them when it closes either.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01JLHp7yEJwPTJ2kw29LWdk1
2026-11-04 13:54:58 -05:00
martipopsandClaude Opus 5.5 c269066ca3 Native mods: a fake player's use closes what it opened
A machine's fake player restored its swapped fields but never ran the close
side of the use. A trader stayed in its session, a vehicle kept its menu's
stand-in, and a shulker box's opener count stayed up. It now runs the real
close paths while the fake inventory is in place, and swaps station,
craft_table, ender_open, hook, experience and the respawn point too.

Closing keeps the use as a player's: the click counts, and the same events
and sounds fire. Refusing to open would need a gate at every open site.

Fixes #9409

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01JLHp7yEJwPTJ2kw29LWdk1
2026-11-04 13:51:58 -05:00
martipopsandClaude Opus 5.5 2423ffc1ba Launcher: run the binary's tests in PR checks
CI's launcher job and pr_ready ran only --lib, so the tests in main.rs's
modules first ran in launcher.yml's cargo test at release. Add --bins to
both. The clippy failure at forge_install_tests.rs:4 is already fixed on
main by 812512980, so it needs no change here.

Fixes #9414

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01JLHp7yEJwPTJ2kw29LWdk1
2026-11-04 13:47:55 -05:00
martipopsandClaude Opus 5.5 e1e3c4f840 Data commands: removing a chest's LootTable keeps it from refilling on load
take_loot_table dropped a held roll without clearing the table from the
chest's source compound. The emptied chest encodes the same as its decoded
source, so the save overlay wrote the source back with its table and the next
load rolled again. It now goes through consume_container_loot, as opening does.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01JLHp7yEJwPTJ2kw29LWdk1
2026-11-04 13:47:43 -05:00
martipopsandClaude Opus 5.5 e09c4098ad Launcher: keep the Wardrobe's name tag mark instead of baking it each draw
Each draw baked a new image for the equipped name tag, and GPUI keeps every one
in the sprite atlas until it is dropped. Marks are now kept per item id, its
file's hash and the window scale. One replaced by a scale change or a new file
is dropped from the atlas on the next frame.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01JLHp7yEJwPTJ2kw29LWdk1
2026-11-04 11:25:26 -05:00
martipopsandClaude Opus 5.5 07b1ea4f21 Controllers: menu buttons press on release; screens declare their buttons
A on a focused button now presses it when let go, if the focus is still on it.
Moving the focus, a cancel, a scroll, a dialog opening or another pad taking over
drops the press. On the title, X opens Options and B focuses Quit Game; on the
pause menu, Y focuses the exit button, and A confirms.

A screen says what a button is for (`ui::action_button`, `widgets::declare_action`)
and its pad button and glyph follow: Done, Back, Cancel, Apply, Options and Exit.
Nothing else names the screen. What a screen declared stops counting once another
is drawn over it or replaces it, and `pad status` lists what is declared, what
isn't and the glyphs drawn. tools/pad_menu_e2e.py checks these with the virtual pad.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01JLHp82xRaic2UQfeBTnyhW
2026-11-04 10:13:55 -05:00
martipopsandClaude Opus 5.5 4682b7838c Merge upstream main into fix/shop-window-clock
Keeps the Paddle checkout from main and the clock and unknown-state fix. Both sides added tests at the end of wardrobe/tests.rs and an item to the same import in wardrobe_page/shop.rs.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01JLHp7yEJwPTJ2kw29LWdk1
2026-11-04 09:42:37 -05:00
martipopsandClaude Opus 5.5 d36aaf9c0c Launcher: the Shop reads its window on the service's time, and an unknown claim state is safe
A fast clock closed a window the service still called open, hiding the Claim button on a set that's retired for good. Each answer's Date header now shows how far the clock is ahead, and the Shop reads the window's dates with that taken off. A clock on time or behind reads as before.

A claim state the launcher doesn't know now parses instead of failing the catalogue and the account's answer. It offers no claim and doesn't say the set is over.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01JLHp7yEJwPTJ2kw29LWdk1
2026-11-04 09:15:05 -05:00
martipopsandClaude Opus 5.5 58ffef7e6b Launcher: a cosmetic item's id and hash can't leave the cache folder
Service::item_cached built its path from catalogue values unchecked. It now refuses an entry
whose id or hash isn't 1 to 64 of a-z, A-Z, 0-9 and _, the rule the game already applies
(horizon_cosmetics::fetch), before the disk or the service is touched.

The hash isn't checked against the bytes: nothing in this repository says what it is a digest of.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01JLHp7yEJwPTJ2kw29LWdk1
2026-11-04 09:14:35 -05:00
martipopsandClaude Opus 5.5 84e3266fcc Controllers: one input path for pad and keyboard; focus menus, crosshair inventories
Input parity (pad and keyboard reach the game the same way):
- Held keys record which device holds them; splitscreen's keyboard
  handoff releases only the keyboard's, so the other player's controller
  keeps its holds.
- The pad sends Shift and Ctrl through the keyboard's modifier state, so
  the stack throw in inventories throws the whole stack again.
- Every bindable controller action has an explicit route, checked by a
  test; screenshot and smooth camera work from a controller binding, and
  pad look counts for the tutorial and zoom like the mouse.
- tools/pad_parity_e2e.py and headless Game tests compare pad and
  keyboard outcomes.

Menus and inventories:
- Menus use focus; inventories, containers and the screens whose
  clickable parts have no focus targets use a crosshair pointer centred on
  the point it clicks. The Menu Navigation option and the right stick
  click's swap are removed.
- A snapping engine settles the pointer: a glide onto the nearest slot,
  flicks commit to the neighbour they head for, the D-pad hops a slot.
- Pointer speed, scroll speed and navigation repeat settings per player.
- Focus starts in vanilla's tab order, returns to the widget a screen was
  left on, and only one widget is ever highlighted.
- Only a new press or real stick movement takes input from the mouse; a
  screen, focus or keyboard change releases held buttons until let go.



Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01JLHp81zX4YZ9N1mLLAwzKH
2026-11-03 23:56:48 -05:00
martipopsandClaude Opus 5.5 ef242dfe34 Merge upstream main into launcher accounts
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-03 16:44:02 -05:00
martipopsandCodex GPT-6 cc66b6f8b6 Merge upstream main into launcher accounts
Preserve the local-server restriction for offline profiles while allowing authenticated Microsoft accounts to join external servers. Keep both translation additions and account regression tests.

Co-Authored-By: Codex GPT-6 <[email protected]>
2026-11-03 13:21:25 -05:00
0a499bde42 Splitscreen: use the launcher's other Microsoft accounts
Hand off private per-account sessions when Splitscreen is enabled, retain unavailable accounts in the picker, and connect guests with their own authentication, skins and secure-chat keys. Preserve per-launch account selection and validate the metadata UUID before accepting a session.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Co-Authored-By: Codex GPT-6 <[email protected]>
2026-11-02 15:33:02 -05:00
martipopsandClaude Opus 5.5 45d56f3d8a Merge upstream main into servers
Lang conflict: main moved "Culling"; this branch's two online-mode strings kept.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-02 13:45:54 -05:00
martipopsandClaude Opus 5.5 c784009d45 Merge upstream main (controller setup merged) into servers
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-02 05:46:25 -05:00
martipopsandClaude Opus 5.5 41883f70f0 Merge upstream main (mouse controls merged) into controller setup
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-02 02:44:49 -05:00
martipopsandClaude Opus 5.5 ab8be4adc3 Merge upstream main (Setup PR merged) into mouse controls
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-02 01:39:57 -05:00
martipops 493a315a44 Merge branch 'split/fresh-controller-setup' into split/fresh-servers 2026-11-01 22:14:41 -05:00
martipops 14419addc0 Merge branch 'split/fresh-mouse-controls' into split/fresh-controller-setup 2026-11-01 22:14:22 -05:00
martipops ce36387b6b Merge branch 'split/fresh-basic-setup' into split/fresh-mouse-controls 2026-11-01 22:14:04 -05:00
martipopsandClaude Opus 5.5 afe39ff137 Merge upstream main into the Setup PR
Re-export list conflict in client_lib.rs: main's list (json_folder) plus split_map.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-01 22:13:41 -05:00
martipopsandClaude Opus 5.5 fa76a40d45 Merge controller setup (main merged) into servers
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-01 22:10:28 -05:00
martipopsandClaude Opus 5.5 e061527c49 Merge mouse controls (main merged) into controller setup
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-01 22:10:14 -05:00
martipopsandClaude Opus 5.5 a8432f5ada Merge the Setup PR (main merged) into mouse controls
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-01 22:09:59 -05:00
martipopsandClaude Opus 5.5 dbce14ff72 Merge upstream main into the Setup PR
Lang files: both sides' new strings kept; for keys main also added to
fr_fr.json (the Splitscreen Setup page), this branch's wording stays.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-01 22:09:29 -05:00
martipopsandClaude Opus 5.5 1a5c943591 Merge split/fresh-controller-setup (main merged) into split/fresh-servers
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-01 21:12:07 -05:00
martipopsandClaude Opus 5.5 024d281d9a Merge split/fresh-mouse-controls (main merged) into split/fresh-controller-setup
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-01 21:12:01 -05:00
martipopsandClaude Opus 5.5 ba1b82058c Merge split/fresh-basic-setup (main merged) into split/fresh-mouse-controls
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-01 21:11:55 -05:00
martipopsandClaude Opus 5.5 587f377a87 Merge upstream main into the Setup PR
Re-export list conflict in client_lib.rs: main's list plus split_map.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-01 21:11:40 -05:00
martipopsandClaude Opus 5.5 26af67b082 Merge controller setup (main merged) into servers
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-01 20:54:14 -05:00
martipopsandClaude Opus 5.5 9d53e1b519 Merge mouse controls (main merged) into controller setup
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-01 20:54:14 -05:00
martipopsandClaude Opus 5.5 9c44e4568d Merge the Setup PR (main merged) into mouse controls
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-01 20:54:09 -05:00
martipopsandClaude Opus 5.5 f3d5a8b94b Merge upstream main into the Setup PR
Main lists monitors once a second (#6620); keep that beside this branch's
split_hud.menu in about_to_wait.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-01 20:49:04 -05:00
martipops 4e4ae63d40 Merge branch 'split/fresh-controller-setup' into split/fresh-servers 2026-11-01 19:32:48 -05:00
martipopsandClaude Opus 5.5 3c3060ae5a Localize the splitscreen join and controller prompts
The join strip, the waiting player's prompt and the controller notices
read horizon.splitscreen.prompt.* keys (en_us, fr_fr) instead of English
literals.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-01 19:32:34 -05:00
martipops 77c58d477d Merge branch 'split/fresh-controller-setup' into split/fresh-servers 2026-11-01 19:19:06 -05:00
martipopsandClaude Opus 5.5 ecf18374a8 Merge upstream main into controller Setup
Upstream's pad rule wins: in a world a pressed controller goes to waiting
players, then joins as the next player; P1 takes it only in a menu or while
waiting for one.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-01 19:19:06 -05:00
martipopsandClaude Opus 5.5 b11536f39a Merge controller Setup (main merged) into servers
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-01 17:58:45 -05:00
martipopsandClaude Opus 5.5 104c359194 Merge mouse controls (main merged) into controller Setup
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-01 17:58:45 -05:00
martipopsandClaude Opus 5.5 52650fb1d2 Merge the Setup PR (main merged) into mouse controls
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-01 17:58:39 -05:00
martipopsandClaude Opus 5.5 b1259ce32a Merge upstream main into the Setup PR
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-01 17:58:04 -05:00
martipopsandClaude Opus 5.5 0f5e1c8773 Keep a controller's sprint and sneak held through the modifier heal
heal_hold_latches releases sneak and sprint when the OS says Shift or Ctrl is up,
to recover a keyboard release that never arrived. A controller's stick click acts
as that key without setting the modifier, so the heal released it the next frame,
before a tick could start the sprint: left stick click stopped sprinting. Skip a
mapping the pad holds (or whose release waits for a tick), as modifiers::reconcile
already does.

Fixes #6377

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-01 16:37:56 -05:00
martipops 018f9005c3 Merge branch 'split/fresh-controller-setup' into split/fresh-servers 2026-11-01 16:20:20 -05:00
martipopsandClaude Opus 5.5 80a2c258d7 pausemenu e2e: Splitscreen Settings shows only while another player plays
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-01 16:20:19 -05:00
martipops cdfe9e9bde Merge branch 'split/fresh-basic-setup' into split/fresh-mouse-controls 2026-11-01 16:14:47 -05:00
martipops 2cce47fc9d Merge branch 'split/fresh-controller-setup' into split/fresh-servers 2026-11-01 16:14:47 -05:00
martipops c73d296888 Merge branch 'split/fresh-mouse-controls' into split/fresh-controller-setup 2026-11-01 16:14:47 -05:00
martipopsandClaude Opus 5.5 972519acdc Setup's switch says On/Off from its own keys, not vanilla's ON/OFF
With prepared resources, options.on/off made it "Splitscreen: OFF", unlike
the label before localization and what the live splitscreen tests expect.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-01 16:14:43 -05:00
martipopsandClaude Opus 5.5 b41cedea4b Localize the online-mode messages for splitscreen players on P1's server
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-01 15:50:34 -05:00
martipopsandClaude Opus 5.5 ccd5b8b2b5 Localize controller Setup: Give Up Pad and the held-player hints
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-01 15:49:24 -05:00
martipops 262ed43366 Merge branch 'split/fresh-controller-setup' into split/fresh-servers 2026-11-01 15:49:24 -05:00
martipops 877d3c95a7 Merge branch 'split/fresh-mouse-controls' into split/fresh-controller-setup
# Conflicts:
#	crates/horizon-client-render/src/split_ui.rs
2026-11-01 15:48:00 -05:00
martipopsandClaude Opus 5.5 018e50afb0 Localize mouse Setup controls: Identify, Names, layouts, drag stops, tooltips
Layout icons and the Auto tooltip now come from the draft's layout index, not
from parsing the English label, so translated labels keep their glyphs.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-01 15:47:04 -05:00
martipops 902cb754ea Merge Setup localization into mouse controls
Co-Authored-By: OpenAI Codex <[email protected]>

# Conflicts:
#	crates/horizon-client-render/src/split_ui.rs
2026-11-01 15:39:43 -05:00
martipopsandOpenAI Codex b3dcefa2ac Localize the splitscreen Setup screen and its window feedback
Resolve labels, status text, instructions and warnings from the language table with parameterized messages and bundled English defaults. Add French translations and a process-isolated locale/pack-override regression that preserves draft state and literal player names.

Co-Authored-By: OpenAI Codex <[email protected]>
2026-11-01 15:38:19 -05:00
martipopsandOpenAI Codex 78ca40d8a5 Merge current main through server and LAN joins
Co-Authored-By: OpenAI Codex <[email protected]>
2026-11-01 15:36:26 -05:00
martipopsandOpenAI Codex 4b80f4dea2 Merge current main through controller Setup
Co-Authored-By: OpenAI Codex <[email protected]>
2026-11-01 15:36:26 -05:00
martipopsandOpenAI Codex 79e3c7dc27 Merge current main through the Setup controls stack
Co-Authored-By: OpenAI Codex <[email protected]>
2026-11-01 15:36:26 -05:00
martipops adea816573 Merge current main into the Setup draft before localization fixes
Co-Authored-By: OpenAI Codex <[email protected]>

# Conflicts:
#	crates/horizon-client/src/client_lib.rs
2026-11-01 15:33:16 -05:00
martipopsandOpenAI Codex 73f9ba613c Cover native input before reclick and foreground-window selection
Co-Authored-By: OpenAI Codex <[email protected]>
2026-11-01 15:00:02 -05:00
martipopsandOpenAI Codex 5296c18b05 Raise native split windows before testing their focus handoff
Exercise P2’s actual controller menu path and check P1’s capture and real mouse movement before any recovery click.

Co-Authored-By: OpenAI Codex <[email protected]>
2026-11-01 15:00:02 -05:00
martipopsandOpenAI Codex 81ad72d464 Keep native window handoff test aware of per-player menus
Co-Authored-By: OpenAI Codex <[email protected]>
2026-11-01 14:58:30 -05:00
martipopsandOpenAI Codex 8f7ccd6d0e Close the selected players retained menu before testing windowed movement
Co-Authored-By: OpenAI Codex <[email protected]>
2026-11-01 14:58:30 -05:00
martipopsandOpenAI Codex a74c13032b Use position stability in native input regression checks
Co-Authored-By: OpenAI Codex <[email protected]>
2026-11-01 14:57:24 -05:00
martipopsandOpenAI Codex d884729a0e Observe settled positions in the native input regression
A paused client can retain its last velocity without moving; wait for actual position stability before measuring another owner’s movement.

Co-Authored-By: OpenAI Codex <[email protected]>
2026-11-01 14:57:24 -05:00
martipopsandOpenAI Codex 14c3a6e42e Merge portable native mouse fixture updates
Co-Authored-By: OpenAI Codex <[email protected]>
2026-11-01 14:56:47 -05:00
martipopsandOpenAI Codex a5da7abce2 Keep the native mouse regression fixture portable across filesystem paths
Co-Authored-By: OpenAI Codex <[email protected]>
2026-11-01 14:56:47 -05:00