launcher: notice when an interrupted apply was finished or rolled back (retries while another window applies), windows take over config changes made in another window, hints and settings wrap at the minimum window size, data paths with .. cleaned up, boot-to-level starts bound to their level (ignored for other levels)

This commit is contained in:
MineTec committed 2026-11-07 12:48:43 +01:00
1 parent 8b78958306
commit c4fa500198
30 files changed
+695 -102

No files matched your search

+4
View File
@@ -84,7 +84,11 @@ Test World with all mods; boot-to-level + all exe mods (River loading card); pra
on-demand files are fragile; the wizard could warn when the chosen folder is under `%OneDrive%`.
* ~~**Interrupted apply**~~ – fixed 2026-11-07: `cd-active.new.complete` marker +
`ModManager.recoverInterruptedApply()` (GUI start, Play, `--launch`), see llamamod-app.md.
Follow-up 2026-11-07: the GUI tells the user once what was repaired and retries when another
window held the apply lock (was silently skipped).
* ~~A `config.json` saved by a stale window overwrites activeMods/gameExeSha256~~ – fixed
2026-11-07: field-level merge-on-save under `.config.lock` (`Config.save`).
Follow-up: the window rebuilds its Mods/Settings tabs after a merge or when activated with a
changed config.json (`Config.refresh`), so its check boxes no longer show stale values.
* ~~Old Wine versions are not detected~~ – 2026-11-07: `wine --version` in Settings, warning below
Wine 5.0 (Settings in red, once before Play); missing Wine gives a clear message.
Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

+15 -1
View File
@@ -73,6 +73,15 @@ instance last loaded/saved: fields it did not change keep what another window/CL
meanwhile (mod options merge per mod and key; unknown keys of newer versions are kept); a field
changed on both sides = last writer wins. The object then holds the merged values. A `new
Config()` that never touched a file overwrites everything (installer, tests).
`save` returns true when the merge pulled in values written elsewhere; `Config.refresh(file)` does
the same merge without writing (unsaved changes of this instance are kept). The launcher refreshes
when its window is activated and after a save that pulled something in, then rebuilds the Mods and
Settings tabs (status "Took over changes made in another LlamaMod window."), so a stale window's
next click cannot undo another window's selection.
Screenshots: `img/app/two-windows-before.jpg` / `-after.jpg` (right window ticked Test World, left
window after a click into it), `img/app/interrupted-apply-notice.jpg`, `img/app/saves-min-width.jpg`,
`img/app/settings-min-width.jpg` (hints are `ui/WrapLabel`s: they wrap at the panel width, the
Settings tab tracks the viewport width, the header subtitle is shortened in the middle before the buttons).
## First start
@@ -157,7 +166,12 @@ after the swap. If the app is killed between the two renames, `ModManager.recove
(GUI start, Play, CLI `--launch`) moves `cd-active.new` in when its marker matches config.json's
activeKey (exe and config are only written after the swap, so they still describe the previous
selection), otherwise moves `cd-active.old` back; without either nothing is touched (Play then
restores the original as before). Applying (and restoring)
restores the original as before). It returns a `Recovery`: NONE, FINISHED (new folder moved in),
RESTORED (old folder back), BUSY (another window/CLI holds `.apply.lock`: `BusyException`), FAILED.
The launcher shows FINISHED/RESTORED once (status line + small dialog: "The last apply was
interrupted; LlamaMod finished it." / "…restored the previous mod selection."); after BUSY it checks
again every 3 s and on window activation while idle, and Play reports the lock instead of starting
(`ui/RecoveryNotice`). CLI `--launch` prints the same texts. Applying (and restoring)
is refused while the game runs (`GameLauncher.isRunning()`) and holds an exclusive lock on
`<data>/.apply.lock` (a second window/CLI/editor gets "Another LlamaMod window or command is applying
mods"); every run is logged to `logs/apply.log`.
+10 -1
View File
@@ -10,7 +10,16 @@ no world map. Used by the level editor's Play button (details, offsets and tests
| `slot` | 3 | save slot the game plays with (new game if empty) |
| `logos` | on | skip logo movies and title screen (skipped if intro-skip already patched them) |
| `quitOnEscape` | off | Escape (pause) ends the game at once through the normal exit path |
| `start` | empty | "x, y, z[, yaw]" in cells: moves the level's player start (WAD rebuild) |
| `start` | empty | "x, y, z[, yaw][ @ world/chapter]" in cells: moves the level's player start (WAD rebuild) |
**Start bound to a level** (2026-11-07): a start with "@ world/chapter"
(`BootToLevelMod.formatStart(world, chapter, …)`) is used only while `world`/`chapter` name that
level; for any other level it is ignored with a progress note ("Player start ignored: it was set
for world W chapter C") instead of failing with "no collision floor" (a play-test whose restore
never ran left its start in config.json, and every later apply for another level failed). A start
without "@" applies to whatever level is chosen (old configs, hand-typed values) and is still
checked strictly. Tests: `BootToLevelModTest.startOfAnotherLevelIsIgnored`, `parsesStartLevel`.
The editor's play-test (`PlaytestRunner.install`) should write the bound form – see the report.
Patches: `jmp` at 0x549C50 (main-menu frame handler) → once: read slots (FUN_0041c0e0), load
slot (FUN_0041cc70), set tribe/world/chapter/map 0x584EB4…, music shutdown, state 0x5846E4 = 3,