From 0c44b39e9e7a8f39aa2ffa1b34b18fe717d7bdea Mon Sep 17 00:00:00 2001 From: Adrian Bonpin Date: Sun, 28 Jun 2026 21:21:29 +0800 Subject: [PATCH] fix(plugin): use correct SteamClient.GameSessions.RegisterForAppLifetimeNotifications API for game detection --- plugins/decky-vault/src/index.tsx | 36 +++++++++++++++++++----------- plugins/decky-vault/src/types.d.ts | 28 ++++++++++++++++++----- 2 files changed, 45 insertions(+), 19 deletions(-) diff --git a/plugins/decky-vault/src/index.tsx b/plugins/decky-vault/src/index.tsx index 55a0e97..cc9ddb0 100644 --- a/plugins/decky-vault/src/index.tsx +++ b/plugins/decky-vault/src/index.tsx @@ -40,22 +40,33 @@ function Content() { setGameName, } = useSession() const gameStartedUnregRef = useRef<{ unregister: () => void } | null>(null) - const gameStoppedUnregRef = useRef<{ unregister: () => void } | null>(null) // ── Register SteamClient game events ────────────────────────── useEffect(() => { try { - // Use RegisterForGameStarted/Stopped — these are the most widely used - // APIs in Decky plugins despite TypeScript type warnings. - const startedReg = SteamClient.Apps.RegisterForGameStarted((appId: number) => { - onGameStart(appId, `App ${appId}`) - }) - gameStartedUnregRef.current = startedReg - - const stoppedReg = SteamClient.Apps.RegisterForGameStopped((_appId: number) => { - onGameStop() - }) - gameStoppedUnregRef.current = stoppedReg + // Use RegisterForAppLifetimeNotifications — the correct API for + // detecting when games start/stop on Steam Deck. + const reg = SteamClient.GameSessions.RegisterForAppLifetimeNotifications( + (notification: AppLifetimeNotification) => { + if (notification.bRunning) { + // Game started — try to get the display name from appStore + let gameName = `App ${notification.unAppID}` + try { + const overview = window.appStore?.GetAppOverviewByAppID(notification.unAppID) + if (overview?.display_name) { + gameName = overview.display_name + } + } catch { + // fallback + } + onGameStart(notification.unAppID, gameName) + } else { + // Game stopped + onGameStop() + } + }, + ) + gameStartedUnregRef.current = reg } catch (e) { console.warn("[DeckyVault] SteamClient event registration failed:", e) } @@ -63,7 +74,6 @@ function Content() { return () => { try { gameStartedUnregRef.current?.unregister() - gameStoppedUnregRef.current?.unregister() } catch { // ignore } diff --git a/plugins/decky-vault/src/types.d.ts b/plugins/decky-vault/src/types.d.ts index 31cdccb..fb8826a 100644 --- a/plugins/decky-vault/src/types.d.ts +++ b/plugins/decky-vault/src/types.d.ts @@ -4,13 +4,12 @@ declare global { const SteamClient: { + GameSessions: { + RegisterForAppLifetimeNotifications: ( + callback: (notification: AppLifetimeNotification) => void, + ) => { unregister: () => void } + } Apps: { - RegisterForGameStarted: ( - callback: (appId: number) => void, - ) => { unregister: () => void } - RegisterForGameStopped: ( - callback: (appId: number) => void, - ) => { unregister: () => void } RegisterForGameActionStart: ( callback: (gameActionId: number, appId: string, action: string, source: number) => void, ) => { unregister: () => void } @@ -25,6 +24,23 @@ declare global { GetUIMode: () => Promise } } + + interface AppLifetimeNotification { + unAppID: number + nInstanceID: number + bRunning: boolean + } + + interface Window { + appStore: { + GetAppOverviewByAppID: (appId: number) => SteamAppOverview | null + } + } + + interface SteamAppOverview { + appid: number + display_name: string + } } export {} \ No newline at end of file