diff --git a/legendary/cli.py b/legendary/cli.py index d04bb21..c884c51 100644 --- a/legendary/cli.py +++ b/legendary/cli.py @@ -146,9 +146,19 @@ class LegendaryCLI: games, dlc_list = self.core.get_game_and_dlc_list( platform_override=args.platform_override, skip_ue=not args.include_ue ) + # Get information for games that cannot be installed through legendary (yet), such + # as games that have to be activated on and launched through Origin. + if args.include_noasset: + na_games, na_dlcs = self.core.get_non_asset_library_items(skip_ue=not args.include_ue) + games.extend(na_games) + else: + na_dlcs = [] + # sort games and dlc by name games = sorted(games, key=lambda x: x.app_title.lower()) for citem_id in dlc_list.keys(): + if citem_id in na_dlcs: + dlc_list[citem_id].extend(na_dlcs[citem_id]) dlc_list[citem_id] = sorted(dlc_list[citem_id], key=lambda d: d.app_title.lower()) if args.csv or args.tsv: @@ -173,8 +183,12 @@ class LegendaryCLI: print('\nAvailable games:') for game in games: print(f' * {game.app_title} (App name: {game.app_name} | Version: {game.app_version})') + if not game.app_version: + print(' ! This game has to be activated and installed through third-party store (not supported)') for dlc in dlc_list[game.asset_info.catalog_item_id]: print(f' + {dlc.app_title} (App name: {dlc.app_name} | Version: {dlc.app_version})') + if not dlc.app_version: + print(' ! This DLC is included in the game does not have to be downloaded separately') print(f'\nTotal: {len(games)}') @@ -1254,6 +1268,8 @@ def main(): type=str, help='Override platform that games are shown for (e.g. Win32/Mac)') list_parser.add_argument('--include-ue', dest='include_ue', action='store_true', help='Also include Unreal Engine content (Engine/Marketplace) in list') + list_parser.add_argument('--include-non-installable', dest='include_noasset', action='store_true', + help='Include apps that are not installable (e.g. that have to be activated on Origin)') list_parser.add_argument('--csv', dest='csv', action='store_true', help='List games in CSV format') list_parser.add_argument('--tsv', dest='tsv', action='store_true', help='List games in TSV format') list_parser.add_argument('--json', dest='json', action='store_true', help='List games in JSON format') diff --git a/legendary/core.py b/legendary/core.py index 33231f7..6a2ff35 100644 --- a/legendary/core.py +++ b/legendary/core.py @@ -255,6 +255,38 @@ class LegendaryCore: return _ret, _dlc + def get_non_asset_library_items(self, skip_ue=True) -> (List[Game], Dict[str, List[Game]]): + """ + Gets a list of Games without assets for installation, for instance Games delivered via + third-party stores that do not have assets for installation + + :param skip_ue: Ingore Unreal Marketplace entries + :return: List of Games and DLC that do not have assets + """ + _ret = [] + _dlc = defaultdict(list) + # get all the appnames we have to ignore + ignore = set(i.app_name for i in self.get_assets()) + + for libitem in self.egs.get_library_items(): + if libitem['namespace'] == 'ue' and skip_ue: + continue + if libitem['appName'] in ignore: + continue + + game = self.lgd.get_game_meta(libitem['appName']) + if not game: + eg_meta = self.egs.get_game_info(libitem['namespace'], libitem['catalogItemId']) + game = Game(app_name=libitem['appName'], app_version=None, + app_title=eg_meta['title'], asset_info=None, metadata=eg_meta) + + if game.is_dlc: + _dlc[game.metadata['mainGameItem']['id']].append(game) + elif not any(i['path'] == 'mods' for i in game.metadata.get('categories', [])): + _ret.append(game) + + return _ret, _dlc + def get_dlc_for_game(self, app_name): game = self.get_game(app_name) if not game: @@ -347,11 +379,11 @@ class LegendaryCore: params.extend(shlex.split(install.launch_parameters, posix=False)) params.extend([ - '-AUTH_LOGIN=unused', - f'-AUTH_PASSWORD={game_token}', - '-AUTH_TYPE=exchangecode', - f'-epicapp={app_name}', - '-epicenv=Prod']) + '-AUTH_LOGIN=unused', + f'-AUTH_PASSWORD={game_token}', + '-AUTH_TYPE=exchangecode', + f'-epicapp={app_name}', + '-epicenv=Prod']) if install.requires_ot and not offline: self.log.info('Getting ownership token.') @@ -368,10 +400,10 @@ class LegendaryCore: language_code = self.language_code params.extend([ - '-EpicPortal', - f'-epicusername={user_name}', - f'-epicuserid={account_id}', - f'-epiclocale={language_code}' + '-EpicPortal', + f'-epicusername={user_name}', + f'-epicuserid={account_id}', + f'-epiclocale={language_code}' ]) if extra_args: