From ed8e79455bc9dc9da0fe11590ab77004fe60558d Mon Sep 17 00:00:00 2001 From: aclist <92275929+aclist@users.noreply.github.com> Date: Sat, 9 May 2026 23:53:14 +0900 Subject: [PATCH] feat: concatenate launch parameters --- dzgui/api/servers.py | 6 +++-- dzgui/api/steam.py | 8 ++++-- dzgui/managers/connection.py | 35 +++++++++++++------------ dzgui/managers/threading.py | 3 +++ dzgui/model/servers.py | 9 +++---- dzgui/views/base.py | 3 ++- dzgui/views/components/connect_panel.py | 3 ++- dzgui/views/dialogs/generic.py | 3 +++ dzgui/views/mixins/context_mixin.py | 4 +-- dzgui/views/mixins/cursor_mixin.py | 3 ++- dzgui/views/pages/preconnect.py | 4 +++ dzgui/views/trees/tree_servers.py | 3 ++- 12 files changed, 52 insertions(+), 32 deletions(-) diff --git a/dzgui/api/servers.py b/dzgui/api/servers.py index b3eebd1..c335ab4 100644 --- a/dzgui/api/servers.py +++ b/dzgui/api/servers.py @@ -462,7 +462,7 @@ def query_playercount(record: Record) -> tuple[int, int] | None: def query_by_ip(addr: str) -> A2SInfo: record = short_ip_to_record(addr) - return query_by_record(record) + return query_by_record(record, update_gameport=True) def query_by_id(server_id: int, key: str) -> dict[Any] | None: """ @@ -472,9 +472,11 @@ def query_by_id(server_id: int, key: str) -> dict[Any] | None: return query_by_record(record) -def query_by_record(record: Record) -> A2SInfo: +def query_by_record(record: Record, update_gameport: bool = False) -> A2SInfo: try: info = a2s.info((record.ip, record.qport), 3.0) + if update_gameport: + record = Record(record.ip, info.port, record.qport) return A2SInfo(record, info) except Exception as e: logger.warning(e) diff --git a/dzgui/api/steam.py b/dzgui/api/steam.py index c906587..8946b72 100644 --- a/dzgui/api/steam.py +++ b/dzgui/api/steam.py @@ -14,9 +14,13 @@ logger = logging.getLogger(APP_NAME) def concat_mods(mods: list[str]) -> str: + from dzgui.util.symlink import _hash + + hashes = [] for mod in mods: - mods[mod] = f"@{mod}" - return ";".join(mods) + md5sum = _hash(mod) + hashes.append(md5sum) + return ";".join(hashes) def get_local_signatures(version_file: Path) -> dict[str, int]: diff --git a/dzgui/managers/connection.py b/dzgui/managers/connection.py index 296bb79..b819a88 100644 --- a/dzgui/managers/connection.py +++ b/dzgui/managers/connection.py @@ -30,9 +30,10 @@ from dzgui.const.constants import ( APPID_DAYZ_EXP, APPNAME_DAYZ, APPNAME_DAYZ_EXP, + DAYZ_BINARY, ) from dzgui.const.enum import Preferences -from dzgui.init.proc import foreground, is_dayz_running, is_steam_running +from dzgui.init.proc import foreground, is_dayz_running, is_steam_running, is_running from dzgui.managers.threading import call_on_thread, StoredFunc, ThreadingManager from dzgui.strings.server_mods import checkmark, resync from dzgui.util.format import format_mib @@ -241,26 +242,29 @@ class ConnectionManager: dialog = ExceptionDialog(self.controller, server_timeout) dialog.run() + # TODO: threading def _connect_steam(self) -> None: - print(self.record.ip) - print(self.record.gameport) - print(self.appid) - addr = f"{self.record.ip}:{self.record.gameport}" - playername = "test" + playername = self.controller.query_config(Preferences.NAME) proc = connect(addr, self.appid, playername, self.remote_mod_ids) # TODO: test returncode - # proc.returncode - # TODO: wait for DAYZ_BINARY to load - # TODO: add to history file and list store - @call_on_thread("Waiting for Steam to update mods") + # self.thread_man.update_dialog("Waiting for DayZ to launch") + # while not is_running(DAYZ_BINARY): + # time.sleep(1) + # TODO: wait for DAYZ_BINARY to load + # on cleanup: + # TODO: add to history file and list store + # proxy_model.append_to_history() + def _update_mods(self, raise_window: bool) -> None: # NOTE: fast enqueue all mods in auto mode prefs = self.controller.get_prefs() + + # TODO: increment dialog progress message for title, mod, stamp, size in self.missing_mods: # TODO: boolean cancel button on threadman dialog sets event inside threadman - # TODO: check for early cancel event via sigint + # check for early cancel event via sigint enqueue_mod(mod, self.appid) time.sleep(2) @@ -282,18 +286,15 @@ class ConnectionManager: break time.sleep(1) - # TODO: update version file update_signatures(self.missing_mods, prefs.paths.version) - # TODO: get config path or just push steam path directly rebuild_symlinks(prefs.paths.config) - # TODO: update tree checkmarks when finished - # TODO: make this internal to preconnect page - func = StoredFunc(self.controller.update_status) - self.thread_man.set_cleanup_func(func) + @call_on_thread("Waiting for Steam to update mods") def update_and_connect(self, raise_window: bool) -> None: if len(self.missing_mods) > 0: self._update_mods(raise_window) else: self._connect_steam() + func = StoredFunc(self.controller.update_status) + self.thread_man.set_cleanup_func(func) diff --git a/dzgui/managers/threading.py b/dzgui/managers/threading.py index f451715..52f884a 100644 --- a/dzgui/managers/threading.py +++ b/dzgui/managers/threading.py @@ -72,6 +72,9 @@ class ThreadingManager: def set_job_count(self, jobs: int) -> None: self.jobs = jobs + def update_dialog(self, msg: str) -> None: + GLib.idle_add(lambda: self.wait_dialog.update_text(msg)) + def increment_dialog(self) -> None: GLib.idle_add(self.wait_dialog.increment) diff --git a/dzgui/model/servers.py b/dzgui/model/servers.py index 4341936..86bd973 100644 --- a/dzgui/model/servers.py +++ b/dzgui/model/servers.py @@ -40,7 +40,6 @@ class NewPlayerCount: queue: int - class ServerModelManager: def __init__(self, controller: "Controller", tv: "ServerTreeView") -> None: @@ -174,9 +173,11 @@ class ServerModelManager: ] for future in as_completed(futures): res = future.result(timeout=API_TIMEOUT) + self.thread_man.increment_dialog() # NOTE: failing entries are culled if res is None: + # TODO: log which servers failed continue servers.append(res) if len(servers) == 0: @@ -257,9 +258,7 @@ class ServerModelManager: proxy_man = self._get_proxy_man() proxy_man.update_playercount(self.playercount) - def _parse_single_record( - self, response: "A2SInfo", delete: bool = False - ) -> None: + def _parse_single_record(self, response: "A2SInfo", delete: bool = False) -> None: self.preserve_on_fail = True row = response.as_row() if row is None: @@ -275,7 +274,7 @@ class ServerModelManager: proxy_man = self._get_proxy_man() config_man = self.controller.get_config_man() fqip = Servers.response_to_fqip(row) - record = response.get_record() #Servers.response_to_record(row) + record = response.get_record() # Servers.response_to_record(row) # TODO: less convoluted if delete: diff --git a/dzgui/views/base.py b/dzgui/views/base.py index 35119c6..7672a4c 100644 --- a/dzgui/views/base.py +++ b/dzgui/views/base.py @@ -9,6 +9,7 @@ from dzgui.const.enum import NotebookPage from dzgui.controllers.emitter import Emitter from dzgui.controllers.mc import Controller from dzgui.util import css, strings +from dzgui.util.keys import is_ctrl_mask from dzgui.views.components.connect_panel import ConnectPanel from dzgui.views.components.crumbs import Breadcrumbs from dzgui.views.components.right_panel import RightPanel @@ -164,7 +165,7 @@ class Notebook(ScrollableMixin, Gtk.Notebook): # type: ignore def _on_keypress(self, widget: Gtk.Widget, event: Gdk.EventKey) -> bool: match event.keyval: case Gdk.KEY_Right | Gdk.KEY_l: - if event.state is Gdk.ModifierType.CONTROL_MASK: + if is_ctrl_mask(event): return False MainController.get_emitter().emit("request_button_box_focus") return True diff --git a/dzgui/views/components/connect_panel.py b/dzgui/views/components/connect_panel.py index 1ebf1b2..fbf8f6a 100644 --- a/dzgui/views/components/connect_panel.py +++ b/dzgui/views/components/connect_panel.py @@ -3,6 +3,7 @@ from typing import TYPE_CHECKING from dzgui.const.constants import UDP_PORT from dzgui.model.servers import ServerModelManager from dzgui.strings import connect_panel +from dzgui.util.keys import is_ctrl_mask from dzgui.views.components.buttons import ( AddButton, ClipboardButton, @@ -78,7 +79,7 @@ class LanPanel(Gtk.Frame): self.entry.set_sensitive(False) def _on_lan_keypress(self, widget: Gtk.Entry, event: Gdk.EventKey) -> bool: - if event.state & Gdk.ModifierType.CONTROL_MASK: + if is_ctrl_mask(event): if event.keyval == Gdk.KEY_d: self.default_radio.set_active(True) self.controller.grab_active_treeview() diff --git a/dzgui/views/dialogs/generic.py b/dzgui/views/dialogs/generic.py index 17029c1..c95d2d0 100644 --- a/dzgui/views/dialogs/generic.py +++ b/dzgui/views/dialogs/generic.py @@ -109,6 +109,9 @@ class WaitDialog(GenericDialog): else: spinner.start() + def update_text(self, msg: str) -> None: + self.format_secondary_text(msg) + def increment(self, msg: str = "") -> None: if msg != "": self.format_secondary_text(msg) diff --git a/dzgui/views/mixins/context_mixin.py b/dzgui/views/mixins/context_mixin.py index 6a0a577..bfee8b9 100644 --- a/dzgui/views/mixins/context_mixin.py +++ b/dzgui/views/mixins/context_mixin.py @@ -2,7 +2,7 @@ import logging from dzgui.const.constants import APP_NAME from dzgui.const.enum import ContextMenu -from dzgui.util.keys import is_navkey +from dzgui.util.keys import is_ctrl_mask, is_navkey from dzgui.util.strings import edit_note from dzgui.views.trees.tree_base import TreeView @@ -30,7 +30,7 @@ class ContextMixin(TreeView): return False self._process_button_event(event) case Gdk.EventType.KEY_PRESS: - if event.state is not Gdk.ModifierType.CONTROL_MASK: + if not is_ctrl_mask(event): return False if event.keyval is not Gdk.KEY_l: return False diff --git a/dzgui/views/mixins/cursor_mixin.py b/dzgui/views/mixins/cursor_mixin.py index 58087e9..e9be244 100644 --- a/dzgui/views/mixins/cursor_mixin.py +++ b/dzgui/views/mixins/cursor_mixin.py @@ -1,5 +1,6 @@ from dzgui.const.enum import CursorPosition from dzgui.const.constants import SEPARATOR +from dzgui.util.keys import is_ctrl_mask import gi @@ -19,7 +20,7 @@ class CursorMixin: case Gdk.KEY_k: self._move_cursor(CursorPosition.UP) case Gdk.KEY_l | Gdk.KEY_Right: - if event.state is Gdk.ModifierType.CONTROL_MASK: + if is_ctrl_mask(event): return self.emitter.emit("request_button_box_focus") # type: ignore case _: diff --git a/dzgui/views/pages/preconnect.py b/dzgui/views/pages/preconnect.py index cee8276..b16e427 100644 --- a/dzgui/views/pages/preconnect.py +++ b/dzgui/views/pages/preconnect.py @@ -7,6 +7,7 @@ from dzgui.const.constants import ( ) from dzgui.const.enum import NotebookPage from dzgui.util.css import add_class +from dzgui.util.keys import is_ctrl_mask from dzgui.util.localize import number from dzgui.strings.server_mods import checkmark from dzgui.strings import preconnect @@ -211,6 +212,9 @@ class PreConnectionAssistant(Gtk.ScrolledWindow): def _on_keypress(self, widget: Self, event: Gdk.EventKey) -> None: if event.keyval == Gdk.KEY_Escape: self.back.emit("clicked") + if is_ctrl_mask(event): + if event.keyval == Gdk.KEY_u: + self.ok.emit("clicked") def _on_ok_clicked(self, button: Gtk.Button) -> None: # TODO: cancel mod downloads diff --git a/dzgui/views/trees/tree_servers.py b/dzgui/views/trees/tree_servers.py index 76e8f08..cf1ada5 100644 --- a/dzgui/views/trees/tree_servers.py +++ b/dzgui/views/trees/tree_servers.py @@ -12,6 +12,7 @@ from dzgui.managers.filter import FilterManager from dzgui.model.proxy_model import ProxyModelManager from dzgui.util import strings from dzgui.util.dist import CalcDist +from dzgui.util.keys import is_ctrl_mask from dzgui.views.mixins.context_mixin import ContextMixin from typing import Literal, TYPE_CHECKING @@ -229,7 +230,7 @@ class ServerTreeView(ContextMixin, TreeView): # type: ignore return True def _on_server_keypress(self, treeview: Gtk.TreeView, event: Gdk.EventKey) -> None: - if event.state is Gdk.ModifierType.CONTROL_MASK: + if is_ctrl_mask(event): match event.keyval: case Gdk.KEY_f: self.emitter.emit("request_keyword_focus")