[cli/core/utils] Add (janky) EOS overlay install support on non-Windows

This commit is contained in:
derrod 2021-12-31 18:46:09 +01:00
parent ecb230511f
commit 0298a53315
3 changed files with 95 additions and 31 deletions

View file

@ -1950,13 +1950,41 @@ class LegendaryCLI:
logger.info(f'Exchange code: {token["code"]}') logger.info(f'Exchange code: {token["code"]}')
def manage_eos_overlay(self, args): def manage_eos_overlay(self, args):
prefix = None
if os.name != 'nt': if os.name != 'nt':
logger.fatal('This command is only supported on Windows.') if args.app:
app_name = self._resolve_aliases(args.app)
# try getting bottle/prefix from config
if sys_platform == 'darwin':
args.bottle = self.core.lgd.config.get(app_name, 'crossover_bottle', fallback=None)
args.prefix = self.core.lgd.config.get(f'{app_name}.env', 'WINEPREFIX', fallback=None)
args.prefix = self.core.lgd.config.get(app_name, 'wine_prefix', fallback=args.prefix)
else:
# try using defaults if they exist
if sys_platform == 'darwin':
args.bottle = self.core.lgd.config.get('default', 'crossover_bottle', fallback=None)
args.prefix = self.core.lgd.config.get('default.env', 'WINEPREFIX', fallback=None)
args.prefix = self.core.lgd.config.get('default', 'wine_prefix', fallback=args.prefix)
if sys_platform == 'darwin' and args.bottle:
if not mac_is_valid_bottle(args.bottle):
logger.error('Invalid bottle specified.')
return
prefix = mac_get_bottle_path(args.bottle)
elif args.prefix:
if not os.path.exists(args.prefix):
logger.error(f'Prefix "{args.prefix}" does not exist.')
return
prefix = args.prefix
else:
logger.error('Need either config default, --prefix, --bottle, or --app to install the overlay to.')
return return
if args.action == 'info': if args.action == 'info':
reg_paths = query_registry_entries() reg_paths = query_registry_entries(prefix)
available_installs = self.core.search_overlay_installs() available_installs = self.core.search_overlay_installs(prefix)
igame = self.core.lgd.get_overlay_install_info() igame = self.core.lgd.get_overlay_install_info()
if not igame: if not igame:
logger.info('No Legendary-managed installation found.') logger.info('No Legendary-managed installation found.')
@ -1991,7 +2019,7 @@ class LegendaryCLI:
if igame: if igame:
args.path = igame.install_path args.path = igame.install_path
else: else:
available_installs = self.core.search_overlay_installs() available_installs = self.core.search_overlay_installs(prefix)
args.path = available_installs[0] args.path = available_installs[0]
if not self.core.is_overlay_install(args.path): if not self.core.is_overlay_install(args.path):
@ -2000,22 +2028,22 @@ class LegendaryCLI:
args.path = os.path.normpath(args.path) args.path = os.path.normpath(args.path)
# Check for existing entries # Check for existing entries
reg_paths = query_registry_entries() reg_paths = query_registry_entries(prefix)
if old_path := reg_paths["overlay_path"]: if old_path := reg_paths["overlay_path"]:
if os.path.normpath(old_path) == args.path: if os.path.normpath(old_path) == args.path:
logger.info(f'Overlay already enabled, nothing to do.') logger.info(f'Overlay already enabled, nothing to do.')
return return
else: else:
logger.info(f'Updating overlay registry entries from "{old_path}" to "{args.path}"') logger.info(f'Updating overlay registry entries from "{old_path}" to "{args.path}"')
remove_registry_entries() remove_registry_entries(prefix)
add_registry_entries(args.path) add_registry_entries(args.path, prefix)
logger.info(f'Enabled overlay at: {args.path}') logger.info(f'Enabled overlay at: {args.path}')
elif args.action == 'disable': elif args.action == 'disable':
logger.info('Disabling overlay (removing registry keys)..') logger.info('Disabling overlay (removing registry keys)..')
reg_paths = query_registry_entries() reg_paths = query_registry_entries(prefix)
old_path = reg_paths["overlay_path"] old_path = reg_paths["overlay_path"]
remove_registry_entries() remove_registry_entries(prefix)
# if the install is not managed by legendary, specify the command including the path # if the install is not managed by legendary, specify the command including the path
if self.core.is_overlay_installed(): if self.core.is_overlay_installed():
logger.info(f'To re-enable the overlay, run: legendary eos-overlay enable') logger.info(f'To re-enable the overlay, run: legendary eos-overlay enable')
@ -2033,7 +2061,12 @@ class LegendaryCLI:
return return
logger.info('Removing registry entries...') logger.info('Removing registry entries...')
remove_registry_entries() remove_registry_entries(prefix)
if os.name != 'nt':
logger.info(f'Registry entries in prefixes other than "{prefix}" were not removed. '
f'This shoouldn\'t cause any issues as the overlay will simply fail to load.')
logger.info('Deleting overlay installation...') logger.info('Deleting overlay installation...')
self.core.remove_overlay_install() self.core.remove_overlay_install()
logger.info('Done.') logger.info('Done.')
@ -2073,15 +2106,15 @@ class LegendaryCLI:
# Check for existing registry entries, and remove them if necessary # Check for existing registry entries, and remove them if necessary
install_path = os.path.normpath(igame.install_path) install_path = os.path.normpath(igame.install_path)
reg_paths = query_registry_entries() reg_paths = query_registry_entries(prefix)
if old_path := reg_paths["overlay_path"]: if old_path := reg_paths["overlay_path"]:
if os.path.normpath(old_path) != install_path: if os.path.normpath(old_path) != install_path:
logger.info(f'Updating overlay registry entries from "{old_path}" to "{install_path}"') logger.info(f'Updating overlay registry entries from "{old_path}" to "{install_path}"')
remove_registry_entries() remove_registry_entries(prefix)
else: else:
logger.info(f'Registry entries already exist. Done.') logger.info(f'Registry entries already exist. Done.')
return return
add_registry_entries(install_path) add_registry_entries(install_path, prefix)
logger.info('Done.') logger.info('Done.')
def crossover_setup(self, args): def crossover_setup(self, args):
@ -2609,10 +2642,23 @@ def main():
metavar='<install|update|remove|enable|disable|info>') metavar='<install|update|remove|enable|disable|info>')
eos_overlay_parser.add_argument('--path', dest='path', action='store', eos_overlay_parser.add_argument('--path', dest='path', action='store',
help='Path to the EOS overlay folder to be enabled/installed to.') help='Path to the EOS overlay folder to be enabled/installed to.')
# eos_overlay_parser.add_argument('--prefix', dest='prefix', action='store',
# help='WINE prefix to install the overlay in') if os.name != 'nt':
# eos_overlay_parser.add_argument('--app', dest='app', action='store', eos_overlay_parser.add_argument('--prefix', dest='prefix', action='store',
# help='Use this app\'s wine prefix (if configured in config)') help='WINE prefix to install the overlay in')
eos_overlay_parser.add_argument('--app', dest='app', action='store',
help='Use this app\'s wine prefix (if configured in config)')
if sys_platform == 'darwin':
eos_overlay_parser.add_argument('--bottle', dest='bottle', action='store',
help='WINE prefix to install the overlay in')
else:
eos_overlay_parser.add_argument('--bottle', dest='prefix', action='store', help=argparse.SUPPRESS)
else:
eos_overlay_parser.add_argument('--prefix', dest='prefix', action='store', help=argparse.SUPPRESS)
eos_overlay_parser.add_argument('--bottle', dest='prefix', action='store', help=argparse.SUPPRESS)
eos_overlay_parser.add_argument('--app', dest='app', action='store', help=argparse.SUPPRESS)
cx_parser.add_argument('--reset', dest='reset', action='store_true', cx_parser.add_argument('--reset', dest='reset', action='store_true',
help='Reset default/app-specific crossover configuration') help='Reset default/app-specific crossover configuration')

