Skip to content

Commit

Permalink
Add experimental custom path support
Browse files Browse the repository at this point in the history
Ammo will now search in the --conf dir for files ending in .json. The
filename represents the name of a game, and the contents define the
properties. Games defined like this will appear in the game selection
menu and should be possible to manage.

This is primarily written to get GoG up and running, but I'm currently
running into an issue where the GoG version of the game won't load
plugins and overwrites Plugins.txt with a default every time I try to
launch the game.

In any case, see #42 for an
example of a game configured like this.
  • Loading branch information
cyberrumor committed Mar 10, 2024
1 parent 087b45c commit 232197c
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 28 deletions.
76 changes: 50 additions & 26 deletions ammo/game_controller.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/usr/bin/env python3
import json
import re
from typing import Union
from dataclasses import (
Expand All @@ -7,6 +8,7 @@
)
from enum import Enum
from pathlib import Path

from .mod_controller import (
Game,
ModController,
Expand All @@ -20,7 +22,19 @@
@dataclass(frozen=True, kw_only=True)
class GameSelection:
name: field(default_factory=str)
library: field(default_factory=Path)
directory: field(default_factory=Path)
data: field(default_factory=Path)
dlc_file: field(default_factory=Path)
plugin_file: field(default_factory=Path)

def __post_init__(self):
"""
Validate that all paths are absolute.
"""
assert self.directory.is_absolute()
assert self.data.is_absolute()
assert self.dlc_file.is_absolute()
assert self.plugin_file.is_absolute()


class GameController(Controller):
Expand All @@ -45,15 +59,15 @@ def __init__(self, args):
"Starfield": "1716740",
}
self.downloads = self.args.downloads.resolve(strict=True)
self.games: list[GameSelection] = []

# Find games from instances of Steam
self.libraries: list[Path] = []
self.steam = Path.home() / ".local/share/Steam/steamapps"
self.flatpak = (
Path.home()
/ ".var/app/com.valvesoftware.Steam/.local/share/Steam/steamapps"
)
self.libraries: list[Path] = []
self.games: list[GameSelection] = []

for source in [self.steam, self.flatpak]:
if (source / "libraryfolders.vdf").exists() is False:
continue
Expand All @@ -75,13 +89,37 @@ def __init__(self, args):
if game.name not in self.ids:
continue

pfx = library / f"compatdata/{self.ids[game.name]}/pfx"
app_data = pfx / "drive_c/users/steamuser/AppData/Local"

game_selection = GameSelection(
name=game.name,
library=library,
directory=library / f"common/{game.name}",
data=library / f"common/{game.name}/Data",
dlc_file=app_data
/ f"{game.name.replace('t 4', 't4')}/DLCList.txt",
plugin_file=app_data
/ f"{game.name.replace('t 4', 't4')}/Plugins.txt",
)

self.games.append(game_selection)

# Find manually configured games
if args.conf.exists():
for i in args.conf.iterdir():
if i.is_file() and i.suffix == ".json":
with open(i, "r") as file:
j = json.loads(file.read())
game_selection = GameSelection(
name=i.stem,
directory=Path(j["directory"]),
data=Path(j["data"]),
dlc_file=Path(j["dlc_file"]),
plugin_file=Path(j["plugin_file"]),
)
if game_selection not in self.games:
self.games.append(game_selection)

if len(self.games) == 0:
raise FileNotFoundError(
f"Supported games {list(self.ids)} not found in {self.libraries}"
Expand All @@ -104,7 +142,7 @@ def __str__(self) -> str:
result += "-------|-----\n"
for i, game in enumerate(self.games):
index = f"[{i}]"
result += f"{index:<7} {game.name} ({game.library})\n"
result += f"{index:<7} {game.name} ({game.directory})\n"
return result

def _autocomplete(self, text: str, state: int) -> Union[str, None]:
Expand All @@ -117,9 +155,7 @@ def _populate_index_commands(self) -> None:
"""
for i, game in enumerate(self.games):
setattr(self, str(i), lambda self, i=i: self._manage_game(i))
full_location = str((game.library / "common" / game.name)).replace(
str(Path.home()), "~", 1
)
full_location = str(game.directory).replace(str(Path.home()), "~", 1)
self.__dict__[str(i)].__doc__ = full_location

def _manage_game(self, index: int) -> None:
Expand All @@ -129,18 +165,6 @@ def _manage_game(self, index: int) -> None:
"""
game_selection = self.games[index]

app_id = self.ids[game_selection.name]
pfx = game_selection.library / f"compatdata/{app_id}/pfx"
directory = game_selection.library / f"common/{game_selection.name}"
app_data = (
game_selection.library / f"{pfx}/drive_c/users/steamuser/AppData/Local"
)
dlc_file = app_data / f"{game_selection.name.replace('t 4', 't4')}/DLCList.txt"
plugin_file = (
app_data / f"{game_selection.name.replace('t 4', 't4')}/Plugins.txt"
)
data = directory / "Data"

ammo_conf_dir = self.args.conf.resolve() / game_selection.name
ammo_mods_dir = (self.args.mods or ammo_conf_dir / "mods").resolve()
ammo_conf = ammo_conf_dir / "ammo.conf"
Expand All @@ -160,13 +184,13 @@ def enabled_formula(line) -> bool:
return line.strip().startswith("*")

game = Game(
game_selection.name,
directory,
data,
ammo_conf,
dlc_file,
plugin_file,
ammo_mods_dir,
game_selection.name,
game_selection.directory,
game_selection.data,
game_selection.dlc_file,
game_selection.plugin_file,
enabled_formula,
)

Expand Down
4 changes: 2 additions & 2 deletions ammo/mod_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,13 @@

@dataclass(frozen=True)
class Game:
ammo_conf: Path
ammo_mods_dir: Path
name: str
directory: Path
data: Path
ammo_conf: Path
dlc_file: Path
plugin_file: Path
ammo_mods_dir: Path
enabled_formula: Callable[[str], bool] = field(
default=lambda line: line.strip().startswith("*")
)
Expand Down

0 comments on commit 232197c

Please sign in to comment.