launcher: wizard bar follows the copied megabytes, saves table shows 4 rows at the minimum size, mods tab keeps focus and caret when it is rebuilt, take-over notice expires; geom_export previews in game space; apptest checks every menu step with longer holds, loads slot 2, retries an early crash once and records load
This commit is contained in:
1 parent
d030c9c6c7
commit
d6f84be125
19 files changed
+650
-67
No files matched your search
+4
-1
@@ -210,7 +210,10 @@ Implemented in `tools/geom_import.py` (OBJ → TRAK + MAP tile part, rest of the
|
||||
`geom_export`/`geom_import` = the old raw export space (z < 0).
|
||||
* `geom_export.py WAD OUT [--collision] [--objects] [--export-space]` → level.obj/mtl (UV, vertex colours, one
|
||||
object per tile), page_NN.png, collision.obj (groups matNN_grpG), objects.obj, preview_top/persp.png
|
||||
(textured software renderer).
|
||||
(textured software renderer, right-handed camera, always in game space – the same way round as in the
|
||||
game, checked against an in-game shot of t1l1m001: `img/geom_preview_handedness.jpg`; before 2026-11-07
|
||||
the previews rendered export space and were mirrored). `tools/vorschau/render_level.py` (Blender) reads
|
||||
file space and is not mirrored either (checked on the test world, 2026-11-07).
|
||||
* `geom_import.py BASE.wad MESH.obj NEW.wad [--coll-obj C.obj] [--keep-tiles] [--zones flat|keep] [--default-tex N] [--export-space]`
|
||||
* `geom_demo.py BASE.wad demo.obj [--plaza]` – example geometry made of texture-tile quads.
|
||||
* `geomlib.py` – parser/builder (TRAK, STPC models, MAP tile part, TEXT table/pages, collision).
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 79 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 58 KiB |
+32
-4
@@ -76,8 +76,14 @@ 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.
|
||||
Settings tabs (status "Took over changes made in another LlamaMod window.", transient: after 6 s the
|
||||
previous status comes back, `ui/StatusLine.flash`), so a stale window's next click cannot undo another
|
||||
window's selection. The Mods tab rebuild keeps keyboard focus, caret and selection of the option the user
|
||||
is typing in (`ui/FocusKeeper`: inputs are tagged `modId/optionKey`; FlatLaf's select-all on focus gain is
|
||||
suppressed for the restored field, it would eat the next key).
|
||||
Short windows: header 150 px from 860 px window height, 104 px below, 92 px below 700 px. The Saves tab
|
||||
shows the table legend ("Coins: …") in the left column, so at the 820×640 minimum the chapter table
|
||||
still shows 4 rows (7 at 720 px; `img/app/saves-640.jpg`).
|
||||
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
|
||||
@@ -92,6 +98,9 @@ looking for `…/Hd/groove.exe` next to `…/Cd/wads/`. After copying, `platform
|
||||
same checks as `deb-build/build.sh` (FESOUND.WAD length field, "OFNI" at offset 4 of every level
|
||||
WAD, `music/english.cvs` must not end in 4 MiB of zeros); damaged copies are rejected.
|
||||
The ISO also contains three `(null)king*.ksv` leftovers; they are not copied.
|
||||
Wizard progress: the bar follows the copied bytes exactly (`Installer.COPY_SHARE` of the install progress
|
||||
is the copy), so "Copying 553 of 568 MB" stands next to 97 %; the short steps after it (check, game folder,
|
||||
re-applying mods) show a busy bar without a percentage (`img/app/wizard-copy-mb-fixed.jpg`).
|
||||
|
||||
## Registry, CD path and the exe patch
|
||||
|
||||
@@ -356,14 +365,14 @@ and hard-linked into each session (~30 MB per session + ~200 MB Wine prefix on f
|
||||
T=tools/apptest.py
|
||||
$T run NAME --display 5 --mods fog,testworld --opt fog.strength=2 --level 1 1 \
|
||||
--seq "Up:1.5 shot:walk a+x:0.5 sleep=1 shot:after" --out DIR [--keep]
|
||||
# setup + apply + unlock slot 3 at world/chapter (cursor) + start + tolevel + keys + stop
|
||||
# setup + apply + unlock slots 2 and 3 at world/chapter (cursor) + start + tolevel (slot 2) + keys + stop
|
||||
# exit 0 ok, 3 crash, 4 timeout; DIR: report.json, 00_start.png, seq_NN_*.jpg, 99_end.jpg,
|
||||
# zz_failure.jpg, game.log, apply.log
|
||||
$T setup NAME # install session (fast after the template exists)
|
||||
$T apply NAME fog,mirror --opt fog.strength=0 --opt mirror.on=true # no ids = original
|
||||
$T unlock NAME 3 WORLD CHAPTER # slot 3, map cursor on WORLD/CHAPTER (do this before start)
|
||||
$T start NAME --display 5 # Xvfb + private pulse + `--launch`; waits for window and audio
|
||||
$T tolevel NAME --world 1 # menu "Spiel starten" -> slot 3 -> map -> Enter -> skip fly-by
|
||||
$T tolevel NAME --world 1 [--slot 3] # menu "Spiel starten" -> slot (default 3) -> map -> Enter -> skip fly-by
|
||||
$T keys NAME Up:1.5 x a+x:0.5 sleep=2 shot:name dialog --out DIR # KEY[:hold s], default hold 0.2 s
|
||||
$T shot NAME out.png [--small] # 1920x1080 PNG, --small = 960x540 JPEG
|
||||
$T ocr NAME [WxH+X+Y] # German tesseract OCR
|
||||
@@ -393,5 +402,24 @@ s.key("Up", 1.5); s.shot("a.png"); print(s.crashed()); s.stop()`.
|
||||
Controls are camera-relative (see testharness.md for movement measurements).
|
||||
* Navigation timing (Wine 6, llvmpipe): menu ~6 s, slot ~14 s, gameplay ~25 s after start.
|
||||
`tolevel(world=9)` waits for the beige world-9 map, other worlds for a stable picture.
|
||||
* Flakiness under load: with several agents' games running (load average 30 on 6 cores) the game
|
||||
draws only a few frames per second and the slot screen ignores presses shorter than a frame
|
||||
(seen 2026-11-07 at load ~30: the save slot carousel ignored Left/Right – 0.3 to 4 s holds – for
|
||||
minutes while Return/Escape worked; root cause not found). `run` therefore loads **slot 2**, where
|
||||
the carousel opens (no turning; slot 3 gets the same unlock for mods whose save-slot option is 3);
|
||||
3 + 3 runs passed after that change. `tolevel` checks every menu step and repeats it with longer
|
||||
holds (Return on menus 0.6 s first – 0.2 s presses were often missed under load, reported by the
|
||||
test-world agent too): Return on the main menu until the slot screen shows (0.8/1.0/1.2 s), Right one step at a
|
||||
time until OCR reads the wanted slot (the carousel wraps 3 → 1; a step that did not move is
|
||||
repeated with 0.6/1.0/1.5 s; gives up after 240 s), Return on the slot until the slot screen is
|
||||
gone, Return on the map again if the picture did not change after 8 s. Before opening the slot it
|
||||
checks the slot text: an empty slot (would start a new game in the village) or another world's
|
||||
name (`SLOT_WORLD_NAMES`, verified: 1 "dorf", 9 "testlevel") is an error instead of a wrong level.
|
||||
`run` retries the start once when the game crashed before the main menu (Wine page fault at
|
||||
start-up) or the slot screen never came: report.json `"retries": [{attempt, phase, error}]`,
|
||||
`retry1_failure.jpg`/`retry1_game.log` in the out dir, result line "OK (after a retry: …)";
|
||||
`--no-retry` turns it off. report.json also records `load_avg`/`cpus`. Your own key sequences
|
||||
(`--seq`) are not retried: hold keys ≥0.5 s for menus when the machine is busy.
|
||||
Offline tests of the retry/slot logic: `python3 -m unittest tools/test_apptest.py`.
|
||||
* Session state (PIDs, display): `<root>/<name>/harness/state.json`; logs `xvfb.log`, `pulse.log`
|
||||
there, game output in `data/logs/game.log`. Delete `<root>/<name>` to start from scratch.
|
||||
Reference in new issue
Block a user