View file

@ -1755,22 +1755,30 @@ class LegendaryCore:
def is_overlay_install(path): def is_overlay_install(path):
return os.path.exists(os.path.join(path, 'EOSOVH-Win64-Shipping.dll')) return os.path.exists(os.path.join(path, 'EOSOVH-Win64-Shipping.dll'))
def search_overlay_installs(self): def search_overlay_installs(self, prefix=None):
locations = [] locations = []
install_info = self.lgd.get_overlay_install_info() install_info = self.lgd.get_overlay_install_info()
if install_info: if install_info:
locations.append(install_info.install_path) locations.append(install_info.install_path)
if os.name == 'nt':
# Launcher path # Launcher path
locations.append(os.path.expandvars(r'%programfiles(x86)%\Epic Games\Launcher\Portal\Extras\Overlay')) locations.append(os.path.expandvars(r'%programfiles(x86)%\Epic Games\Launcher\Portal\Extras\Overlay'))
# EOSH path # EOSH path
locations.append(os.path.expandvars(f'%programfiles(x86)%\\Epic Games\\Epic Online Services' locations.append(os.path.expandvars(f'%programfiles(x86)%\\Epic Games\\Epic Online Services'
f'\\managedArtifacts\\{EOSOverlayApp.app_name}')) f'\\managedArtifacts\\{EOSOverlayApp.app_name}'))
else:
# Launcher path
locations.append(os.path.join(prefix, 'drive_c', 'Program Files (x86)',
'Epic Games/Launcher/Portal/Extras/Overlay'))
# EOSH path
locations.append(os.path.join(prefix, 'drive_c', 'Program Files (x86)',
f'Epic Games/Epic Online Services/managedArtifacts/{EOSOverlayApp.app_name}'))
# normalise all paths # normalise all paths
locations = [os.path.normpath(x) for x in locations] locations = [os.path.normpath(x) for x in locations]
paths = query_registry_entries() paths = query_registry_entries(prefix)
if paths['overlay_path']: if paths['overlay_path']:
reg_path = os.path.normpath(paths['overlay_path']) reg_path = os.path.normpath(paths['overlay_path'])
if reg_path not in locations: if reg_path not in locations:

