a2qlinux 0.2.0__tar.gz → 0.2.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. {a2qlinux-0.2.0 → a2qlinux-0.2.1}/CHANGELOG.md +13 -0
  2. {a2qlinux-0.2.0 → a2qlinux-0.2.1}/PKG-INFO +5 -3
  3. {a2qlinux-0.2.0 → a2qlinux-0.2.1}/README.md +4 -2
  4. {a2qlinux-0.2.0 → a2qlinux-0.2.1}/a2qlinux/_version.py +2 -2
  5. {a2qlinux-0.2.0 → a2qlinux-0.2.1}/a2qlinux/bin/questlog_ctl.exe +0 -0
  6. {a2qlinux-0.2.0 → a2qlinux-0.2.1}/a2qlinux/bin/wpcap.dll +0 -0
  7. {a2qlinux-0.2.0 → a2qlinux-0.2.1}/a2qlinux/config.py +20 -0
  8. {a2qlinux-0.2.0 → a2qlinux-0.2.1}/a2qlinux/setup_desktop.py +18 -12
  9. a2qlinux-0.2.1/bridge/build.sh +81 -0
  10. {a2qlinux-0.2.0 → a2qlinux-0.2.1}/docs/ARCHITECTURE.md +36 -5
  11. {a2qlinux-0.2.0 → a2qlinux-0.2.1}/docs/INSTALL.md +69 -17
  12. {a2qlinux-0.2.0 → a2qlinux-0.2.1}/tests/test_config.py +34 -0
  13. a2qlinux-0.2.0/bridge/build.sh +0 -26
  14. {a2qlinux-0.2.0 → a2qlinux-0.2.1}/.gitignore +0 -0
  15. {a2qlinux-0.2.0 → a2qlinux-0.2.1}/LICENSE +0 -0
  16. {a2qlinux-0.2.0 → a2qlinux-0.2.1}/a2qlinux/__init__.py +0 -0
  17. {a2qlinux-0.2.0 → a2qlinux-0.2.1}/a2qlinux/desktop.py +0 -0
  18. {a2qlinux-0.2.0 → a2qlinux-0.2.1}/a2qlinux/launcher.py +0 -0
  19. {a2qlinux-0.2.0 → a2qlinux-0.2.1}/a2qlinux/pcap_bridge.py +0 -0
  20. {a2qlinux-0.2.0 → a2qlinux-0.2.1}/a2qlinux/steam.py +0 -0
  21. {a2qlinux-0.2.0 → a2qlinux-0.2.1}/a2qlinux/tray.py +0 -0
  22. {a2qlinux-0.2.0 → a2qlinux-0.2.1}/a2qlinux/update.py +0 -0
  23. {a2qlinux-0.2.0 → a2qlinux-0.2.1}/bridge/questlog_ctl.c +0 -0
  24. {a2qlinux-0.2.0 → a2qlinux-0.2.1}/bridge/tests/bridge_client_test.c +0 -0
  25. {a2qlinux-0.2.0 → a2qlinux-0.2.1}/bridge/tests/zorder_guard_test.c +0 -0
  26. {a2qlinux-0.2.0 → a2qlinux-0.2.1}/bridge/wpcap_bridge.c +0 -0
  27. {a2qlinux-0.2.0 → a2qlinux-0.2.1}/docs/README.md +0 -0
  28. {a2qlinux-0.2.0 → a2qlinux-0.2.1}/docs/RELEASE.md +0 -0
  29. {a2qlinux-0.2.0 → a2qlinux-0.2.1}/docs/TROUBLESHOOTING.md +0 -0
  30. {a2qlinux-0.2.0 → a2qlinux-0.2.1}/docs/UPDATING.md +0 -0
  31. {a2qlinux-0.2.0 → a2qlinux-0.2.1}/docs/USING.md +0 -0
  32. {a2qlinux-0.2.0 → a2qlinux-0.2.1}/pyproject.toml +0 -0
  33. {a2qlinux-0.2.0 → a2qlinux-0.2.1}/tests/__init__.py +0 -0
  34. {a2qlinux-0.2.0 → a2qlinux-0.2.1}/tests/test_desktop.py +0 -0
  35. {a2qlinux-0.2.0 → a2qlinux-0.2.1}/tests/test_launcher.py +0 -0
  36. {a2qlinux-0.2.0 → a2qlinux-0.2.1}/tests/test_pcap_bridge.py +0 -0
  37. {a2qlinux-0.2.0 → a2qlinux-0.2.1}/tests/test_replay_stream.py +0 -0
  38. {a2qlinux-0.2.0 → a2qlinux-0.2.1}/tests/test_setup_desktop.py +0 -0
  39. {a2qlinux-0.2.0 → a2qlinux-0.2.1}/tests/test_steam.py +0 -0
  40. {a2qlinux-0.2.0 → a2qlinux-0.2.1}/tests/test_update.py +0 -0
  41. {a2qlinux-0.2.0 → a2qlinux-0.2.1}/tools/__init__.py +0 -0
  42. {a2qlinux-0.2.0 → a2qlinux-0.2.1}/tools/pcap2questlog.py +0 -0
  43. {a2qlinux-0.2.0 → a2qlinux-0.2.1}/tools/replay_stream.py +0 -0
  44. {a2qlinux-0.2.0 → a2qlinux-0.2.1}/tools/tcp_owner_probe.c +0 -0
