Compare commits

..

2 Commits

Author SHA1 Message Date
99c099e3e3 docs: add more docs 2023-06-21 21:09:19 +07:00
359e2b30df feat: add version and channel override 2023-06-21 21:08:56 +07:00
2 changed files with 89 additions and 3 deletions

View File

@ -3,7 +3,7 @@ from os import PathLike
from pathlib import Path
from enum import Enum
from vollerei.abc.launcher.game import GameABC
from vollerei.hsr.constants import MD5SUMS
from vollerei.hsr.constants import md5sums
class GameChannel(Enum):
@ -14,9 +14,49 @@ class GameChannel(Enum):
class Game(GameABC):
def __init__(self, path: PathLike = None):
self._path: Path | None = Path(path) if path else None
self._version_override: tuple[int, int, int] | None = None
self._channel_override: GameChannel | None = None
@property
def version_override(self) -> tuple[int, int, int] | None:
"""
Override the game version.
This can be useful if you want to override the version of the game
and additionally working around bugs.
"""
return self._version_override
@version_override.setter
def version_override(self, version: tuple[int, int, int] | str | None):
if isinstance(version, str):
version = tuple(int(i) for i in version.split("."))
self._version_override = version
@property
def channel_override(self) -> GameChannel | None:
"""
Override the game channel.
Because game channel detection isn't implemented yet, you may need
to use this for some functions to work.
This can be useful if you want to override the channel of the game
and additionally working around bugs.
"""
return self._channel_override
@channel_override.setter
def channel_override(self, channel: GameChannel | str | None):
if isinstance(channel, str):
channel = GameChannel[channel]
self._channel_override = channel
@property
def path(self) -> Path | None:
"""
Path to the game folder.
"""
return self._path
@path.setter
@ -24,6 +64,9 @@ class Game(GameABC):
self._path = Path(path)
def data_folder(self) -> Path:
"""
Path to the game data folder.
"""
return self._path.joinpath("StarRail_Data")
def is_installed(self) -> bool:
@ -115,11 +158,15 @@ class Game(GameABC):
Only works for Star Rail version 1.0.5, other versions will return None
This is not needed for game patching, since the patcher will automatically
detect the channel.
Returns:
GameChannel: The current game channel.
"""
if self.get_version() == (1, 0, 5):
for channel, v in MD5SUMS["1.0.5"].values():
version = self._version_override or self.get_version()
if version == (1, 0, 5):
for channel, v in md5sums["1.0.5"].values():
for file, md5sum in v.values():
if (
md5(self._path.joinpath(file).read_bytes()).hexdigest()

View File

@ -30,6 +30,8 @@ class PatchType(Enum):
class Patcher(PatcherABC):
"""
Patch helper for HSR.
By default this will use Jadeite as it is maintained and more stable.
"""
def __init__(self, patch_type: PatchType = PatchType.Jadeite):
@ -43,6 +45,9 @@ class Patcher(PatcherABC):
@property
def patch_type(self) -> PatchType:
"""
Patch type, can be either Astra or Jadeite
"""
return self._patch_type
@patch_type.setter
@ -68,6 +73,9 @@ class Patcher(PatcherABC):
f.write(file_version)
def update_patch(self):
"""
Update the patch
"""
try:
match self._patch_type:
case PatchType.Astra:
@ -158,6 +166,15 @@ class Patcher(PatcherABC):
rmtree(self._jadeite, ignore_errors=True)
def patch_game(self, game: Game):
"""
Patch the game
If you use Jadeite (by default), this will just download Jadeite files
and won't actually patch the game because Jadeite will do that automatically.
Args:
game (Game): The game to patch
"""
if not game.is_installed():
raise PatcherError(GameNotInstalledError("Game is not installed"))
match self._patch_type:
@ -167,6 +184,14 @@ class Patcher(PatcherABC):
return self._patch_jadeite()
def unpatch_game(self, game: Game):
"""
Unpatch the game
If you use Jadeite (by default), this will just delete Jadeite files.
Args:
game (Game): The game to unpatch
"""
if not game.is_installed():
raise PatcherError(GameNotInstalledError("Game is not installed"))
match self._patch_type:
@ -176,9 +201,23 @@ class Patcher(PatcherABC):
self._unpatch_jadeite()
def check_telemetry(self) -> list[str]:
"""
Check if telemetry servers are accessible by the user
Returns:
list[str]: A list of telemetry servers that are accessible
"""
return telemetry.check_telemetry()
def block_telemetry(self, telemetry_list: list[str] = None):
"""
Block the telemetry servers
If telemetry_list is not provided, it will be checked automatically.
Args:
telemetry_list (list[str], optional): A list of telemetry servers to block.
"""
if not telemetry_list:
telemetry_list = telemetry.check_telemetry()
telemetry.block_telemetry(telemetry_list)