diff --git a/NSLGameScanner.py b/NSLGameScanner.py index 1d1ec9b..3ed8ffc 100644 --- a/NSLGameScanner.py +++ b/NSLGameScanner.py @@ -10,6 +10,7 @@ import sys import subprocess import sqlite3 +import csv from urllib.request import urlopen from urllib.request import urlretrieve from urllib.parse import quote @@ -375,12 +376,18 @@ def is_match(name1, name2): # Add or update the proton compatibility settings + def add_compat_tool(app_id, launchoptions): if 'CompatToolMapping' not in config_data['InstallConfigStore']['Software']['Valve']['Steam']: config_data['InstallConfigStore']['Software']['Valve']['Steam']['CompatToolMapping'] = {} print(f"CompatToolMapping key not found in config.vdf, creating.") if 'chrome' in launchoptions: return False + + if 'PROTONPATH' in launchoptions: + print("PROTONPATH found in launch options. Skipping compatibility tool update.") + return False + elif str(app_id) in config_data['InstallConfigStore']['Software']['Valve']['Steam']['CompatToolMapping']: config_data['InstallConfigStore']['Software']['Valve']['Steam']['CompatToolMapping'][str(app_id)]['name'] = f'{compat_tool_name}' config_data['InstallConfigStore']['Software']['Valve']['Steam']['CompatToolMapping'][str(app_id)]['config'] = '' @@ -388,6 +395,10 @@ def add_compat_tool(app_id, launchoptions): print(f"Updated CompatToolMapping entry for appid: {app_id}") return compat_tool_name else: + # Skip if the shortcut has already been processed by UMU + if app_id in umu_processed_shortcuts: + print(f"CompatTool update skipped for {app_id} because it was already processed by UMU.") + return None config_data['InstallConfigStore']['Software']['Valve']['Steam']['CompatToolMapping'][str(app_id)] = {'name': f'{compat_tool_name}', 'config': '', 'priority': '250'} print(f"Created new CompatToolMapping entry for appid: {app_id}") return compat_tool_name @@ -407,6 +418,8 @@ def check_if_shortcut_exists(shortcut_id, display_name, exe_path, start_dir, lau #End of Code + + #Start of Refactoring code from the .sh file sys.path.insert(0, os.path.expanduser(f"{logged_in_home}/Downloads/NonSteamLaunchersInstallation/lib/python{python_version}/site-packages")) print(sys.path) @@ -439,6 +452,17 @@ def create_new_entry(shortcutdirectory, appname, launchoptions, startingdir): exe_path = f"{shortcutdirectory}" signed_shortcut_id = get_steam_shortcut_id(exe_path, appname) unsigned_shortcut_id = get_unsigned_shortcut_id(signed_shortcut_id) + + # **Intercept and modify the shortcut based on UMU data** + exe_path, startingdir, launchoptions = modify_shortcut_for_umu(appname, exe_path, launchoptions, startingdir) + + # Check if the shortcut has already been processed by UMU and skip compat tool if so + if unsigned_shortcut_id in umu_processed_shortcuts: + print(f"Skipping compatibility tool for {appname}, as it has already been processed by UMU.") + compatTool = None # Skip adding compatibility tool + else: + compatTool = add_compat_tool(unsigned_shortcut_id, launchoptions) + # Only store the app ID for specific launchers if appname in ['Epic Games', 'Gog Galaxy', 'Ubisoft Connect', 'Battle.net', 'EA App', 'Amazon Games', 'itch.io', 'Legacy Games', 'Humble Bundle', 'IndieGala Client', 'Rockstar Games Launcher', 'Glyph', 'Playstation Plus', 'VK Play', 'HoYoPlay', 'Nexon Launcher']: app_ids[appname] = unsigned_shortcut_id @@ -457,9 +481,7 @@ def create_new_entry(shortcutdirectory, appname, launchoptions, startingdir): if game_id is not None: get_sgdb_art(game_id, unsigned_shortcut_id) - - # Create a new entry for the Steam shortcut - compatTool= add_compat_tool(unsigned_shortcut_id, launchoptions) + # Create a new entry for the Steam shortcut, only adding the compat tool if it's not processed by UMU new_entry = { 'appid': str(signed_shortcut_id), 'appname': appname, @@ -481,27 +503,163 @@ def create_new_entry(shortcutdirectory, appname, launchoptions, startingdir): '0': 'NonSteamLaunchers' } } + + # Create the decky entry, only including the compatTool if not processed by UMU decky_entry = { 'appname': appname, 'exe': exe_path, 'StartDir': startingdir, 'icon': f"{logged_in_home}/.steam/root/userdata/{steamid3}/config/grid/{get_file_name('icons', unsigned_shortcut_id)}", 'LaunchOptions': launchoptions, - 'CompatTool': compatTool, + 'CompatTool': compatTool, # This will be None if UMU has processed the shortcut 'WideGrid': grid64, 'Grid': gridp64, 'Hero': hero64, 'Logo': logo64, } + # Add the new entry to the shortcuts dictionary and add proton key = get_next_available_key(shortcuts) shortcuts['shortcuts'][key] = new_entry print(f"Added new entry for {appname} to shortcuts.") new_shortcuts_added = True created_shortcuts.append(appname) + + # Mark it as processed by UMU (if it wasn't already processed) + if compatTool is not None: + umu_processed_shortcuts[unsigned_shortcut_id] = True add_compat_tool(unsigned_shortcut_id, launchoptions) +# UMU-related functions +umu_processed_shortcuts = {} +CSV_URL = "https://raw.githubusercontent.com/Open-Wine-Components/umu-database/main/umu-database.csv" + +# Global variable to store CSV data +csv_data = [] + +def fetch_and_parse_csv(): + global csv_data + try: + response = requests.get(CSV_URL) + response.raise_for_status() # Raise an HTTPError for bad responses + csv_data = [row for row in csv.DictReader(response.text.splitlines())] + print("Successfully fetched and parsed CSV data.") + except requests.exceptions.RequestException as e: + print(f"Error fetching UMU data: {e}") + return csv_data + +def list_all_entries(): + global csv_data + if not csv_data: + csv_data = fetch_and_parse_csv() + return csv_data + +def extract_umu_id_from_launch_options(launchoptions): + if 'STEAM_COMPAT_DATA_PATH=' not in launchoptions: + return None + + # EA + match = re.search(r'offerIds=(\d+)', launchoptions) + if match: + return match.group(1) + + # Amazon + match = re.search(r'(amzn1\.adg\.product\.\S+)', launchoptions) + if match: + return match.group(1).rstrip("'") + + # Epic + match = re.search(r'com\.epicgames\.launcher://apps/(\w+)[?&]', launchoptions) + if match: + return match.group(1).lower() if not match.group(1).isdigit() else match.group(1) + + # Ubisoft + match = re.search(r'uplay://launch/(\d+)/\d+', launchoptions) + if match: + return match.group(1) + + # GOG + match = re.search(r'/gameId=(\d+)', launchoptions) + if match: + return match.group(1) + + return None + +def extract_base_path(launchoptions): + match = re.search(r'STEAM_COMPAT_DATA_PATH="([^"]+)"', launchoptions) + if match: + return match.group(1) + raise ValueError("STEAM_COMPAT_DATA_PATH not found in launch options") + +def modify_shortcut_for_umu(appname, exe, launchoptions, startingdir): + # Skip processing if STEAM_COMPAT_DATA_PATH is not present + if 'STEAM_COMPAT_DATA_PATH=' not in launchoptions: + print(f"Launch options for {appname} do not contain STEAM_COMPAT_DATA_PATH. Skipping modification.") + return exe, startingdir, launchoptions + + codename = extract_umu_id_from_launch_options(launchoptions) + if not codename: + print(f"No codename found in launch options for {appname}. Trying to match appname.") + + entries = list_all_entries() + if not entries: + print(f"No entries found in UMU database. Skipping modification for {appname}.") + return exe, startingdir, launchoptions + + if not codename: + for entry in entries: + if entry.get('TITLE') and entry['TITLE'].lower() == appname.lower(): + codename = entry['CODENAME'] + break + + if codename: + for entry in entries: + if entry['CODENAME'] == codename: + umu_id = entry['UMU_ID'].replace("umu-", "") # Remove the "umu-" prefix + base_path = extract_base_path(launchoptions) + new_exe = f'"{logged_in_home}/bin/umu-run" {exe}' + new_start_dir = f'"{logged_in_home}/bin/"' + + # Update only the launchoptions part for different game types + updated_launch = launchoptions + if "origin2://game/launch?offerIds=" in launchoptions: + updated_launch = f'origin2://game/launch?offerIds={codename}' + elif "amazon-games://play/amzn1.adg.product." in launchoptions: + updated_launch = f'amazon-games://play/{codename}' + elif "com.epicgames.launcher://apps/" in launchoptions: + updated_launch = f'-com.epicgames.launcher://apps/{codename}?action=launch&silent=true' + elif "uplay://launch/" in launchoptions: + updated_launch = f'uplay://launch/{codename}/0' + elif "/command=runGame /gameId=" in launchoptions: + updated_launch = f'/command=runGame /gameId={codename} /path={launchoptions.split("/path=")[1]}' + + new_launch_options = ( + f'STEAM_COMPAT_DATA_PATH="{base_path}" ' + f'WINEPREFIX="{base_path}pfx" ' + f'GAMEID="{umu_id}" ' + f'PROTONPATH="{logged_in_home}/.steam/root/compatibilitytools.d/{compat_tool_name}" ' + f'%command% {updated_launch}' + ) + + umu_processed_shortcuts[umu_id] = True + + return new_exe, new_start_dir, new_launch_options + + print(f"No UMU entry found for {appname}. Skipping modification.") + return exe, startingdir, launchoptions + + + + + + + + + + + +