@@ -3,6 +3,19 @@
3
3
  What changed for players, release by release. Technical details are in
4
4
  `docs/ARCHITECTURE.md`.
5
5
 
6
+ ## [0.2.1] — 2026-11-05
7
+
8
+ ### Fixed
9
+ - `a2qlinux-setup --questlog-dir <folder>` now always takes effect: the
10
+ folder is written into the settings file even when that file already
11
+ exists, and the other settings in it stay as they were.
12
+
13
+ ### Changed
14
+ - Installing from the source code is one command, `install-from-source.sh`,
15
+ which builds, installs and sets up. The build looks for Wine's files where
16
+ the distributions in the install guide keep them, and names missing build
17
+ tools with the command that installs them.
18
+
6
19
  ## [0.2.0] — 2026-11-05
7
20
 
8
21
  ### Changed
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: a2qlinux
3
- Version: 0.2.0
3
+ Version: 0.2.1
4
4
  Summary: Questlog Desktop (AION 2 damage meter) on Linux under Proton, with live game traffic.
5
5
  Project-URL: homepage, https://github.com/raman78/A2Qlinux
6
6
  Project-URL: repository, https://github.com/raman78/A2Qlinux
@@ -116,12 +116,14 @@ for Arch, Debian, Ubuntu, Fedora and openSUSE. In short:
116
116
  | `a2qlinux/setup_desktop.py` | `a2qlinux-setup`: dependency and capture checks with install commands, Questlog installation, menu entry, icon |
117
117
  | `a2qlinux/bin/` | the built Windows parts (shipped in the package, not in git) |
118
118
  | `bridge/` | Windows parts in C: `wpcap.dll` stand-in, `questlog_ctl.exe`, their tests; `build.sh` |
119
+ | `install-from-source.sh` | installs this checkout for development: build, editable pipx install, setup |
119
120
  | `tests/` | Python tests: `python3 -m unittest` |
120
121
  | `tools/` | diagnostics: replay-file tools, TCP-owner probe |
121
122
 
122
123
  The Windows parts are built with `clang` against the installed Wine's headers