View file

@ -59,6 +59,11 @@ def query_registry_entries(prefix=None):
else: else:
overlay_path = None overlay_path = None
if overlay_path.startswith('C:'):
overlay_path = os.path.join(prefix, 'drive_c', overlay_path[3:])
elif overlay_path.startswith('Z:'):
overlay_path = overlay_path[2:]
return dict(overlay_path=overlay_path, return dict(overlay_path=overlay_path,
vulkan_hkcu=list(), vulkan_hkcu=list(),
vulkan_hklm=list()) vulkan_hklm=list())
@ -87,7 +92,11 @@ def add_registry_entries(overlay_path, prefix=None):
reg_lines = open(use_reg_file, 'r', encoding='utf-8').readlines() reg_lines = open(use_reg_file, 'r', encoding='utf-8').readlines()
overlay_line = f'"{EOS_OVERLAY_VALUE}"="Z:{overlay_path}"\n' overlay_path = overlay_path.replace('\\', '/')
if overlay_path.startswith('/'):
overlay_path = f'Z:{overlay_path}'
overlay_line = f'"{EOS_OVERLAY_VALUE}"="{overlay_path}"\n'
overlay_idx = None overlay_idx = None
section_idx = None section_idx = None
@ -110,9 +119,9 @@ def add_registry_entries(overlay_path, prefix=None):
def remove_registry_entries(prefix=None): def remove_registry_entries(prefix=None):
if os.name == 'nt': entries = query_registry_entries(prefix)
entries = query_registry_entries()
if os.name == 'nt':
if entries['overlay_path']: if entries['overlay_path']:
logger.debug('Removing HKCU EOS OverlayPath') logger.debug('Removing HKCU EOS OverlayPath')
remove_registry_value(HKEY_CURRENT_USER, EOS_OVERLAY_KEY, EOS_OVERLAY_VALUE) remove_registry_value(HKEY_CURRENT_USER, EOS_OVERLAY_KEY, EOS_OVERLAY_VALUE)
@ -129,6 +138,7 @@ def remove_registry_entries(prefix=None):
if not os.path.exists(use_reg_file): if not os.path.exists(use_reg_file):
raise ValueError('No user.reg file, invalid path') raise ValueError('No user.reg file, invalid path')
if entries['overlay_path']:
reg_lines = open(use_reg_file, 'r', encoding='utf-8').readlines() reg_lines = open(use_reg_file, 'r', encoding='utf-8').readlines()
filtered_lines = [line for line in reg_lines if EOS_OVERLAY_VALUE not in line] filtered_lines = [line for line in reg_lines if EOS_OVERLAY_VALUE not in line]
open(use_reg_file, 'w', encoding='utf-8').writelines(filtered_lines) open(use_reg_file, 'w', encoding='utf-8').writelines(filtered_lines)