Refactoring of game features for better management. (#149)

* Refactoring following uibase change for game features.
* Switch to ruff for linting and formatting.
* Bump stubs to 2.5.1a0.
This commit is contained in:
Mikaël Capelle
2024-06-09 12:25:46 +02:00
committed by GitHub
parent 1fff6d441d
commit 71dbb8c557
41 changed files with 218 additions and 567 deletions
+3 -3
View File
@@ -12,13 +12,13 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: 3.11
python-version: 3.12
- uses: abatilo/actions-poetry@v2
- name: Install
run: |
cd basic_games
poetry install
poetry --no-root install
- name: Lint
run: |
cd basic_games
poetry run poe lint-all
poetry run poe lint
+3 -3
View File
@@ -160,11 +160,11 @@ class BasicModDataChecker(mobase.ModDataChecker):
_regex_patterns: RegexPatterns
"""The regex patterns derived from the file (glob) patterns."""
def __init__(self, file_patterns: GlobPatterns = GlobPatterns()):
def __init__(self, file_patterns: GlobPatterns | None = None):
super().__init__()
self._file_patterns = file_patterns
self._regex_patterns = RegexPatterns(file_patterns)
self._file_patterns = file_patterns or GlobPatterns()
self._regex_patterns = RegexPatterns(self._file_patterns)
def dataLooksValid(
self, filetree: mobase.IFileTree
+4 -1
View File
@@ -80,7 +80,10 @@ class BasicGameSaveGameInfoWidget(mobase.ISaveGameInfoWidget):
"""
super().__init__(parent)
self._get_preview = get_preview or (lambda p: None)
def _no_preview(p: Path) -> None:
return None
self._get_preview = get_preview or _no_preview
self._get_metadata = get_metadata or get_filedate_metadata
self._max_width = max_width or 320
+8 -23
View File
@@ -83,13 +83,13 @@ class BasicGameMapping(Generic[_T]):
if self._apply_fn is not None:
try:
value = self._apply_fn(value)
except: # noqa
except Exception as err:
raise ValueError(
"Basic game plugin from {} has an invalid {} property.".format(
game._fromName, # pyright: ignore[reportPrivateUsage]
self._exposed_name,
)
)
) from err
self._default = lambda game: value # type: ignore
elif default is not None:
self._default = default # type: ignore
@@ -360,19 +360,6 @@ class BasicGameMappings:
)
_GameFeature = (
mobase.BSAInvalidation
| mobase.DataArchives
| mobase.GamePlugins
| mobase.LocalSavegames
| mobase.ModDataChecker
| mobase.ModDataContent
| mobase.SaveGameInfo
| mobase.ScriptExtender
| mobase.UnmanagedMods
)
class BasicGame(mobase.IPluginGame):
"""This class implements some methods from mobase.IPluginGame
to make it easier to create game plugins without having to implement
@@ -408,9 +395,6 @@ class BasicGame(mobase.IPluginGame):
# Path to the game, as set by MO2:
_gamePath: str
# The feature map:
_featureMap: dict[type[_GameFeature], _GameFeature]
def __init__(self):
super(BasicGame, self).__init__()
@@ -418,10 +402,12 @@ class BasicGame(mobase.IPluginGame):
self._fromName = self.__class__.__name__
self._gamePath = ""
self._featureMap = {}
self._mappings: BasicGameMappings = BasicGameMappings(self)
def _register_feature(self, feature: mobase.GameFeature) -> bool:
return self._organizer.gameFeatures().registerFeature(self, feature, 0, True)
# Specific to BasicGame:
def is_steam(self) -> bool:
return self._mappings.steamAPPId.has_value()
@@ -442,7 +428,9 @@ class BasicGame(mobase.IPluginGame):
def init(self, organizer: mobase.IOrganizer) -> bool:
self._organizer = organizer
self._featureMap[mobase.SaveGameInfo] = BasicGameSaveGameInfo()
self._register_feature(BasicGameSaveGameInfo())
if self._mappings.originWatcherExecutables.get():
from .origin_utils import OriginWatcher
@@ -655,6 +643,3 @@ class BasicGame(mobase.IPluginGame):
def savesDirectory(self) -> QDir:
return self._mappings.savesDirectory.get()
def _featureList(self):
return self._featureMap
+3 -2
View File
@@ -26,8 +26,9 @@ def find_epic_games() -> Iterable[tuple[str, Path]]:
try:
with open(manifest_file_path, encoding="utf-8") as manifest_file:
manifest_file_data = json.load(manifest_file)
yield manifest_file_data["AppName"], Path(
manifest_file_data["InstallLocation"]
yield (
manifest_file_data["AppName"],
Path(manifest_file_data["InstallLocation"]),
)
except (json.JSONDecodeError, KeyError):
print(
+7 -10
View File
@@ -191,10 +191,8 @@ class BlackAndWhite2SaveGame(BasicGameSaveGame):
# to UNIX time and offset localtime
self.lastsave = int(
(
(
struct.unpack("q", self.readInf(info, "date"))[0] / 10000
- 11644473600000
)
struct.unpack("q", self.readInf(info, "date"))[0] / 10000
- 11644473600000
)
- (time.localtime().tm_gmtoff * 1000)
)
@@ -262,12 +260,11 @@ class BlackAndWhite2Game(BasicGame):
def init(self, organizer: mobase.IOrganizer) -> bool:
BasicGame.init(self, organizer)
self._featureMap[mobase.ModDataChecker] = BlackAndWhite2ModDataChecker()
self._featureMap[mobase.LocalSavegames] = BasicLocalSavegames(
self.savesDirectory()
)
self._featureMap[mobase.SaveGameInfo] = BasicGameSaveGameInfo(
get_metadata=getMetadata, max_width=400
self._register_feature(BlackAndWhite2ModDataChecker())
self._register_feature(BasicLocalSavegames(self.savesDirectory()))
self._register_feature(
BasicGameSaveGameInfo(get_metadata=getMetadata, max_width=400)
)
return True
+3 -3
View File
@@ -26,7 +26,7 @@ class BaSSaveGame(BasicGameSaveGame):
h, m, s = save_data["playTime"].split(":")
self._elapsed = (int(h), int(m), float(s))
f_stat = self._filepath.stat()
self._created = f_stat.st_ctime
self._created = f_stat.st_birthtime
self._modified = f_stat.st_mtime
def getName(self) -> str:
@@ -83,8 +83,8 @@ class BaSGame(BasicGame):
def init(self, organizer: mobase.IOrganizer) -> bool:
BasicGame.init(self, organizer)
self._featureMap[mobase.SaveGameInfo] = BasicGameSaveGameInfo(
get_metadata=bas_parse_metadata, max_width=400
self._register_feature(
BasicGameSaveGameInfo(get_metadata=bas_parse_metadata, max_width=400)
)
return True
+7 -7
View File
@@ -314,14 +314,14 @@ class Cyberpunk2077Game(BasicGame):
def init(self, organizer: mobase.IOrganizer) -> bool:
super().init(organizer)
self._featureMap[mobase.LocalSavegames] = BasicLocalSavegames(
self.savesDirectory()
self._register_feature(BasicLocalSavegames(self.savesDirectory()))
self._register_feature(
BasicGameSaveGameInfo(
lambda p: Path(p or "", "screenshot.png"),
parse_cyberpunk_save_metadata,
)
)
self._featureMap[mobase.SaveGameInfo] = BasicGameSaveGameInfo(
lambda p: Path(p or "", "screenshot.png"),
parse_cyberpunk_save_metadata,
)
self._featureMap[mobase.ModDataChecker] = CyberpunkModDataChecker()
self._register_feature(CyberpunkModDataChecker())
self._modlist_files = ModListFileManager[Literal["archive", "redmod"]](
organizer,
+2 -2
View File
@@ -29,7 +29,7 @@ class DA2Game(BasicGame):
def init(self, organizer: mobase.IOrganizer):
super().init(organizer)
self._featureMap[mobase.SaveGameInfo] = BasicGameSaveGameInfo(
lambda s: s.parent.joinpath("screen.dds")
self._register_feature(
BasicGameSaveGameInfo(lambda s: s.parent.joinpath("screen.dds"))
)
return True
+1 -1
View File
@@ -38,7 +38,7 @@ class DaggerfallUnityModDataChecker(mobase.ModDataChecker):
class DaggerfallUnityGame(BasicGame):
def init(self, organizer: mobase.IOrganizer) -> bool:
super().init(organizer)
self._featureMap[mobase.ModDataChecker] = DaggerfallUnityModDataChecker()
self._register_feature(DaggerfallUnityModDataChecker())
return True
Name = "Daggerfall Unity Support Plugin"
+2 -2
View File
@@ -25,7 +25,7 @@ class DAOriginsGame(BasicGame):
def init(self, organizer: mobase.IOrganizer):
super().init(organizer)
self._featureMap[mobase.SaveGameInfo] = BasicGameSaveGameInfo(
lambda s: s.parent.joinpath("screen.dds")
self._register_feature(
BasicGameSaveGameInfo(lambda s: s.parent.joinpath("screen.dds"))
)
return True
+2 -2
View File
@@ -125,7 +125,7 @@ class DarkestDungeonSaveGame(BasicGameSaveGame):
"Meta2 has wrong number of bytes: " + str(meta2DataLength)
)
meta2List: list[tuple[int, int, int]] = []
for x in range(numMeta2Entries):
for _ in range(numMeta2Entries):
entryHash = int.from_bytes(fp.read(4), "little")
offset = int.from_bytes(fp.read(4), "little")
fieldInfo = int.from_bytes(fp.read(4), "little")
@@ -175,7 +175,7 @@ class DarkestDungeonGame(BasicGame):
def init(self, organizer: mobase.IOrganizer) -> bool:
super().init(organizer)
self._featureMap[mobase.ModDataChecker] = DarkestDungeonModDataChecker()
self._register_feature(DarkestDungeonModDataChecker())
return True
def executables(self):
+1 -3
View File
@@ -43,7 +43,5 @@ class DarkMessiahOfMightAndMagicGame(BasicGame):
def init(self, organizer: mobase.IOrganizer):
super().init(organizer)
self._featureMap[mobase.SaveGameInfo] = BasicGameSaveGameInfo(
self._read_save_tga
)
self._register_feature(BasicGameSaveGameInfo(self._read_save_tga))
return True
+4 -2
View File
@@ -31,7 +31,9 @@ class DivinityOriginalSinGame(BasicGame):
def init(self, organizer: mobase.IOrganizer):
super().init(organizer)
self._featureMap[mobase.SaveGameInfo] = BasicGameSaveGameInfo(
lambda s: s.with_suffix(".png") # Not confirmed
self._register_feature(
BasicGameSaveGameInfo(
lambda s: s.with_suffix(".png") # Not confirmed
)
)
return True
+2 -6
View File
@@ -89,12 +89,8 @@ class DivinityOriginalSinEnhancedEditionGame(BasicGame, mobase.IPluginFileMapper
def init(self, organizer: mobase.IOrganizer):
super().init(organizer)
self._featureMap[mobase.SaveGameInfo] = BasicGameSaveGameInfo(
lambda s: s.with_suffix(".png")
)
self._featureMap[mobase.ModDataChecker] = (
DivinityOriginalSinEnhancedEditionModDataChecker()
)
self._register_feature(BasicGameSaveGameInfo(lambda s: s.with_suffix(".png")))
self._register_feature(DivinityOriginalSinEnhancedEditionModDataChecker())
return True
def mappings(self) -> list[mobase.Mapping]:
+1 -1
View File
@@ -74,7 +74,7 @@ class DungeonSiegeIGame(BasicGame):
def init(self, organizer: mobase.IOrganizer):
super().init(organizer)
self._featureMap[mobase.ModDataChecker] = DungeonSiegeIModDataChecker()
self._register_feature(DungeonSiegeIModDataChecker())
return True
def executables(self):
+1 -1
View File
@@ -74,7 +74,7 @@ class DungeonSiegeIIGame(BasicGame):
def init(self, organizer: mobase.IOrganizer):
super().init(organizer)
self._featureMap[mobase.ModDataChecker] = DungeonSiegeIIModDataChecker()
self._register_feature(DungeonSiegeIIModDataChecker())
return True
def executables(self):
+1 -1
View File
@@ -44,7 +44,7 @@ class GTA3DefinitiveEditionGame(BasicGame):
def init(self, organizer: mobase.IOrganizer) -> bool:
super().init(organizer)
self._featureMap[mobase.ModDataChecker] = GTA3DefinitiveEditionModDataChecker()
self._register_feature(GTA3DefinitiveEditionModDataChecker())
return True
def executables(self):
+1 -3
View File
@@ -44,9 +44,7 @@ class GTASanAndreasDefinitiveEditionGame(BasicGame):
def init(self, organizer: mobase.IOrganizer) -> bool:
super().init(organizer)
self._featureMap[mobase.ModDataChecker] = (
GTASanAndreasDefinitiveEditionModDataChecker()
)
self._register_feature(GTASanAndreasDefinitiveEditionModDataChecker())
return True
def executables(self):
+1 -3
View File
@@ -44,9 +44,7 @@ class GTAViceCityDefinitiveEditionGame(BasicGame):
def init(self, organizer: mobase.IOrganizer) -> bool:
super().init(organizer)
self._featureMap[mobase.ModDataChecker] = (
GTAViceCitysDefinitiveEditionModDataChecker()
)
self._register_feature(GTAViceCitysDefinitiveEditionModDataChecker())
return True
def executables(self):

Some files were not shown because too many files have changed in this diff Show More