123
- (`bridge/build.sh`) — by the release workflow for the packages, by hand in a
124
- source checkout; built files are not kept in the repository. Releasing:
124
+ (`bridge/build.sh`) — by the release workflow for the packages, by
125
+ `install-from-source.sh` in a source checkout; built files are not kept in
126
+ the repository. Releasing:
125
127
  [docs/RELEASE.md](https://github.com/raman78/A2Qlinux/blob/main/docs/RELEASE.md).
126
128
 
127
129
  ## Not affiliated
@@ -74,12 +74,14 @@ for Arch, Debian, Ubuntu, Fedora and openSUSE. In short:
74
74
  | `a2qlinux/setup_desktop.py` | `a2qlinux-setup`: dependency and capture checks with install commands, Questlog installation, menu entry, icon |
75
75
  | `a2qlinux/bin/` | the built Windows parts (shipped in the package, not in git) |
76
76
  | `bridge/` | Windows parts in C: `wpcap.dll` stand-in, `questlog_ctl.exe`, their tests; `build.sh` |
77
+ | `install-from-source.sh` | installs this checkout for development: build, editable pipx install, setup |
77
78
  | `tests/` | Python tests: `python3 -m unittest` |
78
79
  | `tools/` | diagnostics: replay-file tools, TCP-owner probe |
79
80
 
80
81
  The Windows parts are built with `clang` against the installed Wine's headers
81
- (`bridge/build.sh`) — by the release workflow for the packages, by hand in a
82
- source checkout; built files are not kept in the repository. Releasing:
82
+ (`bridge/build.sh`) — by the release workflow for the packages, by
83
+ `install-from-source.sh` in a source checkout; built files are not kept in
84
+ the repository. Releasing:
83
85
  [docs/RELEASE.md](https://github.com/raman78/A2Qlinux/blob/main/docs/RELEASE.md).
84
86
 
85
87
  ## Not affiliated
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
18
18
  commit_id: str | None
19
19
  __commit_id__: str | None
20
20
 
21
- __version__ = version = '0.2.0'
22
- __version_tuple__ = version_tuple = (0, 2, 0)
21
+ __version__ = version = '0.2.1'
22
+ __version_tuple__ = version_tuple = (0, 2, 1)
23
23
 
24
24
  __commit_id__ = commit_id = None
@@ -140,6 +140,26 @@ def template(questlog_dir=None):
140
140
  return "\n".join(lines)
141
141
 
142
142
 
143
+ def set_questlog_dir(questlog_dir, path=CONFIG_PATH):
144
+ """Write `questlog_dir` into the settings file, for a2qlinux-setup --questlog-dir.
145
+
146
+ A missing file is created from template(); in an existing one only the
147
+ questlog_dir line changes (or is added), so the user's other settings and
148
+ comments stay as they are.
149
+ """
150
+ path = Path(path)
151
+ line = f"questlog_dir = {_toml(str(questlog_dir))}"
152
+ if not path.exists():
153
+ path.parent.mkdir(parents=True, exist_ok=True)
154
+ path.write_text(template(questlog_dir))
155
+ return
156
+ text = path.read_text()
157
+ new, count = re.subn(r"(?m)^[ \t]*questlog_dir[ \t]*=.*$", lambda _: line, text, count=1)
158
+ if not count:
159
+ new = text + ("" if text.endswith("\n") or not text else "\n") + line + "\n"
160
+ path.write_text(new)
161
+
162
+
143
163
  def _toml(value):
144
164
  if isinstance(value, bool):
145
165
  return "true" if value else "false"
@@ -316,22 +316,28 @@ def main():
316
316
  parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
317
317
  parser.add_argument("--questlog-dir", type=Path,
318
318
  default=None,
319
- help=f"folder with Questlog.exe (default: from {config.CONFIG_PATH}, else ~/Games/Questlog); "
320
- "written into a new settings file")
319
+ help=f"Questlog's folder (default: from {config.CONFIG_PATH}, else ~/Games/Questlog); "
320
+ "written into the settings file. Without Questlog.exe in it, the newest Questlog "
321
+ "is installed there")
321
322
  parser.add_argument("--desktop-shortcut", action="store_true", help="also put the entry on the desktop")
322
323
  args = parser.parse_args()
324
+ created = not config.CONFIG_PATH.exists()
325
+ if args.questlog_dir:
326
+ # Into the settings file, which every A2Qlinux command reads, so the
327
+ # folder used here is the one the launcher uses later.
328
+ config.set_questlog_dir(args.questlog_dir.expanduser().resolve())
329
+ elif created:
330
+ config.CONFIG_PATH.parent.mkdir(parents=True, exist_ok=True)
331
+ config.CONFIG_PATH.write_text(config.template())
323
332
  settings, config_problems = config.load()
324
- questlog_dir = (args.questlog_dir or settings.questlog_dir).expanduser().resolve()
333
+ questlog_dir = settings.questlog_dir.resolve()
325
334
  problems = list(config_problems)
326
- if not config.CONFIG_PATH.exists():
327
- config.CONFIG_PATH.parent.mkdir(parents=True, exist_ok=True)
328
- config.CONFIG_PATH.write_text(config.template(questlog_dir))
329
- print(f"Settings: {config.CONFIG_PATH} (every setting at its default, with comments)")
330
- elif questlog_dir != settings.questlog_dir.resolve():
331
- problems.append(f"--questlog-dir {questlog_dir} differs from {settings.questlog_dir} in "
332
- f"{config.CONFIG_PATH}; set questlog_dir there, which A2Qlinux reads")
333
- else:
334
- print(f"Settings: {config.CONFIG_PATH}")
335
+ print(f"Settings: {config.CONFIG_PATH}"
336
+ + (" (every setting at its default, with comments)" if created else "")
337
+ + (f"; questlog_dir = {questlog_dir}" if args.questlog_dir else ""))
338
+ if os.environ.get("QUESTLOG_DIR"):
339
+ print(f"Note: the QUESTLOG_DIR environment variable sets Questlog's folder to {questlog_dir}, over "
340
+ f"{config.CONFIG_PATH}; the menu entry and Steam do not see that variable.")
335
341
 
336
342
  info = os_release()
337
343
  missing, wanted = missing_packages()
@@ -0,0 +1,81 @@
1
+ #!/bin/bash
2
+ # Build the Windows parts for x64 with clang and Wine's headers and import
3
+ # libraries; no MinGW toolchain is needed:
4
+ # a2qlinux/bin/wpcap.dll stand-in for Npcap's wpcap.dll, fed by the Linux side
5
+ # a2qlinux/bin/questlog_ctl.exe acts on a running Questlog from inside its Wine session
6
+ # bridge/tests/*.exe test programs for the two above
7
+ # tools/tcp_owner_probe.exe diagnostic: does Wine report TCP connection owners
8
+ # Rebuild after a Wine update.
9
+ #
10
+ # Wine's files are looked for where the distributions put them (their package
11
+ # file lists, docs/ARCHITECTURE.md §14); WINE_INCLUDE and WINE_LIB override that.
12
+ # Anything missing is reported with the command that installs it.
13
+ set -euo pipefail
14
+ cd "$(dirname "$0")"
15
+
16
+ # Package names for building, per distribution family (/etc/os-release).
17
+ family=""
18
+ if [ -r /etc/os-release ]; then
19
+ ids=" $(. /etc/os-release; echo "${ID:-} ${ID_LIKE:-}") "
20
+ case "$ids" in
21
+ *" arch "*) family=arch ;;
22
+ *" ubuntu "*|*" debian "*) family=debian ;;
23
+ *" fedora "*) family=fedora ;;
24
+ *" suse "*|*" opensuse "*) family=suse ;;
25
+ esac
26
+ fi
27
+ case "$family" in
28
+ arch) install="sudo pacman -S --needed clang lld wine" ;;
29
+ debian) install="sudo apt install clang lld libwine-dev" ;;
30
+ fedora) install="sudo dnf install clang lld wine-devel" ;;
31
+ suse) install="sudo zypper install clang lld wine-devel" ;;
32
+ *) install="install clang, lld and Wine's development files (headers and import libraries)" ;;
33
+ esac
34
+
35
+ missing=()
36
+ command -v clang >/dev/null || missing+=("clang")
37
+ command -v ld.lld >/dev/null || missing+=("lld (ld.lld)")
38
+
39
+ # Include root: the folder holding msvcrt/ and windows/ (Arch, Fedora, openSUSE:
40
+ # /usr/include/wine; Debian, Ubuntu: /usr/include/wine/wine).
41
+ W="${WINE_INCLUDE:-}"
42
+ if [ -z "$W" ]; then
43
+ for candidate in /usr/include/wine /usr/include/wine/wine; do
44
+ if [ -f "$candidate/windows/windows.h" ] && [ -d "$candidate/msvcrt" ]; then W="$candidate"; break; fi
45
+ done
46
+ fi
47
+ [ -n "$W" ] && [ -f "$W/windows/windows.h" ] || missing+=("Wine's headers (windows/windows.h)")
48
+
49
+ # Import libraries for x86_64 Windows programs (Arch: /usr/lib/wine; openSUSE:
50
+ # /usr/lib64/wine; Debian, Ubuntu: /usr/lib/x86_64-linux-gnu/wine).
51
+ L="${WINE_LIB:-}"
52
+ if [ -z "$L" ]; then
53
+ for candidate in /usr/lib/wine/x86_64-windows /usr/lib64/wine/x86_64-windows \
54
+ /usr/lib/x86_64-linux-gnu/wine/x86_64-windows; do
55
+ if [ -f "$candidate/libkernel32.a" ]; then L="$candidate"; break; fi
56
+ done
57
+ fi
58
+ [ -n "$L" ] && [ -f "$L/libkernel32.a" ] || missing+=("Wine's x86_64 import libraries (x86_64-windows/libkernel32.a)")
59
+
60
+ if [ ${#missing[@]} -gt 0 ]; then
61
+ echo "bridge/build.sh: cannot build, missing: $(IFS=';'; echo "${missing[*]}" | sed 's/;/; /g')" >&2
62
+ echo " $install" >&2
63
+ echo " (Wine's files in other folders: set WINE_INCLUDE and WINE_LIB.)" >&2
64
+ exit 1
65
+ fi
66
+ echo "Wine's headers: $W; import libraries: $L"
67
+
68
+ mkdir -p ../a2qlinux/bin
69
+ CF=(--target=x86_64-w64-windows-gnu -fuse-ld=lld -nostdinc -isystem "$W/msvcrt" -isystem "$W/windows"
70
+ -isystem "$(clang -print-resource-dir)/include" -O2 -Wall -Wextra)
71
+ clang "${CF[@]}" -shared -o ../a2qlinux/bin/wpcap.dll wpcap_bridge.c -nostdlib -L"$L" -lucrtbase -lkernel32 -luser32 -lws2_32 \
72
+ -Wl,--entry=DllMain
73
+ clang "${CF[@]}" -o ../a2qlinux/bin/questlog_ctl.exe questlog_ctl.c -nostdlib -L"$L" -lucrtbase -lkernel32 -luser32 \
74
+ -lshell32 -Wl,--entry=start
75
+ clang "${CF[@]}" -o tests/bridge_client_test.exe tests/bridge_client_test.c -nostdlib -L"$L" -lucrtbase -lkernel32 \
76
+ -Wl,--entry=main
77
+ clang "${CF[@]}" -o tests/zorder_guard_test.exe tests/zorder_guard_test.c -nostdlib -L"$L" -lucrtbase -lkernel32 \
78
+ -luser32 -lshell32 -Wl,--entry=start
79
+ clang "${CF[@]}" -o ../tools/tcp_owner_probe.exe ../tools/tcp_owner_probe.c -nostdlib -L"$L" -lucrtbase \
80
+ -lkernel32 -liphlpapi -lws2_32 -Wl,--entry=main
81
+ echo "built: a2qlinux/bin/wpcap.dll, a2qlinux/bin/questlog_ctl.exe, bridge/tests/*.exe, tools/tcp_owner_probe.exe"
@@ -735,7 +735,8 @@ privileges a Wine process should not have. `dumpcap` gets them through the
735
735
  `wireshark` group and its file capabilities, and runs as the normal user.
736
736
 
737
737
  **The DLL built with clang against Wine's headers**, not MinGW: the build
738
- needs only `clang`, `lld` and the installed Wine (`bridge/build.sh`).
738
+ needs only `clang`, `lld` and the installed Wine's development files
739
+ (`bridge/build.sh`, §14).
739
740
 
740
741
  **Our tray instead of fixing the Wine one** — §6.2. **The guard instead of a
741
742
  patched Proton** — §6.1. **Session end after a delay instead of an immediate
@@ -856,7 +857,15 @@ release.
856
857
  `a2qlinux/config.py` reads `~/.config/a2qlinux/config.toml` (or under
857
858
  `$XDG_CONFIG_HOME`) with the standard library's `tomllib`. `a2qlinux-setup`
858
859
  writes it when missing (`config.template`), with every setting at its
859
- default and a comment for each; it never rewrites an existing file.
860
+ default and a comment for each. It changes an existing file in one case
861
+ only: `a2qlinux-setup --questlog-dir` (`config.set_questlog_dir`) replaces
862
+ the `questlog_dir` line, or adds it, and leaves every other line and comment
863
+ as it was. The setup then reads the folder back from the file, like every
864
+ other command, so the folder it checks and installs Questlog into is the
865
+ one the launcher uses later. An earlier version only wrote the option into
866
+ a new file; with a file already there, the option was refused, and the
867
+ first-installation code would have installed into a folder the settings did
868
+ not name.
860
869
 
861
870
  | Setting | Default | Replaces | Read by |
862
871
  |---|---|---|---|
@@ -980,6 +989,28 @@ case reads as a missing group membership, not as a missing package.
980
989
  `pipx install protontricks` provides the command (its wheel's entry
981
990
  points). Debian's `wireshark-common` asks whether non-root users may
982
991
  capture, with no as the default (its debconf template `install-setuid`);
983
- `dpkg-reconfigure wireshark-common` changes the answer. `bridge/build.sh`
984
- uses Arch's Wine paths; users of other distributions install the package
985
- from PyPI, which carries the built parts (§12).
992
+ `dpkg-reconfigure wireshark-common` changes the answer.
993
+
994
+ **Building from source** (`bridge/build.sh`, `install-from-source.sh`).
995
+ The build needs `clang`, `ld.lld` and Wine's headers and x86_64 import
996
+ libraries. Where the distributions put the latter, from their package file
997
+ lists: headers under `/usr/include/wine` (Arch, Fedora, openSUSE) or
998
+ `/usr/include/wine/wine` (Debian, Ubuntu, package `libwine-dev`); import
999
+ libraries in `x86_64-windows` under `/usr/lib/wine` (Arch),
1000
+ `/usr/lib64/wine` (openSUSE) or `/usr/lib/x86_64-linux-gnu/wine` (Debian,
1001
+ Ubuntu). `build.sh` tries these in turn, takes `WINE_INCLUDE` / `WINE_LIB`
1002
+ over them, and when something is missing prints the family's install line
1003
+ (from `/etc/os-release`, as `a2qlinux-setup` does) and exits 1 before
1004
+ compiling. Fedora 44's `wine-devel` file list (mdapi) showed only
1005
+ `i386-windows` import libraries; whether its x86_64 ones live under
1006
+ `/usr/lib64/wine` is not established, and the build would then say so.
1007
+ Checked here: the detected Arch paths and a Debian-shaped layout given
1008
+ through the variables build code and data sections identical to the
1009
+ previous script's (`llvm-objdump` of `.text`, `.rdata`, `.data`; the files
1010
+ differ only in the PE time stamp, which changes on every build). Only Arch
1011
+ has built it for real. `install-from-source.sh` runs `build.sh`,
1012
+ `pipx install --editable .` (after `pipx uninstall a2qlinux` if one is
1013
+ installed, since pipx refuses a second install), `pipx ensurepath` and
1014
+ `a2qlinux-setup` with `PIPX_BIN_DIR` (default `~/.local/bin`) put first on
1015
+ `PATH`, so the menu entry points at pipx's stable command folder rather
1016
+ than at the environment's own `bin`.
@@ -180,7 +180,7 @@ What the setup does, in order:
180
180
  | checks the programs from "Installing the packages", and for missing ones prints one install command for your distribution | `missing: …` and the command |
181
181
  | tries a one-second capture, to see that capturing is allowed | `capturing is not allowed yet …` and the commands, if not |
182
182
  | starts A2Qlinux's tray icon for a moment, without showing it, to see that it can run on your desktop | a reason, if not; see "The tray icon" in [TROUBLESHOOTING.md](TROUBLESHOOTING.md) |
183
- | installs Questlog in `~/Games/Questlog` if it is not there yet (about 130 MB) | `Downloading Questlog …`, then `Installed Questlog …` |
183
+ | installs Questlog in its folder (`~/Games/Questlog`, or the one given with `--questlog-dir`) if it is not there yet (about 130 MB) | `Downloading Questlog …`, then `Installed Questlog …` |
184
184
  | takes Questlog's icon from it (A2Qlinux does not ship Questlog's logo) | `Icon: …` |
