feat(play): the game settings follow the player into a new build, and Linux builds get --user #84

Merged
HumanBean merged 1 commit from dyst/LongshotLauncher:feat/settings-follow into main 2026-11-15 07:47:15 +00:00
Member

An update into a new folder starts the game from the default settings: the Insert menu's choices and the controls are lost, because the new folder's longshot_options.ini holds only make_game.py's compile_shaders=. Longshot #729 keeps the settings in the user folder the launcher passes with --user. This PR brings the settings to a build that has none, and passes that folder on Linux too.

What changed

  • Linux builds get --user as well (GamePlay.UserFolder, StartInfo): ~/.local/share/longshot, the folder Linux saves already use, so #729's settings are shared there too. The exception: while the build's folder has a user/ of its own, nothing is passed. The game then handles that folder itself, moving an old build's saves into the shared folder at its next start, or keeping a link the player made.
  • Settings brought to a build before Play (Core/SettingsCarry.cs, LauncherService.CarrySettings): when the build's own longshot_options.ini has no setting of the player's (missing, or compile_shaders= alone), it's filled from the newest file among the user folder's and the other builds'. The build's compile_shaders= is kept.
    • Old builds covered: builds from before #729 read that file where it is, so they keep the player's settings too.
    • Hand-off to #729: a #729 build copies it into the user folder at its first start.
    • What's never touched: the launcher never writes the user folder's file, and never writes over a file that has settings or is a link.
    • Failures: one is left out of the way, and the game starts with its own file as before.
    • Notice: the home says once: "Your game settings from your other versions now apply to this one too." This is a new text, so the other languages show it in English for now.
  • Hookshot settings import (HookshotSettings.Import's new optionsFile, LauncherService.OptionsFileOf): the import writes into the file the build reads, which is the user folder's once there is one. Otherwise the game would ignore the imported settings. language.txt stays the build's.
  • BuildFolders: the folders GatherSaves already looked in (every build's, the builds folder's game folders, the 2.x Builder's), now shared with the settings fill.
  • Docs: README (design decisions, Core/ layout), docs/saves.md.

Testing

Tested (Windows 11, .NET SDK 10.0.103):

  • python -I tests/test_launcher_core.py --strict --longshot <Longshot checkout>: 1038 checks pass. That includes the new SettingsCarryChecks, which cover:
    • what counts as a setting;
    • the merge, which keeps the build's compile_shaders= and line endings;
    • the newest file winning, with make_game.py's compile_shaders=-only file never chosen;
    • a build with its own settings, or nothing anywhere, left alone;
    • UserFolder on Windows and Linux, with and without the build's own user/;
    • the Hookshot import into the user folder's file.
      The two existing --user checks now expect the argument on Linux too.
  • dotnet build App -c Release: 0 warnings, 0 errors.
  • python -I tests/test_release.py: the same 6 failures as a clean main checkout on this PC. They're Windows-side (a shell script it can't execute, CRLF in a published file) and in code this PR doesn't touch.
  • One local note: with core.autocrlf=true the signed fixtures check out with CRLF, and the release checks fail on their signatures. git -c core.autocrlf=false checkout -- tests/fixtures fixes the checkout; nothing in this PR changes them.

Not tested:

  • The window and a real Play: the notice on the home, and a game started with the filled file.
  • Linux: no .NET on this PC's Linux (WSL), so neither the checks nor a Linux game start have run there.

Must be tested:

  • Windows, a launcher build from this branch: update a build into a new folder, then press Play. Expect the old build's settings in the new folder's longshot_options.ini (its compile_shaders= kept), the notice on the home once, and the game starting with them.
  • Linux or Steam Deck: press Play on a build whose folder has no user/. Expect the game's log to show it was started with --user ~/.local/share/longshot, and the saves to be the shared ones.

Risks

  • Linux and the 2.x layout: a game on Linux is now started with --user when its folder has no user/. That's the folder the game's own rule already picks for its saves. A player who points the saves elsewhere with a user/ link in the game folder keeps that, because no --user is passed then.
  • Old builds: the settings fill only writes a build's file that has no player settings. A build from before #729 then reads the player's settings, which is the point.
  • Turning it off: revert the commit.

Related: Longshot #729 (the game side). #57 (an update in place) and #78 (the shader caches carried on update) touch the same update path; this one doesn't depend on either. Next, in its own PR: the per-exe Windows GPU preference and NVIDIA profile carried to a new build before Play.

🤖 Generated with Claude Code

An update into a new folder starts the game from the default settings: the Insert menu's choices and the controls are lost, because the new folder's `longshot_options.ini` holds only make_game.py's `compile_shaders=`. Longshot [#729](https://git.magicbean.dev/MagicBeanDev/Longshot/pulls/729) keeps the settings in the user folder the launcher passes with `--user`. This PR brings the settings to a build that has none, and passes that folder on Linux too. ## What changed - **Linux builds get `--user` as well** (`GamePlay.UserFolder`, `StartInfo`): `~/.local/share/longshot`, the folder Linux saves already use, so #729's settings are shared there too. The exception: while the build's folder has a `user/` of its own, nothing is passed. The game then handles that folder itself, moving an old build's saves into the shared folder at its next start, or keeping a link the player made. - **Settings brought to a build before Play** (`Core/SettingsCarry.cs`, `LauncherService.CarrySettings`): when the build's own `longshot_options.ini` has no setting of the player's (missing, or `compile_shaders=` alone), it's filled from the newest file among the user folder's and the other builds'. The build's `compile_shaders=` is kept. - **Old builds covered:** builds from before #729 read that file where it is, so they keep the player's settings too. - **Hand-off to #729:** a #729 build copies it into the user folder at its first start. - **What's never touched:** the launcher never writes the user folder's file, and never writes over a file that has settings or is a link. - **Failures:** one is left out of the way, and the game starts with its own file as before. - **Notice:** the home says once: "Your game settings from your other versions now apply to this one too." This is a new text, so the other languages show it in English for now. - **Hookshot settings import** (`HookshotSettings.Import`'s new `optionsFile`, `LauncherService.OptionsFileOf`): the import writes into the file the build reads, which is the user folder's once there is one. Otherwise the game would ignore the imported settings. `language.txt` stays the build's. - **`BuildFolders`**: the folders `GatherSaves` already looked in (every build's, the builds folder's game folders, the 2.x Builder's), now shared with the settings fill. - **Docs:** README (design decisions, `Core/` layout), `docs/saves.md`. ## Testing **Tested** (Windows 11, .NET SDK 10.0.103): - `python -I tests/test_launcher_core.py --strict --longshot <Longshot checkout>`: 1038 checks pass. That includes the new `SettingsCarryChecks`, which cover: - what counts as a setting; - the merge, which keeps the build's `compile_shaders=` and line endings; - the newest file winning, with make_game.py's `compile_shaders=`-only file never chosen; - a build with its own settings, or nothing anywhere, left alone; - `UserFolder` on Windows and Linux, with and without the build's own `user/`; - the Hookshot import into the user folder's file. The two existing `--user` checks now expect the argument on Linux too. - `dotnet build App -c Release`: 0 warnings, 0 errors. - `python -I tests/test_release.py`: the same 6 failures as a clean `main` checkout on this PC. They're Windows-side (a shell script it can't execute, CRLF in a published file) and in code this PR doesn't touch. - One local note: with `core.autocrlf=true` the signed fixtures check out with CRLF, and the release checks fail on their signatures. `git -c core.autocrlf=false checkout -- tests/fixtures` fixes the checkout; nothing in this PR changes them. **Not tested:** - **The window and a real Play:** the notice on the home, and a game started with the filled file. - **Linux:** no .NET on this PC's Linux (WSL), so neither the checks nor a Linux game start have run there. **Must be tested:** - **Windows, a launcher build from this branch:** update a build into a new folder, then press Play. Expect the old build's settings in the new folder's `longshot_options.ini` (its `compile_shaders=` kept), the notice on the home once, and the game starting with them. - **Linux or Steam Deck:** press Play on a build whose folder has no `user/`. Expect the game's log to show it was started with `--user ~/.local/share/longshot`, and the saves to be the shared ones. ## Risks - **Linux and the 2.x layout:** a game on Linux is now started with `--user` when its folder has no `user/`. That's the folder the game's own rule already picks for its saves. A player who points the saves elsewhere with a `user/` link in the game folder keeps that, because no `--user` is passed then. - **Old builds:** the settings fill only writes a build's file that has no player settings. A build from before #729 then reads the player's settings, which is the point. - **Turning it off:** revert the commit. Related: Longshot [#729](https://git.magicbean.dev/MagicBeanDev/Longshot/pulls/729) (the game side). [#57](https://git.magicbean.dev/MagicBeanDev/LongshotLauncher/pulls/57) (an update in place) and [#78](https://git.magicbean.dev/MagicBeanDev/LongshotLauncher/pulls/78) (the shader caches carried on update) touch the same update path; this one doesn't depend on either. Next, in its own PR: the per-exe Windows GPU preference and NVIDIA profile carried to a new build before Play. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
feat(play): the game settings follow the player into a new build, and Linux builds get --user
All checks were successful
CI / Compile and test (pull_request) Has been skipped
CI / Conventional Commit title (pull_request) Successful in 6s
0f21cd92ee
An update into a new folder started the game from the default settings: its longshot_options.ini held only
make_game.py's compile_shaders=. Longshot's #729 keeps the settings in the user folder the launcher gives
with --user; this brings the settings to a build that has none and gives that folder on Linux too.

- GamePlay.UserFolder: the shared user folder on both systems (on Linux not while the build's folder has a
  user/ of its own, which the game takes in itself or keeps as the player's link); StartInfo passes it on
  Linux too
- SettingsCarry.Fill, before Play (LauncherService.CarrySettings): a build whose file has no setting of the
  player's is filled from the newest of the user folder's and the other builds' files, its compile_shaders=
  kept; the user folder's own file is never written, and a failure never stops the game from starting
- the Hookshot settings import writes into the file the build reads (OptionsFileOf: the user folder's once
  there is one); language.txt stays the build's
- BuildFolders: the folders GatherSaves looked in, shared with the settings
- tests: SettingsCarryChecks; the --user checks now expect it on Linux
HumanBean changed title from WIP: feat(play): the game settings follow the player into a new build, and Linux builds get --user to feat(play): the game settings follow the player into a new build, and Linux builds get --user 2026-11-15 07:47:11 +00:00
HumanBean deleted branch feat/settings-follow 2026-11-15 07:47:16 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
MagicBeanDev/LongshotLauncher!84
No description provided.