diff --git a/.gitignore b/.gitignore index e915029..98b5ac1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,2 @@ -################################################################################ -# This .gitignore file was automatically created by Microsoft(R) Visual Studio. -################################################################################ - -/.vs +.vs +__pycache__ diff --git a/dev/compile-map.py b/scripts/compile-map.py similarity index 98% rename from dev/compile-map.py rename to scripts/compile-map.py index 4013dd2..d65f719 100755 --- a/dev/compile-map.py +++ b/scripts/compile-map.py @@ -9,7 +9,10 @@ import json import string import sys -import tomllib +if sys.version_info >= (3,11): + import tomllib +else: + raise Exception('Python 3.11 or later is required to run this script!') """ Summary of available subs: diff --git a/dev/dev_setup.ps1 b/scripts/dev_setup.ps1 similarity index 100% rename from dev/dev_setup.ps1 rename to scripts/dev_setup.ps1 diff --git a/dev/get_hammer_content.ps1 b/scripts/get_hammer_content.ps1 similarity index 100% rename from dev/get_hammer_content.ps1 rename to scripts/get_hammer_content.ps1 diff --git a/dev/get_latest_js_types.ps1 b/scripts/get_latest_js_types.ps1 similarity index 100% rename from dev/get_latest_js_types.ps1 rename to scripts/get_latest_js_types.ps1 diff --git a/dev/graph-map-results.py b/scripts/graph-map-results.py similarity index 100% rename from dev/graph-map-results.py rename to scripts/graph-map-results.py diff --git a/scripts/steampath.py b/scripts/steampath.py new file mode 100755 index 0000000..63f4c79 --- /dev/null +++ b/scripts/steampath.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 + +import argparse +from utils.steamtools import get_appid_path + +def main(): + parser = argparse.ArgumentParser(description='Finds the installation directory of a Steam app') + parser.add_argument('-a', '--app', dest='APP', type=int, required=True, help='AppID to look for') + args = parser.parse_args() + p = get_appid_path(args.APP) + if p is not None: + print(p) + else: + exit(1) + + +if __name__ == '__main__': + main() diff --git a/scripts/utils/steamtools.py b/scripts/utils/steamtools.py new file mode 100755 index 0000000..08ee0ab --- /dev/null +++ b/scripts/utils/steamtools.py @@ -0,0 +1,77 @@ +import os +import sys +import re +if sys.platform.startswith('win'): + import winreg + + +def get_library_folders() -> list[str]: + """ + Returns a list of Steam libraries on this system + + Returns + ------- + list[str] + List of paths for the Steam libraries + """ + sp = '' + if sys.platform.startswith('linux'): + # Flatpak steam will also create the ~/.steam symlink + sp = os.path.expanduser(f'~/.steam/steam/steamapps/libraryfolders.vdf') + elif sys.platform.startswith('win'): + # Registry trash for Windows. + with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, 'Software\\Wow6432Node\\Valve\\Steam', access=winreg.KEY_READ | winreg.KEY_WOW64_32KEY) as key: + value = winreg.QueryValueEx(key, 'InstallPath') + if value is not None and value[1] == winreg.REG_SZ: + sp = f'{value[0]}\\steamapps\\libraryfolders.vdf' + else: + sp = f'C:\\Program Files (x86)\\Steam\\steamapps\\libraryfolders.vdf' + # Check that the file *actually* exists; Steam in Proton doesn't use registry... + if not os.path.exists(sp): + sp = f'Z:{os.getenv("STEAM_COMPAT_CLIENT_INSTALL_PATH")}\\steam\\steamapps\\libraryfolders.vdf'.replace('/', '\\') + + with open(sp, 'r') as fp: + return [x[1] for x in re.findall(r'\n\s+(\"path\")\s+\"(.+)\"\s*\n', fp.read())] + + +def get_library_for_appid(id: int) -> str | None: + """ + Returns the steam library path that contains the app + + Returns + ------- + str|None + Steam library that contains the appid + """ + folders = get_library_folders() + if folders is None: + return None + + for folder in folders: + if os.path.exists(f'{folder}/steamapps/appmanifest_{id}.acf'): + return folder + return None + + +def get_appid_path(id: int) -> str | None: + """ + Tries to locate the AppID's install location based on Steam's libraryfolders.vdf + + Parameters + ---------- + id: int + AppID to look for + + Returns + ------- + str|None + Install path location or None if it could not be found + """ + lf = get_library_for_appid(id) + if lf is not None: + am = {} + with open(f'{lf}/steamapps/appmanifest_{id}.acf', 'r') as fp: + m = re.findall(r'\n\s+(\"installdir\")\s+\"(.+)\"\s*\n', fp.read()) + if len(m) > 0: + return f'{lf}/steamapps/common/{m[0][1]}' + return None diff --git a/util/steampath.py b/util/steampath.py deleted file mode 100755 index 0931e26..0000000 --- a/util/steampath.py +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/env python3 - -import vdf -import argparse -import os - -def _find_appid_folder(id: int) -> str | None: - lf = {} - # Flatpak steam will also create the ~/.steam symlink - with open(os.path.expanduser(f'~/.steam/steam/steamapps/libraryfolders.vdf'), 'r') as fp: - lf = vdf.parse(fp)['libraryfolders'] - - lfp = None - for k in lf.keys(): - for m in lf[k]['apps'].keys(): - if int(m) == id: - return lf[k]['path'] - return None - - -def get_appid_path(id: int) -> str | None: - """ - Tries to locate the AppID's install location based on Steam's libraryfolders.vdf - - Parameters - ---------- - id: int - AppID to look for - - Returns - ------- - str|None - Install path location or None if it could not be found - """ - lf = _find_appid_folder(id) - if lf is not None: - am = {} - with open(f'{lf}/steamapps/appmanifest_{id}.acf', 'r') as fp: - am = vdf.parse(fp)['AppState'] - return f'{lf}/steamapps/common/{am["installdir"]}' - return None - - -def main(): - parser = argparse.ArgumentParser() - parser.add_argument('-a', '--app', dest='APP', type=int, required=True, help='AppID to look for') - args = parser.parse_args() - p = get_appid_path(args.APP) - if p is not None: - print(p) - else: - exit(1) - - -if __name__ == '__main__': - main()