diff --git a/lmm/cli.py b/lmm/cli.py index a7be6a4..ba1d0fd 100644 --- a/lmm/cli.py +++ b/lmm/cli.py @@ -75,9 +75,17 @@ def launch(game: str, profile: str): runner.run(game) game.wait() - # Unmount - for mount in mounts: - mount.unmount() + # Unmount (with retries) + failed = False + for retry in range(5): + failed = any(not mount.unmount() for mount in mounts) + if not failed: + break + + print(f"Unmounting failed ({retry +1 }/5). Waiting 3s...") + time.sleep(3) + if failed: + print("Unmounting failed!") @cli.command() diff --git a/lmm/games/config.py b/lmm/games/config.py index 8d6b8b5..0171e13 100644 --- a/lmm/games/config.py +++ b/lmm/games/config.py @@ -15,6 +15,10 @@ from lmm.games.ron import ( GAME_NAME as RON, ReadyOrNotGame, ) +from lmm.games.lc import ( + GAME_NAME as LC, + LethalCompanyGame, +) import yaml @@ -34,6 +38,8 @@ def load_game_configs() -> list[Game]: BG3: BaldursGate3Game, PDMM: ProjectDivaMegaMixGame, RON: ReadyOrNotGame, + LC: LethalCompanyGame, + }.get(item, None) if game_cls is None: print(f"Unknown game {item}") diff --git a/lmm/games/lc.py b/lmm/games/lc.py new file mode 100644 index 0000000..9f81c93 --- /dev/null +++ b/lmm/games/lc.py @@ -0,0 +1,93 @@ +from pathlib import Path +from typing import Any + +from lmm.games.game import ProtonGame +from lmm.profile import Profile +from lmm.overlayfs import OverlayFSMount +from lmm.const import LMM_GAMES_PATH +from lmm.runners.base import runner_from_config + +GAME_NAME = "LethalCompany" + + +class LethalCompanyProfile(Profile): + # The names of the directories the the mods directory. + mods: list[str] + + def __init__(self, name: str, mods: list[str], **kwargs): + super().__init__(GAME_NAME, name, **kwargs) + + self.mods = mods + + def get_mod_names(self) -> list[str]: + return self.mods + + +class LethalCompanyGame(ProtonGame): + def __init__(self, profiles: list[LethalCompanyProfile], **kwargs): + super().__init__(GAME_NAME, "1966720", profiles, **kwargs) + + @property + def installation_path(self) -> Path: + return ( + self.steam_library + / "steamapps/common/Lethal Company" + ) + + @property + def game_executable(self) -> Path: + return self.installation_path / "Lethal Company.exe" + + def prepare_overlays( + self, profile: LethalCompanyProfile + ) -> list[OverlayFSMount]: + return [ + OverlayFSMount( + upper=self.installation_path, + lower=profile.mods, + mount=self.installation_path, + cd=LMM_GAMES_PATH / self.name, + ), + ] + + def to_dict(self) -> dict[str, Any]: + return { + "profiles": [ + { + "name": profile.name, + "mods": [ + { + "name": mod, + } + for mod in profile.mods + ], + } + for profile in self.profiles + ] + } + + @classmethod + def from_dict(cls, data: dict[str, Any]) -> "LethalCompanyGame": + profiles = [] + for profile in data["profiles"]: + mods = [mod["name"] for mod in profile["mods"]] + + if "runner" in profile: + runner = runner_from_config(profile["runner"]) + else: + runner = None + + profiles.append( + LethalCompanyProfile( + profile["name"], + mods, + runner=runner, + ), + ) + + if "default_runner" in data: + default_runner = runner_from_config(data["default_runner"]) + else: + default_runner = None + + return LethalCompanyGame(profiles, default_runner=default_runner)