Skip to content

No Man's Sky: built-in handler that manages GCMODSETTINGS.MXML - #619

Merged
ChrisDKN merged 8 commits into
ChrisDKN:Testingfrom
sabrsorensen:nms-gcmodsettings
Oct 1, 2026
Merged

ChrisDKN merged 8 commits into
ChrisDKN:Testingfrom
sabrsorensen:nms-gcmodsettings

Conversation

@sabrsorensen

Copy link
Copy Markdown
Contributor

Summary

Adds a built-in No Man's Sky handler that manages the game's own mod registry, Binaries/SETTINGS/GCMODSETTINGS.MXML. NMS decides each mod's priority and on/off state from that file. The current Resources-branch custom handler links the mod folders but never touches the file, so NMS priority doesn't follow the mod list.

The handler keeps the same name and game_id (No_Man_s_Sky) as that custom handler. Discovery gives built-in handlers priority, so existing profiles carry over unchanged. It subclasses StandardCustomGame with the old definition built in, so deployment is identical and only the MXML handling is new.

What it does

  • On deploy, it writes GCMODSETTINGS.MXML in mod-list order.
    • NMS gives the lowest ModPriority precedence, so Amethyst's highest-priority mod (the one its conflict view shows winning) gets ModPriority 0.
    • The numbers therefore read mirrored against Amethyst's Priority column, which is higher-wins. This is intentional so the winner matches, and is documented in code. The deploy log line states which end wins.
    • [Overwrite] outranks everything.
  • Hand-installed mods keep their entries. Folders in GAMEDATA/MODS that Amethyst didn't deploy keep their entries after Amethyst's, in their original order and on/off state.
  • On restore, the user's original file is put back exactly. This uses a per-profile backup and state file, following the BG3 handler's modsettings.lsx handling: SHA-256 integrity checks, and a recovery copy if the game changed the file at runtime.
  • VFS deploys generate the file inside the private view via _vfs_post_view_build, as Cyberpunk does for its archive modlist.txt. The real game folder is not modified.
  • Root_Folder: a GCMODSETTINGS.MXML in Root_Folder (for example, one captured as a runtime file under the old handler) wins, and raises a deploy warning.
  • Unreadable original: if the original file can't be read, a deploy warning says hand-installed entries weren't carried over.
  • "Disable all mods" launch toggle (play bar → Launch settings) sets DisableAllMods, which NMS has no in-game switch for. It's applied on the next deploy.
  • Format: the output matches the game's byte for byte: UTF-8 BOM, CRLF, tabs, and no newline after </Data>.
  • Also included: a bundled 256×256 banner (icons/games/No_Man_s_Sky.png, from the definition's image_url); the handler reports is_custom = False, so the "Edit custom game" and "Force update handler" actions don't target the shadowed JSON; and translation markers for the toggle.

Files

  • src/Utils/nms/gcmodsettings.py: parse, build, order and write, with no dependency on Qt or game objects.
  • src/Games/No Man's Sky/no_mans_sky.py: the handler.
  • src/Utils/nms/_selftest.py: a runnable self-test, following the Utils/vfs/_selftest.py convention.
  • Meson wiring for the above.

Testing

  • python3 src/Utils/nms/_selftest.py passes (39 checks). It covers:
    • byte-exact round trips of real game-written files;
    • ordering, shared folders, Overwrite, case-insensitive matching, loose files in MODS/, preserved entries, escaping;
    • backup and restore, including tamper and runtime-change cases;
    • the physical and VFS deploy paths, the Root_Folder case, the corrupt-original warning and the DisableAllMods toggle.
  • discover_games() loads NoMansSky with no load failures.
  • Manual test on a live Steam install (NixOS), on the branch as tested before a clean rebase onto current main:
    • normal deploy writes the expected order;
    • reordering swaps which mod wins in-game;
    • the game kept Amethyst's ordering when it rewrote the file on launch;
    • the DisableAllMods toggle works both ways;
    • restore brings back the original file with hand-installed mods kept;
    • VFS deploy leaves the real file unmodified while the mods apply.

Notes / follow-ups

  • Once this lands, Custom Handlers/No_Man_s_Sky.json on the Resources branch can be removed. Until then the built-in handler shadows it.
  • The ~130 lines of backup/state/restore helpers are a near-verbatim copy of the BG3 modsettings.lsx helpers, and a comment in the handler says so. If a third handler needs the same exact-restore behaviour, they could move into a shared helper. I kept BG3 untouched in this PR.

🤖 Generated with Claude Code

sabrsorensen and others added 8 commits September 30, 2026 17:05
Mirrors the Baldur's Gate 3 modsettings.lsx backup/state/restore helpers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DhVuRBjYHgoPvYK63yz1N7
Replaces the Resources-branch custom handler definition (same name and
game_id, so profiles carry over) and writes the game's mod registry on
deploy in modlist order, restoring the user's original on restore.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DhVuRBjYHgoPvYK63yz1N7
…ot_Folder

- VFS deploys now write the file into the private view via
  _vfs_post_view_build (as Cyberpunk does for its archive modlist); the
  real game folder is no longer modified and the game sees the result.
- A GCMODSETTINGS.MXML shipped in Root_Folder wins and raises a deploy
  warning instead of silently replacing the generated file.
- The built-in handler no longer reports is_custom, so the custom-game
  edit / force-update actions don't target the shadowed JSON.
- Self-tests for the deploy/restore wiring.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DhVuRBjYHgoPvYK63yz1N7
- icons/games/No_Man_s_Sky.png: the definition's image_url banner,
  resized to the bundled 256x256 convention.
- An unreadable original GCMODSETTINGS.MXML now raises a deploy warning
  (same message as the log line) since hand-installed entries are lost.
- Add the game folder's __init__.py like every other handler folder.
- Note that the backup/restore helpers mirror the BG3 handler's.
- unmanaged_folders is annotated Iterable[str].

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DhVuRBjYHgoPvYK63yz1N7
NMS has no in-game switch for GCMODSETTINGS' DisableAllMods, so expose it
as a handler LaunchToggle (play bar > Launch settings), like Morrowind's
skip-launcher toggle. The generated file - physical or VFS view - follows
the toggle; restore still puts the user's original back exactly.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DhVuRBjYHgoPvYK63yz1N7
Amethyst's Priority column rises toward the winner (higher wins, as in
MO2) while NMS gives ModPriority 0 precedence. The handler maps winner to
winner, so the numbers read mirrored; say so in the code and make the
deploy log line state which end wins.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DhVuRBjYHgoPvYK63yz1N7
@ChrisDKN
ChrisDKN changed the base branch from main to Testing September 30, 2026 23:40
@ChrisDKN
ChrisDKN merged commit f9c880a into ChrisDKN:Testing Oct 1, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants