def runner(self): """Return the runner instance used by this install""" if not self._runner: if self.platform == "windows": self._runner = winesteam.winesteam() self._runner = steam.steam() return self._runner
def check_steam_install(self): """Checks that the required version of Steam is installed. Return a boolean indicating whether is it or not. """ if self.steam_data['platform'] == 'windows': # Check that wine is installed wine_runner = wine.wine() if not wine_runner.is_installed(): logger.debug('Wine is not installed') wine_runner.install( downloader=self.parent.start_download, callback=self.check_steam_install ) return False # Getting data from Wine Steam steam_runner = winesteam.winesteam() if not steam_runner.is_installed(): logger.debug('Winesteam not installed') winesteam.download_steam( downloader=self.parent.start_download, callback=self.on_steam_downloaded ) return False return True else: steam_runner = steam.steam() if not steam_runner.is_installed(): raise ScriptingError( "Install Steam for Linux and start installer again" ) return True
def _download_steam_data(self, file_uri, file_id): try: parts = file_uri.split(":", 2) steam_rel_path = parts[2].strip() except IndexError: raise ScriptingError("Malformed steam path: %s" % file_uri) if steam_rel_path == "/": steam_rel_path = "." self.steam_data = {"appid": parts[1], "steam_rel_path": steam_rel_path, "file_id": file_id} if parts[0] == "$WINESTEAM": appid = self.steam_data["appid"] logger.debug("Getting Wine Steam data for appid %s" % appid) self.parent.set_status("Getting Wine Steam game data") self.steam_data["platform"] = "windows" # Check that wine is installed wine_runner = wine.wine() if not wine_runner.is_installed(): wine_runner.install() # Getting data from Wine Steam steam_runner = winesteam.winesteam() if not steam_runner.is_installed(): winesteam.download_steam( downloader=self.parent.start_download, callback=self.parent.on_steam_downloaded ) else: self.install_steam_game(winesteam.winesteam) else: # Getting data from Linux Steam self.parent.set_status("Getting Steam game data") self.steam_data["platform"] = "linux" self.install_steam_game(steam.steam)
def complete_steam_install(self, dest, appid): self.parent.wait_for_user_action( "Steam will now install, press Ok when install is finished", self.on_winesteam_installed, appid ) steam_runner = winesteam.winesteam() async_call(steam_runner.install, None, dest)
def sync_steam_local(self): """Sync Steam games in library with Steam and Wine Steam""" steamrunner = steam() winesteamrunner = winesteam() installed = set() uninstalled = set() # Get installed steamapps installed_steamapps = self.get_installed_steamapps(steamrunner) installed_winesteamapps = self.get_installed_steamapps(winesteamrunner) for game_info in self.library: slug = game_info['slug'] runner = game_info['runner'] steamid = game_info['steamid'] installed_in_steam = steamid in installed_steamapps installed_in_winesteam = steamid in installed_winesteamapps # Set installed if not game_info['installed']: if not installed_in_steam: # (Linux Steam only) continue logger.debug("Setting %s as installed" % game_info['name']) config_id = (game_info['configpath'] or config.make_game_config_id(slug)) game_id = pga.add_or_update( name=game_info['name'], runner='steam', slug=slug, installed=1, configpath=config_id, ) game_config = config.LutrisConfig( runner_slug='steam', game_config_id=config_id, ) game_config.raw_game_config.update({'appid': str(steamid)}) game_config.save() installed.add(game_id) # Set uninstalled elif not (installed_in_steam or installed_in_winesteam): if runner not in ['steam', 'winesteam']: continue if runner == 'steam' and not steamrunner.is_installed(): continue if runner == 'winesteam' and not winesteamrunner.is_installed(): continue logger.debug("Setting %(name)s (%(steamid)s) as uninstalled", game_info) game_id = pga.add_or_update( name=game_info['name'], runner='', slug=game_info['slug'], installed=0 ) uninstalled.add(game_id) return (installed, uninstalled)
def get_steamapps_paths(flat=False): from lutris.runners import winesteam, steam if flat: steamapps_paths = [] else: steamapps_paths = {'linux': [], 'windows': []} winesteam_runner = winesteam.winesteam() steam_runner = steam.steam() for folder in steam_runner.get_steamapps_dirs(): if flat: steamapps_paths.append(folder) else: steamapps_paths['linux'].append(folder) for folder in winesteam_runner.get_steamapps_dirs(): if flat: steamapps_paths.append(folder) else: steamapps_paths['windows'].append(folder) return steamapps_paths
def sync_steam_local(self, caller): """Sync Steam games in library with Steam and Wine Steam""" logger.debug("Syncing local steam games") steamrunner = steam() winesteamrunner = winesteam() # Get installed steamapps installed_steamapps = self._get_installed_steamapps(steamrunner) installed_winesteamapps = self._get_installed_steamapps(winesteamrunner) for game_info in self.library: runner = game_info['runner'] game = Game(game_info['slug']) steamid = game_info['steamid'] installed_in_steam = steamid in installed_steamapps installed_in_winesteam = steamid in installed_winesteamapps # Set installed if not game_info['installed']: if not installed_in_steam: # (Linux Steam only) continue logger.debug("Setting %s as installed" % game_info['name']) pga.add_or_update(game_info['name'], 'steam', game_info['slug'], installed=1) game.config.game_config.update({'game': {'appid': str(steamid)}}) game.config.save() caller.view.set_installed(Game(game_info['slug'])) # Set uninstalled elif not (installed_in_steam or installed_in_winesteam): if runner not in ['steam', 'winesteam']: continue if runner == 'steam' and not steamrunner.is_installed(): continue if runner == 'winesteam' and not winesteamrunner.is_installed(): continue logger.debug("Setting %s as uninstalled" % game_info['name']) pga.add_or_update(game_info['name'], '', game_info['slug'], installed=0) caller.view.set_uninstalled(game_info['slug'])
def sync_steam_local(self): """Sync Steam games in library with Steam and Wine Steam""" logger.debug("Syncing local steam games") steamrunner = steam() winesteamrunner = winesteam() installed = set() uninstalled = set() # Get installed steamapps installed_steamapps = self._get_installed_steamapps(steamrunner) installed_winesteamapps = self._get_installed_steamapps(winesteamrunner) for game_info in self.library: slug = game_info["slug"] runner = game_info["runner"] steamid = game_info["steamid"] installed_in_steam = steamid in installed_steamapps installed_in_winesteam = steamid in installed_winesteamapps # Set installed if not game_info["installed"]: if not installed_in_steam: # (Linux Steam only) continue logger.debug("Setting %s as installed" % game_info["name"]) pga.add_or_update(game_info["name"], "steam", slug, installed=1) game_config = config.LutrisConfig(runner_slug="steam", game_slug=game_info["slug"]) game_config.raw_game_config.update({"appid": str(steamid)}) game_config.save() installed.add(slug) # Set uninstalled elif not (installed_in_steam or installed_in_winesteam): if runner not in ["steam", "winesteam"]: continue if runner == "steam" and not steamrunner.is_installed(): continue if runner == "winesteam" and not winesteamrunner.is_installed(): continue logger.debug("Setting %s as uninstalled" % game_info["name"]) pga.add_or_update(game_info["name"], "", game_info["slug"], installed=0) uninstalled.add(slug) return (installed, uninstalled)
def get_steamapps_paths(flat=False): from lutris.runners import winesteam, steam if flat: steamapps_paths = [] else: steamapps_paths = { 'linux': [], 'windows': [] } winesteam_runner = winesteam.winesteam() steam_runner = steam.steam() for folder in steam_runner.get_steamapps_dirs(): if flat: steamapps_paths.append(folder) else: steamapps_paths['linux'].append(folder) for folder in winesteam_runner.get_steamapps_dirs(): if flat: steamapps_paths.append(folder) else: steamapps_paths['windows'].append(folder) return steamapps_paths
def _download_steam_data(self, file_uri, file_id): try: parts = file_uri.split(":", 2) steam_rel_path = parts[2].strip() except IndexError: raise ScriptingError("Malformed steam path: %s" % file_uri) if steam_rel_path == "/": steam_rel_path = "." self.steam_data = { 'appid': parts[1], 'steam_rel_path': steam_rel_path, 'file_id': file_id } if parts[0] == '$WINESTEAM': appid = self.steam_data['appid'] logger.debug("Getting Wine Steam data for appid %s" % appid) self.parent.set_status('Getting Wine Steam game data') self.steam_data['platform'] = "windows" # Check that wine is installed wine_runner = wine.wine() if not wine_runner.is_installed(): wine_runner.install() # Getting data from Wine Steam steam_runner = winesteam.winesteam() if not steam_runner.is_installed(): winesteam.download_steam( downloader=self.parent.start_download, callback=self.parent.on_steam_downloaded ) else: self.install_steam_game(winesteam.winesteam) else: # Getting data from Linux Steam self.parent.set_status('Getting Steam game data') self.steam_data['platform'] = "linux" self.install_steam_game(steam.steam) self.iter_game_files() return True
def _download_file(self, game_file): """Download a file referenced in the installer script Game files can be either a string, containing the location of the file to fetch or a dict with the following keys: - url : location of file, if not present, filename will be used this should be the case for local files - filename : force destination filename when url is present or path of local file """ # Setup file_id, file_uri and local filename file_id = game_file.keys()[0] if isinstance(game_file[file_id], dict): filename = game_file[file_id]['filename'] file_uri = game_file[file_id]['url'] else: file_uri = game_file[file_id] filename = os.path.basename(file_uri) if file_uri.startswith("/"): file_uri = "file://" + file_uri elif file_uri.startswith(("$WINESTEAM", "$STEAM")): # Download Steam data try: parts = file_uri.split(":", 2) steam_rel_path = parts[2].strip() except IndexError: raise ScriptingError("Malformed steam path: %s" % file_uri) if steam_rel_path == "/": steam_rel_path = "." self.steam_data = { 'appid': parts[1], 'steam_rel_path': steam_rel_path, 'file_id': file_id } if parts[0] == '$WINESTEAM': appid = self.steam_data['appid'] logger.debug("Getting Wine Steam data for appid %s" % appid) self.parent.set_status('Getting Wine Steam game data') self.steam_data['platform'] = "windows" # Check that wine is installed wine_runner = wine.wine() if not wine_runner.is_installed(): wine_runner.install() # Getting data from Wine Steam steam_runner = winesteam.winesteam() if not steam_runner.is_installed(): winesteam.download_steam( downloader=self.parent.start_download, callback=self.parent.on_steam_downloaded ) else: self.install_steam_game(winesteam.winesteam) return else: # Getting data from Linux Steam self.parent.set_status('Getting Steam game data') self.steam_data['platform'] = "linux" self.install_steam_game(steam.steam) return logger.debug("Fetching [%s]: %s" % (file_id, file_uri)) # Check for file availability in PGA pga_uri = pga.check_for_file(self.game_slug, file_id) if pga_uri: file_uri = pga_uri # Setup destination path dest_file = os.path.join(self.download_cache_path, filename) if file_uri.startswith("N/A"): # Ask the user where is the file located parts = file_uri.split(":", 1) if len(parts) == 2: message = parts[1] else: message = "Please select file '%s'" % file_id self.current_file_id = file_id self.parent.ask_user_for_file(message) return if os.path.exists(dest_file): logger.debug("Destination file exists") if settings.KEEP_CACHED_ASSETS: self.game_files[file_id] = dest_file self.iter_game_files() return else: os.remove(dest_file) # Change parent's status self.parent.set_status('Fetching %s' % file_uri) self.game_files[file_id] = dest_file self.parent.start_download(file_uri, dest_file)
def complete_steam_install(self, dest): winesteam_runner = winesteam.winesteam() async_call(winesteam_runner.install, self.on_winesteam_installed, dest)
def on_steam_downloaded(self, *args): logger.debug("Steam downloaded") dest = winesteam.get_steam_installer_dest() winesteam_runner = winesteam.winesteam() AsyncCall(winesteam_runner.install, self.on_winesteam_installed, dest)
def create_prefix( prefix, wine_path=None, arch=WINE_DEFAULT_ARCH, overrides={}, install_gecko=None, install_mono=None, ): """Create a new Wine prefix.""" if not prefix: raise ValueError("No Wine prefix path given") logger.info("Creating a %s prefix in %s", arch, prefix) # Follow symlinks, don't delete existing ones as it would break some setups if os.path.islink(prefix): prefix = os.readlink(prefix) # Avoid issue of 64bit Wine refusing to create win32 prefix # over an existing empty folder. if os.path.isdir(prefix) and not os.listdir(prefix): os.rmdir(prefix) if not wine_path: wine = import_runner("wine") wine_path = wine().get_executable() if not wine_path: logger.error("Wine not found, can't create prefix") return wineboot_path = os.path.join(os.path.dirname(wine_path), "wineboot") if not system.path_exists(wineboot_path): logger.error( "No wineboot executable found in %s, " "your wine installation is most likely broken", wine_path, ) return if install_gecko == "False": overrides["mshtml"] = "disabled" if install_mono == "False": overrides["mscoree"] = "disabled" wineenv = { "WINEARCH": arch, "WINEPREFIX": prefix, "WINEDLLOVERRIDES": get_overrides_env(overrides), } system.execute([wineboot_path], env=wineenv) for loop_index in range(50): time.sleep(0.25) if system.path_exists(os.path.join(prefix, "user.reg")): break if loop_index == 20: logger.warning("Wine prefix creation is taking longer than expected...") if not os.path.exists(os.path.join(prefix, "user.reg")): logger.error( "No user.reg found after prefix creation. " "Prefix might not be valid" ) return logger.info("%s Prefix created in %s", arch, prefix) prefix_manager = WinePrefixManager(prefix) prefix_manager.setup_defaults() if 'steamapps/common' in prefix.lower(): from lutris.runners.winesteam import winesteam runner = winesteam() logger.info("Transfering Steam information from default prefix to new prefix") dest_path = '/tmp/steam.reg' default_prefix = runner.get_default_prefix(runner.default_arch) wineexec( "regedit", args=r"/E '%s' 'HKEY_CURRENT_USER\Software\Valve\Steam'" % dest_path, prefix=default_prefix ) set_regedit_file( dest_path, wine_path=wine_path, prefix=prefix, arch=arch ) try: os.remove(dest_path) except FileNotFoundError: logger.error("File %s was already removed", dest_path) steam_drive_path = os.path.join(prefix, 'dosdevices', 's:') if not system.path_exists(steam_drive_path): logger.info("Linking Steam default prefix to drive S:") os.symlink(os.path.join(default_prefix, 'drive_c'), steam_drive_path)
def _download_file(self, game_file): """Download a file referenced in the installer script Game files can be either a string, containing the location of the file to fetch or a dict with the following keys: - url : location of file, if not present, filename will be used this should be the case for local files - filename : force destination filename when url is present or path of local file """ # Setup file_id, file_uri and local filename file_id = game_file.keys()[0] if isinstance(game_file[file_id], dict): filename = game_file[file_id]['filename'] file_uri = game_file[file_id]['url'] else: file_uri = game_file[file_id] filename = os.path.basename(file_uri) if file_uri.startswith("/"): file_uri = "file://" + file_uri elif file_uri.startswith(("$WINESTEAM", "$STEAM")): # Download Steam data try: parts = file_uri.split(":", 2) steam_rel_path = parts[2].strip() except IndexError: raise ScriptingError("Malformed steam path: %s" % file_uri) if steam_rel_path == "/": steam_rel_path = "." self.steam_data = { 'appid': parts[1], 'steam_rel_path': steam_rel_path, 'file_id': file_id } if parts[0] == '$WINESTEAM': self.steam_data['platform'] = "windows" # Getting data from Wine Steam steam_runner = winesteam.winesteam() if not steam_runner.is_installed(): # Downoad Steam for Windows steam_installer_path = os.path.join( settings.TMP_PATH, "SteamInstall.msi" ) self.parent.start_download( winesteam.winesteam.installer_url, steam_installer_path, self.parent.on_steam_downloaded, self.steam_data['appid'] ) else: self.install_steam_game(winesteam.winesteam) return else: # Getting data from Linux Steam self.steam_data['platform'] = "linux" self.install_steam_game(steam.steam) return logger.debug("Fetching [%s]: %s" % (file_id, file_uri)) # Check for file availability in PGA pga_uri = pga.check_for_file(self.game_slug, file_id) if pga_uri: file_uri = pga_uri # Setup destination path dest_file = os.path.join(self.download_cache_path, filename) if file_uri.startswith("N/A"): # Ask the user where is the file located parts = file_uri.split(":", 1) if len(parts) == 2: message = parts[1] else: message = "Please select file '%s'" % file_id self.current_file_id = file_id self.parent.ask_user_for_file(message) return if os.path.exists(dest_file): logger.debug("Destination file exists") if settings.KEEP_CACHED_ASSETS: self.game_files[file_id] = dest_file self.iter_game_files() return else: os.remove(dest_file) # Change parent's status self.parent.set_status('Fetching %s' % file_uri) self.game_files[file_id] = dest_file self.parent.start_download(file_uri, dest_file)
def complete_steam_install(self, dest): winesteam_runner = winesteam.winesteam() AsyncCall(winesteam_runner.install, self.on_winesteam_installed, dest)
def create_prefix( prefix, wine_path=None, arch=WINE_DEFAULT_ARCH, overrides={}, install_gecko=None, install_mono=None, ): """Create a new Wine prefix.""" if not prefix: raise ValueError("No Wine prefix path given") logger.info("Creating a %s prefix in %s", arch, prefix) # Follow symlinks, don't delete existing ones as it would break some setups if os.path.islink(prefix): prefix = os.readlink(prefix) # Avoid issue of 64bit Wine refusing to create win32 prefix # over an existing empty folder. if os.path.isdir(prefix) and not os.listdir(prefix): os.rmdir(prefix) if not wine_path: wine = import_runner("wine") wine_path = wine().get_executable() if not wine_path: logger.error("Wine not found, can't create prefix") return wineboot_path = os.path.join(os.path.dirname(wine_path), "wineboot") if not system.path_exists(wineboot_path): logger.error( "No wineboot executable found in %s, " "your wine installation is most likely broken", wine_path, ) return if install_gecko == "False": overrides["mshtml"] = "disabled" if install_mono == "False": overrides["mscoree"] = "disabled" wineenv = { "WINEARCH": arch, "WINEPREFIX": prefix, "WINEDLLOVERRIDES": get_overrides_env(overrides), } system.execute([wineboot_path], env=wineenv) for loop_index in range(50): time.sleep(0.25) if system.path_exists(os.path.join(prefix, "user.reg")): break if loop_index == 20: logger.warning( "Wine prefix creation is taking longer than expected...") if not os.path.exists(os.path.join(prefix, "user.reg")): logger.error("No user.reg found after prefix creation. " "Prefix might not be valid") return logger.info("%s Prefix created in %s", arch, prefix) prefix_manager = WinePrefixManager(prefix) prefix_manager.setup_defaults() if 'steamapps/common' in prefix.lower(): from lutris.runners.winesteam import winesteam runner = winesteam() logger.info( "Transfering Steam information from default prefix to new prefix") dest_path = '/tmp/steam.reg' default_prefix = runner.get_default_prefix(runner.default_arch) wineexec("regedit", args=r"/E '%s' 'HKEY_CURRENT_USER\Software\Valve\Steam'" % dest_path, prefix=default_prefix) set_regedit_file(dest_path, wine_path=wine_path, prefix=prefix, arch=arch) try: os.remove(dest_path) except FileNotFoundError: logger.error("File %s was already removed", dest_path) steam_drive_path = os.path.join(prefix, 'dosdevices', 's:') if not system.path_exists(steam_drive_path): logger.info("Linking Steam default prefix to drive S:") os.symlink(os.path.join(default_prefix, 'drive_c'), steam_drive_path)