mirror of
https://github.com/aclist/dztui.git
synced 2026-10-25 12:12:31 +01:00
Compare commits
13
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
343630d2da | ||
|
|
d63c7ce3ec | ||
|
|
f7ad357e6f | ||
|
|
035a01fe34 | ||
|
|
7dd14804aa | ||
|
|
1cc1ba2864 | ||
|
|
8c4d0aecdc | ||
|
|
616f18452a | ||
|
|
1064f7a9d6 | ||
|
|
b0e85f0e35 | ||
|
|
4d02604bcf | ||
|
|
ebffbe39f2 | ||
|
|
61860f6aee |
No files matched your search
+20
-8
@@ -255,16 +255,28 @@ class PeFileError(Exception):
|
|||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def parse_version_number(data: BinaryIO) -> FileVersion:
|
def parse_version_number(data: BinaryIO) -> FileVersion:
|
||||||
# https://learn.microsoft.com/en-us/windows/win32/api/verrsrc/ns-verrsrc-vs_fixedfileinfo
|
# https://learn.microsoft.com/en-us/windows/win32/api/verrsrc/ns-verrsrc-vs_fixedfileinfo
|
||||||
minor = struct.unpack("<L", data.read(4))[0] >> 16 & 0xFFFF
|
"""
|
||||||
major = struct.unpack("<L", data.read(4))[0] >> 0 & 0xFFFF
|
Note: structure differs from standard VS_FIXEDFILEINFO
|
||||||
build = struct.unpack("<L", data.read(4))[0] >> 0 & 0xFFFF
|
Major: lower 16 bits of first DWORD
|
||||||
# NOTE: 0-pad revision number
|
Minor: upper 16 bits of first DWORD
|
||||||
revision = str(struct.unpack("<L", data.read(4))[0] >> 16 & 0xFFFF)
|
Build: lower 16 bits of third DWORD
|
||||||
offset = 3 - len(revision)
|
Revision: upper 16 bits of second DWORD, zero-padded
|
||||||
padded = "0" * offset + revision
|
Lower 16 bits of revision DWORD appear unused.
|
||||||
return FileVersion(major, minor, build, padded)
|
"""
|
||||||
|
major_minor = struct.unpack("<I", data.read(4))[0]
|
||||||
|
revision_pair = struct.unpack("<I", data.read(4))[0]
|
||||||
|
build_dword = struct.unpack("<I", data.read(4))[0]
|
||||||
|
|
||||||
|
major = major_minor & 0xFFFF
|
||||||
|
minor = (major_minor >> 16) & 0xFFFF
|
||||||
|
build = build_dword & 0xFFFF
|
||||||
|
revision = (revision_pair >> 16) & 0xFFFF
|
||||||
|
revision = f"{revision:03d}"
|
||||||
|
|
||||||
|
return FileVersion(major, minor, build, revision)
|
||||||
|
|
||||||
|
|
||||||
def seek_to_hex(address: str, data: BinaryIO) -> None:
|
def seek_to_hex(address: str, data: BinaryIO) -> None:
|
||||||
|
|||||||
@@ -346,7 +346,7 @@ def get_details(record: Record) -> Details | None:
|
|||||||
dlc = strings.dlc_none
|
dlc = strings.dlc_none
|
||||||
case 2:
|
case 2:
|
||||||
dlc = strings.dlc_frostline
|
dlc = strings.dlc_frostline
|
||||||
case 3:
|
case 4:
|
||||||
dlc = strings.dlc_badlands
|
dlc = strings.dlc_badlands
|
||||||
case _:
|
case _:
|
||||||
dlc = strings.unspecified
|
dlc = strings.unspecified
|
||||||
|
|||||||
+21
-3
@@ -1,13 +1,14 @@
|
|||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import psutil
|
import psutil
|
||||||
|
import re
|
||||||
import requests
|
import requests
|
||||||
import subprocess
|
import subprocess
|
||||||
import vdf # type: ignore
|
import vdf # type: ignore
|
||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from requests.exceptions import HTTPError
|
from requests.exceptions import HTTPError
|
||||||
from typing import Any, Union
|
from typing import Any, Generator, Union
|
||||||
from warnings import deprecated
|
from warnings import deprecated
|
||||||
|
|
||||||
from dzgui.api.acf import ACF
|
from dzgui.api.acf import ACF
|
||||||
@@ -20,6 +21,7 @@ from dzgui.const.constants import (
|
|||||||
DAYZ_LAUNCHER,
|
DAYZ_LAUNCHER,
|
||||||
DEBIAN_STEAM_PATH,
|
DEBIAN_STEAM_PATH,
|
||||||
DEFAULT_STEAM_PATH,
|
DEFAULT_STEAM_PATH,
|
||||||
|
DOWNLOADS_PATH,
|
||||||
FLATPAK_STEAM_PATH,
|
FLATPAK_STEAM_PATH,
|
||||||
LIBRARYFOLDERS_PATH,
|
LIBRARYFOLDERS_PATH,
|
||||||
UBUNTU_STEAM_PATH,
|
UBUNTU_STEAM_PATH,
|
||||||
@@ -265,12 +267,12 @@ def find_user_id_32(path: Path) -> int:
|
|||||||
|
|
||||||
|
|
||||||
class SteamAPIKeyError(Exception):
|
class SteamAPIKeyError(Exception):
|
||||||
def __init__(self, msg=None):
|
def __init__(self, msg: str | None = None):
|
||||||
super().__init__(msg or api_validation_error)
|
super().__init__(msg or api_validation_error)
|
||||||
|
|
||||||
|
|
||||||
class SteamWorkshopEndpointError(Exception):
|
class SteamWorkshopEndpointError(Exception):
|
||||||
def __init__(self, msg=None):
|
def __init__(self, msg: str | None = None):
|
||||||
super().__init__(msg or workshop_endpoint_error)
|
super().__init__(msg or workshop_endpoint_error)
|
||||||
|
|
||||||
|
|
||||||
@@ -439,6 +441,22 @@ def is_dayz_running() -> bool:
|
|||||||
return any(s in item for sublist in procs for item in sublist for s in substring)
|
return any(s in item for sublist in procs for item in sublist for s in substring)
|
||||||
|
|
||||||
|
|
||||||
|
def get_pending_downloads(steam_path: Path, appid: int) -> Generator[Path, None, None]:
|
||||||
|
root_path = get_app_path(steam_path, appid)
|
||||||
|
downloads_dir = root_path / DOWNLOADS_PATH
|
||||||
|
files = downloads_dir.iterdir()
|
||||||
|
return files
|
||||||
|
|
||||||
|
|
||||||
|
def is_dayz_downloading(steam_path: Path, appid: int) -> bool:
|
||||||
|
files = get_pending_downloads(steam_path, appid)
|
||||||
|
reg = re.compile(rf"^state_(?:{APPID_DAYZ_EXP}|{APPID_DAYZ})_.*\.patch$")
|
||||||
|
pending = [f for f in files if reg.match(f.name)]
|
||||||
|
if len(pending) > 0:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def get_app_path(folders_path: Path, appid: int) -> Path:
|
def get_app_path(folders_path: Path, appid: int) -> Path:
|
||||||
app_path = None
|
app_path = None
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ DAYZ_BINARY = "DayZ_x64.exe"
|
|||||||
DAYZ_LAUNCHER = "DayZLauncher.exe"
|
DAYZ_LAUNCHER = "DayZLauncher.exe"
|
||||||
|
|
||||||
LIBRARYFOLDERS_PATH = "steamapps/libraryfolders.vdf"
|
LIBRARYFOLDERS_PATH = "steamapps/libraryfolders.vdf"
|
||||||
|
DOWNLOADS_PATH = "steamapps/downloading"
|
||||||
WORKSHOP_PATH = "steamapps/workshop/content/" + str(APPID_DAYZ)
|
WORKSHOP_PATH = "steamapps/workshop/content/" + str(APPID_DAYZ)
|
||||||
|
|
||||||
STEAM_CMD = "steam"
|
STEAM_CMD = "steam"
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ from dzgui.api.shortcuts import Shortcuts
|
|||||||
from dzgui.api.steam import (
|
from dzgui.api.steam import (
|
||||||
connect,
|
connect,
|
||||||
connect_debug,
|
connect_debug,
|
||||||
|
is_dayz_downloading,
|
||||||
get_app_allows_downloads,
|
get_app_allows_downloads,
|
||||||
get_app_name,
|
get_app_name,
|
||||||
get_needs_update,
|
get_needs_update,
|
||||||
@@ -84,6 +85,7 @@ class Prerequisites:
|
|||||||
available_space: float
|
available_space: float
|
||||||
passworded: bool
|
passworded: bool
|
||||||
dayz_running: bool
|
dayz_running: bool
|
||||||
|
download_paused: bool
|
||||||
steam_proc: SteamProcess
|
steam_proc: SteamProcess
|
||||||
mods: list[list[str]]
|
mods: list[list[str]]
|
||||||
game_mode: bool
|
game_mode: bool
|
||||||
@@ -169,6 +171,7 @@ class ConnectionManager:
|
|||||||
free_mib = format_mib(free)
|
free_mib = format_mib(free)
|
||||||
|
|
||||||
dayz_running = is_dayz_running()
|
dayz_running = is_dayz_running()
|
||||||
|
download_paused = is_dayz_downloading(steam_path, self.appid)
|
||||||
|
|
||||||
running_app = get_running_app()
|
running_app = get_running_app()
|
||||||
if running_app is not None:
|
if running_app is not None:
|
||||||
@@ -210,6 +213,7 @@ class ConnectionManager:
|
|||||||
available_space=free_mib,
|
available_space=free_mib,
|
||||||
passworded=info.password_protected,
|
passworded=info.password_protected,
|
||||||
dayz_running=dayz_running,
|
dayz_running=dayz_running,
|
||||||
|
download_paused=download_paused,
|
||||||
steam_proc=steam_proc,
|
steam_proc=steam_proc,
|
||||||
mods=remote_mods,
|
mods=remote_mods,
|
||||||
game_mode=game_mode,
|
game_mode=game_mode,
|
||||||
|
|||||||
@@ -47,3 +47,7 @@ running_app = (
|
|||||||
"Either stop the game first, or update your global Steam settings or the game's local settings.\n"
|
"Either stop the game first, or update your global Steam settings or the game's local settings.\n"
|
||||||
"Otherwise, mods may be queued for download but never update."
|
"Otherwise, mods may be queued for download but never update."
|
||||||
)
|
)
|
||||||
|
downloads_paused = (
|
||||||
|
"It looks like DayZ may have a pending update on Steam that was paused.\n"
|
||||||
|
"To enqueue mods for download, unpause any pending DayZ update and allow it to complete."
|
||||||
|
)
|
||||||
@@ -76,7 +76,7 @@ class SubmitField(Gtk.Box):
|
|||||||
self.button = Gtk.Button(label=options.save_button)
|
self.button = Gtk.Button(label=options.save_button)
|
||||||
|
|
||||||
self.button.connect("clicked", self._on_save_clicked)
|
self.button.connect("clicked", self._on_save_clicked)
|
||||||
self.entry.connect("insert-text", self._on_text_typed)
|
self.entry.connect("changed", self._on_text_typed)
|
||||||
self.entry.connect("activate", self._on_field_activated)
|
self.entry.connect("activate", self._on_field_activated)
|
||||||
self.entry.get_property("buffer").connect("deleted-text", self._on_text_deleted)
|
self.entry.get_property("buffer").connect("deleted-text", self._on_text_deleted)
|
||||||
|
|
||||||
@@ -113,13 +113,9 @@ class SubmitField(Gtk.Box):
|
|||||||
def _on_text_typed(
|
def _on_text_typed(
|
||||||
self,
|
self,
|
||||||
entry: Gtk.Entry,
|
entry: Gtk.Entry,
|
||||||
text: str,
|
|
||||||
length: int,
|
|
||||||
pos: int,
|
|
||||||
) -> None:
|
) -> None:
|
||||||
|
|
||||||
buffer = entry.get_property("buffer")
|
text = entry.get_text()
|
||||||
text = buffer.get_text() + text
|
|
||||||
state = self._is_valid_text(text)
|
state = self._is_valid_text(text)
|
||||||
self.button.set_sensitive(state)
|
self.button.set_sensitive(state)
|
||||||
|
|
||||||
|
|||||||
@@ -279,6 +279,8 @@ class PreConnectionAssistant(Gtk.Box):
|
|||||||
warnings.append(preconnect.protected_server)
|
warnings.append(preconnect.protected_server)
|
||||||
if prereqs.dayz_running is True:
|
if prereqs.dayz_running is True:
|
||||||
warnings.append(preconnect.dayz_running)
|
warnings.append(preconnect.dayz_running)
|
||||||
|
if len(prereqs.mods) > 0 and prereqs.download_paused:
|
||||||
|
warnings.append(preconnect.downloads_paused)
|
||||||
|
|
||||||
allows_dl, running_app = prereqs.allows_downloads
|
allows_dl, running_app = prereqs.allows_downloads
|
||||||
if len(prereqs.mods) > 0 and allows_dl is False:
|
if len(prereqs.mods) > 0 and allows_dl is False:
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@ description = "DayZ server browser and mod manager for Linux"
|
|||||||
authors = [
|
authors = [
|
||||||
{name = "aclist"}
|
{name = "aclist"}
|
||||||
]
|
]
|
||||||
version = "7.0.0b26"
|
version = "7.0.0b28"
|
||||||
license = "GPL-3.0-or-later"
|
license = "GPL-3.0-or-later"
|
||||||
license-files = ["LICENSE"]
|
license-files = ["LICENSE"]
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import pytest
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from dzgui.api.steam import is_dayz_downloading
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"file_list, expect",
|
||||||
|
[
|
||||||
|
(["state_221100_1111.patch"], True),
|
||||||
|
(["state_730_1111.patch"], False),
|
||||||
|
(["state_1024020_1111.patch"], True),
|
||||||
|
(["221100"], False),
|
||||||
|
(["221100", "state_221100_1111.patch"], True),
|
||||||
|
(["state_221100_1111.patch", "state_1024020_1111.patch"], True),
|
||||||
|
(["state_221100_1111"], False),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_dayz_patch_pending(monkeypatch, file_list, expect) -> None:
|
||||||
|
def mock_get_pending_downloads(steam_path: Path, appid: int) -> None:
|
||||||
|
files = [Path(file) for file in file_list]
|
||||||
|
return files
|
||||||
|
|
||||||
|
monkeypatch.setattr(
|
||||||
|
"dzgui.api.steam.get_pending_downloads", mock_get_pending_downloads
|
||||||
|
)
|
||||||
|
assert is_dayz_downloading(Path("/tmp"), Path("/tmp")) == expect
|
||||||
Reference in new issue
Block a user