From d6f84be125980f3ab72da33cc52fdbb0f294f9a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elias=20M=C3=BCller?= Date: Sat, 7 Nov 2026 14:00:22 +0100 Subject: [PATCH] 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 --- notes/geometry.md | 5 +- notes/img/app/saves-640.jpg | Bin 0 -> 80786 bytes notes/img/app/wizard-copy-mb-fixed.jpg | Bin 0 -> 22600 bytes notes/img/geom_preview_handedness.jpg | Bin 0 -> 59503 bytes notes/llamamod-app.md | 36 +++- .../llamamod/platform/Installer.java | 5 +- .../eliasmueller/llamamod/ui/FocusKeeper.java | 98 +++++++++ .../eliasmueller/llamamod/ui/MainFrame.java | 17 +- .../eliasmueller/llamamod/ui/ModsPanel.java | 33 +-- .../eliasmueller/llamamod/ui/SavesPanel.java | 11 +- .../eliasmueller/llamamod/ui/SetupWizard.java | 27 ++- .../eliasmueller/llamamod/ui/StatusLine.java | 36 ++++ .../llamamod/ui/FocusKeeperTest.java | 83 ++++++++ .../llamamod/ui/MainFrameLayoutTest.java | 16 ++ .../llamamod/ui/SetupWizardProgressTest.java | 18 ++ .../llamamod/ui/StatusLineTest.java | 45 +++++ tools/apptest.py | 188 +++++++++++++++--- tools/geom_export.py | 13 +- tools/test_apptest.py | 86 ++++++++ 19 files changed, 650 insertions(+), 67 deletions(-) create mode 100644 notes/img/app/saves-640.jpg create mode 100644 notes/img/app/wizard-copy-mb-fixed.jpg create mode 100644 notes/img/geom_preview_handedness.jpg create mode 100644 src/main/java/com/eliasmueller/llamamod/ui/FocusKeeper.java create mode 100644 src/main/java/com/eliasmueller/llamamod/ui/StatusLine.java create mode 100644 src/test/java/com/eliasmueller/llamamod/ui/FocusKeeperTest.java create mode 100644 src/test/java/com/eliasmueller/llamamod/ui/MainFrameLayoutTest.java create mode 100644 src/test/java/com/eliasmueller/llamamod/ui/SetupWizardProgressTest.java create mode 100644 src/test/java/com/eliasmueller/llamamod/ui/StatusLineTest.java create mode 100644 tools/test_apptest.py diff --git a/notes/geometry.md b/notes/geometry.md index 43d084e..8e73b4a 100644 --- a/notes/geometry.md +++ b/notes/geometry.md @@ -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). diff --git a/notes/img/app/saves-640.jpg b/notes/img/app/saves-640.jpg new file mode 100644 index 0000000000000000000000000000000000000000..486e255a2df51a41182e77fa1211012d1eada7c7 GIT binary patch literal 80786 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 literal 0 HcmV?d00001 diff --git a/notes/img/app/wizard-copy-mb-fixed.jpg b/notes/img/app/wizard-copy-mb-fixed.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0bddc19ca668f48f2fe2aa3dd1ee9a209bf24fa6 GIT binary patch literal 22600 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 literal 0 HcmV?d00001 diff --git a/notes/img/geom_preview_handedness.jpg b/notes/img/geom_preview_handedness.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4da54031b117e9fb8ff1b1841195e3489de7fc9b GIT binary patch literal 59503 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%0AY57%{?1S@FBA>xHh_Yc}cMpr_Z&KIET7v*y$Iu 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�H;RrE{4?Zpm*QcKo0u&^si;r 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 BpWgrg literal 0 HcmV?d00001 diff --git a/notes/llamamod-app.md b/notes/llamamod-app.md index 25ee282..1d96ad8 100644 --- a/notes/llamamod-app.md +++ b/notes/llamamod-app.md @@ -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): `//harness/state.json`; logs `xvfb.log`, `pulse.log` there, game output in `data/logs/game.log`. Delete `/` to start from scratch. diff --git a/src/main/java/com/eliasmueller/llamamod/platform/Installer.java b/src/main/java/com/eliasmueller/llamamod/platform/Installer.java index ed51fa7..75f45dc 100644 --- a/src/main/java/com/eliasmueller/llamamod/platform/Installer.java +++ b/src/main/java/com/eliasmueller/llamamod/platform/Installer.java @@ -53,7 +53,7 @@ public final class Installer { List cd = src.cdFiles(); long total = totalSize(hd) + totalSize(cd); long[] done = {0}; - Progress copyP = p.sub(0, 0.85); + Progress copyP = p.sub(0, COPY_SHARE); // files already copied are only trusted when an interrupted install of the same source // resumes; a new setup (other or repaired image) copies everything again Path marker = paths.root().resolve("original").resolve(".install-source"); @@ -152,6 +152,9 @@ public final class Installer { } } + /** Share of {@link #install}'s progress that is the file copy (byte-proportional); the rest is quick steps. */ + public static final double COPY_SHARE = 0.85; + /** "Copying 123 of 568 MB (wads/t1l1m001.wad)". */ static String copyMessage(long done, long total, String file) { return String.format(Locale.ROOT, "Copying %d of %d MB (%s)", done >> 20, total >> 20, file); diff --git a/src/main/java/com/eliasmueller/llamamod/ui/FocusKeeper.java b/src/main/java/com/eliasmueller/llamamod/ui/FocusKeeper.java new file mode 100644 index 0000000..c36ee02 --- /dev/null +++ b/src/main/java/com/eliasmueller/llamamod/ui/FocusKeeper.java @@ -0,0 +1,98 @@ +package com.eliasmueller.llamamod.ui; + +import java.awt.Component; +import java.awt.Container; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import javax.swing.JComponent; +import javax.swing.JSpinner; +import javax.swing.SwingUtilities; +import javax.swing.text.JTextComponent; + +/** + * Keeps keyboard focus (and caret/selection) across a rebuild that replaces components: inputs are tagged with a + * stable key, the focused one is remembered before the rebuild and its replacement focused afterwards. + */ +final class FocusKeeper { + private static final String KEY = "llamamod.focusKey"; + private static final String SELECT_ALL_POLICY = "JTextField.selectAllOnFocusPolicy"; + + /** What had the focus: the tag of the input and, for text, caret and selection. */ + record Snapshot(String key, int caret, int selStart, int selEnd) {} + + private FocusKeeper() {} + + static T tag(T c, String key) { + c.putClientProperty(KEY, key); + return c; + } + + /** The tagged input that contains {@code focusOwner} (e.g. a spinner's text field), or null. */ + static Snapshot capture(Component focusOwner, Container root) { + for (Component c = focusOwner; c != null && c != root; c = c.getParent()) { + if (c instanceof JComponent j && j.getClientProperty(KEY) instanceof String key) { + if (focusOwner instanceof JTextComponent t) { + return new Snapshot(key, t.getCaretPosition(), t.getSelectionStart(), t.getSelectionEnd()); + } + return new Snapshot(key, -1, -1, -1); + } + } + return null; + } + + /** Finds the replacement of the remembered input under {@code root}, restores caret/selection; null if gone. */ + static Component restore(Snapshot s, Container root) { + if (s == null) { + return null; + } + JComponent c = find(root, s.key()); + if (c == null) { + return null; + } + Component target = + c instanceof JSpinner sp && sp.getEditor() instanceof JSpinner.DefaultEditor ed ? ed.getTextField() : c; + if (target instanceof JTextComponent t && s.caret() >= 0) { + int len = t.getDocument().getLength(); + int a = Math.min(s.selStart(), len); + int b = Math.min(s.selEnd(), len); + if (a != b) { + // keep the direction: the caret is where the user left it + t.setCaretPosition(s.caret() == a ? b : a); + t.moveCaretPosition(Math.min(s.caret(), len)); + } else { + t.setCaretPosition(Math.min(s.caret(), len)); + } + } + return target; + } + + /** Focuses the restored input without FlatLaf's select-all on focus gain (it would eat the next key). */ + static void focus(Component c) { + if (c instanceof JTextComponent t) { + t.putClientProperty(SELECT_ALL_POLICY, "never"); + t.addFocusListener(new FocusAdapter() { + @Override + public void focusGained(FocusEvent e) { + t.removeFocusListener(this); + SwingUtilities.invokeLater(() -> t.putClientProperty(SELECT_ALL_POLICY, null)); + } + }); + } + c.requestFocusInWindow(); + } + + private static JComponent find(Container root, String key) { + for (Component c : root.getComponents()) { + if (c instanceof JComponent j && key.equals(j.getClientProperty(KEY))) { + return j; + } + if (c instanceof Container sub) { + JComponent f = find(sub, key); + if (f != null) { + return f; + } + } + } + return null; + } +} diff --git a/src/main/java/com/eliasmueller/llamamod/ui/MainFrame.java b/src/main/java/com/eliasmueller/llamamod/ui/MainFrame.java index 8ff2f66..74bcfde 100644 --- a/src/main/java/com/eliasmueller/llamamod/ui/MainFrame.java +++ b/src/main/java/com/eliasmueller/llamamod/ui/MainFrame.java @@ -48,6 +48,7 @@ final class MainFrame extends JFrame { private final HeaderPanel header = new HeaderPanel(); private final JButton playButton = new JButton(Strings.t("play")); private final JLabel statusLabel = new JLabel(" "); + private final StatusLine statusLine = new StatusLine(statusLabel, StatusLine.TRANSIENT_MS); private final JProgressBar progress = new JProgressBar(0, 1000); private final JButton cancelButton = new JButton(Strings.t("cancel")); private final JTabbedPane tabs = new JTabbedPane(); @@ -124,15 +125,19 @@ final class MainFrame extends JFrame { return l; } - /** Short windows (laptops, 720p) get a lower header so the mod list keeps its room. */ + /** Short windows (laptops, 720p) get a lower header so the mod list and the save table keep their room. */ private void fitHeader() { - int h = getHeight() < 860 ? 104 : 150; + int h = headerHeight(getHeight()); if (header.getPreferredSize().height != h) { header.setPreferredSize(new Dimension(900, h)); header.revalidate(); } } + static int headerHeight(int windowHeight) { + return windowHeight < 700 ? 92 : windowHeight < 860 ? 104 : 150; + } + private void buildUi() { JPanel root = new JPanel(new BorderLayout()); header.setLayout(new BorderLayout()); @@ -284,7 +289,7 @@ final class MainFrame extends JFrame { } modsPanel.reload(); settingsPanel.reload(); - setStatus(Strings.t("status.configMerged")); + setTransientStatus(Strings.t("status.configMerged")); } void onBusy(Consumer l) { @@ -300,7 +305,11 @@ final class MainFrame extends JFrame { } void setStatus(String s) { - statusLabel.setText(s); + statusLine.set(s); + } + + void setTransientStatus(String s) { + statusLine.flash(s); } private void updateGameRunning() { diff --git a/src/main/java/com/eliasmueller/llamamod/ui/ModsPanel.java b/src/main/java/com/eliasmueller/llamamod/ui/ModsPanel.java index 7c29c26..657c7f7 100644 --- a/src/main/java/com/eliasmueller/llamamod/ui/ModsPanel.java +++ b/src/main/java/com/eliasmueller/llamamod/ui/ModsPanel.java @@ -9,6 +9,7 @@ import com.eliasmueller.llamamod.mods.levels.LevelProjects; import com.eliasmueller.llamamod.util.SwingListeners; import java.awt.BorderLayout; import java.awt.Color; +import java.awt.Component; import java.awt.Cursor; import java.awt.Dimension; import java.awt.FlowLayout; @@ -17,6 +18,7 @@ import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.GridLayout; import java.awt.Insets; +import java.awt.KeyboardFocusManager; import java.awt.Point; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; @@ -116,6 +118,9 @@ final class ModsPanel extends JPanel { // rebuilding the cards must not move the list: new spinners and text fields scroll themselves into view Point keep = firstReload ? new Point() : scroll.getViewport().getViewPosition(); firstReload = false; + // e.g. a config merge while the user types in an option: the new field gets the focus and caret + FocusKeeper.Snapshot focus = FocusKeeper.capture( + KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(), list); list.removeAll(); boxes.clear(); removeButtons.clear(); @@ -148,6 +153,10 @@ final class ModsPanel extends JPanel { updateState(); list.revalidate(); list.repaint(); + Component refocus = FocusKeeper.restore(focus, list); + if (refocus != null) { + FocusKeeper.focus(refocus); + } SwingUtilities.invokeLater(() -> { var viewport = scroll.getViewport(); viewport.validate(); @@ -248,7 +257,7 @@ final class ModsPanel extends JPanel { outer.add(c, BorderLayout.CENTER); JCheckBox cb = new JCheckBox(); cb.setSelected(frame.state.cfg.enabledMods.contains(m.id())); - boxes.put(m.id(), cb); + boxes.put(m.id(), FocusKeeper.tag(cb, m.id())); GridBagConstraints g = cell(0, 0, 1, GridBagConstraints.NORTHWEST); g.gridheight = 2; g.insets = new Insets(0, 0, 0, 10); @@ -451,7 +460,7 @@ final class ModsPanel extends JPanel { int row = 0; for (ModOption o : m.options()) { String v = values.get(o.key()); - JComponent input = optionInput(m, o, v); + JComponent input = optionInput(m, o, v, m.id() + "/" + o.key()); String tip = tip(o); GridBagConstraints g = new GridBagConstraints(); g.gridy = row; @@ -513,12 +522,12 @@ final class ModsPanel extends JPanel { return t; } - private JComponent optionInput(Mod m, ModOption o, String value) { + private JComponent optionInput(Mod m, ModOption o, String value, String key) { switch (o.type()) { case BOOL -> { JCheckBox b = new JCheckBox(o.label(), Boolean.parseBoolean(value)); b.addActionListener(e -> setOption(m, o, Boolean.toString(b.isSelected()), b)); - optionInputs.add(b); + optionInputs.add(FocusKeeper.tag(b, key)); return b; } case INT -> { @@ -527,7 +536,7 @@ final class ModsPanel extends JPanel { Long.valueOf(v), Long.valueOf(o.min()), Long.valueOf(o.max()), Long.valueOf(1))); s.addChangeListener(e -> setOption(m, o, Long.toString(((Number) s.getValue()).longValue()), s)); s.setPreferredSize(new Dimension(110, s.getPreferredSize().height)); - optionInputs.add(s); + optionInputs.add(FocusKeeper.tag(s, key)); return s; } case CHOICE -> { @@ -540,7 +549,7 @@ final class ModsPanel extends JPanel { } c.addActionListener(e -> setOption(m, o, o.choices().get(c.getSelectedIndex()).value(), c)); - optionInputs.add(c); + optionInputs.add(FocusKeeper.tag(c, key)); return c; } case MULTI -> { @@ -563,16 +572,16 @@ final class ModsPanel extends JPanel { } setOption(m, o, o.multiValue(chosen), p); }); - optionInputs.add(b); + optionInputs.add(FocusKeeper.tag(b, key + "#" + c.value())); p.add(b); } return p; } case SEED -> { - JTextField t = textInput(m, o, value, 12); + JTextField t = textInput(m, o, value, 12, key); JButton random = new JButton(Strings.t("mods.option.random")); random.addActionListener(e -> t.setText(ModOptions.randomSeed())); - optionInputs.add(random); + optionInputs.add(FocusKeeper.tag(random, key + "#random")); JPanel p = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0)); p.setOpaque(false); p.add(t); @@ -581,15 +590,15 @@ final class ModsPanel extends JPanel { return p; } default -> { - return textInput(m, o, value, 20); + return textInput(m, o, value, 20, key); } } } - private JTextField textInput(Mod m, ModOption o, String value, int columns) { + private JTextField textInput(Mod m, ModOption o, String value, int columns, String key) { JTextField t = new JTextField(value, columns); SwingListeners.onTextChange(t, () -> setOption(m, o, t.getText(), t)); - optionInputs.add(t); + optionInputs.add(FocusKeeper.tag(t, key)); return t; } diff --git a/src/main/java/com/eliasmueller/llamamod/ui/SavesPanel.java b/src/main/java/com/eliasmueller/llamamod/ui/SavesPanel.java index ba3faf6..f67fcdb 100644 --- a/src/main/java/com/eliasmueller/llamamod/ui/SavesPanel.java +++ b/src/main/java/com/eliasmueller/llamamod/ui/SavesPanel.java @@ -78,9 +78,14 @@ final class SavesPanel extends JPanel { JPanel left = new JPanel(new BorderLayout()); JLabel hint = App.hintLabel(Strings.t("saves.hint"), 200, 11.5f); hint.setBorder(BorderFactory.createEmptyBorder(12, 2, 0, 0)); + // the table's legend lives here, where there is room: at the minimum window height every + // line under the table would cost a table row + JLabel coinsHint = App.hintLabel(Strings.t("saves.coinsHint"), 200, 11.5f); + coinsHint.setBorder(BorderFactory.createEmptyBorder(10, 2, 0, 0)); JPanel leftTop = new JPanel(new BorderLayout()); leftTop.add(slots, BorderLayout.NORTH); leftTop.add(hint, BorderLayout.CENTER); + leftTop.add(coinsHint, BorderLayout.SOUTH); left.add(leftTop, BorderLayout.NORTH); add(left, BorderLayout.WEST); @@ -94,7 +99,7 @@ final class SavesPanel extends JPanel { slotTitle.setFont(slotTitle.getFont().deriveFont(Font.BOLD, 17f)); ed.add(slotTitle, g); g.gridy++; - g.insets = new Insets(2, 0, 10, 0); + g.insets = new Insets(2, 0, 4, 0); ed.add(slotInfo, g); for (int w = 1; w <= Worlds.COUNT; w++) { @@ -143,10 +148,6 @@ final class SavesPanel extends JPanel { JScrollPane sp = new JScrollPane(table); sp.setPreferredSize(new Dimension(420, 180)); ed.add(sp, g); - g.gridy++; - g.weighty = 0; - g.fill = GridBagConstraints.HORIZONTAL; - ed.add(App.hintLabel(Strings.t("saves.coinsHint"), 2000, 11.5f), g); add(ed, BorderLayout.CENTER); JPanel buttons = new JPanel(new BorderLayout()); diff --git a/src/main/java/com/eliasmueller/llamamod/ui/SetupWizard.java b/src/main/java/com/eliasmueller/llamamod/ui/SetupWizard.java index b6f1351..a03459a 100644 --- a/src/main/java/com/eliasmueller/llamamod/ui/SetupWizard.java +++ b/src/main/java/com/eliasmueller/llamamod/ui/SetupWizard.java @@ -313,6 +313,24 @@ final class SetupWizard extends JDialog { dispose(); } + /** + * The bar follows the copied megabytes exactly (so it matches the "Copying x of y MB" text); the short steps + * after the copy show a busy bar instead of a percentage. + */ + private void showProgress(double installFraction, String message) { + double copy = barFraction(installFraction); + boolean copying = copy < 1; + bar.setIndeterminate(!copying); + bar.setStringPainted(copying); + bar.setValue((int) Math.round(copy * 1000)); + progressText.setText(message); + } + + /** Copy share of the installer progress mapped onto 0..1. */ + static double barFraction(double installFraction) { + return Math.max(0, Math.min(1, installFraction / Installer.COPY_SHARE)); + } + private void startInstall() { if (!checkSource()) { frame.error(new IllegalArgumentException(Strings.t("wizard.noSource"))); @@ -331,10 +349,7 @@ final class SetupWizard extends JDialog { Progress p = new Progress() { @Override public void update(double f, String m) { - SwingUtilities.invokeLater(() -> { - bar.setValue((int) (f * 1000)); - progressText.setText(m); - }); + SwingUtilities.invokeLater(() -> showProgress(f, m)); } @Override @@ -346,10 +361,10 @@ final class SetupWizard extends JDialog { @Override protected Object doInBackground() throws Exception { try (GameSource gs = GameSource.open(src)) { - new Installer(state.paths).install(gs, state.cfg, p.sub(0, 0.95)); + new Installer(state.paths).install(gs, state.cfg, p); } // re-setup keeps the active mods - state.modManager.apply(state.activeMods(), p.sub(0.95, 1)); + state.modManager.apply(state.activeMods(), (f, m) -> p.update(1, m)); return state.saves.migrateNullSaves(); } diff --git a/src/main/java/com/eliasmueller/llamamod/ui/StatusLine.java b/src/main/java/com/eliasmueller/llamamod/ui/StatusLine.java new file mode 100644 index 0000000..8b4dd63 --- /dev/null +++ b/src/main/java/com/eliasmueller/llamamod/ui/StatusLine.java @@ -0,0 +1,36 @@ +package com.eliasmueller.llamamod.ui; + +import javax.swing.JLabel; +import javax.swing.Timer; + +/** The status bar text: lasting messages, and transient ones that give way to the lasting one after a while. */ +final class StatusLine { + static final int TRANSIENT_MS = 6000; + + private final JLabel label; + private final Timer expire; + private String resting; + + StatusLine(JLabel label, int transientMs) { + this.label = label; + this.resting = label.getText(); + expire = new Timer(transientMs, e -> label.setText(resting)); + expire.setRepeats(false); + } + + void set(String s) { + expire.stop(); + resting = s; + label.setText(s); + } + + /** Shown for a few seconds, then the last lasting message comes back (unless something newer replaced it). */ + void flash(String s) { + label.setText(s); + expire.restart(); + } + + boolean showingTransient() { + return expire.isRunning(); + } +} diff --git a/src/test/java/com/eliasmueller/llamamod/ui/FocusKeeperTest.java b/src/test/java/com/eliasmueller/llamamod/ui/FocusKeeperTest.java new file mode 100644 index 0000000..db5fadc --- /dev/null +++ b/src/test/java/com/eliasmueller/llamamod/ui/FocusKeeperTest.java @@ -0,0 +1,83 @@ +package com.eliasmueller.llamamod.ui; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertSame; + +import javax.swing.JPanel; +import javax.swing.JSpinner; +import javax.swing.JTextField; +import javax.swing.SpinnerNumberModel; +import org.junit.jupiter.api.Test; + +class FocusKeeperTest { + private static JPanel form(String text) { + JPanel root = new JPanel(); + JPanel card = new JPanel(); + card.add(FocusKeeper.tag(new JTextField(text, 10), "mod/name")); + card.add(FocusKeeper.tag(new JSpinner(new SpinnerNumberModel(5, 0, 9, 1)), "mod/count")); + root.add(card); + return root; + } + + private static JTextField field(JPanel root) { + return (JTextField) ((JPanel) root.getComponent(0)).getComponent(0); + } + + @Test + void caretMovesToTheRebuiltField() { + JPanel before = form("llama"); + JTextField old = field(before); + old.setCaretPosition(3); + FocusKeeper.Snapshot s = FocusKeeper.capture(old, before); + assertNotNull(s); + assertEquals("mod/name", s.key()); + + JPanel after = form("llama"); + assertSame(field(after), FocusKeeper.restore(s, after)); + assertEquals(3, field(after).getCaretPosition()); + } + + @Test + void selectionAndShorterTextAreHandled() { + JPanel before = form("llamas"); + JTextField old = field(before); + old.setCaretPosition(1); + old.moveCaretPosition(5); + FocusKeeper.Snapshot s = FocusKeeper.capture(old, before); + + JPanel after = form("llamas"); + FocusKeeper.restore(s, after); + assertEquals(1, field(after).getSelectionStart()); + assertEquals(5, field(after).getSelectionEnd()); + assertEquals(5, field(after).getCaretPosition()); + + JPanel shorter = form("ll"); + FocusKeeper.restore(s, shorter); + assertEquals(2, field(shorter).getCaretPosition()); + } + + @Test + void spinnerEditorMapsToTheSpinner() { + JPanel before = form("x"); + JSpinner sp = (JSpinner) ((JPanel) before.getComponent(0)).getComponent(1); + JTextField editor = ((JSpinner.DefaultEditor) sp.getEditor()).getTextField(); + FocusKeeper.Snapshot s = FocusKeeper.capture(editor, before); + assertEquals("mod/count", s.key()); + + JPanel after = form("x"); + JSpinner sp2 = (JSpinner) ((JPanel) after.getComponent(0)).getComponent(1); + assertSame(((JSpinner.DefaultEditor) sp2.getEditor()).getTextField(), FocusKeeper.restore(s, after)); + } + + @Test + void untaggedOrMissingGivesNull() { + JPanel root = new JPanel(); + JTextField plain = new JTextField(); + root.add(plain); + assertNull(FocusKeeper.capture(plain, root)); + assertNull(FocusKeeper.capture(null, root)); + assertNull(FocusKeeper.restore(new FocusKeeper.Snapshot("gone", 0, 0, 0), root)); + } +} diff --git a/src/test/java/com/eliasmueller/llamamod/ui/MainFrameLayoutTest.java b/src/test/java/com/eliasmueller/llamamod/ui/MainFrameLayoutTest.java new file mode 100644 index 0000000..7a7ee01 --- /dev/null +++ b/src/test/java/com/eliasmueller/llamamod/ui/MainFrameLayoutTest.java @@ -0,0 +1,16 @@ +package com.eliasmueller.llamamod.ui; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.Test; + +class MainFrameLayoutTest { + @Test + void headerShrinksForShortWindows() { + assertEquals(150, MainFrame.headerHeight(900)); + assertEquals(104, MainFrame.headerHeight(760)); + assertEquals(104, MainFrame.headerHeight(720)); + // the 640 px minimum: the Saves table keeps four rows + assertEquals(92, MainFrame.headerHeight(640)); + } +} diff --git a/src/test/java/com/eliasmueller/llamamod/ui/SetupWizardProgressTest.java b/src/test/java/com/eliasmueller/llamamod/ui/SetupWizardProgressTest.java new file mode 100644 index 0000000..2acac9a --- /dev/null +++ b/src/test/java/com/eliasmueller/llamamod/ui/SetupWizardProgressTest.java @@ -0,0 +1,18 @@ +package com.eliasmueller.llamamod.ui; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import com.eliasmueller.llamamod.platform.Installer; +import org.junit.jupiter.api.Test; + +class SetupWizardProgressTest { + @Test + void barFollowsTheCopiedMegabytes() { + // 553 of 568 MB copied: the bar must say 97 %, not the 78 % of the whole setup + double copied = 553.0 / 568.0; + assertEquals(copied, SetupWizard.barFraction(copied * Installer.COPY_SHARE), 1e-9); + assertEquals(0, SetupWizard.barFraction(0)); + assertEquals(1, SetupWizard.barFraction(Installer.COPY_SHARE)); + assertEquals(1, SetupWizard.barFraction(0.9)); // checking/creating: full (shown as busy) + } +} diff --git a/src/test/java/com/eliasmueller/llamamod/ui/StatusLineTest.java b/src/test/java/com/eliasmueller/llamamod/ui/StatusLineTest.java new file mode 100644 index 0000000..faced30 --- /dev/null +++ b/src/test/java/com/eliasmueller/llamamod/ui/StatusLineTest.java @@ -0,0 +1,45 @@ +package com.eliasmueller.llamamod.ui; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import javax.swing.JLabel; +import javax.swing.SwingUtilities; +import org.junit.jupiter.api.Test; + +class StatusLineTest { + private static void onEdt(Runnable r) throws Exception { + SwingUtilities.invokeAndWait(r); + } + + @Test + void transientMessageGivesWayToTheLastingOne() throws Exception { + JLabel l = new JLabel(" "); + StatusLine s = new StatusLine(l, 150); + onEdt(() -> { + s.set("Ready."); + s.flash("Took over changes made in another LlamaMod window."); + }); + assertEquals("Took over changes made in another LlamaMod window.", l.getText()); + assertTrue(s.showingTransient()); + Thread.sleep(600); + onEdt(() -> {}); + assertEquals("Ready.", l.getText()); + assertFalse(s.showingTransient()); + } + + @Test + void newerLastingMessageIsNotOverwritten() throws Exception { + JLabel l = new JLabel(" "); + StatusLine s = new StatusLine(l, 150); + onEdt(() -> { + s.set("Ready."); + s.flash("merged"); + s.set("Applying mods"); + }); + Thread.sleep(600); + onEdt(() -> {}); + assertEquals("Applying mods", l.getText()); + } +} diff --git a/tools/apptest.py b/tools/apptest.py index 2a76c10..b86a811 100755 --- a/tools/apptest.py +++ b/tools/apptest.py @@ -14,14 +14,17 @@ Commands (NAME first; --display only for 'start'/'run', remembered afterwards): apptest.py apply NAME [ids] [--opt id.k=v]... apply mods (none = original) via the app CLI apptest.py unlock NAME SLOT WORLD CHAPTER unlock up to WORLD/CHAPTER, map cursor there apptest.py start NAME --display N Xvfb :N + private pulse + game (app --launch) - apptest.py tolevel NAME [--world W] main menu -> slot 3 -> map -> level -> gameplay + apptest.py tolevel NAME [--world W] [--slot S] main menu -> slot S (3) -> map -> level -> gameplay apptest.py keys NAME Up:1.5 x sleep=1 a+x:0.5 shot:name ... key sequence (hold s, default 0.2) apptest.py shot NAME out.png [--small] screenshot (1920x1080 PNG, --small = 960x540 JPEG) apptest.py ocr NAME [WxH+X+Y] German OCR of the screen (or a crop) apptest.py status NAME game/window/crash/audio state (exit 3 = crashed) apptest.py stop NAME kill game (wineserver -k), Xvfb and pulse of NAME apptest.py run NAME --display N --mods a,b [--opt id.k=v]... --level W C [--seq "..."] --out DIR [--keep] - all in one; exit 0 ok, 3 crash, 4 timeout, 2 usage + [--no-retry] all in one; exit 0 ok, 3 crash, 4 timeout, 2 usage. + A crash before the main menu or a missed save slot screen + is retried once (report.json "retries", out/retry1_*); + --no-retry turns that off Options of every command: --root DIR, --jar FILE (default: newest build/libs/*-all.jar), --iso FILE (default ~/Downloads/GROOVE_DK.iso). Python: `from apptest import Session`. @@ -34,6 +37,7 @@ Safety: never uses display :0, never touches ~/.wine-lama, kills only PIDs it st import fcntl import json import os +import re import shutil import signal import subprocess @@ -51,6 +55,10 @@ SLOT_CROP = "1600x280+160+740" # save-slot text "Gespeichertes Spiel N / MENU_CROP = "700x300+1150+650" # main menu items (bottom right) +# world -> word the save slot shows for it (OCR, lower case); only the verified ones +SLOT_WORLD_NAMES = {1: "dorf", 9: "testlevel"} + + class Crash(Exception): pass @@ -517,8 +525,8 @@ class Session: raise Timeout("timeout (%d s) waiting for %s" % (timeout, what)) # ------------------------------------------------------------ navigation - def tolevel(self, world=None, skip_flyby=True): - """Main menu -> "Spiel starten" -> slot 3 (rightmost) -> map (cursor from --unlock ... --cursor) + def tolevel(self, world=None, skip_flyby=True, on_menu=None, slot=3): + """Main menu -> "Spiel starten" -> save slot (default 3) -> map (cursor from --unlock ... --cursor) -> Enter -> skip the fly-by -> gameplay. Returns timings.""" T = {} t0 = tx = time.time() @@ -528,10 +536,14 @@ class Session: raise Crash(c) if fuzzy_in("spiel starten", self.ocr(MENU_CROP, threshold=75, psm=6, scale="100%")): log("main menu") + if on_menu: + on_menu() time.sleep(0.5) - self.key("Return") + self.key("Return", 0.6) break if fuzzy_in("gespeichertes", self.slot_text()): + if on_menu: + on_menu() break if time.time() - tx > 40: log("no menu yet -> Return (skips logo/demo)") @@ -541,21 +553,15 @@ class Session: raise Timeout("main menu not reached") time.sleep(1) T["menu"] = round(time.time() - t0, 1) - self.wait_for(lambda: fuzzy_in("gespeichertes", self.slot_text()), 20, "save slot screen") - time.sleep(0.4) - for _ in range(2): # 3-slot slider without wrap: slot 3 is the rightmost - self.key("Right", 0.3) - time.sleep(0.3) - for i in range(3): - time.sleep(0.6) - t = self.slot_text() - if fuzzy_in("kapitel", t) and not fuzzy_in("leer", t): - log("slot: %s" % t.split(" | ")[0]) - break - self.key("Right", 0.3) - else: - log("WARNING: slot 3 text not recognised (%s)" % t) - self.key("Return") + self._to_slot_screen() + t = self._select_slot(slot) + if not self._slot_ok(t): + # an empty slot starts a new game in the village: never the level that was asked for + raise Timeout("save slot %d is empty (%s) - unlock it first" % (slot, t)) + name = SLOT_WORLD_NAMES.get(world) + if name and not fuzzy_in(name, t): + raise Timeout("save slot %d holds another world (%s), expected %r" % (slot, t, name)) + self._open_slot() T["slot"] = round(time.time() - t0, 1) if world == 9: self.wait_for(lambda: self.classify() == "map", 30, "world 9 map") @@ -563,10 +569,11 @@ class Session: else: self.wait_for(lambda: self.classify() not in ("black", "none"), 30, "map") self.wait_stable(still=1.5, timeout=20) - self.key("Return") + map_thumb = self.thumb() + self.key("Return", 0.6) t_load = time.time() T["map"] = round(t_load - t0, 1) - skipped, good, states = False, 0, [] + skipped, good, states, again = False, 0, [], 0 while time.time() - t_load < 150: c = self.crashed() if c: @@ -575,7 +582,12 @@ class Session: if not states or states[-1] != st: states.append(st) log("state: %s (%.1f s after level start)" % (st, time.time() - t_load)) - if st == "letterbox" and skip_flyby and not skipped: + if "black" not in states and "letterbox" not in states and time.time() - t_load > 8 + 8 * again \ + and again < 2 and self.diff(self.thumb(), map_thumb) < 6: + again += 1 # still on the map: the Return was missed + log("level did not start -> Return again") + self.key("Return", 0.6 + 0.3 * again) + elif st == "letterbox" and skip_flyby and not skipped: time.sleep(0.5) self.key("Return") skipped = True @@ -596,6 +608,79 @@ class Session: log("gameplay after %.1f s, states %s" % (T["gameplay"], states)) return T + def _to_slot_screen(self, timeout=45): + """Waits for the save slot screen; a Return the menu missed (still fading in, or a key press shorter + than one frame on a loaded machine) is repeated, held a little longer each time.""" + t0 = tr = time.time() + holds = [0.8, 1.0, 1.2] + while time.time() - t0 < timeout: + c = self.crashed() + if c: + raise Crash(c) + if fuzzy_in("gespeichertes", self.slot_text()): + return + if time.time() - tr > 5 and fuzzy_in("spiel starten", self.ocr(MENU_CROP, threshold=75, psm=6, + scale="100%")): + hold = holds.pop(0) if holds else 1.2 + log("still in the main menu -> Return again (held %.1f s)" % hold) + self.key("Return", hold) + tr = time.time() + time.sleep(0.7) + raise Timeout("timeout (%d s) waiting for save slot screen" % timeout) + + @staticmethod + def _slot_ok(text): + return fuzzy_in("kapitel", text) and not fuzzy_in("leer", text) + + @staticmethod + def _slot_no(text): + """Slot number from "gespeichertes spiel N" (OCR text), or None.""" + m = re.search(r"spiel\s*([123])\b", text) + return int(m.group(1)) if m else None + + def _select_slot(self, slot=3, timeout=240): + """Turns the save slot carousel (it opens on slot 2) to `slot` and checks its text after every step. + The carousel wraps (3 -> 1) and ignores keys while it turns, so Right is pressed once per step and + only again when the text shows another slot. A step that did not move is repeated with a longer + hold (0.3/0.6/1.0/1.5 s). On a busy machine (load ~30, several games) the carousel ignored + Left/Right for minutes while Return/Escape worked: `run` therefore uses slot 2, which needs no + turning.""" + self.wait_stable(still=0.8, timeout=6) + holds = [0.3, 0.6, 1.0, 1.5] + t0 = time.time() + t = self.slot_text() + while time.time() - t0 < timeout: + if self._slot_no(t) == slot: + log("slot: %s" % t.split(" | ")[0]) + return t + if not fuzzy_in("gespeichertes", t): + raise Timeout("save slot screen lost while selecting slot %d (%s)" % (slot, t)) + before = self._slot_no(t) + self.key("Right", holds[0]) + t1 = time.time() + while time.time() - t1 < 8: # the carousel turns, then the new text shows + time.sleep(0.6) + t = self.slot_text() + if self._slot_no(t) not in (None, before): + break + else: + if len(holds) > 1: + holds.pop(0) + log("slot carousel did not move (slot %s) -> Right again, held %.1f s" % (before, holds[0])) + raise Timeout("save slot %d not selected after %d s (%s)" % (slot, timeout, t)) + + def _open_slot(self): + """Return on the slot until the slot screen is gone (a short press can be missed under load).""" + for hold in (0.6, 0.9, 1.2): + self.key("Return", hold) + t1 = time.time() + while time.time() - t1 < 6: + time.sleep(0.7) + if not fuzzy_in("gespeichertes", self.slot_text()): + return + log("still on the save slot screen -> Return again") + raise Timeout("save slot did not open") + def status(self): s = {"display": self.display, "data": self.data, "game_pids": self.game_pids(), "window": self.find_window() if self.display and self.state.get("xvfb_pid") else None, @@ -606,18 +691,53 @@ class Session: return s -def run(sess, mods, opts, level, seq, out, keep=False): +def start_to_level(sess, level, out, report, retry=True): + """start + tolevel; a crash before the main menu (Wine page faults at start-up, not caused by mods) or a + menu that was not recognised is retried once with a fresh game start. Each retry is listed in + report["retries"] and logged; the failed attempt's screenshot/log go to out/retry1_*.""" + for attempt in (1, 2): + phase = "start" + try: + sess.start() + if level: + phase = "menu" + report["tolevel"] = sess.tolevel(world=level[0], slot=2, + on_menu=lambda: report.update(menu_reached=True)) + return + except (Crash, Timeout) as e: + early = isinstance(e, Crash) and not report.get("menu_reached") or \ + isinstance(e, Timeout) and "save slot" in str(e) + if not retry or attempt == 2 or not early: + raise + log("WARNING: %s during %s -> stopping and starting the game once more" % (e, phase)) + try: + sess.shot(os.path.join(out, "retry1_failure.jpg"), small=True) + except SystemExit: + pass + gl = os.path.join(sess.data, "logs", "game.log") + if os.path.exists(gl): + shutil.copy(gl, os.path.join(out, "retry1_game.log")) + report.setdefault("retries", []).append({"attempt": attempt, "phase": phase, "error": str(e)}) + report.pop("menu_reached", None) + sess.stop() + + +def run(sess, mods, opts, level, seq, out, keep=False, retry=True): os.makedirs(out, exist_ok=True) - report = {"mods": mods, "opts": opts, "level": level} + # a busy machine (several agents' games) slows the game to a few frames per second: the usual cause of + # missed key presses; recorded to tell flaky runs apart + report = {"mods": mods, "opts": opts, "level": level, "load_avg": [round(x, 1) for x in os.getloadavg()], + "cpus": os.cpu_count()} code = 0 try: sess.setup() report["apply"] = sess.apply(mods, opts).strip().splitlines()[-3:] if level: + # slot 2 is where the carousel opens (no turning, see _select_slot); slot 3 gets the same + # progress for mods whose "save slot" option defaults to 3 + sess.unlock(2, level[0], level[1]) sess.unlock(3, level[0], level[1]) - sess.start() - if level: - report["tolevel"] = sess.tolevel(world=level[0]) + start_to_level(sess, level, out, report, retry) sess.shot(os.path.join(out, "00_start.png")) if seq: report["shots"] = sess.keys(seq, outdir=out) @@ -647,7 +767,8 @@ def run(sess, mods, opts, level, seq, out, keep=False): json.dump(report, open(os.path.join(out, "report.json"), "w"), indent=1) if not keep: sess.stop() - log("result: %s" % (report.get("error") or "OK")) + retried = "" if not report.get("retries") else " (after a retry: %s)" % report["retries"][0]["error"] + log("result: %s%s" % (report.get("error") or "OK", retried)) return code @@ -660,7 +781,8 @@ def main(argv): i = 0 while i < len(rest): a = rest[i] - if a in ("--display", "--root", "--jar", "--iso", "--mods", "--world", "--seq", "--out") and i + 1 < len(rest): + if a in ("--display", "--root", "--jar", "--iso", "--mods", "--world", "--slot", "--seq", "--out") \ + and i + 1 < len(rest): kw[a[2:]] = rest[i + 1] i += 2 elif a == "--opt" and i + 1 < len(rest): @@ -685,7 +807,8 @@ def main(argv): elif cmd == "start": s.start() elif cmd == "tolevel": - print(json.dumps(s.tolevel(world=int(kw["world"]) if "world" in kw else None))) + print(json.dumps(s.tolevel(world=int(kw["world"]) if "world" in kw else None, + slot=int(kw.get("slot", 3))))) elif cmd == "keys": print(s.keys(pos, outdir=kw.get("out"))) elif cmd == "shot": @@ -703,7 +826,8 @@ def main(argv): print("run needs --display N and --out DIR") return 2 mods = [x for x in kw.get("mods", "").split(",") if x] - return run(s, mods, opts, kw.get("level"), kw.get("seq"), kw["out"], keep="--keep" in pos) + return run(s, mods, opts, kw.get("level"), kw.get("seq"), kw["out"], keep="--keep" in pos, + retry="--no-retry" not in pos) else: print(__doc__) return 2 diff --git a/tools/geom_export.py b/tools/geom_export.py index e712125..7544efc 100644 --- a/tools/geom_export.py +++ b/tools/geom_export.py @@ -9,7 +9,8 @@ Writes to outdir: page_NN.png texture pages (256x256, from TEXT) collision.obj (--collision) collision polygons, grouped by material objects.obj (--objects) static STPC object models side by side - preview_top.png, preview_persp.png textured software renderings for checking + preview_top.png, preview_persp.png textured software renderings for checking (game space, + the same way round as in the game) Coordinates: OBJ file space = game space (x, y, z_game): right-handed, y up, z > 0 in the grid, as Blender shows the level the same way round as the game (geomlib.to_file). --export-space writes @@ -101,6 +102,11 @@ def write_mtl(path, tris, texs, npages): # ------------------------------------------------------------ software renderer +def game_space_tris(tris): + """world_tris (export space) -> game space for the right-handed preview camera.""" + return [([G.to_file(p) for p in P], *rest) for P, *rest in tris] + + def render(tris, pages, cam, size, path, texs): Wd, Hd = size eye, target, fov = cam @@ -237,10 +243,13 @@ def main(): for k, im in enumerate(imgs): Image.fromarray(im).save(os.path.join(a.outdir, f'page_{k:02d}.png')) size = tuple(int(s) for s in a.size.split('x')) + # the renderer's camera is right-handed: game space shows the level as the game does + # (export space would come out mirrored); also with --export-space + tris = game_space_tris(tris) P = np.array([p for t in tris for p in t[0]]) lo, hi = P.min(0), P.max(0); c = (lo + hi) / 2 ext = max(hi[0] - lo[0], hi[2] - lo[2]) - # top view (almost vertical, north = -z at the top) + # top view (almost vertical, game -z at the top) render(tris, imgs, ((c[0], hi[1] + ext * 1.2, c[2] + 0.01), (c[0], lo[1], c[2]), 50), size, os.path.join(a.outdir, 'preview_top.png'), texs) render(tris, imgs, ((c[0] + ext * 0.35, hi[1] + ext * 0.45, hi[2] + ext * 0.45), tuple(c), 60), size, diff --git a/tools/test_apptest.py b/tools/test_apptest.py new file mode 100644 index 0000000..4ede2e7 --- /dev/null +++ b/tools/test_apptest.py @@ -0,0 +1,86 @@ +"""Offline tests of apptest's retry/slot logic (no game needed): python3 -m unittest tools/test_apptest.py""" +import os +import sys +import tempfile +import unittest + +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) +import apptest as A # noqa: E402 + + +class FakeSession: + def __init__(self, outcomes): + self.outcomes = list(outcomes) # per start: None ok, or exception raised by start/tolevel + self.data = tempfile.mkdtemp() + self.starts = self.stops = 0 + + def start(self): + self.starts += 1 + o = self.outcomes.pop(0) + if isinstance(o, A.Crash) and "start" in str(o): + raise o + self._next = o + + def tolevel(self, world=None, slot=3, on_menu=None): + o = self._next + if isinstance(o, A.Crash) and "level" in str(o): + on_menu() + raise o + if o: + raise o + on_menu() + return {"slot": slot} + + def shot(self, path, small=False): + open(path, "w").close() + + def stop(self): + self.stops += 1 + + +class StartRetryTest(unittest.TestCase): + def setUp(self): + self.out = tempfile.mkdtemp() + + def test_early_crash_is_retried_once_and_reported(self): + s, rep = FakeSession([A.Crash("start: page fault"), None]), {} + A.start_to_level(s, (1, 1), self.out, rep) + self.assertEqual(2, s.starts) + self.assertEqual([{"attempt": 1, "phase": "start", "error": "start: page fault"}], rep["retries"]) + self.assertEqual({"slot": 2}, rep["tolevel"]) + self.assertTrue(os.path.exists(os.path.join(self.out, "retry1_failure.jpg"))) + + def test_missed_slot_screen_is_retried(self): + s, rep = FakeSession([A.Timeout("timeout (45 s) waiting for save slot screen"), None]), {} + A.start_to_level(s, (1, 1), self.out, rep) + self.assertEqual("menu", rep["retries"][0]["phase"]) + + def test_crash_after_the_menu_is_not_retried(self): + s, rep = FakeSession([A.Crash("level: page fault"), None]), {} + with self.assertRaises(A.Crash): + A.start_to_level(s, (1, 1), self.out, rep) + self.assertEqual(1, s.starts) + self.assertNotIn("retries", rep) + + def test_second_failure_and_no_retry_raise(self): + s = FakeSession([A.Crash("start: a"), A.Crash("start: b")]) + with self.assertRaises(A.Crash): + A.start_to_level(s, None, self.out, {}) + self.assertEqual(2, s.starts) + s = FakeSession([A.Crash("start: a"), None]) + with self.assertRaises(A.Crash): + A.start_to_level(s, None, self.out, {}, retry=False) + + +class SlotTextTest(unittest.TestCase): + def test_slot_number_and_content(self): + S = A.Session + self.assertEqual(2, S._slot_no(". gespeichertes spiel 2 u leer | gespeichertes spiel 2 u leer")) + self.assertEqual(3, S._slot_no("gespeichertes spiel 3 dorf kapitel 1")) + self.assertIsNone(S._slot_no("eingabe neues spiel starten")) + self.assertTrue(S._slot_ok("gespeichertes spiel 2 u testlevel kapitel 1 goldmünzen")) + self.assertFalse(S._slot_ok("gespeichertes spiel 2 u leer")) + + +if __name__ == "__main__": + unittest.main()