steam: egpu auto-detect wrapper für alle spiele

- steam-egpu-patch-all.py: patcht localconfig.vdf (124 spiele auf einmal)
- steam-egpu: launcher der vor jedem start neue spiele sync't
- steam-egpu.desktop: ersetzt den normalen steam-launcher
This commit is contained in:
Kay Türtscher 2026-06-06 13:23:31 +02:00
parent aead7a8b80
commit 44e6b00fb7
3 changed files with 186 additions and 0 deletions

View file

@ -0,0 +1,49 @@
[Desktop Entry]
Name=Steam (eGPU Sync)
Comment=Application for managing and playing games on Steam
Comment[de]=Anwendung zum Verwalten und Spielen von Spielen auf Steam (mit eGPU-Auto-Sync)
Exec=/home/nepharius/SuperX-goes-Arch/tools/steam-egpu %U
Icon=steam
Terminal=false
Type=Application
Categories=Network;FileTransfer;Game;
MimeType=x-scheme-handler/steam;x-scheme-handler/steamlink;
Actions=Store;Community;Library;Servers;Screenshots;News;Settings;BigPicture;Friends;
PrefersNonDefaultGPU=true
X-KDE-RunOnDiscreteGpu=true
[Desktop Action Store]
Name=Store
Exec=/usr/bin/steam steam://store
[Desktop Action Community]
Name=Community
Exec=/usr/bin/steam steam://url/CommunityHome/
[Desktop Action Library]
Name=Library
Exec=/usr/bin/steam steam://open/games
[Desktop Action Servers]
Name=Servers
Exec=/usr/bin/steam steam://open/servers
[Desktop Action Screenshots]
Name=Screenshots
Exec=/usr/bin/steam steam://open/screenshots
[Desktop Action News]
Name=News
Exec=/usr/bin/steam steam://openurl/https://store.steampowered.com/news
[Desktop Action Settings]
Name=Settings
Exec=/usr/bin/steam steam://open/settings
[Desktop Action BigPicture]
Name=Big Picture
Exec=/usr/bin/steam steam://open/bigpicture
[Desktop Action Friends]
Name=Friends
Exec=/usr/bin/steam steam://open/friends

18
tools/steam-egpu Executable file
View file

@ -0,0 +1,18 @@
#!/bin/bash
# steam-egpu — Wrapper der vor jedem Steam-Start die Launch Options sync't
# Ersetzt den normalen "steam"-Aufruf. Trägt superx-game-wrapper
# automatisch in alle Spiele ein, die noch keine LaunchOptions haben.
#
# Installation: siehe tools/install-egpu.sh (Schritt 5)
WRAPPER_STRING="/home/nepharius/SuperX-goes-Arch/tools/superx-game-wrapper.sh %command%"
CONFIG="$HOME/.local/share/Steam/userdata/19491507/config/localconfig.vdf"
SYNC_SCRIPT="/home/nepharius/SuperX-goes-Arch/.venv/bin/python3 /home/nepharius/SuperX-goes-Arch/tools/steam-egpu-patch-all.py"
# Sync: alle Spiele ohne LaunchOptions bekommen den Wrapper
if [ -f "$CONFIG" ]; then
$SYNC_SCRIPT -y 2>/dev/null &
fi
# Steam starten
exec /usr/bin/steam "$@"

View file

@ -0,0 +1,119 @@
#!/usr/bin/env python3
"""Patcht Steam localconfig.vdf — setzt superx-game-wrapper für ALLE Spiele.
Usage:
python tools/steam-egpu-patch-all.py # alle Spiele patchen
python tools/steam-egpu-patch-all.py --undo # Wrapper entfernen
python tools/steam-egpu-patch-all.py --dry-run # nur anzeigen
Danach Steam neustarten.
"""
import json, subprocess, sys, os, shutil, argparse
from pathlib import Path
STEAM_DIR = Path.home() / ".local/share/Steam"
USERDATA = STEAM_DIR / "userdata" / "19491507" / "config" / "localconfig.vdf"
WRAPPER = "/home/nepharius/SuperX-goes-Arch/tools/superx-game-wrapper.sh %command%"
LAUNCH_KEY = "LaunchOptions"
def parse_args():
parser = argparse.ArgumentParser(description="Steam Launch Options für eGPU-Wrapper patchen")
parser.add_argument("--undo", action="store_true", help="Wrapper aus allen Spielen entfernen")
parser.add_argument("--dry-run", action="store_true", help="Nur anzeigen, nicht schreiben")
parser.add_argument("--yes", "-y", action="store_true", help="Keine Bestätigungsfrage")
return parser.parse_args()
def main():
args = parse_args()
if not USERDATA.exists():
print(f"ERROR: {USERDATA} nicht gefunden. Steam jemals gestartet?")
sys.exit(1)
# VDF parsen
import vdf
with open(USERDATA) as f:
raw = f.read()
config = vdf.loads(raw)
apps = config.get("UserLocalConfigStore", {}).get("Software", {}).get(
"Valve", {}
).get("Steam", {}).get("apps", {})
if not apps:
print("Keine Apps in localconfig.vdf gefunden. Steam muss mindestens einmal gestartet sein.")
sys.exit(1)
total = len(apps)
count_wrapper = 0
count_other = 0
count_empty = 0
count_patched = 0
count_removed = 0
for appid, appcfg in apps.items():
current = appcfg.get(LAUNCH_KEY, "")
if current == WRAPPER:
count_wrapper += 1
elif current:
count_other += 1
else:
count_empty += 1
print(f"Spiele insgesamt: {total}")
print(f" {count_wrapper} haben bereits den Wrapper")
print(f" {count_other} haben andere Launch Options")
print(f" {count_empty} haben keine Launch Options")
print()
if args.dry_run:
if args.undo:
print(f"[DRY-RUN] Würde Wrapper aus {count_wrapper} Spielen entfernen")
else:
target = total - count_wrapper
print(f"[DRY-RUN] Würde Wrapper in {target} Spielen setzen")
if count_other > 0:
print(f"[DRY-RUN] ACHTUNG: {count_other} Spiele mit bestehenden Launch Options werden ÜBERSCHRIEBEN!")
return
# Backup
backup = USERDATA.with_suffix(".vdf.bak")
shutil.copy2(USERDATA, backup)
print(f"Backup: {backup}")
if args.undo:
for appid, appcfg in apps.items():
if appcfg.get(LAUNCH_KEY) == WRAPPER:
del appcfg[LAUNCH_KEY]
count_removed += 1
print(f"Wrapper entfernt aus {count_removed} Spielen")
else:
for appid, appcfg in apps.items():
if appcfg.get(LAUNCH_KEY) == WRAPPER:
continue
appcfg[LAUNCH_KEY] = WRAPPER
count_patched += 1
print(f"Wrapper gesetzt in {count_patched} Spielen")
if count_other > 0:
print(f"WARNUNG: {count_other} Spiele hatten andere Launch Options — wurden überschrieben!")
# Zurückschreiben
new_vdf = vdf.dumps(config, pretty=True)
if not args.yes and sys.stdout.isatty():
confirm = input("Schreiben? [y/N] ")
if confirm.lower() != "y":
print("Abgebrochen.")
sys.exit(0)
with open(USERDATA, "w") as f:
f.write(new_vdf)
print(f"\nFertig. Steam neustarten!")
print(f"Falls was schiefgeht: cp {backup} {USERDATA}")
if __name__ == "__main__":
main()