From a1930f09c695f0cbee4c707e54811ea4deaae379 Mon Sep 17 00:00:00 2001 From: June Stepp Date: Wed, 31 Dec 2025 12:31:42 -0600 Subject: [PATCH 1/6] build: Fix Windows installer when some DLL versions are lowered --- build/windows_installer/Package.wxs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/build/windows_installer/Package.wxs b/build/windows_installer/Package.wxs index 9366309f..c9fc7a10 100644 --- a/build/windows_installer/Package.wxs +++ b/build/windows_installer/Package.wxs @@ -18,6 +18,9 @@ in the MSI version field. --> + + From 226291e93e83ed5adbf07d44e017460b63facd84 Mon Sep 17 00:00:00 2001 From: June Stepp Date: Wed, 31 Dec 2025 13:21:17 -0600 Subject: [PATCH 2/6] fix(addon_manager): strip search text --- src/onelauncher/addon_manager_window.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/onelauncher/addon_manager_window.py b/src/onelauncher/addon_manager_window.py index d2061b39..87213262 100644 --- a/src/onelauncher/addon_manager_window.py +++ b/src/onelauncher/addon_manager_window.py @@ -1294,6 +1294,7 @@ def searchDB(self, table: QtWidgets.QTableWidget, text: str) -> None: table.clearContents() table.setRowCount(0) + text = text.strip() if text: for word in text.split(): search_word = f"%{word}%" From 08546fb31285cb4a5cb26b806a8e91d0846fd071 Mon Sep 17 00:00:00 2001 From: June Stepp Date: Wed, 31 Dec 2025 13:37:07 -0600 Subject: [PATCH 3/6] fix(addon_manager): correct `.plugin{compendium}` invalid XML error --- src/onelauncher/addon_manager_window.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/onelauncher/addon_manager_window.py b/src/onelauncher/addon_manager_window.py index 87213262..45e2a52f 100644 --- a/src/onelauncher/addon_manager_window.py +++ b/src/onelauncher/addon_manager_window.py @@ -577,7 +577,7 @@ def parseCompendiumFile(self, file: Path, tag: str) -> AddonInfo | None: try: doc = defusedxml.minidom.parse(str(file)) except ExpatError: - logger.exception("Compendium file has invalid XML: %s", file) + logger.exception("`%s` has invalid XML", file.name) return None nodes = doc.getElementsByTagName(tag)[0].childNodes for node in nodes: From 28d894dfd82d9fd8132b64ce8d88c0eab98a7d35 Mon Sep 17 00:00:00 2001 From: June Stepp Date: Wed, 31 Dec 2025 13:38:00 -0600 Subject: [PATCH 4/6] fix(addon_manager): don't install plugin if it has invalid `.plugin` files --- src/onelauncher/addon_manager_window.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/onelauncher/addon_manager_window.py b/src/onelauncher/addon_manager_window.py index 45e2a52f..598c5612 100644 --- a/src/onelauncher/addon_manager_window.py +++ b/src/onelauncher/addon_manager_window.py @@ -843,6 +843,11 @@ def install_plugin( # will be ignored by both me and the game. plugin_files = list(author_folder.glob("*.plugin")) + # Don't install if there are invalid `.plugin` files. + for plugin_file in plugin_files: + if self.parseCompendiumFile(plugin_file, "Information") is None: + return + existing_compendium_file = self.get_existing_compendium_file(author_folder) if existing_compendium_file is False: return From 950929e3cc18aff1a96f80bb84bd7f2029126a7f Mon Sep 17 00:00:00 2001 From: June Stepp Date: Wed, 31 Dec 2025 14:01:52 -0600 Subject: [PATCH 5/6] fix(patch_game): don't create window for `run_ptch_client.exe` on Windows --- src/onelauncher/patch_game.py | 49 +++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/src/onelauncher/patch_game.py b/src/onelauncher/patch_game.py index d1e2a763..45a0282f 100644 --- a/src/onelauncher/patch_game.py +++ b/src/onelauncher/patch_game.py @@ -1,6 +1,7 @@ import logging import os import subprocess +import sys from functools import partial from pathlib import Path from types import MappingProxyType @@ -347,7 +348,7 @@ async def patch_game( ) environment = MappingProxyType(os.environ) - if os.name == "nt": + if sys.platform == "win32": # The directory with TTEPatchClient.dll has to be in the PATH for # patchclient.dll to find it when OneLauncher is compiled with Nuitka. environment = MappingProxyType( @@ -383,29 +384,33 @@ async def patch_game( progress.progress_text_suffix = ( f" Phase {i + 2}/{len(PATCHCLIENT_PATCH_PHASES) + 1}" ) - process: trio.Process = await nursery.start( - partial( - trio.run_process, - ( - *command, - # `run_ptch_client.exe` takes everything that will get - # passed to `patchclient.dll` as a single argument. - " ".join( - get_patchclient_arguments( - phase=phase, - patch_server_url=patch_server_url, - game_id=game_id, - config_manager=config_manager, - ) - ), + run_patching = partial( + trio.run_process, + ( + *command, + # `run_ptch_client.exe` takes everything that will get + # passed to `patchclient.dll` as a single argument. + " ".join( + get_patchclient_arguments( + phase=phase, + patch_server_url=patch_server_url, + game_id=game_id, + config_manager=config_manager, + ) ), - check=False, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - env=environment, - cwd=game_config.game_directory, - ) + ), + check=False, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + env=environment, + cwd=game_config.game_directory, ) + if sys.platform == "win32": + process: trio.Process = await nursery.start( + partial(run_patching, creationflags=subprocess.CREATE_NO_WINDOW) + ) + else: + process: trio.Process = await nursery.start(run_patching) if process.stdout is None or process.stderr is None: raise TypeError("Process pipe is `None`") From 24ef7e4125fd82b3197b242f41c5c1fdd894e696 Mon Sep 17 00:00:00 2001 From: June Stepp Date: Wed, 31 Dec 2025 11:11:15 -0600 Subject: [PATCH 6/6] 2.1.0 release --- CHANGELOG.md | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++ pyproject.toml | 2 +- uv.lock | 2 +- 3 files changed, 96 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f98a5eeb..94e7fc16 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,99 @@ # Changelog +## 2.1.0 (2026-01-01) + +Plenty of fixes and improvements. A few of the most notable are first-class macOS support, splash screens and initial data patching support, new game installation on macOS and Linux, and an option to close OneLauncher once a game is started. The full changelog is below. + +### Features + +- [**breaking**] Switch to Cyclopts for CLI + - Options with choices use hyphens. Example: `--game lotro_preview` -> + `--game lotro-preview` + - `--startup-script` -> `--startup-scripts` + - Shell completions need to be reinstalled. +- Add option to close OneLauncher once a game is started +- Add `log_verbosity` option +- Sort old worlds to bottom of worlds list +- Update WINE and DXVK, switch to WINE wow64 +- Support macOS native menu bar +- Add macOS Crossover to setup wizard search dirs +- Mac WINE support +- Add macOS building +- Add macOS installation section to README.md +- Get rid of the start game window. Running the game is done fully from the main window now. +- Support patching for splash screens and initial data +- Allow creating new game installations. This is disabled on Windows for now pending testing. +- Set important `UserPreferences.ini` values +- Remove patch client filename option from settings window +- Use icons for select from file browser buttons +- Add message to preview client newsfeeds linking to where the latest info is +- Compare product tokens with world allowed/denied billing roles + +### Fixes + +- *(newsfeed)* Remove extra spaces in "..." link +- *(nix)* FHS run +- Improve UI label buddies and tab order +- Include system environment when starting standard game launcher +- Styling on macOS +- Don't pass sys.argv to QApplication. +- Don't skip CaseInsensitiveAbsolutePath processing on Windows +- *(addon_manager)* `getAddonObjectFromRow` with no interface ID +- *(addon_manager)* Uninstall with addons button from remote table +- *(addon_manager)* `getSelectedAddons` with remote table +- *(addon_manager)* Duplication and DB clear issues from using `isTableEmpty` +- *(addon_manager)* Use `self.tables_loaded` instead of `self.isTableEmpty` +- *(addon_manager)* Updating multiple addons at once +- *(addon_manager)* Strip search text +- *(addon_manager)* Correct `.plugin{compendium}` invalid XML error +- *(addon_manager)* Don't install plugin if it has invalid `.plugin` files +- Handle empty `queueurls` +- Still check for updates on dev releases +- Restrict keyboard interrupts to checkpoints +- Cancel app on uncaught exception +- *(settings_window)* Close before showing other windows post setup wizard +- *(setup_wizard)* Search for games non-blocking from start +- *(setup_wizard)* Keep open while settings are being saved +- *(setup_wizard)* Both select and check user-added game directories +- *(setup_wizard)* Improve QFileDialog usage +- Prevent game launch when initial data patching is needed +- Handle when there is no system keyring or it fails to unlock +- Don't the start game when there are world queue errors +- Handle username or password too short errors +- *(world_login_queue)* Better handle HRESULT 0x80004005 +- Improve world status error messages +- Remove custom official servers ciphers config. It is no longer necessary. +- Windows installer when some DLL versions are lowered +- Don't create window for `run_ptch_client.exe` on Windows + +### Internal + +- Update dependencies +- Log more information. +- Don't pre-format log messages +- Don't log to file during testing +- *(addon_manager)* Add `AddonType`, misc +- *(wine)* Reorder methods +- Use `trio.run_process` instead of `QProcess` +- Use attrs for `GameLauncherConfig` +- Use tuples for official domain constants +- Raise `RelativePathError` in `CaseInsensitiveAbsolutePath` +- Use `onelauncher/external` directory for `run_ptch_client.exe` +- Standardize UI naming around `*_window` +- Move all current UI only code to `ui/` +- Remove `processEvents` call for game banner +- Remove README banner image in BBCode conversion +- Mention using fhs-run for source OneLauncher +- Skip case-sensitive-only tests on macOS +- *(nix)* Don't use private tmp in FHS env +- *(nuitka_compile)* Improve how output dir is specified +- *(nuitka_compile)* Don't exclude asyncio +- Add status checks to CI +- Add spell checker +- Pin GitHub actions to specific commits +- Update GitHub Actions Nuitka caching +- Update `build.yml` + ## 2.0.2 (2025-06-03) This update has quite a few small fixes and improvements. The full changelog is below. diff --git a/pyproject.toml b/pyproject.toml index 841cd4b1..638707e4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "OneLauncher" -version = "2.0.2" +version = "2.1.0" description = "The OneLauncher to rule them all" authors = [{ name = "June Stepp", email = "contact@junestepp.me" }] requires-python = ">=3.11,<3.12" diff --git a/uv.lock b/uv.lock index fcffa37c..a313f63e 100644 --- a/uv.lock +++ b/uv.lock @@ -552,7 +552,7 @@ wheels = [ [[package]] name = "onelauncher" -version = "2.0.2" +version = "2.1.0" source = { editable = "." } dependencies = [ { name = "asyncache" },