185
185
  | creates the "Questlog (AION 2)" entry in your applications menu | `Menu entry: …` |
186
186
  | prints the line for Steam's launch options, used in the optional last section | `Steam > AION 2 > …` |
@@ -188,10 +188,29 @@ What the setup does, in order:
188
188
  It runs nothing with `sudo` and changes nothing in the game; the commands
189
189
  that need administrator rights are printed for you to run.
190
190
 
191
- If you already have Questlog unpacked somewhere else, give its folder once
192
- as `a2qlinux-setup --questlog-dir <folder>`; it is written into A2Qlinux's
193
- settings file and nothing is downloaded. If the automatic installation
194
- fails, the message says why; installing Questlog by hand is described in
191
+ **Questlog in another folder.** A2Qlinux keeps Questlog in `~/Games/Questlog`
192
+ unless you tell it otherwise. To use another folder, run the setup once
193
+ with it:
194
+
195
+ ```
196
+ a2qlinux-setup --questlog-dir <folder>
197
+ ```
198
+
199
+ The setup writes that folder into A2Qlinux's settings file (only that line;
200
+ your other settings stay), so the menu entry, the Steam launch option and
201
+ every later run of the setup use it; you do not give it again. Then:
202
+
203
+ | What is in the folder | What the setup does |
204
+ |---|---|
205
+ | a Questlog you unpacked before (`Questlog.exe` is there) | uses it; nothing is downloaded |
206
+ | nothing, or the folder does not exist yet | installs the newest Questlog there |
207
+ | other files, but no `Questlog.exe` | installs nothing, and says so; choose an empty folder |
208
+
209
+ To move back to the default, run it with `--questlog-dir ~/Games/Questlog`,
210
+ or change `questlog_dir` in the settings file.
211
+
212
+ If the automatic installation fails, the message says why; installing
213
+ Questlog by hand is described in
195
214
  [UPDATING.md](UPDATING.md#installing-questlog-by-hand).
196
215
 
197
216
  The menu entry keeps itself up to date: each time `a2qlinux` starts, it
@@ -199,18 +218,51 @@ checks that the entry (and the desktop icon, if you have one) still runs
199
218
  this installation, and writes it again if not, for example after A2Qlinux
200
219
  was reinstalled elsewhere. Options you added to the entry by hand stay.
201
220
 
202
- **From the source code instead** (for changing A2Qlinux itself): in a copy of
203
- the repository, build the small Windows parts once (needs `clang`, `lld` and
204
- `wine`), then install that copy so that your changes take effect at once,
205
- instead of steps 1 and 2:
206
- ```
207
- bash bridge/build.sh && pipx install --editable .
208
- ```
209
- Then run `a2qlinux-setup` as above. The build script looks for Wine's
210
- files where Arch and CachyOS put them (`/usr/include/wine`,
211
- `/usr/lib/wine/x86_64-windows`). On other distributions `pipx install
212
- a2qlinux` is the simpler way, since that package comes with these parts
213
- built.
221
+ ### From the source code instead
222
+
223
+ This is for changing A2Qlinux itself; to use it, the PyPI package above is
224
+ all you need. Installing from a copy of the repository differs in two
225
+ ways. The small Windows parts A2Qlinux puts into the game's Proton
226
+ environment are not in the repository, only in the PyPI package, so they
227
+ are built first. And the copy is installed *editable*: pipx runs the files
228
+ in your copy instead of its own copies of them, so a change you make takes
229
+ effect the next time A2Qlinux starts, without installing again.
230
+
231
+ 1. Install what the build needs, besides the packages above:
232
+
233
+ | Distribution | Command |
234
+ |---|---|
235
+ | Arch, CachyOS | `sudo pacman -S --needed clang lld wine` |
236
+ | Debian, Ubuntu | `sudo apt install clang lld libwine-dev` |
237
+ | Fedora | `sudo dnf install clang lld wine-devel` |
238
+ | openSUSE | `sudo zypper install clang lld wine-devel` |
239
+
240
+ `clang` and `lld` compile and link the Windows parts; the Wine package
241
+ provides the Windows headers and libraries they are built against.
242
+ 2. Get the repository and run its installer from it:
243
+ ```
244
+ git clone https://github.com/raman78/A2Qlinux.git && cd A2Qlinux && ./install-from-source.sh --desktop-shortcut
245
+ ```
246
+ 3. Open a new terminal, so that the A2Qlinux commands are found, and read
247
+ the end of what the installer printed, as in step 4 above.
248
+
249
+ What `install-from-source.sh` does, in order, with a line `== 1/4 …` and so
250
+ on for each step:
251
+
252
+ | Step | Command it runs | Why |
253
+ |---|---|---|
254
+ | 1 | `bash bridge/build.sh` | builds the Windows parts into the copy. It finds Wine's files in the folders Arch, Debian, Ubuntu, Fedora and openSUSE use; if something is missing it prints the install command for your distribution |
255
+ | 2 | `pipx install --editable .` | installs this copy (the `.` is the current folder); an A2Qlinux installed before is removed first, whether from PyPI or another copy |
256
+ | 3 | `pipx ensurepath` | as in step 2 above |
257
+ | 4 | `a2qlinux-setup` | the same checks and setup as above; options given to the installer, such as `--desktop-shortcut`, are passed on |
258
+
259
+ Run it again after `git pull` when the Windows parts changed, or after a
260
+ Wine update (the parts are built against the installed Wine). A change to
261
+ the Python files needs nothing. Building has been tried on Arch and
262
+ CachyOS only so far; the other distributions' folders come from their
263
+ package file lists. If Wine's files are somewhere else, the build says so;
264
+ give the folders as `WINE_INCLUDE=<folder with windows/windows.h>` and
265
+ `WINE_LIB=<folder with libkernel32.a>` in front of the command.
214
266
 
215
267
  ## Checking that it works
216
268
 
@@ -78,5 +78,39 @@ class LoadTest(unittest.TestCase):
78
78
  self.assertEqual(settings.after_game, "keep")
79
79
 
80
80
 
81
+ class SetQuestlogDirTest(unittest.TestCase):
82
+ """a2qlinux-setup --questlog-dir writes the folder into the settings file, new or existing."""
83
+
84
+ def setUp(self):
85
+ self.tmp = tempfile.TemporaryDirectory()
86
+ self.path = Path(self.tmp.name) / "a2qlinux" / "config.toml"
87
+
88
+ def tearDown(self):
89
+ self.tmp.cleanup()
90
+
91
+ def test_a_missing_file_is_created_with_the_folder(self):
92
+ config.set_questlog_dir("/games/QL", self.path)
93
+ settings, problems = config.load(self.path)
94
+ self.assertEqual((settings.questlog_dir, problems), (Path("/games/QL"), []))
95
+ self.assertIn("after_game", self.path.read_text()) # the full template
96
+
97
+ def test_an_existing_file_changes_only_that_line(self):
98
+ self.path.parent.mkdir(parents=True)
99
+ self.path.write_text('# mine\nquestlog_dir = "/old"\nauto_update = false # off\n')
100
+ config.set_questlog_dir("/new/QL", self.path)
101
+ self.assertEqual(self.path.read_text(), '# mine\nquestlog_dir = "/new/QL"\nauto_update = false # off\n')
102
+
103
+ def test_a_file_without_the_line_gets_it_added(self):
104
+ self.path.parent.mkdir(parents=True)
105
+ self.path.write_text("auto_update = false")
106
+ config.set_questlog_dir("/new/QL", self.path)
107
+ settings, problems = config.load(self.path)
108
+ self.assertEqual((settings.questlog_dir, settings.auto_update, problems), (Path("/new/QL"), False, []))
109
+
110
+ def test_quotes_and_backslashes_in_the_folder_survive(self):
111
+ config.set_questlog_dir('/games/"odd" \\ name', self.path)
112
+ self.assertEqual(config.load(self.path)[0].questlog_dir, Path('/games/"odd" \\ name'))
113
+
114
+
81
115
  if __name__ == "__main__":
82
116
  unittest.main()
@@ -1,26 +0,0 @@
1
- #!/bin/bash
2
- # Build the Windows parts for x64 with clang and Wine's headers and import
3
- # libraries; no MinGW toolchain is needed:
4
- # a2qlinux/bin/wpcap.dll stand-in for Npcap's wpcap.dll, fed by the Linux side
5
- # a2qlinux/bin/questlog_ctl.exe acts on a running Questlog from inside its Wine session
6
- # bridge/tests/*.exe test programs for the two above
7
- # tools/tcp_owner_probe.exe diagnostic: does Wine report TCP connection owners
8
- # Rebuild after a Wine update.
9
- set -euo pipefail
10
- cd "$(dirname "$0")"
11
- mkdir -p ../a2qlinux/bin
12
- W=/usr/include/wine
13
- L=/usr/lib/wine/x86_64-windows
14
- CF=(--target=x86_64-w64-windows-gnu -fuse-ld=lld -nostdinc -isystem "$W/msvcrt" -isystem "$W/windows"
15
- -isystem "$(clang -print-resource-dir)/include" -O2 -Wall -Wextra)
16
- clang "${CF[@]}" -shared -o ../a2qlinux/bin/wpcap.dll wpcap_bridge.c -nostdlib -L"$L" -lucrtbase -lkernel32 -luser32 -lws2_32 \
17
- -Wl,--entry=DllMain
18
- clang "${CF[@]}" -o ../a2qlinux/bin/questlog_ctl.exe questlog_ctl.c -nostdlib -L"$L" -lucrtbase -lkernel32 -luser32 \
19
- -lshell32 -Wl,--entry=start
20
- clang "${CF[@]}" -o tests/bridge_client_test.exe tests/bridge_client_test.c -nostdlib -L"$L" -lucrtbase -lkernel32 \
21
- -Wl,--entry=main
22
- clang "${CF[@]}" -o tests/zorder_guard_test.exe tests/zorder_guard_test.c -nostdlib -L"$L" -lucrtbase -lkernel32 \
23
- -luser32 -lshell32 -Wl,--entry=start
24
- clang "${CF[@]}" -o ../tools/tcp_owner_probe.exe ../tools/tcp_owner_probe.c -nostdlib -L"$L" -lucrtbase \
25
- -lkernel32 -liphlpapi -lws2_32 -Wl,--entry=main
26
- echo "built: a2qlinux/bin/wpcap.dll, a2qlinux/bin/questlog_ctl.exe, bridge/tests/*.exe, tools/tcp_owner_probe.exe"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes