mirror of
https://github.com/derrod/legendary.git
synced 2024-12-22 01:45:28 +00:00
[cli/core/models/utils] macOS cloud save support
This commit is contained in:
parent
4eaa608370
commit
1dfc5aabe7
|
@ -447,7 +447,7 @@ class LegendaryCLI:
|
|||
continue
|
||||
|
||||
game = self.core.get_game(igame.app_name)
|
||||
if not game or not game.supports_cloud_saves:
|
||||
if not game or not (game.supports_cloud_saves or game.supports_mac_cloud_saves):
|
||||
if igame.app_name in latest_save:
|
||||
# this should never happen unless cloud save support was removed from a game
|
||||
logger.warning(f'{igame.app_name} has remote save(s) but does not support cloud saves?!')
|
||||
|
@ -462,7 +462,7 @@ class LegendaryCLI:
|
|||
|
||||
# if there is no saved save path, try to get one
|
||||
if not igame.save_path:
|
||||
save_path = self.core.get_save_path(igame.app_name)
|
||||
save_path = self.core.get_save_path(igame.app_name, platform=igame.platform)
|
||||
|
||||
# ask user if path is correct if computing for the first time
|
||||
logger.info(f'Computed save path: "{save_path}"')
|
||||
|
@ -902,7 +902,7 @@ class LegendaryCLI:
|
|||
end_t = time.time()
|
||||
if not args.no_install:
|
||||
# Allow setting savegame directory at install time so sync-saves will work immediately
|
||||
if game.supports_cloud_saves and args.save_path:
|
||||
if (game.supports_cloud_saves or game.supports_mac_cloud_saves) and args.save_path:
|
||||
igame.save_path = args.save_path
|
||||
|
||||
postinstall = self.core.install_game(igame)
|
||||
|
@ -930,7 +930,7 @@ class LegendaryCLI:
|
|||
self.install_game(args)
|
||||
args.yes, args.app_name = _yes, _app_name
|
||||
|
||||
if game.supports_cloud_saves and not game.is_dlc:
|
||||
if (game.supports_cloud_saves or game.supports_mac_cloud_saves) and not game.is_dlc:
|
||||
# todo option to automatically download saves after the installation
|
||||
# args does not have the required attributes for sync_saves in here,
|
||||
# not sure how to solve that elegantly.
|
||||
|
@ -1399,13 +1399,20 @@ class LegendaryCLI:
|
|||
game.app_version(args.platform)))
|
||||
all_versions = {k: v.build_version for k,v in game.asset_infos.items()}
|
||||
game_infos.append(InfoItem('All versions', 'platform_versions', all_versions, all_versions))
|
||||
# Cloud save support for Mac and Windows
|
||||
game_infos.append(InfoItem('Cloud saves supported', 'cloud_saves_supported',
|
||||
game.supports_cloud_saves, game.supports_cloud_saves))
|
||||
game.supports_cloud_saves or game.supports_mac_cloud_saves,
|
||||
game.supports_cloud_saves or game.supports_mac_cloud_saves))
|
||||
cs_dir = None
|
||||
if game.supports_cloud_saves:
|
||||
cs_dir = game.metadata['customAttributes']['CloudSaveFolder']['value']
|
||||
else:
|
||||
game_infos.append(InfoItem('Cloud save folder (Windows)', 'cloud_save_folder', cs_dir, cs_dir))
|
||||
|
||||
cs_dir = None
|
||||
game_infos.append(InfoItem('Cloud save folder', 'cloud_save_folder', cs_dir, cs_dir))
|
||||
if game.supports_mac_cloud_saves:
|
||||
cs_dir = game.metadata['customAttributes']['CloudSaveFolder_MAC']['value']
|
||||
game_infos.append(InfoItem('Cloud save folder (Mac)', 'cloud_save_folder_mac', cs_dir, cs_dir))
|
||||
|
||||
game_infos.append(InfoItem('Is DLC', 'is_dlc', game.is_dlc, game.is_dlc))
|
||||
# Find custom launch options, if available
|
||||
launch_options = []
|
||||
|
|
|
@ -14,6 +14,7 @@ from multiprocessing import Queue
|
|||
from platform import system
|
||||
from requests import session
|
||||
from requests.exceptions import HTTPError
|
||||
from sys import platform as sys_platform
|
||||
from uuid import uuid4
|
||||
from urllib.parse import urlencode, parse_qsl
|
||||
|
||||
|
@ -673,9 +674,14 @@ class LegendaryCore:
|
|||
|
||||
return _saves
|
||||
|
||||
def get_save_path(self, app_name):
|
||||
def get_save_path(self, app_name, platform='Windows'):
|
||||
game = self.lgd.get_game_meta(app_name)
|
||||
|
||||
if platform == 'Mac':
|
||||
save_path = game.metadata['customAttributes'].get('CloudSaveFolder_MAC', {}).get('value')
|
||||
else:
|
||||
save_path = game.metadata['customAttributes'].get('CloudSaveFolder', {}).get('value')
|
||||
|
||||
if not save_path:
|
||||
raise ValueError('Game does not support cloud saves')
|
||||
|
||||
|
@ -689,13 +695,19 @@ class LegendaryCore:
|
|||
'{epicid}': self.lgd.userdata['account_id']
|
||||
}
|
||||
|
||||
if os.name == 'nt':
|
||||
if sys_platform == 'win32':
|
||||
path_vars.update({
|
||||
'{appdata}': os.path.expandvars('%LOCALAPPDATA%'),
|
||||
'{userdir}': os.path.expandvars('%userprofile%/documents'),
|
||||
# '{userprofile}': os.path.expandvars('%userprofile%'), # possibly wrong
|
||||
'{userprofile}': os.path.expandvars('%userprofile%'),
|
||||
'{usersavedgames}': os.path.expandvars('%userprofile%/Saved Games')
|
||||
})
|
||||
elif sys_platform == 'darwin' and platform == 'Mac':
|
||||
path_vars.update({
|
||||
'{appdata}': os.path.expandvars('~/Library/Application Support'),
|
||||
'{userdir}': os.path.expandvars('~/Documents'),
|
||||
'{userlibrary}': os.path.expandvars('~/Library')
|
||||
})
|
||||
else:
|
||||
# attempt to get WINE prefix from config
|
||||
wine_pfx = self.lgd.config.get(app_name, 'wine_prefix', fallback=None)
|
||||
|
@ -724,8 +736,8 @@ class LegendaryCore:
|
|||
# these paths should always use a forward slash
|
||||
new_save_path = [path_vars.get(p.lower(), p) for p in save_path.split('/')]
|
||||
absolute_path = os.path.realpath(os.path.join(*new_save_path))
|
||||
# attempt to resolve as much as possible on case-insensitive file-systems
|
||||
if os.name != 'nt':
|
||||
# attempt to resolve as much as possible on case-sensitive file-systems
|
||||
if os.name != 'nt' and platform != 'Mac':
|
||||
absolute_path = case_insensitive_path_search(absolute_path)
|
||||
|
||||
return absolute_path
|
||||
|
@ -765,6 +777,7 @@ class LegendaryCore:
|
|||
game = self.lgd.get_game_meta(app_name)
|
||||
custom_attr = game.metadata['customAttributes']
|
||||
save_path = custom_attr.get('CloudSaveFolder', {}).get('value')
|
||||
save_path_mac = custom_attr.get('CloudSaveFolder_MAC', {}).get('value')
|
||||
|
||||
include_f = exclude_f = None
|
||||
if not disable_filtering:
|
||||
|
@ -774,12 +787,12 @@ class LegendaryCore:
|
|||
if (_exclude := custom_attr.get('CloudExcludeList', {}).get('value', None)) is not None:
|
||||
exclude_f = _exclude.split(',')
|
||||
|
||||
if not save_path:
|
||||
if not save_path and not save_path_mac:
|
||||
raise ValueError('Game does not support cloud saves')
|
||||
|
||||
sgh = SaveGameHelper()
|
||||
files = sgh.package_savegame(save_dir, app_name, self.egs.user.get('account_id'),
|
||||
save_path, include_f, exclude_f, local_dt)
|
||||
save_path, save_path_mac, include_f, exclude_f, local_dt)
|
||||
|
||||
if not files:
|
||||
self.log.info('No files to upload. If you believe this is incorrect run command with "--disable-filters"')
|
||||
|
|
|
@ -75,6 +75,10 @@ class Game:
|
|||
def supports_cloud_saves(self):
|
||||
return self.metadata and (self.metadata.get('customAttributes', {}).get('CloudSaveFolder') is not None)
|
||||
|
||||
@property
|
||||
def supports_mac_cloud_saves(self):
|
||||
return self.metadata and (self.metadata.get('customAttributes', {}).get('CloudSaveFolder_MAC') is not None)
|
||||
|
||||
@property
|
||||
def catalog_item_id(self):
|
||||
if not self.metadata:
|
||||
|
|
|
@ -51,8 +51,8 @@ class SaveGameHelper:
|
|||
_tmp_file.seek(0)
|
||||
return ci
|
||||
|
||||
def package_savegame(self, input_folder: str, app_name: str = '',
|
||||
epic_id: str = '', cloud_folder: str = '',
|
||||
def package_savegame(self, input_folder: str, app_name: str = '', epic_id: str = '',
|
||||
cloud_folder: str = '', cloud_folder_mac: str = '',
|
||||
include_filter: list = None,
|
||||
exclude_filter: list = None,
|
||||
manifest_dt: datetime = None):
|
||||
|
@ -61,6 +61,7 @@ class SaveGameHelper:
|
|||
:param app_name: App name for savegame being stored
|
||||
:param epic_id: Epic account ID
|
||||
:param cloud_folder: Folder the savegame resides in (based on game metadata)
|
||||
:param cloud_folder_mac: Folder the macOS savegame resides in (based on game metadata)
|
||||
:param include_filter: list of patterns for files to include (excludes all others)
|
||||
:param exclude_filter: list of patterns for files to exclude (includes all others)
|
||||
:param manifest_dt: datetime for the manifest name (optional)
|
||||
|
@ -77,6 +78,8 @@ class SaveGameHelper:
|
|||
manifest_dt = datetime.utcnow()
|
||||
m.meta.build_version = manifest_dt.strftime('%Y.%m.%d-%H.%M.%S')
|
||||
m.custom_fields['CloudSaveFolder'] = cloud_folder
|
||||
if cloud_folder_mac:
|
||||
m.custom_fields['CloudSaveFolder_MAC'] = cloud_folder_mac
|
||||
|
||||
self.log.info(f'Packing savegame for "{app_name}", input folder: {input_folder}')
|
||||
files = []
|
||||
|
|
Loading…
Reference in a new issue