Improvements to try resolve the issues with login checksums.
This commit is contained in:
@@ -4,6 +4,7 @@ from __future__ import annotations
|
||||
|
||||
from dataclasses import asdict, dataclass
|
||||
from datetime import datetime
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
@@ -33,6 +34,7 @@ WINETRICKS_CODEPAGE_PROBE = (
|
||||
WINETRICKS_PROTON7_PROBE = 'winetricks_early_wine_arch cmd.exe /c "echo %$1%"'
|
||||
RUNTIME_DEFAULT_SYNC = "runtime-default"
|
||||
CACHYOS_MARKER = "cachyos"
|
||||
GAME_RUNTIME_CONFIGURATION_VERSION = 1
|
||||
|
||||
|
||||
class RuntimeErrorPT(RuntimeError):
|
||||
@@ -159,6 +161,8 @@ def prepare_game_runtime(
|
||||
elif selection.kind in {"proton7", "proton7-container"}:
|
||||
if not selection.proton_path or not selection.steam_root:
|
||||
raise RuntimeErrorPT("incomplete Proton 7 runtime selection")
|
||||
if not runner.dry_run and _game_runtime_ready(paths, selection):
|
||||
return results
|
||||
if not runner.dry_run:
|
||||
paths.compat_data.mkdir(parents=True, exist_ok=True)
|
||||
proton = Path(selection.proton_path)
|
||||
@@ -237,11 +241,13 @@ def prepare_game_runtime(
|
||||
raise RuntimeErrorPT(f"unsupported runtime kind: {selection.kind}")
|
||||
if not runner.dry_run:
|
||||
_write_json(
|
||||
paths.state / "game-runtime.json",
|
||||
paths.game_runtime_marker,
|
||||
{
|
||||
"configuration_version": GAME_RUNTIME_CONFIGURATION_VERSION,
|
||||
"configured_at": datetime.now().astimezone().isoformat(),
|
||||
"native_d3d43": True,
|
||||
"dxvk_d3d9_override": DXVK_D3D9_OVERRIDE,
|
||||
"proton_identity": _proton_identity(selection),
|
||||
"runtime": asdict(selection),
|
||||
},
|
||||
)
|
||||
@@ -572,6 +578,69 @@ def _proton_prefix_ready(prefix: Path) -> bool:
|
||||
).exists()
|
||||
|
||||
|
||||
def _game_runtime_ready(paths: AppPaths, selection: RuntimeSelection) -> bool:
|
||||
marker = _read_json(paths.game_runtime_marker)
|
||||
identity = _proton_identity(selection)
|
||||
if marker is None or identity is None:
|
||||
return False
|
||||
if marker.get("configuration_version") != GAME_RUNTIME_CONFIGURATION_VERSION:
|
||||
return False
|
||||
if marker.get("runtime") != asdict(selection):
|
||||
return False
|
||||
if marker.get("proton_identity") != identity:
|
||||
return False
|
||||
if marker.get("native_d3d43") is not True:
|
||||
return False
|
||||
if marker.get("dxvk_d3d9_override") != DXVK_D3D9_OVERRIDE:
|
||||
return False
|
||||
if not _proton_prefix_ready(paths.proton_prefix):
|
||||
return False
|
||||
if not native_d3d_ready(paths.proton_prefix):
|
||||
return False
|
||||
if not _d3d9_override_ready(paths.proton_prefix):
|
||||
return False
|
||||
return _proton_game_link_ready(paths)
|
||||
|
||||
|
||||
def _d3d9_override_ready(prefix: Path) -> bool:
|
||||
try:
|
||||
registry = (prefix / "user.reg").read_text(
|
||||
encoding="utf-8",
|
||||
errors="replace",
|
||||
).casefold()
|
||||
except OSError:
|
||||
return False
|
||||
return f'"d3d9"="{DXVK_D3D9_OVERRIDE}"' in registry
|
||||
|
||||
|
||||
def _proton_game_link_ready(paths: AppPaths) -> bool:
|
||||
link = paths.proton_prefix / "drive_c/Program Files (x86)/Pristontale EU"
|
||||
if not link.is_symlink():
|
||||
return False
|
||||
try:
|
||||
return link.resolve(strict=True) == paths.runtime_view.resolve(strict=True)
|
||||
except (OSError, RuntimeError):
|
||||
return False
|
||||
|
||||
|
||||
def _proton_identity(selection: RuntimeSelection) -> dict[str, str] | None:
|
||||
if not selection.proton_path:
|
||||
return None
|
||||
proton = Path(selection.proton_path)
|
||||
identity_paths = {
|
||||
"proton": proton,
|
||||
"version": proton.parent / "version",
|
||||
"toolmanifest": proton.parent / "toolmanifest.vdf",
|
||||
}
|
||||
identity: dict[str, str] = {}
|
||||
for name, path in identity_paths.items():
|
||||
try:
|
||||
identity[name] = _sha256(path)
|
||||
except OSError:
|
||||
return None
|
||||
return identity
|
||||
|
||||
|
||||
def _find_proton_wine_tools(proton: Path) -> tuple[Path, Path] | None:
|
||||
for directory in (proton.parent / "files/bin", proton.parent / "dist/bin"):
|
||||
wine = directory / "wine"
|
||||
@@ -586,3 +655,19 @@ def _write_json(path: Path, value: object) -> None:
|
||||
temporary = path.with_name(f".{path.name}.{os.getpid()}.tmp")
|
||||
temporary.write_text(json.dumps(value, indent=2, sort_keys=True) + "\n", encoding="utf-8")
|
||||
temporary.replace(path)
|
||||
|
||||
|
||||
def _read_json(path: Path) -> dict[str, object] | None:
|
||||
try:
|
||||
value = json.loads(path.read_text(encoding="utf-8"))
|
||||
except (OSError, UnicodeError, json.JSONDecodeError):
|
||||
return None
|
||||
return value if isinstance(value, dict) else None
|
||||
|
||||
|
||||
def _sha256(path: Path) -> str:
|
||||
digest = hashlib.sha256()
|
||||
with path.open("rb") as handle:
|
||||
for chunk in iter(lambda: handle.read(1024 * 1024), b""):
|
||||
digest.update(chunk)
|
||||
return digest.hexdigest()
|
||||
|
||||
Reference in New Issue
Block a user