mirror of
https://github.com/ModOrganizer2/modorganizer-basic_games.git
synced 2026-07-27 14:07:29 -07:00
Merge branch 'ashemedai-ea-desktop-support' into qt6
# Conflicts: # README.md # basic_game.py
This commit is contained in:
@@ -158,6 +158,7 @@ class Witcher3Game(BasicGame):
|
||||
| GameOriginManifestIds | Origin Manifest ID of the game (Optional) | `originManifestIds` | `List[str]` or `str` |
|
||||
| GameOriginWatcherExecutables | Executables to watch for Origin DRM (Optional) | `originWatcherExecutables` | `List[str]` or `str` |
|
||||
| GameEpicId | Epic ID (`AppName`) of the game (Optional) | `epicAPPId` | `List[str]` or `str` |
|
||||
| GameEaDesktopId | EA Desktop ID of the game (Optional) | `eaDesktopContentId` | `List[str]` or `str` or `int` |
|
||||
|
||||
You can use the following variables for `str`:
|
||||
|
||||
@@ -169,9 +170,11 @@ You can use the following variables for `str`:
|
||||
|
||||
The meta-plugin provides some useful extra feature:
|
||||
|
||||
1. **Automatic Steam, GOG, Origin and Epic game detection:** If you provide Steam, GOG, Origin or Epic IDs for the game
|
||||
(via `GameSteamId`, `GameGogId`, `GameOriginManifestIds`, or `GameEpicId`), the game will be listed in the list of
|
||||
available games when creating a new MO2 instance (if the game is installed via Steam, GOG, Origin or Epic Games / Legendary).
|
||||
1. **Automatic Steam, GOG, Origin, Epic Games and EA Desktop detection:** If you provide
|
||||
Steam, GOG, Origin or Epic IDs for the game (via `GameSteamId`, `GameGogId`,
|
||||
`GameOriginManifestIds`, `GameEpicId` or `GameEaDesktopId`), the game will be listed
|
||||
in the list of available games when creating a new MO2 instance (if the game is
|
||||
installed via Steam, GOG, Origin, Epic Games / Legendary or EA Desktop).
|
||||
2. **Basic save game preview:** If you use the Python version, and if you can easily obtain a picture (file)
|
||||
for any saves, you can provide basic save-game preview by using the `BasicGameSaveGameInfo`.
|
||||
See [games/game_witcher3.py](games/game_witcher3.py) for more details.
|
||||
@@ -184,5 +187,6 @@ Game IDs can be found here:
|
||||
- For Epic Games (`AppName`) from:
|
||||
- `C:\ProgramData\Epic\EpicGamesLauncher\Data\Manifests\` (.item files)
|
||||
- or: `C:\ProgramData\Epic\EpicGamesLauncher\UnrealEngineLauncher\LauncherInstalled.dat`
|
||||
- For Legendary (alt. Epic launcher) via command `legendary list-games`
|
||||
- For Legendary (alt. Epic launcher) via command `legendary list-games`
|
||||
or from: `%USERPROFILE%\.config\legendary\installed.json`
|
||||
- For EA Desktop from `<EA Games install location>\<game title>\__Installer\installerdata.xml`
|
||||
|
||||
+26
-1
@@ -210,6 +210,7 @@ class BasicGameMappings:
|
||||
originManifestIds: BasicGameOptionsMapping[str]
|
||||
originWatcherExecutables: BasicGameMapping[List[str]]
|
||||
epicAPPId: BasicGameOptionsMapping[str]
|
||||
eaDesktopContentId: BasicGameOptionsMapping[str]
|
||||
|
||||
@staticmethod
|
||||
def _default_documents_directory(game):
|
||||
@@ -328,6 +329,13 @@ class BasicGameMappings:
|
||||
self.epicAPPId = BasicGameOptionsMapping(
|
||||
game, "GameEpicId", "epicAPPId", default=lambda g: "", apply_fn=ids_apply
|
||||
)
|
||||
self.eaDesktopContentId = BasicGameOptionsMapping(
|
||||
game,
|
||||
"GameEaDesktopId",
|
||||
"eaDesktopContentId",
|
||||
default=lambda g: "",
|
||||
apply_fn=ids_apply,
|
||||
)
|
||||
|
||||
|
||||
class BasicGame(mobase.IPluginGame):
|
||||
@@ -341,9 +349,11 @@ class BasicGame(mobase.IPluginGame):
|
||||
gog_games: Dict[str, Path]
|
||||
origin_games: Dict[str, Path]
|
||||
epic_games: Dict[str, Path]
|
||||
eadesktop_games: Dict[str, Path]
|
||||
|
||||
@staticmethod
|
||||
def setup():
|
||||
from .eadesktop_utils import find_games as find_eadesktop_games
|
||||
from .epic_utils import find_games as find_epic_games
|
||||
from .gog_utils import find_games as find_gog_games
|
||||
from .origin_utils import find_games as find_origin_games
|
||||
@@ -353,6 +363,7 @@ class BasicGame(mobase.IPluginGame):
|
||||
BasicGame.gog_games = find_gog_games()
|
||||
BasicGame.origin_games = find_origin_games()
|
||||
BasicGame.epic_games = find_epic_games()
|
||||
BasicGame.eadesktop_games = find_eadesktop_games()
|
||||
|
||||
# File containing the plugin:
|
||||
_fromName: str
|
||||
@@ -390,6 +401,9 @@ class BasicGame(mobase.IPluginGame):
|
||||
def is_epic(self) -> bool:
|
||||
return self._mappings.epicAPPId.has_value()
|
||||
|
||||
def is_eadesktop(self) -> bool:
|
||||
return self._mappings.eaDesktopContentId.has_value()
|
||||
|
||||
# IPlugin interface:
|
||||
|
||||
def init(self, organizer: mobase.IOrganizer) -> bool:
|
||||
@@ -457,6 +471,11 @@ class BasicGame(mobase.IPluginGame):
|
||||
self.setGamePath(BasicGame.epic_games[epic_id])
|
||||
return
|
||||
|
||||
for eadesktop_content_id in self._mappings.eaDesktopContentId.get():
|
||||
if eadesktop_content_id in BasicGame.eadesktop_games:
|
||||
self.setGamePath(BasicGame.eadesktop_games[eadesktop_content_id])
|
||||
return
|
||||
|
||||
def gameName(self) -> str:
|
||||
return self._mappings.gameName.get()
|
||||
|
||||
@@ -489,6 +508,9 @@ class BasicGame(mobase.IPluginGame):
|
||||
def epicAPPId(self) -> str:
|
||||
return self._mappings.epicAPPId.current()
|
||||
|
||||
def eaDesktopContentId(self) -> str:
|
||||
return self._mappings.eaDesktopContentId.current()
|
||||
|
||||
def binaryName(self) -> str:
|
||||
return self._mappings.binaryName.get()
|
||||
|
||||
@@ -589,7 +611,7 @@ class BasicGame(mobase.IPluginGame):
|
||||
|
||||
path = Path(path)
|
||||
|
||||
# Check if we have a matching steam ID or GOG id and set the index accordingly:
|
||||
# Check if we have a matching steam, GOG, Origin or EA Desktop id and set the index accordingly:
|
||||
for steamid, steampath in BasicGame.steam_games.items():
|
||||
if steampath == path:
|
||||
self._mappings.steamAPPId.set_value(steamid)
|
||||
@@ -602,6 +624,9 @@ class BasicGame(mobase.IPluginGame):
|
||||
for epicid, epicpath in BasicGame.epic_games.items():
|
||||
if epicpath == path:
|
||||
self._mappings.epicAPPId.set_value(epicid)
|
||||
for eadesktopid, eadesktoppath in BasicGame.eadesktop_games.items():
|
||||
if eadesktoppath == path:
|
||||
self._mappings.eaDesktopContentId.set_value(eadesktopid)
|
||||
|
||||
def documentsDirectory(self) -> QDir:
|
||||
return self._mappings.documentsDirectory.get()
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
|
||||
import configparser
|
||||
import os
|
||||
import xml.etree.ElementTree as et
|
||||
from pathlib import Path
|
||||
from typing import Dict, List
|
||||
|
||||
|
||||
def find_games() -> Dict[str, Path]:
|
||||
"""
|
||||
Find the list of EA Desktop games installed.
|
||||
|
||||
Returns:
|
||||
A mapping from EA Desktop content IDs to install locations for available
|
||||
EA Desktop games.
|
||||
"""
|
||||
games: Dict[str, Path] = {}
|
||||
|
||||
local_app_data_path = os.path.expandvars("%LocalAppData%")
|
||||
ea_desktop_settings_path = Path(local_app_data_path).joinpath("Electronic Arts", "EA Desktop")
|
||||
|
||||
if not ea_desktop_settings_path.exists:
|
||||
return games
|
||||
|
||||
user_ini, *_ = list(ea_desktop_settings_path.glob("user_*.ini"))
|
||||
|
||||
# The INI file in its current form has no section headers.
|
||||
# So we wrangle the input to add it all under a fake section.
|
||||
with open(user_ini) as f:
|
||||
ini_content = "[mod_organizer]\n" + f.read()
|
||||
|
||||
config = configparser.ConfigParser()
|
||||
config.read_string(ini_content)
|
||||
|
||||
install_path = Path(config.get("mod_organizer", "user.downloadinplacedir"))
|
||||
|
||||
for game_dir in install_path.iterdir():
|
||||
installer_file = game_dir.joinpath("__Installer", "installerdata.xml")
|
||||
xml_tree = et.parse(installer_file)
|
||||
root = xml_tree.getroot()
|
||||
|
||||
# For all manifest files the following XPath expression returns the
|
||||
# numeric ID. There are, in some cases, also name IDs but we do not
|
||||
# consider these.
|
||||
content_id = root.find(".//contentIDs/contentID[1]")
|
||||
game_id = content_id.text
|
||||
games[game_id] = game_dir
|
||||
|
||||
return games
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
games = find_games()
|
||||
for k, v in games.items():
|
||||
print("Found game with id {} at {}.".format(k, v))
|
||||
@@ -20,6 +20,7 @@ class DA2Game(BasicGame):
|
||||
GameSteamId = 1238040
|
||||
GameOriginManifestIds = ["OFB-EAST:59474", "DR:201797000"]
|
||||
GameOriginWatcherExecutables = ("DragonAge2.exe",)
|
||||
GameEaDesktopId = [70784, 1002980]
|
||||
|
||||
def version(self):
|
||||
# Don't forget to import mobase!
|
||||
|
||||
+2
-1
@@ -10,7 +10,7 @@ class DAOriginsGame(BasicGame):
|
||||
|
||||
Name = "Dragon Age Origins Support Plugin"
|
||||
Author = "Patchier"
|
||||
Version = "1.1.0"
|
||||
Version = "1.1.1"
|
||||
|
||||
GameName = "Dragon Age: Origins"
|
||||
GameShortName = "dragonage"
|
||||
@@ -20,6 +20,7 @@ class DAOriginsGame(BasicGame):
|
||||
GameSaveExtension = "das"
|
||||
GameSteamId = [17450, 47810]
|
||||
GameGogId = 1949616134
|
||||
GameEaDesktopId = [70377, 70843]
|
||||
|
||||
def init(self, organizer: mobase.IOrganizer):
|
||||
super().init(organizer)
|
||||
|
||||
Reference in New Issue
Block a user