feat: launch offline (WIP))

This commit is contained in:
aclist 2026-06-07 20:17:58 +09:00
parent 0070fe4061
commit 831bd9145d
9 changed files with 82 additions and 6 deletions

View File

@ -146,7 +146,7 @@ def connect(client: str, addr: str, appid: int, name: str, mods: list[str]) -> i
return proc.returncode
def load_to_menu(client: str, addr: str, appid: int, name: str, mods: list[str]) -> int:
def load_to_menu(client: str, appid: int, name: str, mods: list[str]) -> int:
"""Loads to the menu screen with the selected mods; used for AFK/pre-joining"""
concat = concat_mods(mods)
client_args = concat_bash_args(client)
@ -162,6 +162,22 @@ def load_to_menu(client: str, addr: str, appid: int, name: str, mods: list[str])
proc = subprocess.run([*client_args, *params])
return proc.returncode
def launch_offline(client: str, addr: str, appid: int, name: str, mods: list[str], mission: str) -> int:
"""Launch offline with specific mods/missions"""
concat = concat_mods(mods)
client_args = concat_bash_args(client)
params = [
"-applaunch",
str(appid),
"-nolauncher",
"-nosplash",
"-skipintro",
f"-name={name}",
f"-mod={concat}",
f"-mission={mission}"
]
proc = subprocess.run([*client_args, *params])
return proc.returncode
def find_user_id(path: Path) -> str | None:
resolved_path = path / "config" / "loginusers.vdf"

View File

@ -103,6 +103,7 @@ class Preferences(EnumWithAttrs):
class NotebookPage(EnumWithAttrs):
OFFLINE = {"crumbs": strings.crumbs.offline, "statusbar": True}
CHANGELOG = {"crumbs": strings.crumbs.changelog, "statusbar": True}
DEVELOPERS = {"crumbs": strings.crumbs.developers, "statusbar": False}
HELP = {"crumbs": strings.crumbs._help, "statusbar": True}

View File

@ -26,7 +26,7 @@ from dzgui.model.servers import ServerModelManager
from dzgui.util.diag import write_diagnostic
from dzgui.util.format import format_player_count
from dzgui.util.open_links import open_user_workshop, open_workshop_page
from dzgui.views.dialogs.filepicker import FilePicker
from dzgui.views.dialogs.filepicker import FilePicker, FolderPicker
from dzgui.views.dialogs.generic import ExceptionDialog
import gi
@ -47,6 +47,7 @@ if TYPE_CHECKING:
from dzgui.views.components.filter_panel import FilterPanel
from dzgui.views.components.right_panel import RightPanel
from dzgui.views.components.statusbar import Statusbar
from dzgui.views.pages.offline import OfflineLoader
from dzgui.views.pages.options import Options
from dzgui.views.pages.preconnect import PreConnectionAssistant
from dzgui.views.pages.servers import ServerNotebook
@ -72,6 +73,7 @@ class AppNavigation:
filters: "FilterPanel"
preconnect: "PreConnectionAssistant"
options: "Options"
offline_loader: "OfflineLoader"
class Controller(GObject.GObject):
@ -288,6 +290,10 @@ class Controller(GObject.GObject):
dialog = ExceptionDialog(self, str(e))
dialog.run()
def set_custom_folder(self) -> None:
picker = FolderPicker(self.mediator.window)
return picker.pick_folder()
def update_api_key(self, key: Preferences, text: str) -> None:
self.config_man.update_api_key(key, text)
@ -533,3 +539,7 @@ class Controller(GObject.GObject):
self.clear_cancel_event()
return True
return False
def open_offline(self, mods) -> None:
self.open_page(NotebookPage.OFFLINE)
self.mediator.offline_loader.populate(mods)

View File

@ -267,7 +267,7 @@ class ConnectionManager:
if menu_only:
rc = load_to_menu(client, addr, self.appid, playername, self.remote_mod_ids)
else:
rc = connect(client, addr, self.appid, playername, self.remote_mod_ids)
rc = connect(client, self.appid, playername, self.remote_mod_ids)
if rc != 0:
# TODO: log/pop the error
func = StoredFunc(self.controller.update_status)

View File

@ -273,6 +273,7 @@ class Crumbs:
thanks: str
developers: str
default: str
offline: str
@dataclass(slots=True, frozen=True)
@ -462,6 +463,7 @@ crumbs = Crumbs(
thanks="Help > Special thanks",
developers="Options > Developers",
default="Servers > ",
offline="Mods > Play offline"
)
no_mods = "No local mods found."

View File

@ -110,8 +110,13 @@ class Notebook(ScrollableMixin, Gtk.Notebook): # type: ignore
self.connection = PreConnectionAssistant(MainController)
from dzgui.views.pages.offline import OfflineLoader
self.offline = OfflineLoader(MainController)
self.pages = {
self.help: NotebookPage.HELP,
self.offline: NotebookPage.OFFLINE,
self.clog: NotebookPage.CHANGELOG,
self.keys: NotebookPage.KEYS,
self.settings: NotebookPage.OPTIONS,

View File

@ -1,5 +1,4 @@
from typing import Self, Union, TYPE_CHECKING
from warnings import deprecated
from dzgui.const.enum import NotebookPage, ServerTab
from dzgui.util.strings import esc_to_return, question_to_return
@ -70,6 +69,7 @@ class Statusbar(Gtk.Grid):
NotebookPage.CHANGELOG,
NotebookPage.LOG,
NotebookPage.CONNECTION,
NotebookPage.OFFLINE,
):
self.set_by_context(enum, esc_to_return)
return

View File

@ -33,3 +33,28 @@ class FilePicker(Gtk.FileChooserDialog):
self.destroy()
return Path(file)
return None
class FolderPicker(Gtk.FileChooserDialog):
def __init__(self, parent: Gtk.Window) -> None:
super().__init__(
title=picker.title,
action=Gtk.FileChooserAction.SELECT_FOLDER,
parent=parent,
resizable=True,
)
self.add_buttons("_Cancel", Gtk.ResponseType.CANCEL)
self.add_buttons("_OK", Gtk.ResponseType.OK)
self.set_default_response(Gtk.ResponseType.OK)
def pick_folder(self) -> Path | None:
res = self.run()
if res in (Gtk.ResponseType.CANCEL, Gtk.ResponseType.DELETE_EVENT):
self.destroy()
return None
if res == Gtk.ResponseType.OK:
folder = self.get_current_folder()
if folder is not None:
self.destroy()
return Path(folder)
return None

View File

@ -11,21 +11,38 @@ if TYPE_CHECKING:
from dzgui.controllers.mc import Controller
class Mods(NoOverlayScrolledWindow):
def __init__(self, controller: "Controller") -> None:
super().__init__()
self.box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
self.controller = controller
self.emitter = controller.get_emitter()
self.tree = ModTreeView(controller)
self.tree.set_vexpand(True)
self.add(self.tree)
self.offline_button = Gtk.Button(
label="Play offline",
halign=Gtk.Align.START,
margin_top=10,
margin_bottom=10,
)
self.offline_button.connect("clicked", self._on_offline_clicked)
self.box.add(self.offline_button)
self.box.add(self.tree)
self.add(self.box)
self.controller.register_widget("modtreeview", self.tree)
self.connect("map", self._on_map)
self.connect("unmap", self._on_unmap)
def _on_offline_clicked(self, button: Gtk.Button) -> None:
self.controller.open_offline(self.tree.get_model())
# TODO: add offline page
def _on_unmap(self, widget: Self) -> None:
self.emitter.emit("mod_page_toggled", False)