diff --git a/src/deck-components/steam-client/App.ts b/src/deck-components/steam-client/App.ts new file mode 100644 index 00000000..09138910 --- /dev/null +++ b/src/deck-components/steam-client/App.ts @@ -0,0 +1,1640 @@ +import {JsPbMessage, OperationResponse, Result, Unregisterable} from "./index"; +import {FilePrivacyState, Screenshot} from "./Screenshots"; + +/** + * Represents various functions related to Steam applications. + */ +export interface Apps { + /** + * Adds a non-Steam application shortcut to the local Steam library. + * @param appName The name of the non-Steam application. + * @param executablePath The path to the executable file of the non-Steam application. + * @param directory The working directory for the non-Steam application. + * @param launchOptions Options to be passed when launching the non-Steam application. + * @returns A Promise that resolves to a unique AppID assigned to the added non-Steam application shortcut. + */ + AddShortcut(appName: string, executablePath: string, directory: string, launchOptions: string): Promise; + + /** + * Backups an app to the specified path. + * @param appId The ID of the application to back up. + * @param backupToPath The path to store the backup. + * @returns A Promise that resolves to a number. This value may be "20" for backup busy and "0" for success. + */ + BackupFilesForApp(appId: number, backupToPath: string): Promise; + + /** + * Opens the screenshot folder for a specific app. + * @param appId The ID of the app to browse screenshots for. + * @param handle The screenshot handle to use. + */ + BrowseScreenshotForApp(appId: string, handle: number): void; + + /** + * Opens the screenshot folder for a specific app. + * @param appId The ID of the app to browse screenshots for. + */ + BrowseScreenshotsForApp(appId: string): void; + + /** + * Cancels the current backup process. + */ + CancelBackup(): void; + + /** + * Cancels a specific game action. + * @param gameActionId The ID of the game action to cancel. + */ + CancelGameAction(gameActionId: number): void; + + /** + * Cancels the launch of an application with the specified ID. + * @param appId The ID of the application whose launch is to be canceled. + */ + CancelLaunch(appId: string): void; + + /** + * Clears the custom artwork for a given application. + * @param appId The ID of the application to clear custom artwork for. + * @param assetType The type of artwork to clear. + */ + ClearCustomArtworkForApp(appId: number, assetType: AppArtworkAssetType): Promise; + + /** + * Clears the custom logo position for a specific application. + * @param appId The ID of the application. + * @returns A Promise that resolves once the custom logo position is cleared. + */ + ClearCustomLogoPositionForApp(appId: number): Promise; + + ClearProton(appId: number): Promise; + + /** + * Continues a specific game action. + * @param gameActionId The ID of the game action to continue. + * @param actionType The type of action to perform during continuation. + * @remarks actionType - "SkipShaders", "skip", "ShowDurationControl" todo: + */ + ContinueGameAction(gameActionId: number, actionType: string): void; + + /** + * Creates a Steam application shortcut on the desktop. + * @param appId The ID of the application for which to create a desktop shortcut. + */ + CreateDesktopShortcutForApp(appId: number): void; + + /** + * Download a workshop item. + * @param appId The ID of the application. + * @param itemId The ID of the workshop item. + * @param param1 Additional parameter (exact usage may vary). + */ + DownloadWorkshopItem(appId: number, itemId: string, param1: boolean): void; + + /** + * Retrieves achievements within a specified time range for a given app. + * @param appId The ID of the application. + * @param start The start of the time range as a Unix timestamp. + * @param end The end of the time range as a Unix timestamp. + * @returns A Promise that resolves to an array of AppAchievement objects. + */ + GetAchievementsInTimeRange(appId: number, start: number, end: number): Promise; + + /** + * Retrieves a list of active game actions, such as launching an application. + * @returns A Promise that resolves to an array of active game actions. + */ + GetActiveGameActions(): Promise; + + /** + * Retrieves a list of available compatibility tools for a specific application. + * @param appId The ID of the application to retrieve compatibility tools for. + * @returns A Promise that resolves to an array of CompatibilityToolInfo objects. + */ + GetAvailableCompatTools(appId: number): Promise; + + /** + * Represents a function to retrieve the name of the application in a backup folder. + * @param appBackupPath The path to the application's backup folder. + * @returns A Promise that resolves to the name of the application in the backup folder, or undefined if the path is invalid. + * @remarks This function checks for the "sku.sis" file in that path. + */ + GetBackupsInFolder(appBackupPath: string): Promise; + + /** + * Retrieves cached details for a specific application. + * @param appId The ID of the application. + * @returns A Promise that resolves to a stringified object. + */ + GetCachedAppDetails(appId: number): Promise; // todo: Parsing nightmare + + GetCloudPendingRemoteOperations(appId: number): Promise; + + GetCompatExperiment(param0: number): Promise; + + GetConflictingFileTimestamps(appId: number): Promise; + + /** + * Retrieves details for a specific screenshot upload. + * @param appId The ID of the application. + * @param hHandle The handle of the screenshot upload. + * @returns A Promise that resolves to details about the screenshot upload. + */ + GetDetailsForScreenshotUpload(appId: string, hHandle: number): Promise; + + /** + * Retrieves details for multiple screenshot uploads. + * @param appId The ID of the application. + * @param hHandles An array of handles of the screenshot uploads. + * @returns A Promise that resolves to details about the screenshot uploads. + */ + GetDetailsForScreenshotUploads(appId: string, hHandles: number[]): Promise; + + /** + * Retrieves a list of downloaded workshop items for a specific application. + * @param appId The ID of the application to retrieve downloaded workshop items for. + * @returns A Promise that resolves to an array of downloaded workshop items for the specified application. + */ + GetDownloadedWorkshopItems(appId: number): Promise; + + GetDurationControlInfo(appId: number): Promise; // any - {"bApplicable": true} - overlay usage? + + /** + * Retrieves achievement information for a specific application for a given friend. + * @param appId The ID of the application to retrieve achievement information for. + * @param friendSteam64Id The Steam64 ID of the friend for whom to retrieve achievement information. + * @returns A Promise that resolves to an object containing achievement information for the specified friend and application. + */ + GetFriendAchievementsForApp(appId: string, friendSteam64Id: string): Promise; + + /** + * Retrieves a list of friends who play the specified application. + * @param appId The ID of the application. + * @returns A Promise that resolves to an array of Steam64 IDs representing friends who play the application. + */ + GetFriendsWhoPlay(appId: number): Promise; + + /** + * Retrieves details of a game action. + * @param appId The ID of the application. + * @param callback The callback function to handle the retrieved game action details and state. + * @param callback.gameAction The game action received in the callback. + * @param callback.state The state manager received in the callback. + */ + GetGameActionDetails(appId: number, callback: (gameAction: GameAction) => void): void; + + GetGameActionForApp( + appId: string, + callback: ( + gameActionId: number, + /** + * This parameter is a number only with the value `0`. + */ + appId: number | string, + taskName: AppAction, + ) => void, + ): void; + + /** + * Retrieves launch options for a specified application. + * These options may include different configurations or settings for launching the application, such as DirectX, Vulkan, OpenGL, 32-bit, 64-bit, etc. + * This function does not retrieve launch/argument options inputted by the user. + * @param appId The ID of the application. + * @returns A Promise that resolves to an array of launch options for the specified application. + */ + GetLaunchOptionsForApp(appId: number): Promise; + + /** + * @returns A Promise that resolves to a ProtoBuf message. If deserialized, returns {@link LibraryBootstrapData}. + */ + GetLibraryBootstrapData(): Promise; + + /** + * Retrieves achievement information for the authenticated user in a specific Steam application. + * @param appId The ID of the application to retrieve achievement information for. + * @returns A Promise that resolves to an AppAchievementResponse object containing the achievement information for the authenticated user in the specified application. + */ + GetMyAchievementsForApp(appId: string): Promise; + + /** + * Retrieves the playtime information for a specific application. + * @param appId The ID of the application to get playtime information for. + * @returns A Promise that resolves to playtime information or undefined if not available. + */ + GetPlaytime(appId: number): Promise; + + GetPrePurchasedApps(appIds: number[]): Promise; + + /** + * Retrieves the resolution override for a specific application. + * @param appId The ID of the application to retrieve the resolution override for. + * @returns A Promise that resolves to a string of the resolution override. + */ + GetResolutionOverrideForApp(appId: number): Promise; + + /** + * Represents a function to retrieve detailed information about a specific screenshot. + * @param appId The ID of the application the screenshot belongs to. + * @param hHandle The handle of the screenshot. + * @returns A Promise that resolves to detailed information about the specified screenshot. + */ + GetScreenshotInfo(appId: string, hHandle: number): Promise; + + /** + * Represents a function to retrieve screenshots within a specified time range. + * @param appId The ID of the application. + * @param start The start of the time range as a Unix timestamp. + * @param end The end of the time range as a Unix timestamp. + * @returns A Promise that resolves to an array of screenshots taken within the specified time range. + */ + GetScreenshotsInTimeRange(appId: number, start: number, end: number): Promise; + + /** + * Retrieves shortcut data for a given shortcut file path. + * @param pathToShortcut The path to the shortcut file. + * @returns A Promise that resolves to the shortcut data. + */ + GetShortcutDataForPath(pathToShortcut: string): Promise; + + /** + * Represents a function to retrieve details about a soundtrack associated with a soundtrack application. + * The soundtrack has to be installed. + * @param appId The ID of the soundtrack application. + * @returns A Promise that resolves to the details of the soundtrack associated with the specified soundtrack application. + */ + GetSoundtrackDetails(appId: number): Promise; + + // [...appStore.m_mapStoreTagLocalization.keys()] + GetStoreTagLocalization(tags: number[]): Promise; + + /** + * Retrieves a list of subscribed workshop item details for a specific application. + * @param appId The ID of the application to retrieve subscribed workshop item details for. + * @param itemIds Workshop item IDs to retrieve details for. + * @returns A Promise that resolves to an array of subscribed workshop item details for the specified application. + * @throws Throws if the query failed. + */ + GetSubscribedWorkshopItemDetails(appId: number, itemIds: string[]): Promise; + + /** + * Retrieves a list of subscribed workshop items for a specific application. + * @param appId The ID of the application to retrieve subscribed workshop items for. + * @returns A Promise that resolves to an array of subscribed workshop items for the specified application. + */ + GetSubscribedWorkshopItems(appId: number): Promise; + + InstallFlatpakAppAndCreateShortcut(appName: string, appCommandLineOptions: string): Promise; // returns {"appid":0,"strInstallOutput":""} + JoinAppContentBeta(appId: number, name: string): any; + + JoinAppContentBetaByPassword(appId: number, accessCode: any): Promise; // any.strName + + ListFlatpakApps(): Promise; + + /** + * @throws if the user does not own the app or no EULA. + */ + LoadEula(appId: number): Promise; // Doesn't bring up the EULA dialog, just returns the eula data + MarkEulaAccepted(param0: any, param1: any, param2: any): any; + + MarkEulaRejected: any; + + /** + * Move specified workshop item load order. + * @param appId The ID of the application. + * @param oldOrder The item to move, referenced by its position number. + * @param newOrder The position number to move the item to. + * @remarks Orders are zero-indexed. + */ + MoveWorkshopItemLoadOrder(appId: number, oldOrder: number, newOrder: number): void; + + /** + * Opens the settings dialog for a specific application. + * @param appId The ID of the application for which to open the settings dialog. + * @param section The section (tab) to switch to. + */ + OpenAppSettingsDialog(appId: number, section: string): void; + + /** + * Raises the window for a given application. + * @param appId The ID of the application to raise the window of. + * @returns A Promise that resolves to a number. + * @todo Returns a result enum? 1 if ok, 2 if not running + */ + RaiseWindowForGame(appId: number): Promise; // ResumeGameInProgress + + /* + "CMsgAchievementChange" + OnAchievementChange(e) { + var t; + const n = l.on.deserializeBinary(e).toObject(), + o = null !== (t = null == n ? void 0 : n.appid) && void 0 !== t ? t : 0; + 0 != o ? (this.m_mapMyAchievements.has(o) || this.m_mapInflightMyAchievementsRequests.has(o)) && this.LoadMyAchievements(o) : console.error("Received invalid appid in OnAchievementChange") + } + + message CMsgAchievementChange { + optional uint32 appid = 1; + } + */ + /** + * Registers a callback function to be called when achievement changes occur. + * @param callback The callback function to be called. + * @returns An object that can be used to unregister the callback. + */ + RegisterForAchievementChanges(callback: (data: ArrayBuffer) => void): Unregisterable; + + RegisterForAppBackupStatus(callback: (appBackupStatus: AppBackupStatus) => void): Unregisterable; + + /** + * Registers a callback function to be called when app details change. + * @param appId The ID of the application to monitor. + * @param callback The callback function to be called. + * @returns An object that can be used to unregister the callback. + */ + RegisterForAppDetails(appId: number, callback: (appDetails: AppDetails) => void): Unregisterable; + + /* + + message CAppOverview_Change { + repeated .CAppOverview app_overview = 1; + repeated uint32 removed_appid = 2; + optional bool full_update = 3; + optional bool update_complete = 4; + } + */ + /** + * If `data` is deserialized, returns {@link AppOverview_Change}. + * @remarks This is not a mistake, it doesn't return anything. + */ + RegisterForAppOverviewChanges(callback: (data: ArrayBuffer) => void): void; + + RegisterForDRMFailureResponse( + callback: (appid: number, eResult: number, errorCode: number) => void, + ): Unregisterable; + + /** + * Registers a callback function to be called when a game action ends. + * @param callback The callback function to be called. + * @returns An object that can be used to unregister the callback. + */ + RegisterForGameActionEnd(callback: (gameActionIdentifier: number) => void): Unregisterable; + + // "error" is a localization token + RegisterForGameActionShowError(callback: (gameActionId: number, appId: string, actionName: string, error: string, param4: string) => void): Unregisterable; + + /** + * Registers a callback function to be called when a game action UI is shown. + * @param callback The callback function to be called. + * @returns An object that can be used to unregister the callback. + */ + RegisterForGameActionShowUI(callback: () => void): Unregisterable; // todo: no idea what this callback is from + + /** + * Registers a callback function to be called when a game action starts. + * @param callback The callback function to be called. + * @returns An object that can be used to unregister the callback. + */ + RegisterForGameActionStart( + callback: (gameActionIdentifier: number, appId: string, action: string, param3: AppLaunchSource) => void, + ): Unregisterable; + + /** + * Registers a callback function to be called when a game action task changes. + * @param callback The callback function to be called. + * @returns An object that can be used to unregister the callback. + */ + RegisterForGameActionTaskChange( + callback: ( + gameActionIdentifier: number, + appId: string, + action: string, + requestedAction: string, + param4: string, + ) => void, + ): Unregisterable; + + /** + * Registers a callback function to be called when a user requests a game action. + * @param callback The callback function to be called. + * @returns An object that can be used to unregister the callback. + */ + RegisterForGameActionUserRequest( + callback: ( + gameActionIdentifier: number, + appId: string, + action: string, + requestedAction: string, + appId2: string, + ) => void, + ): Unregisterable; + + /** + * @todo returns undefined (now)? + * @todo does not exist on Steam Version: 1718064497 + */ + RegisterForLocalizationChanges(callback: (data: ArrayBuffer) => void): Unregisterable; + + RegisterForPrePurchasedAppChanges(callback: () => void): Unregisterable; // Unknown, did have it show up a few times, but not callback parameters + RegisterForShowMarketingMessageDialog: Unregisterable; + + /** + * Registers a callback function to be notified when workshop items are added or removed from a Steam application. + * @param callback The callback function to be called. + * @returns An object that can be used to unregister the callback. + */ + RegisterForWorkshopChanges(callback: (appId: number) => void): Unregisterable; + + RegisterForWorkshopItemDownloads( + appId: number, + callback: (appId: number, publishedFileId: string, param2: number) => void, + ): Unregisterable; + + RegisterForWorkshopItemInstalled: any; + + /** + * Removes a non-Steam application shortcut from the Steam library. + * @param appId The ID of the application for which to remove the shortcut. + */ + RemoveShortcut(appId: number): void; + + ReportLibraryAssetCacheMiss(appId: number, assetType: AppArtworkAssetType): void; + + ReportMarketingMessageDialogShown(): void; + + RequestIconDataForApp(appId: number): any; + + RequestLegacyCDKeysForApp(appId: number): any; + + /** + * Runs a game with specified parameters. Focuses the game if already launched. + * @param appId The ID of the application to run. + * @param launchOptions Additional launch options for the application. + * @param param2 Additional parameter (exact usage may vary). + * @param launchSource + * @remarks `launchOptions` is appended before the ones specified in the application's settings. + */ + RunGame(appId: string, launchOptions: string, param2: number, launchSource: AppLaunchSource): void; + + /* + function u(e, t) { + return t instanceof Map || t instanceof Set ? Array.from(t) : t; + } + SteamClient.Apps.SaveAchievementProgressCache( + JSON.stringify(this.m_achievementProgress, u) + ); + */ + SaveAchievementProgressCache(progress: string): any; + + /** + * Scans the system for installed non-Steam applications. + * @returns A Promise that resolves to an array of NonSteamApp objects representing installed non-Steam applications. + * @remarks This function scans the user's system for installed applications that are not part of the Steam library. It does not scan for shortcuts added to the Steam library. + * + * On Linux, it scans inside /usr/share/applications and $XDG_DATA_HOME/applications. + */ + ScanForInstalledNonSteamApps(): Promise; + + /** + * Sets the automatic update behavior for a Steam application. + * @param appId The ID of the application to set the update behavior for. + * @param mode The update behavior mode to set. + * @remarks This function only works with installed Steam applications. + */ + SetAppAutoUpdateBehavior(appId: number, mode: AutoUpdateBehavior): void; + + /** + * Sets the background downloads behavior for a specific Steam application. + * @param appId The ID of the application to set the background downloads behavior for. + * @param mode The background downloads mode to set. + * @remarks This function only works with installed Steam applications. + */ + SetAppBackgroundDownloadsBehavior(appId: number, mode: BackgroundDownloadsBehavior): void; + + /** + * Sets the current language for a specific Steam application. + * @param appId The ID of the application to set the current language for. + * @param language The language to set, represented as a language (e.g., "english", "spanish", "tchinese", "schinese"). + */ + SetAppCurrentLanguage(appId: number, language: string): void; + + /** + * Sets the blocked state for apps. + * @param appIds An array of app IDs to set the blocked state for. + * @param state The state to set (true for blocked, false for unblocked). + */ + SetAppFamilyBlockedState(appIds: number[], state: boolean): void; + + /** + * Sets launch options for a Steam application. + * @param appId The ID of the application to set launch options for. + * @param launchOptions The launch options to be set for the application. + */ + SetAppLaunchOptions(appId: number, launchOptions: string): void; + + /** + * Sets a resolution override for a Steam application. + * @param appId The ID of the application to set the resolution override for. + * @param resolution The resolution to be set for the application. It can be "Default", "Native", or other compatible resolutions for the user's monitor. + */ + SetAppResolutionOverride(appId: number, resolution: string): any; + + /** + * Sets cached details for a specific application. + * @param appId The ID of the application. + * @param details The details to be cached, a stringified object. + * @returns A Promise that resolves when the details are successfully cached. + * todo: might return boolean? + */ + SetCachedAppDetails(appId: number, details: string): Promise; + + SetControllerRumblePreference(appId: number, param1: number): any; // param1 - enum for preference + + /** + * Sets the custom artwork for a given application. + * @param appId The ID of the application to set custom artwork for. + * @param base64Image Base64 encoded image. + * @param imageType "jpeg" or "png". + * @param assetType The type of artwork to set. + * @returns A Promise that resolves after the custom artwork is set. + */ + SetCustomArtworkForApp(appId: number, base64Image: string, imageType: string, assetType: AppArtworkAssetType): Promise; + + /** + * Sets a custom logo position for a specific app. + * @param appId The ID of the application. + * @param details The details of the custom logo position, expected to be a stringified {@link LogoPositionForApp} object. + * @returns A Promise that resolves when the custom logo position is successfully set. + */ + SetCustomLogoPositionForApp(appId: number, details: string): Promise; + + /** + * Sets the enabled state for downloadable content (DLC) of a specific app. + * @param appId The ID of the parent application. + * @param appDLCId The ID of the DLC to set the state for. + * @param value The value to set (true for enabled, false for disabled). + */ + SetDLCEnabled(appId: number, appDLCId: number, value: boolean): void; + + /** + * Set a local screenshot's caption. + * @param appId The application ID the screenshot belongs to. + * @param hHandle The handle of the screenshot. + * @param caption + */ + SetLocalScreenshotCaption(appId: string, hHandle: any, caption: string): void; + + /** + * Set a local screenshot's privacy state. + * @param appId The application ID the screenshot belongs to. + * @param hHandle The handle of the screenshot. + * @param privacy Screenshot privacy state. + */ + SetLocalScreenshotPrivacy(appId: string, hHandle: any, privacy: FilePrivacyState): void; + + /** + * Set a local screenshot's spoiler state. + * @param appId The application ID the screenshot belongs to. + * @param hHandle The handle of the screenshot. + * @param spoilered Is the screenshot spoilered? + */ + SetLocalScreenshotSpoiler(appId: string, hHandle: any, spoilered: boolean): void; + + /** + * Sets the icon for a non-Steam application shortcut. + * @param appId The ID of the application to set the shortcut icon for. + * @param iconPath The path to the icon image (can be png or tga format). + */ + SetShortcutIcon(appId: number, iconPath: string): void; + + /** + * Sets whether a non-Steam application shortcut should be included in the VR library. + * @param appId The ID of the application to set the VR status for. + * @param value A boolean indicating whether the application should be included in the VR library. + */ + SetShortcutIsVR(appId: number, value: boolean): void; + + /** + * Sets launch options for a non-Steam application shortcut. + * @param appId The ID of the application to set the launch options for. + * @param launchOptions The launch options to be used when starting the application. + */ + SetShortcutLaunchOptions(appId: number, launchOptions: string): void; + + /** + * Sets the name for a non-Steam application shortcut. + * @param appId The ID of the application to set the shortcut name for. + * @param shortcutName The name to be displayed for the application shortcut. + */ + SetShortcutName(appId: number, shortcutName: string): void; + + /** + * Sets the starting directory for a non-Steam application shortcut. + * @param appId The ID of the application to set the starting directory for. + * @param directory The directory from which the application should be launched. + */ + SetShortcutStartDir(appId: number, directory: string): void; + + /** + * Sets the client ID for streaming for a specific application. + * @param appId The ID of the application. + * @param clientId The client ID for streaming. + */ + SetStreamingClientForApp(appId: number, clientId: string): void; + + SetThirdPartyControllerConfiguration(appId: number, param1: number): any; + + /** + * Sets the workshop items disabled state. + * @param appId The ID of the application. + * @param itemIds Workshop item IDs to change the state for. + * @param value `true` to disable, `false` otherwise. + */ + SetWorkshopItemsDisabledLocally(appId: number, itemIds: string[], value: boolean): void; + + /** + * Sets the workshop items load order for a specified application. + * @param appId The ID of the application. + * @param itemIds Workshop item IDs. + * @remarks `itemIds` has to be the full list of subscribed items, otherwise the specified items get moved to the last position. + */ + SetWorkshopItemsLoadOrder(appId: number, itemIds: string[]): void; + + /** + * Opens the controller configurator for a specific application. + * @param appId The ID of the application for which to open the controller configurator. + */ + ShowControllerConfigurator(appId: number): void; + + /** + * Opens the Steam store page for a specific application. + * @param appId The ID of the application. + */ + ShowStore(appId: number): void; + + SpecifyCompatExperiment: any; + + /** + * Specifies a compatibility tool by its name for a given application. If strToolName is an empty string, the specified application will no longer use a compatibility tool. + * @param appId The ID of the application to specify compatibility tool for. + * @param strToolName The name of the compatibility tool to specify. + */ + SpecifyCompatTool(appId: number, strToolName: string): void; + + StreamGame(appId: number, clientId: string, param2: number): void; + + /** + * Subscribes or unsubscribes from a workshop item for a specific app. + * @param appId The ID of the application. + * @param workshopId The ID of the workshop item. + * @param subscribed True to subscribe, false to unsubscribe. + */ + SubscribeWorkshopItem(appId: number, workshopId: string, subscribed: boolean): void; + + /** + * Terminates a running application. + * @param appId The ID of the application to terminate. + * @param param1 Additional parameter. Exact usage may vary. + */ + TerminateApp(appId: string, param1: boolean): void; + + // "#AppProperties_SteamInputDesktopConfigInLauncher" + ToggleAllowDesktopConfiguration(appId: number): any; + + /** + * Toggles the Steam Cloud synchronization for game saves for a specific application. + * @param appId The ID of the application. + * @remarks This function modifies the "/userdata//7/remote/sharedconfig.vdf" file. + */ + ToggleAppSteamCloudEnabled(appId: number): void; + + // "#AppProperties_EnableSteamCloudSyncOnSuspend" + ToggleAppSteamCloudSyncOnSuspendEnabled(appId: number): any; + + /** + * Toggles the Steam Overlay setting for a specific application. + * @param appId The ID of the application. + */ + ToggleEnableSteamOverlayForApp(appId: number): void; + + // "#AppProperties_ResolutionOverride_Internal" + ToggleOverrideResolutionForInternalDisplay(appId: number): any; + + UninstallFlatpakApp(app: string): Promise; + + /** + * Verifies the integrity of an app's files. + * @param appId The ID of the app to verify. + */ + VerifyApp(appId: number): Promise; // todo: returns {"nGameActionID":9} +} + +export enum AppArtworkAssetType { + Capsule = 0, + Hero = 1, + Logo = 2, + Header = 3, + Icon = 4, + HeroBlur = 5, +} + +export type AppAchievements = { + nAchieved: number; + nTotal: number; + vecAchievedHidden: AppAchievement[]; + vecHighlight: AppAchievement[]; + vecUnachieved: AppAchievement[]; +}; + +export interface AppAchievement { + bAchieved: boolean; + bHidden: boolean; + flMinProgress: number; + flCurrentProgress: number; + flMaxProgress: number; + /** How many players have this achievement, in percentage. */ + flAchieved: number; + /** When this achievement was unlocked. */ + rtUnlocked: number; + /** Achievement description. */ + strDescription: string; + /** Achievement ID. */ + strID: string; + /** Achievement icon. */ + strImage: string; + /** Achievement name. */ + strName: string; +} + +export type AppAction = "LaunchApp" | "VerifyApp"; + +export type LaunchAppTask = + | "None" + | "Completed" + | "Cancelled" + | "Failed" + | "Starting" + | "ConnectingToSteam" + | "RequestingLicense" + | "UpdatingAppInfo" + | "UpdatingAppTicket" + | "UnlockingH264" + | "WaitingOnWideVineUpdate" + | "ShowCheckSystem" + | "CheckTimedTrial" + | "GetDurationControl" + | "ShowDurationControl" + | "ShowLaunchOption" + | "ShowEula" + | "ShowVR2DWarning" + | "ShowVROculusOnly" + | "ShowVRStreamingLaunch" + | "ShowGameArgs" + | "ShowCDKey" + | "WaitingPrevProcess" + | "DownloadingDepots" + | "DownloadingWorkshop" + | "UpdatingDRM" + | "GettingLegacyKey" + | "ProcessingInstallScript" + | "RunningInstallScript" + | "SynchronizingCloud" + | "SynchronizingControllerConfig" + | "ShowNoControllerConfig" + | "ProcessingShaderCache" + | "VerifyingFiles" + | "KickingOtherSession" + | "WaitingOpenVRAppQuit" + | "SiteLicenseSeatCheckout" + | "DelayLaunch" + | "CreatingProcess" + | "WaitingGameWindow" + +export interface GameAction { + nGameActionID: number; + gameid: string; + strActionName: AppAction; + strTaskName: LaunchAppTask; + strTaskDetails: string; + nLaunchOption: number; + nSecondsRemaing: number; //fixme: not a typo, actually valve + strNumDone: string; + strNumTotal: string; + bWaitingForUI: boolean; +} + +export interface ConflictingFileTimestamp { + rtLocalTime: number; + rtRemoteTime: number; +} + +/** + * Represents information about a compatibility tool. + */ +export interface CompatibilityToolInfo { + /** Name of the compatibility tool. */ + strToolName: string; + /** Display name of the compatibility tool. */ + strDisplayName: string; +} + + +/** + * Represents details about a single screenshot upload. + */ +export interface DetailsForScreenshotUpload { + /** + * The size of the screenshot upload on disk (including thumbnail). + */ + strSizeOnDisk: string; + + /** + * The amount of cloud storage available. + */ + strCloudAvailable: string; + + /** + * The total cloud storage. + */ + strCloudTotal: string; +} + +/** + * Represents details about multiple screenshot uploads. + */ +export interface DetailsForScreenshotUploads { + /** + * The total size of all screenshot uploads on disk (sum of sizes including thumbnails). + */ + unSizeOnDisk: number; + + /** + * The amount of cloud storage available. + */ + strCloudAvailable: string; + + /** + * The total cloud storage. + */ + strCloudTotal: string; +} + +export interface WorkshopItem { + unAppID: number; + ulPublishedFileID: string; +} + +export interface AppAchievementData { + rgAchievements: AppAchievement[]; +} + +export interface AppAchievementResponse { + result: number; + data: AppAchievementData; +} + +export interface LaunchOption { + /** + * @remarks This is an integer, despite the prefix. 0 if false, 1 if true. + */ + bIsLaunchOptionTypeExemptFromGameTheater: number; + /** + * @remarks This is an integer, despite the prefix. 0 if false, 1 if true. + */ + bIsVRLaunchOption: number; + eType: AppLaunchOptionType; + nIndex: number; + /** + * Label localization string. + */ + strDescription: string; + strGameName: string; +} + +/** + * Represents playtime information for an application. + */ +export interface Playtime { + /** Total playtime in minutes for the last 2 weeks. */ + nPlaytimeLastTwoWeeks: number; + /** Total playtime in minutes. */ + nPlaytimeForever: number; + /** Last played time in Unix Epoch time format. */ + rtLastTimePlayed: number; +} + +export interface PrePurchaseApp { + nAppID: number; + eState: AppReleaseState; +} + +export interface PrePurchaseInfo { + apps: PrePurchaseApp[]; + lastChangeNumber: number; +} + + +export enum AppReleaseState { + Unknown = 0, + Unavailable = 1, + Prerelease = 2, + PreloadOnly = 3, + Released = 4, + Disabled = 5, +} + +export enum AppLaunchOptionType { + None = 0, + Default = 1, + SafeMode = 2, + Multiplayer = 3, + Config = 4, + OpenVR = 5, + Server = 6, + Editor = 7, + Manual = 8, + Benchmark = 9, + Option1 = 10, + Option2 = 11, + Option3 = 12, + OculusVR = 13, + OpenVROverlay = 14, + OSVR = 15, + OpenXR = 16, + Dialog = 1e3, +} + +export interface Shortcut { + bIsApplication: boolean; + strAppName: string; + strExePath: string; + strArguments: string; + strCmdline: string; + strShortcutPath: string | undefined; + strSortAs: string | undefined; + strIconDataBase64: string | undefined; +} + +export interface SoundtrackDetails { + tracks: Track[]; + metadata: SoundtrackMetadata; + vecAdditionalImageAssetURLs: string[]; + strCoverImageAssetURL: string; +} + +export interface Track { + discNumber: number; + trackNumber: number; + durationSeconds: number; + trackDisplayName: string; +} + +export interface SoundtrackMetadata { + artist: string; +} + +export interface StoreTagLocalization { + tag: number; + string: string; +} + +export interface WorkshopItemDetails { + /** + * Required items' IDs. + */ + children: string[]; + eresult: Result; + /** + * Item size, in byts. + */ + file_size: string; + /** + * Workshop file type. + */ + file_type: WorkshopFileType; + /** + * Item preview image URL. + */ + preview_url: string; + /** + * Item ID. + */ + publishedfileid: string; + /** + * Item description. + */ + short_description: string; + /** + * Item tags. + */ + tags: string[]; + /** + * Item title. + */ + title: string; +} + +export enum WorkshopFileType { + Community = 0, + Microtransaction = 1, + Collection = 2, + Art = 3, + Video = 4, + Screenshot = 5, + Game = 6, + Software = 7, + Concept = 8, + WebGuide = 9, + IntegratedGuide = 10, + Merch = 11, + ControllerBinding = 12, + SteamworksAccessInvite = 13, + SteamVideo = 14, + GameManagedItem = 15, +} + +export interface EndUserLicenseAgreement { + id: string; + url: string; + version: number; +} + +export interface AppBackupStatus { + appid: number; + eError: AppError; + strBytesToProcess: string; + strBytesProcessed: string; + strTotalBytesWritten: string; +} + + +/** + * @remarks Not present in any of the Steam files. This is only present as localization strings, whose tokens start with `#Steam_AppUpdateError_`. + */ +export enum AppError { + None = 0, + Unspecified = 1, + Paused = 2, + Canceled = 3, + Suspended = 4, + NoSubscription = 5, + NoConnection = 6, + Timeout = 7, + MissingKey = 8, + MissingConfig = 9, + DiskReadFailure = 10, + DiskWriteFailure = 11, + NotEnoughDiskSpace = 12, + CorruptGameFiles = 13, + WaitingForNextDisk = 14, + InvalidInstallPath = 15, + AppRunning = 16, + DependencyFailure = 17, + NotInstalled = 18, + UpdateRequired = 19, + Busy = 20, + NoDownloadSources = 21, + InvalidAppConfig = 22, + InvalidDepotConfig = 23, + MissingManifest = 24, + NotReleased = 25, + RegionRestricted = 26, + CorruptDepotCache = 27, + MissingExecutable = 28, + InvalidPlatform = 29, + InvalidFileSystem = 30, + CorruptUpdateFiles = 31, + DownloadDisabled = 32, + SharedLibraryLocked = 33, + PendingLicense = 34, + OtherSessionPlaying = 35, + CorruptDownload = 36, + CorruptDisk = 37, + FilePermissions = 38, + FileLocked = 39, + MissingContent = 40, + Requires64BitOS = 41, + MissingUpdateFiles = 42, + NotEnoughDiskQuota = 43, + LockedSiteLicense = 44, + ParentalControlBlocked = 45, + CreateProcessFailure = 46, + SteamClientOutdated = 47, + PlaytimeExceeded = 48, + CorruptFileSignature = 49, + MissingInstalledFiles = 50, + CompatibilityToolFailure = 51, + UnmountedUninstallPath = 52, + InvalidBackupPath = 53, + InvalidPasscode = 54, + ThirdPartyUpdater = 55, + ParentalPlaytimeExceeded = 56, + Max = 57, +} + +export interface AppDetails { + achievements: AppAchievements; + /** Indicates whether the application is available on the store. */ + bAvailableContentOnStore: boolean; + bCanMoveInstallFolder: boolean; + bCloudAvailable: boolean; + bCloudEnabledForAccount: boolean; + bCloudEnabledForApp: boolean; + bCloudSyncOnSuspendAvailable: boolean; + bCloudSyncOnSuspendEnabled: boolean; + /** Indicates whether the application has community market available. */ + bCommunityMarketPresence: boolean; + bEnableAllowDesktopConfiguration: boolean; + bFreeRemovableLicense: boolean; + bHasAllLegacyCDKeys: boolean; + bHasAnyLocalContent: boolean; + bHasLockedPrivateBetas: boolean; + bIsExcludedFromSharing: boolean; + bIsSubscribedTo: boolean; + bIsThirdPartyUpdater: boolean; + bOverlayEnabled: boolean; + bOverrideInternalResolution: boolean; + bRequiresLegacyCDKey: boolean; + bShortcutIsVR: boolean; + bShowCDKeyInMenus: boolean; + bShowControllerConfig: boolean; + bSupportsCDKeyCopyToClipboard: boolean; + bVRGameTheatreEnabled: boolean; + bWorkshopVisible: boolean; + deckDerivedProperties?: AppDeckDerivedProperties; + eAppOwnershipFlags: AppOwnershipFlags | number; // is this a bitmask? + eAutoUpdateValue: AutoUpdateBehavior; + eBackgroundDownloads: BackgroundDownloadsBehavior; + /** + * @todo enum + */ + eCloudSync: number; + /** + * @todo enum + */ + eControllerRumblePreference: number; // ControllerRumbleSetting? + eDisplayStatus: DisplayStatus; + /** + * @todo enum + */ + eEnableThirdPartyControllerConfiguration: number; + /** + * @todo enum + */ + eSteamInputControllerMask: number; + /** + * Index of the install folder. -1 if not installed. + */ + iInstallFolder: number; + /** Disk space required for installation, in bytes. */ + lDiskSpaceRequiredBytes: number; + /** Application disk space usage, in bytes. */ + lDiskUsageBytes: number; + /** DLC disk space usage, in bytes. */ + lDlcUsageBytes: number; + nBuildID: number; + nCompatToolPriority: number; + /** Total play time, in minutes. */ + nPlaytimeForever: number; + /** Screenshot count. */ + nScreenshots: number; + rtLastTimePlayed: number; + rtLastUpdated: number; + rtPurchased: number; + selectedLanguage: AppLanguage; + strCloudBytesAvailable: string; + strCloudBytesUsed: string; + strCompatToolDisplayName: string; + strCompatToolName: string; + strDeveloperName: string; + strDeveloperURL: string; + strDisplayName: string; + strExternalSubscriptionURL: string; + strFlatpakAppID: string; + strHomepageURL: string; + strLaunchOptions: string; + strManualURL: string; + /** Steam64 ID. */ + strOwnerSteamID: string; + strResolutionOverride: string; + strSelectedBeta: string; + strShortcutExe: string; + strShortcutLaunchOptions: string; + strShortcutStartDir: string; + strSteamDeckBlogURL: string; + unAppID: number; + unEntitledContentApp: number; + unTimedTrialSecondsAllowed: number; + unTimedTrialSecondsPlayed: number; + vecBetas: AppBeta[]; + vecChildConfigApps: number[]; + vecDLC: AppDLC[]; + vecDeckCompatTestResults: DeckCompatTestResult[]; + vecLanguages: AppLanguage[]; + vecLegacyCDKeys: any[]; + vecMusicAlbums: AppSoundtrack[]; + /** windows | osx | linux */ + vecPlatforms: string[]; + vecScreenShots: Screenshot[]; + libraryAssets?: AppLibraryAssets; +} + +export interface AppDeckDerivedProperties { + gamescope_frame_limiter_not_supported?: boolean; + non_deck_display_glyphs: boolean; + primary_player_is_controller_slot_0: boolean; + requires_h264: boolean; + requires_internet_for_setup: boolean; + requires_internet_for_singleplayer: boolean; + requires_manual_keyboard_invoke: false; + requires_non_controller_launcher_nav: false; + small_text: boolean; + supported_input: number; +} + +export enum AppOwnershipFlags { + None = 0, + Subscribed = 1, + Free = 2, + RegionRestricted = 4, + LowViolence = 8, + InvalidPlatform = 16, + Borrowed = 32, + FreeWeekend = 64, + Retail = 128, + Locked = 256, + Pending = 512, + Expired = 1024, + Permanent = 2048, + Recurring = 4096, + Canceled = 8192, + AutoGrant = 16384, + PendingGift = 32768, + RentalNotActivated = 65536, + Rental = 131072, + SiteLicense = 262144, + LegacyFreeSub = 524288, + InvalidOSType = 1048576, + TimedTrial = 2097152, +} + +export enum AutoUpdateBehavior { + Always = 0, // (Always keep this game updated) + Launch = 1, // (Only update this game when I launch it) + HighPriority = 2, // (High priority) +} + +export enum BackgroundDownloadsBehavior { + Pause = 0, + Always = 1, + Never = 2, +} + +export enum DisplayStatus { + Invalid = 0, + Launching = 1, + Uninstalling = 2, + Installing = 3, + Running = 4, + Validating = 5, + Updating = 6, + Downloading = 7, + Synchronizing = 8, + ReadyToInstall = 9, + ReadyToPreload = 10, + ReadyToLaunch = 11, + RegionRestricted = 12, + PresaleOnly = 13, + InvalidPlatform = 14, + PreloadComplete = 16, + BorrowerLocked = 17, + UpdatePaused = 18, + UpdateQueued = 19, + UpdateRequired = 20, + UpdateDisabled = 21, + DownloadPaused = 22, + DownloadQueued = 23, + DownloadRequired = 24, + DownloadDisabled = 25, + LicensePending = 26, + LicenseExpired = 27, + AvailForFree = 28, + AvailToBorrow = 29, + AvailGuestPass = 30, + Purchase = 31, + Unavailable = 32, + NotLaunchable = 33, + CloudError = 34, + CloudOutOfDate = 35, + Terminating = 36, + OwnerLocked = 37, + DownloadFailed = 38, + UpdateFailed = 39, +} + +export type AppLanguage = { + strDisplayName: string; + /** A localization string for the language. */ + strShortName: string; +}; + +export interface AppBeta { + /** Beta name. */ + strName: string; + /** Beta description. */ + strDescription: string; +} + +export interface AppDLC { + /** Is the DLC availble on the store? */ + bAvailableOnStore: boolean; + bEnabled: boolean; + /** Disk usage, in bytes. */ + lDiskUsageBytes: number; + /** Purchase date. */ + rtPurchaseDate: number; + rtStoreAssetModifyType: number; + /** Store header image filename. */ + strHeaderFilename: string; + /** Display name. */ + strName: string; + /** State (installed/notinstalled). */ + strState: string; + /** App ID. */ + unAppID: number; +} + +export interface DeckCompatTestResult { + // enum ? + test_result: number; + /** A localization string. */ + test_loc_token: string; +} + +export interface AppSoundtrack { + /** Purchase date. */ + rtPurchaseDate: number; + rtStoreAssetModifyType: number; + /** Display name. */ + strName: string; + /** State (installed/notinstalled). */ + strState: string; + /** App ID. */ + unAppID: number; +} + +export interface AppLibraryAssets { + logoPosition?: LogoPosition; + strCapsuleImage: string; + strHeroBlurImage: string; + strHeroImage: string; + strLogoImage: string; +} + +export interface LogoPosition { + pinnedPosition: LogoPinPositions; + nWidthPct: number; + nHeightPct: number; +} + +export type LogoPinPositions = 'BottomLeft' | 'UpperLeft' | 'CenterCenter' | 'UpperCenter' | 'BottomCenter'; + +/** + * @remarks Not present in any of the Steam files, source: https://gist.github.com/Ne3tCode/fc424ae2bd723d9ccb236eeccce66316#file-steammobile_friendsui_enums-steamd-L1308-L1340 + */ +export enum AppLaunchSource { + None = 0, + _2ftLibraryDetails = 100, + _2ftLibraryListView = 101, + _2ftLibraryGrid = 103, + InstallSubComplete = 104, + DownloadsPage = 105, + RemoteClientStartStreaming = 106, + _2ftMiniModeList = 107, + _10ft = 200, + DashAppLaunchCmdLine = 300, + DashGameIdLaunchCmdLine = 301, + RunByGameDir = 302, + SubCmdRunDashGame = 303, + SteamURL_Launch = 400, + SteamURL_Run = 401, + SteamURL_JoinLobby = 402, + SteamURL_RunGame = 403, + SteamURL_RunGameIdOrJumplist = 404, + SteamURL_RunSafe = 405, + TrayIcon = 500, + LibraryLeftColumnContextMenu = 600, + LibraryLeftColumnDoubleClick = 601, + Dota2Launcher = 700, + IRunGameEngine = 800, + DRMFailureResponse = 801, + DRMDataRequest = 802, + CloudFilePanel = 803, + DiscoveredAlreadyRunning = 804, + GameActionJoinParty = 900, + AppPortraitContextMenu = 1000, +} + +export interface NonSteamApp { + bIsApplication: boolean; + strAppName: string; + strExePath: string; + strArguments: string; + strCmdline: string; + strIconDataBase64: string; +} + +export interface LogoPositionForApp { + nVersion: number; // Usually 1 + logoPosition: LogoPosition; +} + +/** + * CLibraryBootstrapData + */ +export interface LibraryBootstrapData extends JsPbMessage { + app_data(): AppBootstrapData[]; + + add_app_data(param0: any, param1: any): any; + + set_app_data(param0: any): any; +} + +export interface AppBootstrapData { + appid: number; + hidden: boolean; + user_tag: string[]; +} + +/** + * CAppOverview_Change + */ +export interface AppOverview_Change extends JsPbMessage { + app_overview(): SteamAppOverview[]; + + full_update(): boolean; + + removed_appid(): number[]; + + update_complete(): boolean; + + add_app_overview(param0: any, param1: any): any; + + add_removed_appid(param0: any, param1: any): any; + + set_app_overview(param0: any): any; + + set_full_update(param0: any): any; + + set_removed_appid(param0: any): any; + + set_update_complete(param0: any): any; +} + +// Appears to be all optional fields :disaster: +export interface SteamAppOverview { + appid: number; + display_name: string; + visible_in_game_list: boolean; + sort_as: string; + + /* + * Possible bitmask values, but I haven't spotted any of them being masked in the app_type field. + * Should be safe as an enum. + */ + app_type: AppType; + mru_index: number | undefined; + rt_recent_activity_time: number; + minutes_playtime_forever: number; + minutes_playtime_last_two_weeks: number; + rt_last_time_played_or_installed: number; + rt_last_time_played: number; + store_tag?: number[]; + association: SteamAppOverviewAssociation[]; + store_category?: number[]; + rt_original_release_date: number; + rt_steam_release_date: number; + icon_hash: string; + controller_support?: AppControllerSupportLevel; // default none + vr_supported?: boolean; + metacritic_score: number; + size_on_disk?: number; + third_party_mod?: boolean; + icon_data?: string; + icon_data_format?: string; + gameid: string; + library_capsule_filename?: string; + per_client_data: SteamAppOverviewClientData[]; + most_available_clientid: string; + selected_clientid?: string; + rt_store_asset_mtime: number; + rt_custom_image_mtime?: number; + optional_parent_app_id?: number; + owner_account_id?: number; + review_score_with_bombs: number; + review_percentage_with_bombs: number; + review_score_without_bombs: number; + review_percentage_without_bombs: number; + library_id?: string; + vr_only?: boolean; + mastersub_appid?: number; + mastersub_includedwith_logo?: string; + site_license_site_name?: string; + shortcut_override_appid?: number; + steam_deck_compat_category: SteamDeckCompatibilityCategory; // Default should be Unknown + rt_last_time_locally_played?: number; + rt_purchased_time: number; + header_filename?: string; + local_cache_version?: number; + ps4_controller_support?: AppControllerSupportLevel; + ps5_controller_support?: AppControllerSupportLevel; + gamepad_preferred?: boolean; + + m_setStoreCategories: Set; + m_setStoreTags: Set; + canonicalAppType: number; + local_per_client_data: SteamAppOverviewClientData; + most_available_per_client_data: SteamAppOverviewClientData; + selected_per_client_data: SteamAppOverviewClientData; + m_strPerClientData: Set | undefined; + m_strAssociations: Set | undefined; + + BIsModOrShortcut: () => boolean; + BIsShortcut: () => boolean; +} + +export enum AppType { + DepotOnly = -2147483648, + Invalid = 0, + Game = 1, + Application = 2, + Tool = 4, + Demo = 8, + Deprecated = 16, + DLC = 32, + Guide = 64, + Driver = 128, + Config = 256, + Hardware = 512, + Franchise = 1024, + Video = 2048, + Plugin = 4096, + MusicAlbum = 8192, + Series = 16384, + Comic = 32768, + Beta = 65536, + Shortcut = 1073741824, +} + +export interface SteamAppOverviewAssociation { + type: AppAssociationType; // Default should be Invalid + name: string; +} + +export enum AppAssociationType { + Invalid = 0, + Publisher = 1, + Developer = 2, + Franchise = 3, +} + +export enum AppControllerSupportLevel { + None = 0, + Partial = 1, + Full = 2, +} + +export interface SteamAppOverviewClientData { + clientid: string; + client_name: string; + display_status: DisplayStatus; // Default should be Invalid + status_percentage: number; + active_beta?: string; + installed?: boolean; + bytes_downloaded: string; + bytes_total: string; + streaming_to_local_client?: boolean; + is_available_on_current_platform: boolean; + is_invalid_os_type?: boolean; + playtime_left?: number; + cloud_status: AppCloudStatus; +} + +export enum SteamDeckCompatibilityCategory { + Unknown = 0, + Unsupported = 1, + Playable = 2, + Verified = 3, +} + +export enum AppCloudStatus { + Invalid = 0, + Disabled = 1, + Unknown = 2, + Synchronized = 3, + Checking = 4, + OutOfSync = 5, + Uploading = 6, + Downloading = 7, + SyncFailed = 8, + Conflict = 9, + PendingElsewhere = 10, +} diff --git a/src/deck-components/steam-client/Auth.ts b/src/deck-components/steam-client/Auth.ts new file mode 100644 index 00000000..c426952f --- /dev/null +++ b/src/deck-components/steam-client/Auth.ts @@ -0,0 +1,98 @@ +import {JsPbMessage} from "./index"; +import {OSType} from "./system"; + +export interface Auth { + /** + * @returns a boolean indicating if the operation succeeded. + */ + ClearCachedSignInPin(): Promise; + + CurrentUserHasCachedSignInPin(): Promise; + + GetLocalHostname(): Promise; + + /** + * @returns A Promise that resolves to a ProtoBuf message. If deserialized, returns {@link Authentication_DeviceDetails}. + */ + GetMachineID(): Promise; + + GetRefreshInfo(): Promise; + + GetSteamGuardData(param0: any): any; + + IsSecureComputer(): Promise; + + SetCachedSignInPin(pin: string): Promise; + + SetLoginToken(refreshToken: string, accountName: string): any; + + SetSteamGuardData(accountName: string, newGuardData: string): any; + + StartSignInFromCache(param0: any, login: string): Promise; + + UserHasCachedSignInPin(accountName: string): Promise; + + ValidateCachedSignInPin(accountName: string, pin: string): Promise; +} + +export interface AuthRefreshInfo { + reason: number; + account_name: string; + login_id_token: string; +} + +/** + * CAuthentication_DeviceDetails + * + * `deserializeBinary` argument: + * ``` + * [ + * await SteamClient.System.GetOSType(), + * await SteamClient.Auth.GetLocalHostname(), + * await SteamClient.Auth.GetMachineID(), + * ]; + * ``` + */ +export interface Authentication_DeviceDetails extends JsPbMessage { + client_count(): number | undefined; + + device_friendly_name(): string | undefined; + + gaming_device_type(): GamingDeviceType | undefined; + + machine_id(): Uint8Array | string; + + os_type(): OSType | undefined; + + platform_type(): AuthTokenPlatformType | undefined; + + set_client_count(): any; + + set_device_friendly_name(): any; + + set_gaming_device_type(): any; + + set_machine_id(): any; + + set_os_type(): any; + + set_platform_type(): any; +} + +export enum AuthTokenPlatformType { + Unknown = 0, + SteamClient = 1, + WebBrowser = 2, + MobileApp = 3, +} + +export enum GamingDeviceType { + Unknown = 0, + StandardPC = 1, + Console = 256, + PS3 = 272, + Steambox = 288, + Handheld = 512, + Phone = 528, + SteamDeck = 544, +} diff --git a/src/deck-components/steam-client/Broadcast.ts b/src/deck-components/steam-client/Broadcast.ts new file mode 100644 index 00000000..642157fe --- /dev/null +++ b/src/deck-components/steam-client/Broadcast.ts @@ -0,0 +1,59 @@ +import {Result, Unregisterable} from "./index"; + +export interface Broadcast { + /** + * Approves a viewer request for the broadcast. + * @param steamId64 The SteamID64 of the user whose request is to be approved. + * @param param1 Unknown parameter. + */ + ApproveViewerRequest(steamId64: string, param1: number): void; + + /** + * Invites a user identified by their SteamID64 to watch the broadcast. + * @param steamId64 The SteamID64 of the user to invite. + * @returns A Promise indicating the result of the invitation (1 for success, 2 for error). + */ + InviteToWatch(steamId64: string): Promise; + + /** + * Registers a callback to be called when the broadcast status changes. + * @param callback The callback function to be called. + * @returns An object that can be used to unregister the callback. + */ + RegisterForBroadcastStatus(callback: (broadcastStatus: BroadcastStatus) => void): Unregisterable; + + /** + * Registers a callback to be called when viewer requests are received. + * @param callback The callback function to be called. + * @returns An object that can be used to unregister the callback. + */ + RegisterForViewerRequests( + callback: (viewerFriendCode: number, param1: number, param2: number) => void, + ): Unregisterable; + + /** + * Rejects a viewer request for the broadcast. + * @param steamId64 The SteamID64 of the user whose request is to be rejected. + * @param param1 Unknown parameter. + */ + RejectViewerRequest(steamId64: string, param1: number): void; + + /** + * Stops the broadcast. + */ + StopBroadcasting(): void; +} + +export interface BroadcastStatus { + broadcastid: string; + nViewers: number; + nRequests: number; + bIsBroadcasting: boolean; + bIsRecordingDesktop: boolean; + eBroadcastReady: Result; + bBroadcastCapable: boolean; + bMicrophoneEnabled: boolean; + bMicrophoneActive: boolean; + nCurrentFPS: number; + nUploadKbps: number; +} diff --git a/src/deck-components/steam-client/Browser.ts b/src/deck-components/steam-client/Browser.ts new file mode 100644 index 00000000..6df884f7 --- /dev/null +++ b/src/deck-components/steam-client/Browser.ts @@ -0,0 +1,87 @@ +import {Unregisterable} from "./index"; + +export interface Browser { + AddWordToDictionary(word: string): void; + + ClearAllBrowsingData(): void; + + ClearHistory(): void; + + CloseDevTools(): void; + + GetBrowserID(): Promise; + + GetSpellingSuggestions(word: string): string[]; + + GetSteamBrowserID(): Promise; // 16-bit unsigned integer? + + /** + * Hides the mouse cursor until input. + */ + HideCursorUntilMouseEvent(): void; + + /** + * yup that's right, clientY and clientX are reversed + */ + InspectElement(clientY: number, clientX: number): void; + + NotifyUserActivation(): void; + + OpenDevTools(): void; + + /** + * Pastes the clipboard contents. + */ + Paste(): void; + + /** + * @todo unconfirmed + */ + RegisterForGestureEvents(callback: (gesture: TouchGesture) => void): Unregisterable; + + RegisterForOpenNewTab: Unregisterable; + + ReplaceMisspelling: any; + + /** + * Restarts the Steam JS context. + */ + RestartJSContext(): void; + + SetBackgroundThrottlingDisabled(value: boolean): void; + + SetPendingFilePath(path: string): Promise; + + SetShouldExitSteamOnBrowserClosed(value: boolean): any; + + SetTouchGesturesToCancel(gestures: TouchGestureType[]): void; + + /** + * Prompts and downloads a file. + * @param url The URL of the file to download. + */ + StartDownload(url: string): void; +} + +export interface TouchGesture { + eTouchGesture: TouchGestureType; + x: number; + y: number; +} + +export enum TouchGestureType { + None = 0, + Touch = 1, + Tap = 2, + DoubleTap = 3, + ShortPress = 4, + LongPress = 5, + LongTap = 6, + TwoFingerTap = 7, + TapCancelled = 8, + PinchBegin = 9, + PinchUpdate = 10, + PinchEnd = 11, + FlingStart = 12, + FlingCancelled = 13, +} diff --git a/src/deck-components/steam-client/ClientNotifications.ts b/src/deck-components/steam-client/ClientNotifications.ts new file mode 100644 index 00000000..d74ce344 --- /dev/null +++ b/src/deck-components/steam-client/ClientNotifications.ts @@ -0,0 +1,39 @@ +import { BrowserContext } from "./index"; + +export interface ClientNotifications { + /** + * Displays a Steam notification. + * @param notification Notification type. + * @param options Stringified object of {@link SteamNotificationOptions}. + * @param callback + */ + DisplayClientNotification( + notification: ClientUINotificationType, + options: string, + callback: (context: BrowserContext) => void, + ): void; + + /** + * @param notificationId The ID of the notification to handle. + * @param handleAction `true` to execute the callback function associated with the notification, `false` otherwise. + */ + OnRespondToClientNotification(notificationId: number, handleAction: boolean): void; +} + +export interface SteamNotificationOptions { + body: string; + chatroomgroupid?: number; + chatroomid?: number; + icon?: string; + state: string; + /** A Steam64 ID. */ + steamid: string; + tag?: string; + title?: string; +} + +export enum ClientUINotificationType { + GroupChatMessage = 1, + FriendChatMessage = 2, + FriendPersonaState = 3, +} diff --git a/src/deck-components/steam-client/Cloud.ts b/src/deck-components/steam-client/Cloud.ts new file mode 100644 index 00000000..9088ab91 --- /dev/null +++ b/src/deck-components/steam-client/Cloud.ts @@ -0,0 +1,16 @@ +export interface Cloud { + /** + * Resolves a synchronization conflict for an app in the cloud. + * @param appId The ID of the app with the sync conflict. + * @param keepLocal Whether to keep the local version during conflict resolution. + * @returns Returns data related to resolving the sync conflict. + */ + ResolveAppSyncConflict(appId: number, keepLocal: boolean): void; + + /** + * Retries syncing an app with the cloud. + * @param appId The ID of the app to retry syncing. + * @returns Returns data related to retrying the app sync. + */ + RetryAppSync(appId: number): void; +} diff --git a/src/deck-components/steam-client/CommunityItems.ts b/src/deck-components/steam-client/CommunityItems.ts new file mode 100644 index 00000000..9f2e0945 --- /dev/null +++ b/src/deck-components/steam-client/CommunityItems.ts @@ -0,0 +1,24 @@ +export interface CommunityItems { + /* + DownloadMovie(e) { + return (0, o.mG)(this, void 0, void 0, (function* () { + if (0 != e.movie_webm_local_path.length) return !0; + let t = yield SteamClient.CommunityItems.DownloadItemAsset(e.communityitemid, w, e.movie_webm), + n = 1 == t.result; + if (n) { + e.movie_webm_local_path = t.path; + let n = []; + this.m_startupMovies.forEach((t => { + t.movie_webm == e.movie_webm ? n.push(e) : n.push(t) + })), this.m_startupMovies = n + } + return n + })) + } + */ + DownloadItemAsset(communityItemId: string, param1: any, param2: string): any; + + GetItemAssetPath(communityItemId: string, param1: any, param2: string): any; + + RemoveDownloadedItemAsset(communityItemId: string, param1: any, param2: string): any; +} diff --git a/src/deck-components/steam-client/Console.ts b/src/deck-components/steam-client/Console.ts new file mode 100644 index 00000000..3edad44b --- /dev/null +++ b/src/deck-components/steam-client/Console.ts @@ -0,0 +1,41 @@ +import {Unregisterable} from "./index"; + +/** + * Represents the console functionality for executing commands and handling spew output. + */ +export interface Console { + /** + * Executes a console command. + * @param command The command to execute in the console. + */ + ExecCommand(command: string): void; + + /** + * Retrieves autocomplete suggestions for a given console command. + * @param command The console command to provide autocomplete suggestions for. + * @returns A Promise that resolves to an array of autocomplete suggestions. + */ + GetAutocompleteSuggestions(command: string): Promise; + + /** + * Registers a callback function to receive spew output. + * @param callback The callback function that will receive spew output. + * @returns An object that can be used to unregister the callback. + */ + RegisterForSpewOutput(callback: (spewOutput: SpewOutput) => void): Unregisterable; +} + +/** + * Represents spew output information. + */ +export interface SpewOutput { + /** + * The content of the spew output. + */ + spew: string; + + /** + * The type or category of the spew output. + */ + spew_type: "error" | "info" | "input"; +} diff --git a/src/deck-components/steam-client/Customization.ts b/src/deck-components/steam-client/Customization.ts new file mode 100644 index 00000000..854b2836 --- /dev/null +++ b/src/deck-components/steam-client/Customization.ts @@ -0,0 +1,12 @@ +export interface Customization { + GenerateLocalStartupMoviesThumbnails(param0: number): Promise; + + //param0: "startupmovies" + GetDownloadedStartupMovies(param0: string): Promise; + + GetLocalStartupMovies(): Promise; +} + +export interface StartupMovie { + strMovieURL: string; +} diff --git a/src/deck-components/steam-client/Downloads.ts b/src/deck-components/steam-client/Downloads.ts new file mode 100644 index 00000000..ffbd16c6 --- /dev/null +++ b/src/deck-components/steam-client/Downloads.ts @@ -0,0 +1,175 @@ +import {Unregisterable} from "./index"; +import {AppError} from "./App"; + +/** + * Represents functions related to managing downloads in Steam. + */ +export interface Downloads { + /** + * Enables or disables all downloads in Steam. + * @param enable True to enable downloads, false to disable. + */ + EnableAllDownloads(enable: boolean): void; + + /** + * Moves the update for a specific app down the download queue. + * @param appId The ID of the application to move. + */ + MoveAppUpdateDown(appId: number): void; + + /** + * Moves the update for a specific app up the download queue. + * @param appId The ID of the application to move. + */ + MoveAppUpdateUp(appId: number): void; + + PauseAppUpdate(appId: number): void; // Broken? It seems to be removing it from download list like RemoveFromDownloadList + + /** + * Adds the update for a specific app to the download queue. + * @param appId The ID of the application to queue. + */ + QueueAppUpdate(appId: number): void; + + /** + * Registers a callback function to be called when download items change. + * @param callback The callback function to be called. + * @returns An object that can be used to unregister the callback. + */ + RegisterForDownloadItems( + callback: (isDownloading: boolean, downloadItems: DownloadItem[]) => void, + ): Unregisterable; + + /** + * Registers a callback function to be called when download overview changes. + * @param callback The callback function to be called. + * @returns An object that can be used to unregister the callback. + */ + RegisterForDownloadOverview(callback: (downloadOverview: DownloadOverview) => void): Unregisterable; + + /** + * Removes the update for a specific app from the download list and places it in the unscheduled list. + * @param appId The ID of the application to remove. + */ + RemoveFromDownloadList(appId: number): void; + + /** + * Resumes the update for a specific app in the queue. + * @param appId The ID of the application to resume. + */ + ResumeAppUpdate(appId: number): void; + + /** + * Sets an app to launch when its download is complete. + * @param appId The ID of the application to set. + */ + SetLaunchOnUpdateComplete(appId: number): void; + + /** + * Sets the queue index for an app in the download queue. + * @param appId The ID of the application to set the index for. + * @param index The index to set. + * @remarks Index of 0 is the current download in progress. + */ + SetQueueIndex(appId: number, index: number): void; + + /** + * Suspends or resumes download throttling. + * @param suspend Whether to suspend or resume download throttling. + */ + SuspendDownloadThrottling(suspend: boolean): void; + + /** + * Suspends or resumes local transfers. + * @param suspend Whether to suspend or resume local transfers. + */ + SuspendLanPeerContent(suspend: boolean): void; +} + +export interface DownloadItem { + /** True if this app is currently downloading */ + active: boolean; + /** Appid of app */ + appid: number; + /** Current build ID for the installed app, zero if the app isn't installed yet */ + buildid: number; + /** True if this update has been completed */ + completed: boolean; + /** For completed downloads, time of completion, 0 if not completed */ + completed_time: number; + deferred_time: number; + /** Bytes already downloaded, sum across all content types */ + downloaded_bytes: number; + /** If true, game will launch when its download completes successfully */ + launch_on_completion: boolean; + /** True if this app has been paused by the user or the system */ + paused: boolean; + /** Queue index, -1 if the item is unqueued */ + queue_index: number; + /** Build ID that this download is moving towards. This can be the same as buildid.*/ + target_buildid: number; + /** Total bytes to download, sum across all content types */ + total_bytes: number; + /** + * Update error description, when paused and there has been an error. + * Unlocalized and shouldn't be displayed to the user. + */ + update_error: string; + update_result: AppError; + update_type_info: UpdateTypeInfo[]; +} + +export interface DownloadOverview { + /** Set if we are downloading from LAN peer content server */ + lan_peer_hostname: string; + /** True if all downloads are paused */ + paused: boolean; + /** True if download throttling has been temporarily suspended for the current download */ + throttling_suspended: boolean; + /** Appid of currently updating app */ + update_appid: number; + /** Bytes already downloaded */ + update_bytes_downloaded: number; + /** Bytes already processed in current phase - resets to zero when update stage changes */ + update_bytes_processed: number; + /** Bytes already staged */ + update_bytes_staged: number; + /** Total bytes to download */ + update_bytes_to_download: number; + /** Total bytes to process in current phase - resets to zero when update stage changes */ + update_bytes_to_process: number; + /** Total bytes to be staged */ + update_bytes_to_stage: number; + /** Current disk throughput estimate */ + update_disc_bytes_per_second: number; + /** True if the current update is an initial install */ + update_is_install: boolean; + /** True if download and staging sizes are prefetch estimates */ + update_is_prefetch_estimate: boolean; + /** True if the current update is for shader update */ + update_is_shader: boolean; + /** True if the client is running in peer content server mode serving other peers */ + update_is_upload: boolean; + /** True if the current update is for workshop content */ + update_is_workshop: boolean; + /** Current bandwidth estimate for download */ + update_network_bytes_per_second: number; + /** Peak bandwidth estimate for download */ + update_peak_network_bytes_per_second: number; + /** Estimate of remaining time (in seconds) until download completes (not including staging) */ + update_seconds_remaining: number; + /** Time current update started */ + update_start_time: number; + update_state: 'None' | 'Starting' | 'Updating' | 'Stopping'; +} + +export interface UpdateTypeInfo { + /** True if this content type had an update and it has completed */ + completed_update: boolean; + /** Bytes already downloaded for this content type */ + downloaded_bytes: number; + /** True if this content type has or had an update */ + has_update: boolean; + /** Total bytes to download for this content type */ + total_bytes: number; +} diff --git a/src/deck-components/steam-client/FamilySharing.ts b/src/deck-components/steam-client/FamilySharing.ts new file mode 100644 index 00000000..0fb35899 --- /dev/null +++ b/src/deck-components/steam-client/FamilySharing.ts @@ -0,0 +1,42 @@ +/** + * Represents functions related to Steam Family Sharing. + */ +export interface FamilySharing { + /** + * Authorizes library sharing on the local device. + * @returns A Promise that resolves to a status code. + * FamilySettings_SteamGuardRequired - 18 + * FamilySettings_LimitExceeded - 25 + * FamilySettings_FailedToAuthorize - any other number + */ + AuthorizeLocalDevice(): Promise; + + /** + * Deauthorizes library sharing on the local device. + * @returns A Promise that resolves to a status code. + */ + DeauthorizeLocalDevice(): Promise; + + GetAvailableLenders(appId: number): Promise; + + GetFamilyGroupInfo(): Promise; + + RegisterForKickedBorrower: any; + + SetPreferredLender(appId: number, param1: number): Promise; + + // param0 - account id? + // return FamilySettings_TooManyBorrowers - 25, FamilySettings_FailedToUpdateBorrower - any number that's not 1 or previous + UpdateAuthorizedBorrower(param0: number, param1: boolean): Promise; +} + +export interface Lender { + /** + * A Steam64 ID. + */ + steamid: string; + appid: number; + numDlc: number; + bPreferred: boolean; + vecDLC: any[]; +} diff --git a/src/deck-components/steam-client/FriendSettings.ts b/src/deck-components/steam-client/FriendSettings.ts new file mode 100644 index 00000000..d60055fd --- /dev/null +++ b/src/deck-components/steam-client/FriendSettings.ts @@ -0,0 +1,69 @@ +import {Unregisterable} from "./index"; + +/** + * Represents friend settings and configuration. + */ +export interface FriendSettings { + /** + * Retrieves a list of enabled friend settings features. + * @returns A Promise that resolves to an array of enabled friend settings features. + */ + GetEnabledFeatures(): Promise; + + /** + * Registers a callback function to be notified of friend settings changes. + * @param callback The callback function to be called when friend settings change. + * @returns An object that can be used to unregister the callback. + * @remarks The callback receives an escaped JSON object string as "settingsChanges", which should be parsed into {@link FriendSettingsChange} object. + */ + RegisterForSettingsChanges(callback: (settingsChanges: string) => void): Unregisterable; + + SetFriendSettings(details: string): any; // stringified object +} + +export interface FriendSettingsFeature { + feature: string; + bEnabled: boolean; +} + +export interface FriendSettingsEnabledFeature { + DoNotDisturb: number; + LoaderWindowSynchronization: number; + NonFriendMessageHandling: number; + NewVoiceHotKeyState: number; + PersonaNotifications: number; + ServerVirtualizedMemberLists: number; + SteamworksChatAPI: number; + FriendsFilter: number; +} + +export interface FriendSettingsChange { + bNotifications_ShowIngame: number; + bNotifications_ShowOnline: number; + bNotifications_ShowMessage: number; + bNotifications_EventsAndAnnouncements: number; + bSounds_PlayIngame: number; + bSounds_PlayOnline: number; + bSounds_PlayMessage: number; + bSounds_EventsAndAnnouncements: number; + bAlwaysNewChatWindow: number; + bForceAlphabeticFriendSorting: number; + nChatFlashMode: number; + bRememberOpenChats: number; + bCompactQuickAccess: number; + bCompactFriendsList: number; + bNotifications_ShowChatRoomNotification: number; + bSounds_PlayChatRoomNotification: number; + bHideOfflineFriendsInTagGroups: number; + bHideCategorizedFriends: number; + bCategorizeInGameFriendsByGame: number; + nChatFontSize: number; + b24HourClock: number; + bDoNotDisturbMode: number; + bDisableEmbedInlining: number; + bSignIntoFriends: number; + bDisableSpellcheck: number; + bDisableRoomEffects: number; + bAnimatedAvatars: number; + featuresEnabled: FriendSettingsEnabledFeature; +} diff --git a/src/deck-components/steam-client/Friends.ts b/src/deck-components/steam-client/Friends.ts new file mode 100644 index 00000000..18e75b26 --- /dev/null +++ b/src/deck-components/steam-client/Friends.ts @@ -0,0 +1,62 @@ +import { Unregisterable } from "./index"; + +/** + * Represents functions related to managing friends in Steam. + */ +export interface Friends { + /** + * Adds a user to the friend list. + * @param steamId The Steam ID of the user to add as a friend. + * @returns A Promise that resolves to true if the friend was added successfully, false otherwise. + */ + AddFriend(steamId: string): Promise; + + /** + * @returns a list of players you recently played with. + */ + GetCoplayData(): Promise; + + //(e.ConvertTo64BitString(), t.steamidTarget) + InviteUserToCurrentGame(steam64Id: string, param1: any): any; + + /** + * Invites a user to a specific game. + * @param steamId The Steam ID of the user to invite. + * @param appId The ID of the game to invite the user to. + * @param connectString Additional parameters for the invitation. + * @returns A Promise that resolves to true if the user was invited successfully, false otherwise. + */ + InviteUserToGame(steamId: string, appId: number, connectString: string): Promise; + + //(e.ConvertTo64BitString(), t.steamidTarget) + InviteUserToLobby(steam64Id: string, param1: any): any; + + //(e.ConvertTo64BitString()) + InviteUserToRemotePlayTogetherCurrentGame(steam64Id: string): any; + + RegisterForVoiceChatStatus(callback: (status: VoiceChatStatus) => void): Unregisterable; + + /** + * Removes a user from the friend list. + * @param steamId The Steam ID of the user to remove from the friend list. + * @returns A Promise that resolves to true if the friend was removed successfully, false otherwise. + */ + RemoveFriend(steamId: string): Promise; +} + +export interface CoplayData { + currentUsers: CoplayUser[]; + recentUsers: CoplayUser[]; +} + +export interface CoplayUser { + accountid: number; + rtTimePlayed: number; + appid: number; +} + +export interface VoiceChatStatus { + bVoiceChatActive: boolean; + bMicMuted: boolean; + bOutputMuted: boolean; +} diff --git a/src/deck-components/steam-client/GameNotes.ts b/src/deck-components/steam-client/GameNotes.ts new file mode 100644 index 00000000..5c349e38 --- /dev/null +++ b/src/deck-components/steam-client/GameNotes.ts @@ -0,0 +1,30 @@ +export interface GameNotes { + DeleteImage(param0: any): any; + + DeleteNotes: any; + /* + FilenameForNotes(e) { + return "appid" in e ? `notes_${Number(e.appid)}` : `notes_shortcut_${h(e.shortcut)}` + } + DirectoryForNoteImages(e) { + return "appid" in e ? `notes_${Number(e.appid)}_images/` : `notes_shortcut_${h(e.shortcut)}_images/` + } + */ + // {"result":1,"notes":""} + // example: {"notes":[{"id":"lmuudzqn","appid":1716740,"ordinal":0,"time_created":1695401684,"time_modified":1695403395,"title":"Old Earth Cuisine 1:","content":"[h1]Old Earth Cuisine 1:[/h1][list][*][p]Red Meat[/p][/*][/list][h1]Beverage Development 2:[/h1][list][*][p]Tranquilitea Sunray[/p][/*][/list][p][/p]"}]} + GetNotes(filenameForNotes: string, directoryForNoteImages: string): Promise; + + GetNotesMetadata: any; + GetNumNotes: any; + GetQuota: any; + + IterateNotes(appId: number, length: number): any; // Results array of {"result":1,"filename":"","filesize":0,"timestamp":0} + ResolveSyncConflicts: any; + + SaveNotes(filenameForNotes: string, param1: string): Promise; // param1 - notes like escaped json in GetNotes + SyncToClient(): Promise; + + SyncToServer(): Promise; + + UploadImage: any; +} diff --git a/src/deck-components/steam-client/GameRecording.ts b/src/deck-components/steam-client/GameRecording.ts new file mode 100644 index 00000000..cc470fe2 --- /dev/null +++ b/src/deck-components/steam-client/GameRecording.ts @@ -0,0 +1,29 @@ +import type { JsPbMessage, Unregisterable } from "./index"; + +export interface GameRecording { + /** + * If `data` is deserialized, returns {@link CGameRecording_AudioSessionsChanged_Notification}. + */ + RegisterForAudioSessionsChanged(callback: (data: ArrayBuffer) => void): Unregisterable; + SetAudioSessionCaptureState(id: string, name: string, state: boolean): void; +} + +export interface AudioSession { + id(): string | undefined; + name(): string | undefined; + is_system(): boolean | undefined; + is_muted(): boolean | undefined; + is_active(): boolean | undefined; + is_captured(): boolean | undefined; + recent_peak(): number | undefined; + is_game(): boolean | undefined; + is_steam(): boolean | undefined; + is_saved(): boolean | undefined; +} + +/** + * @note Taken from https://github.com/SteamDatabase/SteamTracking/blob/master/Protobufs/steammessages_gamerecording_objects.proto + */ +export interface CGameRecording_AudioSessionsChanged_Notification extends JsPbMessage { + sessions(): AudioSession[]; +} diff --git a/src/deck-components/steam-client/GameSessions.ts b/src/deck-components/steam-client/GameSessions.ts new file mode 100644 index 00000000..a3d28615 --- /dev/null +++ b/src/deck-components/steam-client/GameSessions.ts @@ -0,0 +1,58 @@ +import {Unregisterable} from "./index"; +import {AppAchievements} from "./App"; +import { Screenshot } from "./Screenshots"; + +/** + * Represents functions related to Steam Game Sessions. + */ +export interface GameSessions { + /** + * Registers a callback function to be called when an achievement notification is received. + * @param callback The callback function to be called. + * @returns An object that can be used to unregister the callback. + */ + RegisterForAchievementNotification( + callback: (achievementNotification: AchievementNotification) => void, + ): Unregisterable; + + /** + * Registers a callback function to be called when an app lifetime notification is received. + * @param callback The callback function to be called. + * @returns An object that can be used to unregister the callback. + */ + RegisterForAppLifetimeNotifications( + callback: (appLifetimeNotification: AppLifetimeNotification) => void, + ): Unregisterable; + + /** + * Registers a callback function to be called when a screenshot notification is received. + * @param callback The callback function to be called. + * @returns An object that can be used to unregister the callback. + */ + RegisterForScreenshotNotification( + callback: (screenshotNotification: ScreenshotNotification) => void, + ): Unregisterable; +} + +export interface AchievementNotification { + achievement: AppAchievements; + nCurrentProgress: number; + nMaxProgress: number; + unAppID: number; +} + +/** + * @prop unAppID is not properly set by Steam for non-steam game shortcuts, so it defaults to 0 for them + */ +export interface AppLifetimeNotification { + unAppID: number; + nInstanceID: number; + bRunning: boolean; +} + +export interface ScreenshotNotification { + details: Screenshot; + hScreenshot: number; + strOperation: "deleted" | "written"; + unAppID: number; +} diff --git a/src/deck-components/steam-client/Input.ts b/src/deck-components/steam-client/Input.ts new file mode 100644 index 00000000..1f7fcf84 --- /dev/null +++ b/src/deck-components/steam-client/Input.ts @@ -0,0 +1,741 @@ +import {Unregisterable} from "./index"; + +/** + * Represents functions related to input and controllers in Steam. + */ +export interface Input { + CalibrateControllerIMU(controllerIndex: any): any; + + CalibrateControllerJoystick(controllerIndex: any): any; + + CalibrateControllerTrackpads(controllerIndex: any): any; + + CancelGyroSWCalibration(): any; + + ClearSelectedConfigForApp(appId: number, controllerIndex: number): any; + + CloseDesktopConfigurator: any; + + /** + * Writes text. + * @param textToWrite The text to write. + */ + ControllerKeyboardSendText(textToWrite: string): void; + + /** + * Sets a specified key's pressed state. + * @param keyIndex The key index to set the state for. + * @param state true for pressed, false otherwise. + * @example + * Send paste command: + * ``` + * SteamClient.Input.ControllerKeyboardSetKeyState(EHIDKeyboardKey.LControl, true); + * SteamClient.Input.ControllerKeyboardSetKeyState(EHIDKeyboardKey.V, true); + * SteamClient.Input.ControllerKeyboardSetKeyState(EHIDKeyboardKey.V, false); + * SteamClient.Input.ControllerKeyboardSetKeyState(EHIDKeyboardKey.LControl, false); + * ``` + */ + ControllerKeyboardSetKeyState(keyIndex: HIDKeyboardKey, state: boolean): void; + + DecrementCloudedControllerConfigsCounter(): any; + + DeletePersonalControllerConfiguration(param0: any): any; + + //f.Debug("sending to client"), this.SetEditingConfigurationValue(e, t, c.QU, (e => SteamClient.Input.DuplicateControllerConfigurationSourceMode(this.m_unControllerIndex, e))), this.SaveEditingConfiguration(e), this + DuplicateControllerConfigurationSourceMode(controllerIndex: number, param1: any): any; + + EndControllerDeviceSupportFlow(): any; + + ExportCurrentControllerConfiguration(controllerIndex: number, appId: number, param2: number, title: string, description: string, param5: string): Promise; + + ForceConfiguratorFocus(param0: boolean): any; + + ForceSimpleHapticEvent(param0: number, param1: number, param2: number, param3: number, param4: number): any; + + FreeControllerConfig(m_ChordSummaryConfiguration: any): any; + + GetConfigForAppAndController(appId: number, unControllerIndex: number): any; + + /** + * Retrieves the controller mapping string for the specified controller index. + * @param unControllerIndex The controller index. + * @returns A Promise that resolves to the controller mapping string. + */ + GetControllerMappingString(unControllerIndex: number): Promise; + + GetControllerPreviouslySeen(): Promise; + + GetSteamControllerDongleState(): Promise; + + GetTouchMenuIconsForApp(appId: number): Promise; + + GetXboxDriverInstallState(): Promise; // "{"nResult":0}" + IdentifyController(controllerIndex: number): any; + + InitControllerSounds(): any; + + InitializeControllerPersonalizationSettings(controllerIndex: number): any; + + ModalKeyboardDismissed(): void; + + OpenDesktopConfigurator: any; + + PreviewConfigForAppAndController(appId: number, controllerIndex: number, workshopUri: string): any; + + PreviewControllerLEDColor(flHue: number, flSaturation: number, flBrightness: number): any; + + QueryControllerConfigsForApp(appId: number, controllerIndex: number, param2: boolean): any; + + RegisterForActiveControllerChanges: Unregisterable; // {"nActiveController":0} + //param0 - e possibly appid? + //param1 - some index? + RegisterForConfigSelectionChanges(callback: (param0: number, param1: number) => void): Unregisterable; + + RegisterForControllerAccountChanges: Unregisterable; + + RegisterForControllerAnalogInputMessages( + callback: (controllerAnalogInputMessages: ControllerAnalogInputMessage[]) => void, + ): Unregisterable; + + RegisterForControllerCommandMessages( + callback: (controllerCommandMessage: ControllerCommandMessage) => void, + ): Unregisterable; + + /** + * Registers a callback for changes in controller configuration cloud state. + * @param callback The callback function for config cloud state changes. + * @returns An object that can be used to unregister the callback. + */ + RegisterForControllerConfigCloudStateChanges( + callback: (controllerConfigCloudStateChange: ControllerConfigCloudStateChange) => void, + ): Unregisterable; + + /** + * Registers a callback for receiving controller configuration info messages (controller layouts query, personal controller layout query). + * @param callback The callback function for controller config info messages. + * @returns An object that can be used to unregister the callback. + * @remarks Do Not Use, this will break the controller layout selection unless you know what you are doing. + */ + RegisterForControllerConfigInfoMessages( + callback: ( + controllerConfigInfoMessages: ControllerConfigInfoMessageList[] | ControllerConfigInfoMessageQuery[], + ) => void, + ): Unregisterable; + + /** + * Registers a callback function to be invoked when controller input messages are received. + * @param callback The callback function to be invoked when controller input messages are received. + * @returns An object that can be used to unregister the callback. + */ + RegisterForControllerInputMessages( + callback: (controllerInputMessages: ControllerInputMessage[]) => void, + ): Unregisterable; + + RegisterForControllerListChanges(callback: (controllerListChanges: ControllerInfo[]) => void): Unregisterable; + + /** + * Registers a callback for changes in the controller state (buttons presses, triggers presses, joystick changes etc...). + * @param callback The callback function for controller state changes. + * @returns An object that can be used to unregister the callback. + */ + RegisterForControllerStateChanges( + callback: (controllerStateChanges: ControllerStateChange[]) => void, + ): Unregisterable; + + RegisterForDualSenseUpdateNotification(callback: (m_strDualSenseUpdateProduct: string) => void): Unregisterable; + + /** + * Registers a callback for receiving game keyboard messages (text field popup for inputting text for games when in character creation or etc...). + * @param callback The callback function for game keyboard messages. + * @returns An object that can be used to unregister the callback. + */ + RegisterForGameKeyboardMessages(callback: (gameKeyboardMessage: GameKeyboardMessage) => void): Unregisterable; + + RegisterForRemotePlayConfigChanges(callback: () => void): Unregisterable; + + //data.appId, data.ulConfigId + RegisterForShowControllerLayoutPreviewMessages(callback: (data: any) => void): Unregisterable; + + /* + onTouchMenuInput(e) { + for (let t = 0; t < e.length; t++) { + const n = this.TouchMenuGetKey(e[t]), o = this.m_mapActiveTouchMenus.get(n); + void 0 !== o && o.updateTouchMenuState(e[t]) + } + } + */ + RegisterForTouchMenuInputMessages(callback: (inputs: number[]) => void): Unregisterable; + + RegisterForTouchMenuMessages(callback: (touchMenuMessage: TouchMenuMessage) => void): Unregisterable; + + //param0 - index? + RegisterForUIVisualization(param0: any, param1: any, param2: any): Unregisterable; + + RegisterForUnboundControllerListChanges(callback: (m_unboundControllerList: any) => void): Unregisterable; // param0 is an array + + /* + OnDismissKeyboardMessage(e) { + this.m_WindowStore.SteamUIWindows.forEach((e => e.VirtualKeyboardManager.SetVirtualKeyboardHidden(e.BrowserWindow))) + } + */ + RegisterForUserDismissKeyboardMessages(callback: (param0: any) => void): Unregisterable; + + RegisterForUserKeyboardMessages: Unregisterable; + + RequestGyroActive(controllerIndex: number, param1: boolean): any; + + RequestRemotePlayControllerConfigs(param0: any): any; + + ResetControllerBindings(param0: any): any; + + ResolveCloudedControllerConfigConflict(param0: any): any; + + RestoreControllerPersonalizationSettings(controllerIndex: number): any; + + SaveControllerCalibration(controllerIndex: number): any; + + SaveControllerPersonalizationSettings(param0: any): any; + + SaveControllerSounds: any; + + SaveEditingControllerConfiguration(controllerIndex: number, sharedConfig: boolean): any; + + //this.SetEditingConfigurationValue(e, t, c.sL, (e => SteamClient.Input.SetControllerConfigurationModeShiftBinding(this.m_unControllerIndex, e))) + SetControllerConfigurationModeShiftBinding(controllerIndex: number, param1: any): any; + + SetControllerHapticSetting(controllerIndex: number, eHapticSetting: any): any; + + SetControllerMappingString(mapping: string): void; + + SetControllerName(controllerIndex: number, controllerName: string): any; + + SetControllerNintendoLayoutSetting: any; + SetControllerPersonalizationName: any; + + //param0 - nLStickDeadzone, bSWAntiDrift, nRHapticStrength, flRPadPressureCurve + /* + SteamClient.Input.SetControllerPersonalizationSetting("nLStickDeadzone", e.nLStickDeadzone), + SteamClient.Input.SetControllerPersonalizationSetting("nRStickDeadzone", e.nRStickDeadzone), + SteamClient.Input.SetControllerPersonalizationSetting("bSWAntiDrift", e.bSWAntiDrift ? 1 : 0), + SteamClient.Input.SetControllerPersonalizationSetting("nLHapticStrength", e.nLHapticStrength), + SteamClient.Input.SetControllerPersonalizationSetting("nRHapticStrength", e.nRHapticStrength), + SteamClient.Input.SetControllerPersonalizationSetting("flLPadPressureCurve", 100 * e.flLPadPressureCurve), + SteamClient.Input.SetControllerPersonalizationSetting("flRPadPressureCurve", 100 * e.flRPadPressureCurve), + SteamClient.Input.SetControllerPersonalizationSetting("ePlayerSlotLEDSetting", e), + SteamClient.Input.SetControllerPersonalizationSetting("GyroPreferenceData.nGyroSampleAngleOffsetX", e.nGyroSampleAngleOffsetX), + SteamClient.Input.SetControllerPersonalizationSetting("GyroPreferenceData.bMomentumEnabled", e.bMomentumEnabled ? 1 : 0), + SteamClient.Input.SetControllerPersonalizationSetting("GyroPreferenceData.nMomentumFrictionX", e.nMomentumFrictionX), + SteamClient.Input.SetControllerPersonalizationSetting("GyroPreferenceData.nMomentumFrictionY", e.nMomentumFrictionY), + SteamClient.Input.SetControllerPersonalizationSetting("GyroPreferenceData.nAccerationLevel", e.nAccerationLevel), + SteamClient.Input.SetControllerPersonalizationSetting("GyroPreferenceData.bInvertX", e.bInvertX ? 1 : 0), + SteamClient.Input.SetControllerPersonalizationSetting("GyroPreferenceData.bInvertY", e.bInvertY ? 1 : 0), + SteamClient.Input.SetControllerPersonalizationSetting("GyroPreferenceData.nRotationAngle", e.nRotationAngle), + SteamClient.Input.SetControllerPersonalizationSetting("GyroPreferenceData.nTriggerClamping", e.nTriggerClamping), + SteamClient.Input.SetControllerPersonalizationSetting("GyroPreferenceData.nTriggerClampingAmount", e.nTriggerClampingAmount), + SteamClient.Input.SetControllerPersonalizationSetting("GyroPreferenceData.nGyroEnableButton", e.nGyroEnableButton), + SteamClient.Input.SetControllerPersonalizationSetting("GyroPreferenceData.nGyroEnableButtonBehavior", e.nGyroEnableButtonBehavior), + */ + SetControllerPersonalizationSetting(param0: string, param1: number): any; + + //param0 - flGyroStationaryTolerance, flAccelerometerStationaryTolerance, + /* + SteamClient.Input.SetControllerPersonalizationSettingFloat("GyroPreferenceData.flGyroNaturalSensitivity", e.flGyroNaturalSensitivity), + SteamClient.Input.SetControllerPersonalizationSettingFloat("GyroPreferenceData.flGyroXYRatio", e.flGyroXYRatio), + SteamClient.Input.SetControllerPersonalizationSettingFloat("GyroPreferenceData.flGyroSpeedDeadzone", e.flGyroSpeedDeadzone), + SteamClient.Input.SetControllerPersonalizationSettingFloat("GyroPreferenceData.flGyroPrecisionSpeed", e.flGyroPrecisionSpeed), + SteamClient.Input.SetControllerPersonalizationSettingFloat("flGyroStationaryTolerance", e.flGyroStationaryTolerance), + SteamClient.Input.SetControllerPersonalizationSettingFloat("flAccelerometerStationaryTolerance", e.flAccelerometerStationaryTolerance), + */ + SetControllerPersonalizationSettingFloat(param0: string, param1: number): any; + + SetControllerRumbleSetting(controllerIndex: number, rumblePreference: any): any; + + SetCursorActionset(param0: boolean): any; + + SetDualSenseUpdateNotification(param0: boolean): any + + /* + SetEditingConfigurationValue(e, t, n, o) { + const a = new r.BinaryWriter; + n.serializeBinaryToWriter(n.fromObject(t), a); + const s = a.getResultBase64String(); + f.Debug("SetEditingConfigurationValue serializeBinaryToWriter", (0, i.ZN)(t), s), this.EditingConfigurationWillUpdate(), this.m_updatingEditingConfigurationPromise = o(s).then((t => { + if (null == t) return f.Debug("SetEditingConfigurationValue returned nothing."), void (0, i.z)((() => this.UpdateEditingConfiguration(e, this.m_unControllerIndex, this.EditingConfiguration))); + const n = c.bE.deserializeBinary(t).toObject(); + f.Debug("SetEditingConfigurationValue returned controller configuration.", n), this.UpdateEditingConfiguration(e, this.m_unControllerIndex, n), this.m_nEditNumber++, -1 == n.url.indexOf("autosave://") && this.SaveEditingConfiguration(e) + })).catch((e => { + f.Error("SetEditingConfigurationValue fail:", o, l.jt(e.result), e.message), this.m_bIsUpdatingActiveConfiguration = !1 + })) + } + + SetControllerActionSet(e, t) { + this.SetEditingConfigurationValue(e, t, c.X3, (e => SteamClient.Input.SetEditingControllerConfigurationActionSet(this.m_unControllerIndex, e))) + } + */ + SetEditingControllerConfigurationActionSet(controllerIndex: number, param1: any): any; + + //this.SetEditingConfigurationValue(e, t, c.io, (e => SteamClient.Input.SetEditingControllerConfigurationInputActivator(this.m_unControllerIndex, e))) + SetEditingControllerConfigurationInputActivator(controllerIndex: number, param1: any): any; + + //this.SetEditingConfigurationValue(e, t, c.tH, (e => SteamClient.Input.SetEditingControllerConfigurationInputActivatorEnabled(this.m_unControllerIndex, e))) + SetEditingControllerConfigurationInputActivatorEnabled(controllerIndex: number, param1: any): any; + + //this.SetEditingConfigurationValue(e, t, c.J2, (e => SteamClient.Input.SetEditingControllerConfigurationInputBinding(this.m_unControllerIndex, e))) + SetEditingControllerConfigurationInputBinding(controllerIndex: number, param1: any): any; + + //this.SetEditingConfigurationValue(e, t, c.Sz, (e => SteamClient.Input.SetEditingControllerConfigurationMiscSetting(this.m_unControllerIndex, e))) + SetEditingControllerConfigurationMiscSetting(controllerIndex: number, param1: any): any; + + //f.Debug("sending to client"), this.SetEditingConfigurationValue(e, t, c.QU, (e => SteamClient.Input.SetEditingControllerConfigurationSourceMode(this.m_unControllerIndex, e))) + SetEditingControllerConfigurationSourceMode(controllerIndex: number, param1: any): any; + + SetGamepadKeyboardText(param0: boolean, param1: string): any; + + SetKeyboardActionset(param0: boolean, param1: boolean): any; + + /** + * Sets the mouse position. + * @param pid 0 + * @param x Mouse X position. + * @param y Mouse Y position. + */ + SetMousePosition(pid: number, x: number, y: number): void; + + SetSelectedConfigForApp(appId: number, controllerIndex: number, url: string, param3: boolean): any; + + SetSteamControllerDonglePairingMode(bEnable: boolean, bSilent: boolean): any; + + SetVirtualMenuKeySelected(unControllerIndex: number, unMenuIndex: number, m_controllerMenuActiveMenuItem: number): any; // + SetWebBrowserActionset(param0: boolean): any; + + SetXboxDriverInstallState(param0: any): any; // state + + /** + * Opens the Steam Input controller settings. + * This function displays the Steam Input controller settings for configuration. + */ + ShowControllerSettings(): void; + + StandaloneKeyboardDismissed(): any; + + StartControllerDeviceSupportFlow(param0: any, param1: any, callback: (param2: any) => void): any; + + /* + this.m_updatingEditingConfigurationPromise = SteamClient.Input.StartEditingControllerConfigurationForAppIDAndControllerIndex(e, t).then((n=>{ + const o = c.bE.deserializeBinary(n).toObject(); + f.Debug("Loaded controller config for appid", e, n, o), + (0, + i.z)((()=>this.UpdateEditingConfiguration(e, t, o))) + } + )).catch((n=>{ + f.Debug("Loading controller config for appid rejected", e, n), + (0, + i.z)((()=>this.UpdateEditingConfiguration(e, t, null))) + } + )) + */ + StartEditingControllerConfigurationForAppIDAndControllerIndex(m_appId: number, m_unControllerIndex: number): Promise; + + StartGyroSWCalibration(callback: () => void): any; + + StopEditingControllerConfiguration(controllerIndex: number): any; + + SwapControllerConfigurationSourceModes: any; + + //this.SetEditingConfigurationValue(e, t, c.Qb, (e => SteamClient.Input.SwapControllerModeInputBindings(this.m_unControllerIndex, e))) + SwapControllerModeInputBindings(controllerIndex: number, param1: any): any; + + SwapControllerOrder(controllerIndex1: number, controllerIndex2: number): any; + + SyncCloudedControllerConfigs(): any; + + // type - enum + /* + Off - 0, Tick, Click + */ + TriggerHapticPulse(controllerIndex: number, eHapticType: number, param2: number): any; + + TriggerSimpleHapticEvent( + controllerIndex: number, + eHapticType: number, + unIntensity: number, + ndBGain: number, + param4: number, + ): any; + + UnregisterForControllerStateChanges(): void; + + UnregisterForUIVisualization(controllerIndex: number): any; + + UploadChangesForCloudedControllerConfigs(): any; +} + +export enum HIDKeyboardKey { + Invalid = 0, + BeforeFirst = 3, + A = 4, + B = 5, + C = 6, + D = 7, + E = 8, + F = 9, + G = 10, + H = 11, + I = 12, + J = 13, + K = 14, + L = 15, + M = 16, + N = 17, + O = 18, + P = 19, + Q = 20, + R = 21, + S = 22, + T = 23, + U = 24, + V = 25, + W = 26, + X = 27, + Y = 28, + Z = 29, + Key_1 = 30, + Key_2 = 31, + Key_3 = 32, + Key_4 = 33, + Key_5 = 34, + Key_6 = 35, + Key_7 = 36, + Key_8 = 37, + Key_9 = 38, + Key_0 = 39, + Return = 40, + Escape = 41, + Backspace = 42, + Tab = 43, + Space = 44, + Dash = 45, + Equals = 46, + LeftBracket = 47, + RightBracket = 48, + Backslash = 49, + Unused1 = 50, + Semicolon = 51, + SingleQuote = 52, + Backtick = 53, + Comma = 54, + Period = 55, + ForwardSlash = 56, + CapsLock = 57, + F1 = 58, + F2 = 59, + F3 = 60, + F4 = 61, + F5 = 62, + F6 = 63, + F7 = 64, + F8 = 65, + F9 = 66, + F10 = 67, + F11 = 68, + F12 = 69, + PrintScreen = 70, + ScrollLock = 71, + Break = 72, + Insert = 73, + Home = 74, + PageUp = 75, + Delete = 76, + End = 77, + PageDown = 78, + RightArrow = 79, + LeftArrow = 80, + DownArrow = 81, + UpArrow = 82, + NumLock = 83, + KeypadForwardSlash = 84, + KeypadAsterisk = 85, + KeypadDash = 86, + KeypadPlus = 87, + KeypadEnter = 88, + Keypad_1 = 89, + Keypad_2 = 90, + Keypad_3 = 91, + Keypad_4 = 92, + Keypad_5 = 93, + Keypad_6 = 94, + Keypad_7 = 95, + Keypad_8 = 96, + Keypad_9 = 97, + Keypad_0 = 98, + KeypadPeriod = 99, + LAlt = 100, + LShift = 101, + LWin = 102, + LControl = 103, + RAlt = 104, + RShift = 105, + RWin = 106, + RControl = 107, + VolUp = 108, + VolDown = 109, + Mute = 110, + Play = 111, + Stop = 112, + Next = 113, + Prev = 114, + AfterLast = 115, +} + +export interface ControllerAnalogInputMessage { + nA: number; + x: number; + y: number; + nC: number; +} + +export interface ControllerCommandMessage { + /** + * @todo enum + */ + eAction: number; + nControllerIndex: number; +} + +export interface ControllerConfigCloudStateChange { + bSyncDone: boolean; + bSyncConflict: boolean; + bSyncError: boolean; +} + +export interface ControllerConfigInfoMessage { + appID: number; +} + +export interface ControllerConfigInfoMessageQuery extends ControllerConfigInfoMessage { + bPersonalQueryDone: boolean; +} + +export interface ControllerConfigInfoMessageList extends ControllerConfigInfoMessage { + nControllerType: number; + publishedFileID: string; + accountID: number; + Title: string; + Description: string; + URL: string; + timeUpdated: string; + bOfficial: boolean; + bProgenitorOfficial: boolean; + bRecommended: boolean; + bProgenitorRecommended: boolean; + bUsesSIAPI: boolean; + bUsesMouse: boolean; + bUsesKeyboard: boolean; + bUsesGamepad: boolean; + /** + * @todo unconfirmed + */ + eExportType: ControllerConfigExportType; + playtime: string; + bSelected: boolean; +} + +export enum ControllerConfigExportType { + Unknown = 0, + PersonalLocal = 1, + PersonalCloud = 2, + Community = 3, + Template = 4, + Official = 5, + OfficialDefault = 6, +} + +export interface ControllerInputMessage { + nA: number; + bS: boolean; + nC: number; +} + +export interface ActiveAccount { + strActiveAccountID: string; + strName: string; + strAvatarHash: string; +} + +export interface ControllerInfo { + strName: string; + eControllerType: ControllerType; + nXInputIndex: number; + nControllerIndex: number; + eRumblePreference: number; // ControllerRumbleSetting + bWireless: boolean; + unUniqueID: number; + unVendorID: number; + unProductID: number; + unCapabilities: number; + strFirmwareBuildTime: string; + strSerialNumber: string; + strChipID: string; + nLEDColorR: number; + nLEDColorG: number; + nLEDColorB: number; + flLEDBrightness: number; + flLEDSaturation: number; + nTurnOnSound: number; + nTurnOffSound: number; + nLStickDeadzone: number; + nRStickDeadzone: number; + nLHapticStrength: number; + nRHapticStrength: number; + flLPadPressureCurve: number; + flRPadPressureCurve: number; + bHaptics: boolean; + bSWAntiDrift: boolean; + flGyroStationaryTolerance: number; + flAccelerometerStationaryTolerance: number; + bRemoteDevice: boolean; + bNintendoLayout: boolean; + bUseReversedLayout: boolean; + ActiveAccount: ActiveAccount | undefined; + vecAltAccounts: any[]; // The type for this property might need to be more specific based on the actual data structure +} + +export enum ControllerType { + None = -1, + Unknown = 0, + UnknownSteamController = 1, + SteamController = 2, // Codename Gordon + SteamControllerV2 = 3, // Codename Headcrab + SteamControllerNeptune = 4, // Steam Deck + FrontPanelBoard = 20, + Generic = 30, + XBox360Controller = 31, + XBoxOneController = 32, + PS3Controller = 33, + PS4Controller = 34, + WiiController = 35, + AppleController = 36, + AndroidController = 37, + SwitchProController = 38, + SwitchJoyConLeft = 39, + SwitchJoyConRight = 40, + SwitchJoyConPair = 41, + SwitchProGenericInputOnlyController = 42, + MobileTouch = 43, + SwitchProXInputSwitchController = 44, + PS5Controller = 45, + XboxEliteController = 46, + LastController = 47, // Unverified + PS5EdgeController = 48, + GenericKeyboard = 400, + GenericMouse = 800, +} + +export interface ControllerStateChange { + unControllerIndex: number; + unPacketNum: number; + /** + * Bitmask representing pressed upper buttons. + * - Bit 0-8: Unknown (@todo Please provide more details if known) + * - Bit 9: L4 + * - Bit 10: R4 + * - Bit 11-13: Unknown (@todo Please provide more details if known) + * - Bit 14: Left Joystick Touch + * - Bit 15: Right Joystick Touch + * - Bit 16-17: Unknown (@todo Please provide more details if known) + * - Bit 18: Quick Access Menu + */ + ulUpperButtons: number; + /** + * Bitmask representing pressed buttons. + * - Bit 0: R2 + * - Bit 1: L2 + * - Bit 2: R1 + * - Bit 3: L1 + * - Bit 4: Y + * - Bit 5: B + * - Bit 6: X + * - Bit 7: A + * - Bit 8: D-Pad Up + * - Bit 9: D-Pad Right + * - Bit 10: D-Pad Left + * - Bit 11: D-Pad Down + * - Bit 12: Select + * - Bit 13: Steam/Home + * - Bit 14: Start + * - Bit 15: L5 + * - Bit 16: R5 + * - Bit 17: Left Touchpad Click + * - Bit 18: Right Touchpad Click + * - Bit 19: Left Touchpad Touch + * - Bit 20: Right Touchpad Touch + * - Bit 21: Unknown (@todo Please provide more details if known) + * - Bit 22: L3 + * - Bit 23-25: Unknown (@todo Please provide more details if known) + * - Bit 26: R3 + * - Bit 27-28: Unknown (@todo Please provide more details if known) + * - Bit 29: Mute (Dualsense) + * - Bit 30-31: Unknown (@todo Please provide more details if known) + */ + ulButtons: number; + sLeftPadX: number; + sLeftPadY: number; + sRightPadX: number; + sRightPadY: number; + sCenterPadX: number; + sCenterPadY: number; + sLeftStickX: number; + sLeftStickY: number; + sRightStickX: number; + sRightStickY: number; + sTriggerL: number; + sTriggerR: number; + flTrustedGravityVectorX: number; + flTrustedGravityVectorY: number; + flTrustedGravityVectorZ: number; + flSoftwareQuatW: number; + flSoftwareQuatX: number; + flSoftwareQuatY: number; + flSoftwareQuatZ: number; + flSoftwareGyroDegreesPerSecondPitch: number; + flSoftwareGyroDegreesPerSecondYaw: number; + flSoftwareGyroDegreesPerSecondRoll: number; + flHardwareQuatW: number; + flHardwareQuatX: number; + flHardwareQuatY: number; + flHardwareQuatZ: number; + flHardwareGyroDegreesPerSecondPitch: number; + flHardwareGyroDegreesPerSecondYaw: number; + flHardwareGyroDegreesPerSecondRoll: number; + flGyroNoiseLength: number; + flGyroCalibrationProgress: number; + flGravityVectorX: number; + flGravityVectorY: number; + flGravityVectorZ: number; + flAccelerometerNoiseLength: number; + sBatteryLevel: number; + sPressurePadLeft: number; + sPressurePadRight: number; + sPressureBumperLeft: number; + sPressureBumperRight: number; + unHardwareUpdateInMicrosec: number; +} + +export interface GameKeyboardMessage { + m_bOpen: boolean; + nAppID: number; + m_dwPID: number; + m_dwOverlayPID: number; + m_hPipe: number; + m_eInputMode: number; + m_eLineInputMode: number; + m_pchDescription: string; + m_unCharMax: number; + m_pchExistingText: string; +} + +export interface TouchMenuMessage { + bHasVirtualMenus: boolean; + unControllerIndex: number; + appID: number; +} diff --git a/src/deck-components/steam-client/InstallFolder.ts b/src/deck-components/steam-client/InstallFolder.ts new file mode 100644 index 00000000..fe62ae40 --- /dev/null +++ b/src/deck-components/steam-client/InstallFolder.ts @@ -0,0 +1,168 @@ +import {Unregisterable} from "./index"; +import {AppError} from "./App"; + +/** + * Represents functions related to Steam Install Folders. + */ +export interface InstallFolder { + /** + * Adds a Steam Library folder to the Steam client. + * @param steamLibraryPath The path of the Steam Library folder to be added. + * @returns A Promise that resolves to the index of the added folder. + */ + AddInstallFolder(steamLibraryPath: string): Promise; + + /** + * Opens the file explorer to browse files in a specific Steam Library folder. + * @param folderIndex The index of the folder to be opened. + */ + BrowseFilesInFolder(folderIndex: number): void; + + /** + * Cancels the current move operation for moving game content. + */ + CancelMove(): void; + + /** + * Retrieves a list of installed Steam Library folders. + * @returns A Promise that resolves to an array of SteamInstallFolder objects. + */ + GetInstallFolders(): Promise; + + /** + * Retrieves a list of potential Steam Library folders that can be added. + * @returns A Promise that resolves to an array of PotentialInstallFolder objects. + */ + GetPotentialFolders(): Promise; + + /** + * Moves the installation folder for a specific app to another Steam Library folder. + * @param appId The ID of the application to be moved. + * @param folderIndex The index of the target Steam Library folder. + */ + MoveInstallFolderForApp(appId: number, folderIndex: number): void; + + /** + * Refreshes the list of installed Steam Library folders. + * @returns A Promise or response indicating the refresh operation. + */ + RefreshFolders(): any; + + /** + * Registers a callback function to be called when changes occur in Steam Install Folders. + * @param callback The callback function to be called. + * @returns An object that can be used to unregister the callback. + */ + RegisterForInstallFolderChanges(callback: (folderChange: FolderChange) => void): Unregisterable; + + /** + * Registers a callback function to be called when moving game content progresses. + * @param callback The callback function to be called. + * @returns An object that can be used to unregister the callback. + */ + RegisterForMoveContentProgress(callback: (moveContentProgress: MoveContentProgress) => void): Unregisterable; + + /** + * Registers a callback function to be called when repairing an install folder is finished. + * @param callback The callback function to be called. + * @returns An object that can be used to unregister the callback. + */ + RegisterForRepairFolderFinished(callback: (folderChange: FolderChange) => void): Unregisterable; + + /** + * Removes a Steam Library folder from the Steam client. + * @param folderIndex The index of the folder to be removed. + */ + RemoveInstallFolder(folderIndex: number): void; + + /** + * Repairs an installed Steam Library folder. + * @param folderIndex The index of the folder to be repaired. + */ + RepairInstallFolder(folderIndex: number): void; + + /** + * Sets a specific Steam Library folder as the default install folder. + * @param folderIndex The index of the folder to be set as default. + */ + SetDefaultInstallFolder(folderIndex: number): void; + + /** + * Sets a user-defined label for a specific Steam Library folder. + * @param folderIndex The index of the folder to be labeled. + * @param userLabel The label to be assigned to the folder. + */ + SetFolderLabel(folderIndex: number, userLabel: string): void; +} + +/** + * Represents information about an installation folder. + */ +export interface SteamInstallFolder extends PotentialInstallFolder { + /** Index of the folder. */ + nFolderIndex: number; + /** Used space in the folder. */ + strUsedSize: string; + /** Size of DLC storage used in the folder. */ + strDLCSize: string; + /** Size of workshop storage used in the folder. */ + strWorkshopSize: string; + /** Size of staged storage used in the folder. */ + strStagedSize: string; + /** Indicates if the folder is set as the default installation folder. */ + bIsDefaultFolder: boolean; + /** Indicates if the folder is currently mounted. */ + bIsMounted: boolean; + /** List of applications installed in the folder. */ + vecApps: AppInfo[]; +} + +export interface PotentialInstallFolder { + /** Path of the folder. */ + strFolderPath: string; + /** User label for the folder. */ + strUserLabel: string; + /** Name of the drive where the folder is located. */ + strDriveName: string; + /** Total capacity of the folder. */ + strCapacity: string; + /** Available free space in the folder. */ + strFreeSpace: string; + /** Indicates if the folder is on a fixed drive. */ + bIsFixed: boolean; +} + +/** + * Represents information about an installed application. + */ +export interface AppInfo { + /** ID of the application. */ + nAppID: number; + /** Name of the application. */ + strAppName: string; + /** Sorting information for the application. */ + strSortAs: string; + /** Last played time in Unix Epoch time format. */ + rtLastPlayed: number; + /** Size of used storage by the application. */ + strUsedSize: string; + /** Size of DLC storage used by the application. */ + strDLCSize: string; + /** Size of workshop storage used by the application. */ + strWorkshopSize: string; + /** Size of staged storage used by the application. */ + strStagedSize: string; +} + +export interface FolderChange { + folderIndex: number; +} + +export interface MoveContentProgress { + appid: number; + eError: AppError; + flProgress: number; + strBytesMoved: string; + strTotalBytesToMove: string; + nFilesMoved: number; +} diff --git a/src/deck-components/steam-client/Installs.ts b/src/deck-components/steam-client/Installs.ts new file mode 100644 index 00000000..db0c068c --- /dev/null +++ b/src/deck-components/steam-client/Installs.ts @@ -0,0 +1,131 @@ +import {Unregisterable} from "./index"; +import {AppError} from "./App"; + +/** + * Represents functions related to managing installs and installation wizards in Steam. + */ +export interface Installs { + /** + * Cancels the installation wizard if it is open. + */ + CancelInstall(): void; + + /** + * Continues and starts the installation if the wizard is still open. + */ + ContinueInstall(): void; + + /** + * Retrieves information from the last opened or currently opened installation wizard. + * @returns A Promise that resolves to the InstallInfo. + */ + GetInstallManagerInfo(): Promise; + + /** + * Opens the restore from backup installer wizard for a specific app. + * @param appBackupPath The backup path of the app. + */ + OpenInstallBackup(appBackupPath: string): void; + + /** + * Opens the installation wizard for specified app IDs. + * @param appIds An array of app IDs to install. + */ + OpenInstallWizard(appIds: number[]): void; + + /** + * Opens the uninstall wizard for specified app IDs. + * @param appIds An array of app IDs to uninstall. + * @param dontPrompt Whether to *not* prompt the user to uninstall. + */ + OpenUninstallWizard(appIds: number[], dontPrompt: boolean): void; + + RegisterForShowConfirmUninstall: Unregisterable; // Broken? doesn't seem to work + + /** + * Registers a callback function to be called when the "Failed Uninstall" dialog is shown. + * @param callback The callback function to be called when the dialog is shown. + * @returns An object that can be used to unregister the callback. + */ + RegisterForShowFailedUninstall(callback: (appId: number, reason: AppError) => void): Unregisterable; + + /** + * Registers a callback function to be called when the installation wizard is shown. + * @param callback The callback function to be called. + * @returns An object that can be used to unregister the callback. + */ + RegisterForShowInstallWizard(callback: (data: InstallInfo) => void): Unregisterable; + + RegisterForShowRegisterCDKey: any; + + /** + * Sets a list of app identifiers for downloads in the installation wizard. + * @param appIds An array of app IDs to set. + * @remarks The wizard will not reflect this change immediately, but changing another option will. + */ + SetAppList(appIds: number[]): void; + + /** + * Sets the options for creating shortcuts in the installation wizard. + * @param bDesktopShortcut Whether to create a desktop shortcut. + * @param bSystemMenuShortcut Whether to create a system menu shortcut. + * @remarks The wizard will not reflect this change immediately, but changing another option will. + */ + SetCreateShortcuts(bDesktopShortcut: boolean, bSystemMenuShortcut: boolean): void; + + /** + * Sets the install folder for the installation wizard using an install folder index. + * @param folderIndex The index of the install folder. + * @remarks The wizard will not reflect this change immediately, but changing another option will. + */ + SetInstallFolder(folderIndex: number): void; +} + +export interface InstallInfo { + rgAppIDs: InstallInfoApps[]; + eInstallState: EInstallManagerState; + nDiskSpaceRequired: number; + nDiskSpaceAvailable: number; + nCurrentDisk: number; + nTotalDisks: number; + bCanChangeInstallFolder: boolean; + /** + * Index of the install folder. -1 if not installed. + */ + iInstallFolder: number; + iUnmountedFolder: number; + currentAppID: number; + eAppError: AppError; + errorDetail: string; + bSystemMenuShortcut: boolean; + bDesktopShortcut: boolean; + bIsBackupInstall: boolean; + strPeerContentServer: string; + bPeerContentServerOnline: boolean; + bPeerContentServerAvailable: boolean; +} + +export interface InstallInfoApps { + nAppID: number; + lDiskSpaceRequiredBytes: number; +} + +export enum EInstallManagerState { + None = 0, + Setup = 1, + WaitLicense = 2, + FreeLicense = 3, + ShowCDKey = 4, + WaitAppInfo = 5, + ShowPassword = 6, + ShowConfig = 7, + ShowEULAs = 8, + CreateApps = 9, + ReadFromMedia = 10, + ShowChangeMedia = 11, + WaitLegacyCDKeys = 12, + ShowSignup = 13, + Complete = 14, + Failed = 15, + Canceled = 16, +} diff --git a/src/deck-components/steam-client/Messaging.ts b/src/deck-components/steam-client/Messaging.ts new file mode 100644 index 00000000..07f83f8b --- /dev/null +++ b/src/deck-components/steam-client/Messaging.ts @@ -0,0 +1,21 @@ +import {Unregisterable} from "./index"; + +export interface Messaging { + // section - "ContentManagement", "JumpList", "PostToLibrary" + // seems multipurpose + // callback arguments are the same as in PostMessage + RegisterForMessages( + section: string, + callback: (section: string, param1: string, message: string) => void, + ): Unregisterable; + + /* + function m(e) { + SteamClient.Messaging.PostMessage("LibraryCommands", "ShowFriendChatDialog", JSON.stringify({ + steamid: e.persona.m_steamid.ConvertTo64BitString() + })) + } + SteamClient.Messaging.PostMessage("FriendsUI", "AcceptedRemotePlayInvite", JSON.stringify({id: this.appID})) : SteamClient.Messaging.PostMessage("FriendsUI", "AcceptedGameInvite", JSON.stringify({id: this.appID})) + */ + PostMessage(section: string, param1: string, message: string): void; +} diff --git a/src/deck-components/steam-client/Music.ts b/src/deck-components/steam-client/Music.ts new file mode 100644 index 00000000..c8e53604 --- /dev/null +++ b/src/deck-components/steam-client/Music.ts @@ -0,0 +1,99 @@ +import {Unregisterable} from "./index"; + +/** + * Represents functions related to controlling music playback in the Steam client. + */ +export interface Music { + /** + * Decreases the music volume by 10%. + */ + DecreaseVolume(): void; + + /** + * Increases the music volume by 10%. + */ + IncreaseVolume(): void; + + /** + * Plays the next track in the music playlist. + */ + PlayNext(): void; + + /** + * Plays the previous track in the music playlist. + */ + PlayPrevious(): void; + + /** + * Registers a callback function to be called when music playback changes. + * @param callback The callback function to be called. + * @returns An object that can be used to unregister the callback. + */ + RegisterForMusicPlaybackChanges(callback: (param0: boolean | MusicTrack) => void): Unregisterable; + + /** + * Registers a callback function to be called when the music playback position changes. + * @param callback The callback function to be called. + * @returns An object that can be used to unregister the callback. + */ + RegisterForMusicPlaybackPosition(callback: (position: number) => void): Unregisterable; + + /** + * Sets the playback position of the music track. + * @param position The position to set in seconds. + */ + SetPlaybackPosition(position: number): void; + + /** + * Sets the repeat status for music playback. + * @param status The repeat status. + */ + SetPlayingRepeatStatus(status: MusicRepeatStatus): void; + + /** + * Sets the shuffle status for music playback. + * @param value True to enable shuffle, false to disable shuffle. + */ + SetPlayingShuffled(value: boolean): void; + + /** + * Sets the volume for music playback. + * @param volume The volume level to set. + * @remarks Ranges from 0 to 100. + */ + SetVolume(volume: number): void; + + /** + * Toggles the mute state of the music volume. + */ + ToggleMuteVolume(): void; + + /** + * Toggles between play and pause for music playback. + */ + TogglePlayPause(): void; +} + +export interface MusicTrack { + uSoundtrackAppId: number; + ePlaybackStatus: MusicPlaybackStatus; + eRepeatStatus: MusicRepeatStatus; + bShuffle: boolean; + nVolume: number; + nActiveTrack: number; + nLengthInMsec: number; +} + +export enum MusicPlaybackStatus { + Undefined = 0, + Playing = 1, + Paused = 2, + Idle = 3, +} + +export enum MusicRepeatStatus { + None = 0, + All = 1, + Once = 2, + Max = 3, +} diff --git a/src/deck-components/steam-client/Notifications.ts b/src/deck-components/steam-client/Notifications.ts new file mode 100644 index 00000000..6d05800a --- /dev/null +++ b/src/deck-components/steam-client/Notifications.ts @@ -0,0 +1,333 @@ +import {JsPbMessage, Unregisterable} from "./index"; + +/** + * Everything is taken from here: + * https://github.com/SteamDatabase/SteamTracking/blob/master/Protobufs/steammessages_clientnotificationtypes.proto + */ +export interface Notifications { + /** + * If `data` is deserialized, returns one of the following here: {@link Notifications} + * @returns An object that can be used to unregister the callback. + */ + RegisterForNotifications( + callback: (notificationIndex: number, type: EClientNotificationType, data: ArrayBuffer) => void, + ): Unregisterable; +} + +export enum EClientNotificationType { + Invalid, + DownloadComplete, + FriendInvite, + FriendInGame, + FriendOnline, + Achievement, + LowBattery, + SystemUpdate, + FriendMessage, + GroupChatMessage, + FriendInviteRollup, + FamilySharingDeviceAuthorizationChanged, + FamilySharingStopPlaying, + FamilySharingLibraryAvailable, + Screenshot, + CloudSyncFailure, + CloudSyncConflict, + IncomingVoiceChat, + ClaimSteamDeckRewards, + GiftReceived, + ItemAnnouncement, + HardwareSurvey, + LowDiskSpace, + BatteryTemperature, + DockUnsupportedFirmware, + PeerContentUpload, + CannotReadControllerGuideButton, + Comment, + Wishlist, + TradeOffer, + AsyncGame, + General, + HelpRequest, + OverlaySplashScreen, + BroadcastAvailableToWatch, + TimedTrialRemaining, + LoginRefresh, + MajorSale, + TimerExpired, + ModeratorMsg, + SteamInputActionSetChanged, + RemoteClientConnection, + RemoteClientStartStream, + StreamingClientConnection, + FamilyInvite, + PlaytimeWarning, + FamilyPurchaseRequest, + FamilyPurchaseRequestResponse, + ParentalFeatureRequest, + ParentalPlaytimeRequest, + GameRecordingError, + ParentalFeatureResponse, + ParentalPlaytimeResponse, + RequestedGameAdded, + ClipDownloaded, + GameRecordingStart, + GameRecordingStop, + GameRecordingUserMarkerAdded, + GameRecordingInstantClip, +} + +export enum ESystemUpdateNotificationType { + Invalid, + Available, + NeedsRestart, +} + +export enum EGameRecordingErrorType { + General = 1, + LowDiskSpace, +} + +export interface ClientNotificationGroupChatMessage extends JsPbMessage { + tag(): string; + + /** A Steam64 ID. */ + steamid_sender(): string; + + chat_group_id(): string; + + chat_id(): string; + + title(): string; + + body(): string; + + rawbody(): string; + + icon(): string; + + notificationid(): number; +} + +export interface ClientNotificationFriendMessage extends JsPbMessage { + body(): string; + + icon(): string; + + notificationid(): number; + + response_steamurl(): string; + + /** A Steam64 ID. */ + steamid(): string; + + tag(): string; + + title(): string; +} + +export interface ClientNotificationCloudSyncFailure extends JsPbMessage { + appid(): number; +} + +export interface ClientNotificationCloudSyncConflict extends JsPbMessage { + appid(): number; +} + +export interface ClientNotificationScreenshot extends JsPbMessage { + screenshot_handle(): string; + description(): string; + local_url(): string; +} + +export interface ClientNotificationDownloadCompleted extends JsPbMessage { + appid(): number; + dlc_appid(): number; +} + +export interface ClientNotificationFriendInvite extends JsPbMessage { + steamid(): number; +} + +export interface ClientNotificationFriendInviteRollup extends JsPbMessage { + new_invite_count(): number; +} + +export interface ClientNotificationFriendInGame extends JsPbMessage { + steamid(): number; + game_name(): string; +} + +export interface ClientNotificationFriendOnline extends JsPbMessage { + steamid(): number; +} + +export interface ClientNotificationAchievement extends JsPbMessage { + achievement_id(): string; + appid(): number; + name(): string; + description(): string; + image_url(): string; + achieved(): boolean; + rtime_unlocked(): number; + min_progress(): number; + current_progress(): number; + max_progress(): number; + global_achieved_pct(): number; +} + +export interface ClientNotificationLowBattery extends JsPbMessage { + pct_remaining(): number; +} + +export interface ClientNotificationSystemUpdate extends JsPbMessage { + type(): ESystemUpdateNotificationType; +} + +export interface ClientNotificationFriendMessage extends JsPbMessage { + tag(): string; + steamid(): string; + title(): string; + body(): string; + icon(): string; + notificationid(): number; + response_steamurl(): string; +} + +export interface ClientNotificationGroupChatMessage extends JsPbMessage { + tag(): string; + steamid_sender(): string; + chat_group_id(): string; + chat_id(): string; + title(): string; + body(): string; + rawbody(): string; + icon(): string; + notificationid(): number; +} + +export interface ClientNotificationFamilySharingDeviceAuthorizationChanged extends JsPbMessage { + accountid_owner(): number; + authorized(): boolean; +} + +export interface ClientNotificationFamilySharingStopPlaying extends JsPbMessage { + accountid_owner(): number; + seconds_remaining(): number; + appid(): number; +} + +export interface ClientNotificationFamilySharingLibraryAvailable extends JsPbMessage { + accountid_owner(): number; +} + +export interface ClientNotificationIncomingVoiceChat extends JsPbMessage { + steamid(): number; +} + +export interface ClientNotificationClaimSteamDeckRewards extends JsPbMessage { +} + +export interface ClientNotificationGiftReceived extends JsPbMessage { + sender_name(): string; +} + +export interface ClientNotificationItemAnnouncement extends JsPbMessage { + new_item_count(): number; + new_backpack_items(): boolean; +} + +export interface ClientNotificationHardwareSurveyPending extends JsPbMessage { +} + +export interface ClientNotificationLowDiskSpace extends JsPbMessage { + folder_index(): number; +} + +export interface ClientNotificationBatteryTemperature extends JsPbMessage { + temperature(): number; + notification_type(): string; +} + +export interface ClientNotificationDockUnsupportedFirmware extends JsPbMessage { +} + +export interface ClientNotificationPeerContentUpload extends JsPbMessage { + appid(): number; + peer_name(): string; +} + +export interface ClientNotificationCannotReadControllerGuideButton extends JsPbMessage { + controller_index(): number; +} + +export interface ClientNotificationOverlaySplashScreen extends JsPbMessage { +} + +export interface ClientNotificationBroadcastAvailableToWatch extends JsPbMessage { + broadcast_permission(): number; +} + +export interface ClientNotificationTimedTrialRemaining extends JsPbMessage { + appid(): number; + icon(): string; + offline(): boolean; + allowed_seconds(): number; + played_seconds(): number; +} + +export interface ClientNotificationLoginRefresh extends JsPbMessage { +} + +export interface ClientNotificationTimerExpired extends JsPbMessage { +} + +export interface ClientNotificationSteamInputActionSetChanged extends JsPbMessage { + controller_index(): number; + action_set_name(): string; +} + +export interface ClientNotificationRemoteClientConnection extends JsPbMessage { + machine(): string; + connected(): boolean; +} + +export interface ClientNotificationRemoteClientStartStream extends JsPbMessage { + machine(): string; + game_name(): string; +} + +export interface ClientNotificationStreamingClientConnection extends JsPbMessage { + hostname(): string; + machine(): string; + connected(): boolean; +} + +export interface ClientNotificationPlaytimeWarning extends JsPbMessage { + type(): string; + playtime_remaining(): number; +} + +export interface ClientNotificationGameRecordingError extends JsPbMessage { + game_id(): number; + error_type(): EGameRecordingErrorType; +} + +export interface ClientNotificationGameRecordingStart extends JsPbMessage { + game_id(): number; +} + +export interface ClientNotificationGameRecordingStop extends JsPbMessage { + game_id(): number; + clip_id(): string; + duration_secs(): number; +} + +export interface ClientNotificationGameRecordingUserMarkerAdded extends JsPbMessage { + game_id(): number; +} + +export interface CClientNotificationGameRecordingInstantClip extends JsPbMessage { + game_id(): number; + clip_id(): string; + duration_secs(): number; +} diff --git a/src/deck-components/steam-client/OpenVR.ts b/src/deck-components/steam-client/OpenVR.ts new file mode 100644 index 00000000..25ed556a --- /dev/null +++ b/src/deck-components/steam-client/OpenVR.ts @@ -0,0 +1,122 @@ +import {Unregisterable} from "./index"; + + +export interface OpenVR { + Device: VRDevice; + DeviceProperties: DeviceProperties; + + /** + * @throws OperationResponse if mutual capabilities haven't been loaded. + */ + GetMutualCapabilities(): Promise; + + GetWebSecret(): Promise; + + InstallVR(): any; + + Keyboard: Keyboard; + PathProperties: PathProperties; + + QuitAllVR(): any; + + RegisterForButtonPress: Unregisterable; + + RegisterForHMDActivityLevelChanged(callback: (m_eHMDActivityLevel: EHMDActivityLevel) => void): Unregisterable; + + RegisterForInstallDialog: Unregisterable; + + RegisterForStartupErrors(callback: (clientError: any, initError: any, initErrorString: string) => void): Unregisterable; + + RegisterForVRHardwareDetected(callback: (m_bHMDPresent: any, m_bHMDHardwareDetected: any, m_strHMDName: any) => void): Unregisterable; + + RegisterForVRModeChange(callback: (m_bIsVRRunning: boolean) => void): Unregisterable; + + RegisterForVRSceneAppChange(callback: (param0: number) => void): Unregisterable; + + SetOverlayInteractionAffordance: any; + + StartVR: any; + TriggerOverlayHapticEffect: any; + VRNotifications: VRNotifications; + VROverlay: VROverlay; +} + +export interface VRDevice { + BIsConnected: any; + RegisterForDeviceConnectivityChange: Unregisterable; + + RegisterForVRDeviceSeenRecently(callback: (m_bVRDeviceSeenRecently: any) => void): Unregisterable; +} + +export interface DeviceProperties { + GetBoolDeviceProperty: any; + GetDoubleDeviceProperty: any; + GetFloatDeviceProperty: any; + GetInt32DeviceProperty: any; + GetStringDeviceProperty: any; + RegisterForDevicePropertyChange: Unregisterable; +} + +export interface Keyboard { + Hide(): any; + + /** + * {@link EKeyboardFlags} could be useful here + */ + RegisterForStatus(callback: (m_bIsKeyboardOpen: boolean, m_eKeyboardFlags: number, m_sInitialKeyboardText: string) => void): Unregisterable; + + SendDone(): any; + + SendText(key: string): any; //??? + Show(): any; +} + +export interface PathProperties { + GetBoolPathProperty: any; + GetDoublePathProperty: any; + GetFloatPathProperty: any; + GetInt32PathProperty: any; + GetStringPathProperty: any; + RegisterForPathPropertyChange: any; + SetBoolPathProperty: any; + SetDoublePathProperty: any; + SetFloatPathProperty: any; + SetInt32PathProperty: any; + SetStringPathProperty: any; +} + +export interface VRNotifications { + HideCustomNotification: any; + RegisterForNotificationEvent: Unregisterable; + ShowCustomNotification: any; +} + +export interface VROverlay { + HideDashboard: any; + + IsDashboardVisible(): Promise; + + RegisterForButtonPress: Unregisterable; + RegisterForCursorMovement: Unregisterable; + RegisterForThumbnailChanged: Unregisterable; + RegisterForVisibilityChanged: Unregisterable; + ShowDashboard: any; + + SwitchToDashboardOverlay(param0: string): void; +} + +export enum EHMDActivityLevel { + Unknown = -1, + Idle, + UserInteraction, + UserInteraction_Timeout, + Standby, + Idle_Timeout, +} + +export enum EKeyboardFlags { + Minimal = 1 << 0, + Modal = 1 << 1, + ShowArrowKeys = 1 << 2, + HideDoneKey = 1 << 3, +} diff --git a/src/deck-components/steam-client/Overlay.ts b/src/deck-components/steam-client/Overlay.ts new file mode 100644 index 00000000..867557b8 --- /dev/null +++ b/src/deck-components/steam-client/Overlay.ts @@ -0,0 +1,123 @@ +import {EBrowserType, UIMode, Unregisterable} from "./index"; + +export interface Overlay { + /** + * Destroys the gamepad UI desktop configurator window if open. + */ + DestroyGamePadUIDesktopConfiguratorWindow(): void; + + GetOverlayBrowserInfo(): Promise; + + HandleGameWebCallback(url: string): any; + + HandleProtocolForOverlayBrowser(appId: number, protocol: string): any; + + RegisterForActivateOverlayRequests: Unregisterable; + + /** + * Registers a callback function to be called when a microtransaction authorization is requested. + * @param callback The callback function to be called. + * @returns An object that can be used to unregister the callback. + */ + RegisterForMicroTxnAuth( + callback: (appId: number, microTxnId: string, realm: SteamRealm, microTxnUrl: string) => void, + ): Unregisterable; + + /** + * Registers a callback function to be called when a microtransaction authorization is dismissed by the user in Steam's authorization page. + * @param callback The callback function to be called. + * @returns An object that can be used to unregister the callback. + */ + RegisterForMicroTxnAuthDismiss(callback: (appId: number, microTxnId: string) => void): Unregisterable; + + RegisterForNotificationPositionChanged( + callback: (appId: any, position: NotificationPosition, horizontalInset: number, verticalInset: number) => void, + ): Unregisterable; + + /** + * Registers a callback function to be called when an overlay is activated or closed. + * @param callback The callback function to be called. + * @returns An object that can be used to unregister the callback. + */ + RegisterForOverlayActivated( + callback: (overlayProcessPid: number, appId: number, active: boolean, param3: boolean) => void, + ): Unregisterable; + + /** + * Registers a callback function to be called when the overlay browser protocols change. + * @param callback The callback function to be called. + * @returns An object that can be used to unregister the callback. + */ + RegisterForOverlayBrowserProtocols( + callback: (browseProtocols: OverlayBrowserProtocols) => void, + ): Unregisterable; + + /** + * Registers **the** callback function to be called when the overlay browser information changes. + * @param callback The callback function to be called when the overlay browser information changes. + * @returns An object that can be used to unregister the callback. + * @remarks Do Not Use, this will break the overlay unless you know what you are doing. + */ + RegisterOverlayBrowserInfoChanged(callback: () => void): Unregisterable; + + SetOverlayState(appId: number, uiComposition: UIComposition): any; +} + +export enum NotificationPosition { + TopLeft = 0, + TopRight = 1, + BottomLeft = 2, + BottomRight = 3, +} + +export interface OverlayBrowserInfo { + appID: number; + eBrowserType: EBrowserType; + eUIMode: UIMode; + flDisplayScale?: number; + gameID: string; + nBrowserID: number; + nScreenHeight: number; + nScreenWidth: number; + /** + * The PID of the overlay process. + */ + unPID: number; +} + +export interface OverlayBrowserProtocols { + unAppID: number; + strScheme: string; + bAdded: boolean; +} + +export enum SteamRealm { + Unknown = 0, + Global = 1, + China = 2, +} + +/** + * Controls how Gamescope renders the GamepadUI window when a game is running. + */ +export enum UIComposition { + /** Steam is not rendered on the screen. */ + Hidden = 0, + /** + * Transparent divs will allow pixels from the app behind Steam to penetrate. + * Input goes to **the app**. + */ + Notification = 1, + /** + * Transparent divs will allow pixels from the app behind Steam to penetrate. + * Input goes to **Steam**. + */ + Overlay = 2, + /** Take all of the pixels on the screen, nothing "behind" Steam is shown. */ + Opaque = 3, + /** + * Special composition mode that matches Overlay, but forwards synthetic keyboard + * events to the Gamescope foreground app (game) instead of Steam. + */ + OverlayKeyboard = 4, +} diff --git a/src/deck-components/steam-client/Parental.ts b/src/deck-components/steam-client/Parental.ts new file mode 100644 index 00000000..4e061b68 --- /dev/null +++ b/src/deck-components/steam-client/Parental.ts @@ -0,0 +1,78 @@ +import {Result, Unregisterable} from "./index"; + +/** + * Interface for managing parental control settings. + */ +export interface Parental { + /** + * Locks the parental control settings. + */ + LockParentalLock(): void; + + /** + * Registers a callback function to be invoked when parental settings change. + * @param callback The callback function to be invoked when parental settings change. + * @returns An object that can be used to unregister the callback. + */ + RegisterForParentalSettingsChanges(callback: (parentalSettings: ParentalSettings) => void): Unregisterable; + + /** + * Unlocks the parental lock with the provided PIN. + * @param pin The 4-digit PIN to unlock the parental lock. + * @param param1 Additional parameter. // Todo: Unknown usage. + * @returns A Promise that resolves to a number representing the result of the unlock operation. + */ + UnlockParentalLock(pin: string, param1: boolean): Promise; +} + +/** + * Represents the parental settings and restrictions. + */ +export interface ParentalSettings { + /** + * Indicates whether parental settings are enabled. + */ + enabled: boolean; + /** + * Indicates whether parental settings are locked. + */ + locked: boolean; + /** + * Bitmask representing enabled features. + * - Bit 0: Unknown (@todo Please provide more details if known) + * - Bit 1: Online content & features - Steam Store + * - Bit 2: Online content & features - Community-generated content + * - Bit 3: Online content & features - My online profile, screenshots, and achievements + * - Bit 4: Online content & features - Friends, chat, and groups + * - Bit 5-11: Unknown (@todo Please provide more details if known) + * - Bit 12: Library content - 0: Only games I choose, 1: All games + */ + features: number; + /** + * Indicates whether all apps are allowed. + */ + allowallapps: boolean; + /** + * Base list (type not specified but an object). + * @todo Determine the type of this property. + */ + baselist: any | undefined; + /** + * Custom list of allowed applications. + */ + customlist: AppList; + /** + * Email for recovery (if applicable). + */ + recoveryemail: string | undefined; +} + +/** + * Represents a list of applications with their IDs. + */ +interface AppList { + /** + * Key-value pairs where the key is the `appId` (e.g., "App_123456") and the value indicates whether the appId is allowed during parental lock. + */ + [appId: string]: number; +} diff --git a/src/deck-components/steam-client/RemotePlay.ts b/src/deck-components/steam-client/RemotePlay.ts new file mode 100644 index 00000000..3751bcc2 --- /dev/null +++ b/src/deck-components/steam-client/RemotePlay.ts @@ -0,0 +1,165 @@ +import {ControllerType} from "./Input"; +import {Unregisterable} from "./index"; + +export interface RemotePlay { + BCanAcceptInviteForGame: any; + BCanCreateInviteForGame: any; + + BCanHostIsolatedGameAudio(): Promise; + + BEnabled(): Promise; + + BRemotePlayTogetherGuestOnPhoneOrTablet(steam64Id: string, guestId: number): Promise; + + BRemotePlayTogetherGuestSupported(): Promise; + + CancelInviteAndSession(steam64Id: string): any; + + CancelInviteAndSessionWithGuestID(steam64Id: string, guestId: number): any; + + CloseGroup(): Promise; + + CreateGroup: any; + + CreateInviteAndSession(steam64Id: string, param1: any): any; + + CreateInviteAndSessionWithGuestID(steam64Id: string, guestId: number, param2: any): any; + + GetClientStreamingBitrate(): Promise; //todo: -1 not streaming?? + GetClientStreamingQuality(): Promise; //todo: -1 not streaming?? + GetControllerType(param0: number): Promise; // todo: param0 with value 0 is host controller type - param0 is likely an index of clients or guestId? + GetGameSystemVolume(): Promise; + + GetPerUserInputSettings(steam64Id: string): any; + + GetPerUserInputSettingsWithGuestID(steam64Id: string, guestId: number): any; + + IdentifyController(nControllerIndex: number): any; + + InstallAudioDriver: any; + InstallInputDriver: any; + MoveControllerToSlot: any; + RegisterForAdditionalParentalBlocks: Unregisterable; + RegisterForAudioDriverPrompt: Unregisterable; + RegisterForBitrateOverride: Unregisterable; + RegisterForControllerIndexSet: Unregisterable; + + RegisterForDevicesChanges(callback: (devicesChange: RemotePlayDevice[]) => void): Unregisterable; + + RegisterForGroupCreated: Unregisterable; + RegisterForGroupDisbanded: Unregisterable; + RegisterForInputDriverPrompt: Unregisterable; + RegisterForInputDriverRestartNotice: Unregisterable; + + RegisterForInputUsed( + callback: (steam64Id: string, type: ClientUsedInputType, guestId: number) => void, + ): Unregisterable; // only fires on host + + RegisterForInviteResult: Unregisterable; + + RegisterForNetworkUtilizationUpdate( + callback: (steam64Id: string, guestId: number, networkUtilization: number, networkDuration: number) => void, + ): Unregisterable; // only fires on host + + RegisterForPlaceholderStateChanged(callback: (isShowingPlaceholder: boolean) => void): Unregisterable; + + RegisterForPlayerInputSettingsChanged: Unregisterable; + + RegisterForQualityOverride(callback: (hostStreamingQualityOverride: number) => void): Unregisterable; + + RegisterForRemoteClientLaunchFailed: Unregisterable; + + RegisterForRemoteClientStarted(callback: (steam64Id: string, appId: number) => void): Unregisterable; // only fires on client + + RegisterForRemoteClientStopped(callback: (steam64Id: string, appId: number) => void): Unregisterable; // only fires on client + + RegisterForSessionStarted(callback: (steam64Id: any, gameId: any, guestId: any) => void): Unregisterable; + + RegisterForSessionStopped(callback: (steam64Id: any, guestId: any) => void): Unregisterable; + + RegisterForSettingsChanges(callback: (remotePlaySettings: RemotePlaySettings) => void): Unregisterable; + + SetClientStreamingBitrate(bitrate: number): void; + + SetClientStreamingQuality(quality: number): void; + + SetGameSystemVolume(volume: number): void; + + SetPerUserControllerInputEnabled(steam64Id: string, enabled: boolean): any; + + SetPerUserControllerInputEnabledWithGuestID(steam64Id: string, guestId: number, enabled: boolean): any; + + SetPerUserKeyboardInputEnabled(steam64Id: string, enabled: boolean): any; + + SetPerUserKeyboardInputEnabledWithGuestID(steam64Id: string, guestId: number, enabled: boolean): any; + + SetPerUserMouseInputEnabled(steam64Id: string, enabled: boolean): any; + + SetPerUserMouseInputEnabledWithGuestID(steam64Id: string, guestId: number, enabled: boolean): any; + + SetRemoteDeviceAuthorized: any; + + SetRemoteDevicePIN(pin: number): void; + + SetRemotePlayEnabled(enabled: boolean): void; + + SetStreamingClientConfig: any; + SetStreamingClientConfigEnabled: any; + + SetStreamingDesktopToRemotePlayTogetherEnabled(enabled: boolean): any; + + SetStreamingP2PScope: any; + SetStreamingServerConfig: any; + SetStreamingServerConfigEnabled: any; + + StopStreamingClient(): void; + + StopStreamingSession: any; + StopStreamingSessionAndSuspendDevice: any; + + UnlockH264(): any; + + UnpairRemoteDevices(): void; // unpairs all devices +} + +export enum ClientUsedInputType { + Keyboard = 0, + Mouse = 1, + Controller = 2, + Max = 3, +} + +export interface RemotePlayDevice { + clientName: string; + status: string; // "Connected", "Paired", + formFactor: number; + unStreamingSessionID: number; + bCanSuspend: boolean; +} + +export interface RemotePlaySettings { + bRemotePlaySupported: boolean; + bRemotePlayEnabled: boolean; + eRemotePlayP2PScope: StreamP2PScope; + bRemotePlayServerConfigAvailable: boolean; + bRemotePlayServerConfigEnabled: boolean; + RemotePlayServerConfig: any; // todo: document {} + bRemotePlayClientConfigEnabled: boolean; + unStreamingSessionID: number; + strStreamingClientName: string; + RemotePlayClientConfig: any; // todo: document {} + nDefaultAudioChannels: number; + bDefaultEncodeNVIDIA: boolean; + bDefaultEncodeAMD: boolean; + bDefaultEncodeIntel: boolean; + nAutomaticResolutionX: number; + nAutomaticResolutionY: number; +} + +export enum StreamP2PScope { + Automatic = 0, + Disabled = 1, + OnlyMe = 2, + Friends = 3, + Everyone = 4, +} diff --git a/src/deck-components/steam-client/Screenshots.ts b/src/deck-components/steam-client/Screenshots.ts new file mode 100644 index 00000000..170f7a44 --- /dev/null +++ b/src/deck-components/steam-client/Screenshots.ts @@ -0,0 +1,141 @@ +/** + * Interface for managing screenshots. + */ +export interface Screenshots { + /** + * Deletes a local screenshot. + * @param appId The ID of the application. + * @param screenshotIndex The index of the local screenshot. + * @returns A Promise that resolves to a boolean value indicating whether the deletion was successful. + */ + DeleteLocalScreenshot(appId: string, screenshotIndex: number): Promise; + + DeleteLocalScreenshots(screenshots: ScreenshotToDelete[]): Promise; + + /** + * Retrieves all local screenshots for all applications. + * @returns A Promise that resolves to an array of Screenshot objects. + */ + GetAllAppsLocalScreenshots(): Promise; + + /** + * Retrieves the count of all local screenshots for all applications. + * @returns A Promise that resolves to the count of local screenshots. + */ + GetAllAppsLocalScreenshotsCount(): Promise; + + /** + * Retrieves a range of local screenshots for all applications. + * @param start The starting index of the screenshot range. + * @param end The ending index of the screenshot range. + * @returns A Promise that resolves to an array of Screenshot objects within the specified range. + */ + GetAllAppsLocalScreenshotsRange(start: number, end: number): Promise; + + /** + * Retrieves all local screenshots. + * @returns A Promise that resolves to an array of Screenshot objects. + */ + GetAllLocalScreenshots(): Promise; + + /** + * Retrieves the game associated with a specific local screenshot index. + * @param screenshotIndex The index of the local screenshot. + * @returns A Promise that resolves to the ID of the game associated with the screenshot. + */ + GetGameWithLocalScreenshots(screenshotIndex: number): Promise; + + /** + * Retrieves the last taken local screenshot. + * @returns A Promise that resolves to the last taken local screenshot. + */ + GetLastScreenshotTaken(): Promise; + + /** + * Retrieves a specific local screenshot for an application. + * @param appId The ID of the application. + * @param screenshotIndex The index of the local screenshot. + * @returns A Promise that resolves to the requested local screenshot. + */ + GetLocalScreenshotByHandle(appId: string, screenshotIndex: number): Promise; + + /** + * Retrieves the count of local screenshots for a specific application. + * @param appId The ID of the application. + * @returns A Promise that resolves to the count of local screenshots for the application. + */ + GetLocalScreenshotCount(appId: number): Promise; + + /** + * Retrieves the number of games with local screenshots. + * @returns A Promise that resolves to the number of games with local screenshots. + */ + GetNumGamesWithLocalScreenshots(): Promise; + + /** + * Gets total screenshot usage in the specified library folder. + * @param path Library folder path. + * @returns A Promise that resolves to the number of taken space in bytes. + */ + GetTotalDiskSpaceUsage(path: string): Promise; + + /** + * Opens a local screenshot in the system image viewer. + * If the screenshot index is invalid, this function opens the screenshots directory for the specified application ID. + * @param appId The ID of the application. + * @param screenshotIndex The index of the local screenshot. + */ + ShowScreenshotInSystemViewer(appId: string, screenshotIndex: number): void; + + /** + * Opens the folder containing local screenshots for a specific application. + * @param appId The ID of the application. + */ + ShowScreenshotsOnDisk(appId: string): void; + + /** + * Uploads a local screenshot. + * @param appId The ID of the application. + * @param localScreenshot_hHandle The handle of the local screenshot. + * @param filePrivacyState The privacy state of the screenshot file. + * @returns A Promise that resolves to a boolean value indicating whether the upload was successful. + */ + UploadLocalScreenshot( + appId: string, + localScreenshot_hHandle: number, + filePrivacyState: FilePrivacyState, + ): Promise; +} + +export interface Screenshot { + nAppID: number; + strGameID: string; + hHandle: number; + nWidth: number; + nHeight: number; + nCreated: number; // timestamp + ePrivacy: FilePrivacyState; + strCaption: ''; + bSpoilers: boolean; + strUrl: string; + bUploaded: boolean; + ugcHandle: string; +} + +export interface ScreenshotToDelete { + gameID: string; + rgHandles: number[]; +} + +export interface ScreenshotDeletionResponse { + bSuccess: boolean; + rgFailedRequestIndices: number[]; +} + +export enum FilePrivacyState { + Invalid = -1, + Private = 2, + FriendsOnly = 4, + Public = 8, + Unlisted = 16, +} diff --git a/src/deck-components/steam-client/ServerBrowser.ts b/src/deck-components/steam-client/ServerBrowser.ts new file mode 100644 index 00000000..5c7386d0 --- /dev/null +++ b/src/deck-components/steam-client/ServerBrowser.ts @@ -0,0 +1,356 @@ +import {OperationResponse, Unregisterable} from "./index"; + +/** + * Represents functionality for the server browser. + */ +export interface ServerBrowser { + /** + * Adds a favorite server. + * @param server The server to add. + * @returns A Promise that resolves to an empty string if successful, `Invalid/missing IPv4?` if failed. + */ + AddFavoriteServer(server: ServerBrowserServerFull): Promise; + + /** + * Adds a favorite server by IP. + * @param ip The IP to add to favorite servers. + * @returns A Promise that resolves to an empty string if successful, localization string if failed. + */ + AddFavoriteServersByIP(ip: string): Promise; + + CancelServerQuery(dialogId: number, queryServer: number): void; + + /** + * Connects to a server from a given dialog. + * @param dialogId The dialog ID to use. + * @param password Server password, empty if none. + * @returns A Promise that resolves to a connection status. + */ + ConnectToServer(dialogId: number, password: string): Promise; + + /** + * Creates a server info dialog, on which your friend is playing on. + * @param pid 0 + * @param steamId A Steam64 ID of a friend. + */ + CreateFriendGameInfoDialog(pid: number, steamId: string): void; + + /** + * Creates a server info dialog. + * @param ip The IP to create a dialog for. + * @param port The IP's port. + * @param queryPort + * @returns A Promise that resolves to the current dialog ID. + */ + CreateServerGameInfoDialog(ip: string, port: number, queryPort: number): Promise; + + /** + * Retrieves the server list. + * @param appId The game ID, 0 for every game. + * @param queryType The tab to use. + * @param filters Server filters. + * @param serverCallback What to do with the found server? + * @param requestCompletedCallback The callback function to be called when the request is completed. + * @returns A Promise that resolves to the current server list request ID. + * @throws Throws if the query type is unknown. + * @throws Throws if the filter list isn't key/value pairs, i.e. of an even length. + * @remarks Stops at 10000 if there are more servers to be found. + * @example + * Filter examples, may be combined: + * ``` + * [ 'gamedir', 'cstrike' ] // Doesn't work? + * [ 'hasplayers', '1' ] // Only works with "1"? + * [ 'notfull', '1' ] // Doesn't work? + * [ 'map', 'cs_office' ] // Has to be an exact match! + * ``` + */ + + /* + The enum in question: + + (t = + 'lan' == this.id + ? this.all_servers.length > 0 + ? '#ServerBrowser_NoServersMatch' + : '#ServerBrowser_NoLanServers' + : 'internet' == this.id + ? this.all_servers.length > 0 + ? '#ServerBrowser_NoInternetGamesMatch' + : e == l.zS.k_EServerFailedToRespond + ? '#ServerBrowser_MasterServerNotResponsive' + : e == l.zS.k_ENoServersListedOnMasterServer + ? '#ServerBrowser_MasterServerHasNoServersListed' + : '#ServerBrowser_NoInternetGamesResponded' + : 'favorites' == this.id + ? this.all_servers.length > 0 + ? '#ServerBrowser_NoServersMatch' + : '#ServerBrowser_NoFavoriteServers' + : 'history' == this.id + ? this.all_servers.length > 0 + ? '#ServerBrowser_NoHistoryServersMatch' + : '#ServerBrowser_NoServersPlayed' + : 'friends' == this.id + ? this.all_servers.length > 0 + ? '#ServerBrowser_NoServersMatch' + : '#ServerBrowser_NoFriendsServers' + : 'BUGBUG'), + */ + CreateServerListRequest( + appId: number, + queryType: ServerBrowserTab, + filters: string[], + serverCallback: (server: ServerBrowserServerFull) => void, + requestCompletedCallback: (response: number) => void, + ): Promise; + + /** + * Destroys the game info dialog functions (but not the window). + * @param dialogId The dialog ID to use. + * @remarks ServerBrowser.CancelServerQuery may throw if it tries to ping the server. + */ + DestroyGameInfoDialog(dialogId: number): void; + + /** + * Stops retrieving the server list. + * @param activeServerListRequestId The active server request ID to use. + */ + DestroyServerListRequest(activeServerListRequestId: number): void; + + /** + * Gets a list of games that support the server browser feature. + * @returns A Promise that resolves to a list of games. + */ + GetMultiplayerGames(): Promise; + + /** + * Gets the server browser preferences. + * @returns A Promise that resolves to server browser preferences. + */ + GetServerListPreferences(): Promise; + + /** + * Pings the server of a specified dialog ID. + * @param dialogId The dialog ID to use. + */ + PingServer(dialogId: number): Promise; + + /** + * Registers a callback function to be called when a server gets added to favorite servers. + * @param callback The callback function to be called. + * @returns An object that can be used to unregister the callback. + */ + RegisterForFavorites(callback: (list: ServerBrowserFavoritesAndHistory) => void): Unregisterable; + + /** + * Registers a callback function to be called when idk + * @param dialogId The dialog ID to use. + * @param callback The callback function to be called. + * @returns An object that can be used to unregister the callback. + */ + RegisterForFriendGamePlayed( + dialogId: number, + callback: (server: ServerBrowserFriendServer) => void, + ): Unregisterable; + + /** + * Registers a callback function to be called when a server info dialog opens. + * @param callback The callback function to be called. + * @returns An object that can be used to unregister the callback. + */ + RegisterForGameInfoDialogs(callback: (dialogs: ServerBrowserDialog[]) => void): Unregisterable; + + /** + * Registers a callback function to be called when player details get requested. + * @param dialogId The dialog ID to use. + * @param callback The callback function to be called. + * @returns An object that can be used to unregister the callback. + */ + RegisterForPlayerDetails( + dialogId: number, + callback: (player: ServerBrowserPlayer | ServerBrowserPlayerRefreshStatus) => void, + ): Unregisterable; + + /** + * Registers a callback function to be called when a server gets pinged. + * @param dialogId The dialog ID to use. + * @param callback The callback function to be called. + * @returns An object that can be used to unregister the callback. + */ + RegisterForServerInfo(dialogId: number, callback: (server: ServerBrowserServerFull) => void): Unregisterable; + + /** + * Removes a server from favorite servers. + * @param server The server to remove. + */ + RemoveFavoriteServer(server: ServerBrowserServer): void; + + /** + * Removes a server from history of played servers. + * @param server The server to remove. + */ + RemoveHistoryServer(server: ServerBrowserServer): void; + + /** + * Requests player details for a specific dialog. + * @param dialogId The dialog ID to use. + */ + RequestPlayerDetails(dialogId: number): Promise; + + /** + * Sets the server browser preferences. + * @param prefs Server list preferences. + */ + SetServerListPreferences(prefs: ServerBrowserPreferences): void; +} + +export interface ServerBrowserServer { + /** The ID of the game. */ + appid: number; + /** The server IP. */ + ip: string; + /** The server port. */ + port: number; + queryPort: number; + /** Last time played as a UNIX timestamp. */ + lastPlayed: number; +} + +export interface ServerBrowserServerFull extends ServerBrowserServer { + /** Do not refresh if had unsuccessful response? */ + bDoNotRefresh: boolean; + /** Found the server? */ + bHadSuccessfulResponse: boolean; + /** Has password? */ + bPassword: boolean; + /** Is VAC secured? */ + bSecure: boolean; + /** How many bot players there currently are. */ + botPlayers: number; + /** The server's game name/description. */ + gameDesc: string; + /** The game folder. */ + gameDir: string; + /** Server tags, separated by a comma. */ + gameTags: string; + /** Current server map. */ + map: string; + /** Max players on the server. */ + maxPlayers: number; + /** The server name. */ + name: string; + /** The latency to the server. */ + ping: number; + /** How many players there currently are. */ + players: number; + /** The server's game version it is running on. */ + serverVersion: number; + steamID: string; +} + +export enum JoinServerError { + PingFailed = -3, + Connecting = -2, + Pinging = -1, + None = 0, + VACBanned = 1, + ServerFull = 2, + ModNotInstalled = 3, + AppNotFound = 4, + NotInitialized = 5, +} + +export type ServerBrowserTab = 'internet' | 'favorites' | 'history' | 'lan' | 'friends'; + +export interface ServerBrowserGame { + /** The ID of the game. */ + appid: number; + /** The ID of the game. */ + gameid: string; + /** The game folder. */ + gamedir: string; + /** The game's name. */ + name: string; +} + +export interface ServerBrowserPreferences { + GameList: string; + filters: ServerBrowserTabFilters; +} + +export interface ServerBrowserTabFilters { + favorites: ServerBrowserGameFilter; + friends: ServerBrowserGameFilter; + history: ServerBrowserGameFilter; + internet: ServerBrowserGameFilter; + lan: ServerBrowserGameFilter; +} + +export interface ServerBrowserGameFilter { + /** Has users playing */ + NoEmpty: boolean; + /** Server not full */ + NoFull: boolean; + /** Is not password protected */ + NoPassword: boolean; + /** Anti-cheat */ + Secure: ServerBrowserGameFilterAntiCheat; + /** The ID of the game */ + appid: number; + /** The game folder */ + game: string; + /** Map filter */ + map: string; + /** Latency */ + ping: ServerBrowserGameFilterPing; +} + +export enum ServerBrowserGameFilterAntiCheat { + All = 0, + Secure = 1, + NotSecure = 2, +} + +export enum ServerBrowserGameFilterPing { + All = 0, + LessThan50 = 50, + LessThan100 = 100, + LessThan150 = 150, + LessThan250 = 250, +} + +export interface ServerBrowserFavoritesAndHistory { + favorites: ServerBrowserServer[]; + history: ServerBrowserServer[]; +} + +export interface ServerBrowserFriendServer { + /** The ID of the game. */ + appid: number; + /** Non-Steam server? */ + bNonSteamServer: boolean; + gameText: string; + /** The ID of the game. */ + gameid: string; + steamIDLobby: string; +} + +export interface ServerBrowserDialog { + dialogID: number; + ip: number; + port: number; + queryPort: number; +} + +export interface ServerBrowserPlayerRefreshStatus { + bSuccess: boolean; + bRefreshComplete: boolean; +} + +export interface ServerBrowserPlayer extends ServerBrowserPlayerRefreshStatus { + /** Player name. */ + playerName: string; + /** Player score. */ + score: number; + /** Time played on the server. */ + timePlayed: number; +} diff --git a/src/deck-components/steam-client/Settings.ts b/src/deck-components/steam-client/Settings.ts new file mode 100644 index 00000000..e5085f46 --- /dev/null +++ b/src/deck-components/steam-client/Settings.ts @@ -0,0 +1,655 @@ +import {CompatibilityToolInfo} from "./App"; +import {JsPbMessage, OperationResponse, Unregisterable} from "./index"; + +export interface Settings { + AddClientBeta(name: string, password: string): void; + + /** + * Clears HTTP cache located in `/appcache/httpcache`. + */ + ClearAllHTTPCaches(): void; + + /** + * Clears download cache and logs you out. + */ + ClearDownloadCache(): void; + + GetAccountSettings(): Promise; + + GetAppUsesP2PVoice(appId: number): Promise; + + GetAvailableLanguages(): Promise; + + GetAvailableTimeZones(): Promise; + + // Returns the current language "english" + GetCurrentLanguage(): Promise; + + GetGlobalCompatTools(): Promise; + + /** + * @returns A Promise that resolves to a ProtoBuf message. If deserialized, returns {@link MsgMonitorInfo}. + */ + GetMonitorInfo(): Promise; + + GetOOBETestMode(): Promise; + + GetRegisteredSteamDeck(): Promise; + + // Returns the current timezone + GetTimeZone(): Promise; + + GetWindowed(): Promise; + + IgnoreSteamDeckRewards(): void; + + /** + * Opens the Windows microphones dialog. + */ + OpenWindowsMicSettings(): void; + + RegisterForMicVolumeUpdates: Unregisterable; + + /** + * If `data` is deserialized, returns {@link MsgClientSettings}. + * @returns An object that can be used to unregister the callback. + */ + RegisterForSettingsArrayChanges(callback: (data: ArrayBuffer) => void): Unregisterable; + + RegisterForSettingsChanges(callback: (steamSettings: SteamSettings) => void): Unregisterable; + + RegisterForTimeZoneChange(callback: (timezoneId: string) => void): Unregisterable; // When timezone is changed from settings, callback will return new timezoneId + ReinitMicSettings(): void; + + RenderHotkey(event: KeyCaptureEvent): Promise; + + RequestDeviceAuthInfo(): void; + + // + SelectClientBeta(nBetaID: any): any; + + // Get from available languages + SetCurrentLanguage(strShortName: string): void; + + SetEnableSoftProcessKill(value: boolean): void; // Default value is false, this is Valve internal menu + + SetHostname(hostname: string): void; + + SetMicTestMode: any; + + SetOOBETestMode(value: boolean): void; + + SetPreferredMonitor(monitor: string): void; + + SetRegisteredSteamDeck: any; + + /** + * Sets the "Don't save account credentials on this computer" option. + * @param value Whether to save account credentials. + */ + SetSaveAccountCredentials(value: boolean): void; + + SetSetting(serializedBase64: string): any; + + SetTimeZone(timezoneId: string): void; // You can get valid timezoneIds from GetAvailableTimeZones() + + SetUseNintendoButtonLayout(controllerIndex: number, value: boolean): void; + + SetWindowed(value: boolean): void; + + SpecifyGlobalCompatTool(strToolName: string): void; + + ToggleSteamInstall(): Promise; +} + +export interface AccountSettings { + strEmail: string; + bEmailValidated: boolean; + bHasAnyVACBans: boolean; + bHasTwoFactor: boolean; + eSteamGuardState: ESteamGuardState; + rtSteamGuardEnableTime: number; + bSaveAccountCredentials: boolean; +} + +/** + * @todo unconfirmed, taken from localization strings + */ +export enum ESteamGuardState { + EmailUnverified = 0, + Protected = 1, + Disabled = 2, + Offline = 3, + NotEnabled = 4, +} + +export interface KeyCaptureEvent { + alt_key: boolean; + ctrl_key: boolean; + display_name: string; + meta_key: boolean; + shift_key: boolean; +} + +export interface Language { + language: ELanguage; + strShortName: string; +} + +export enum ELanguage { + None = -1, + English = 0, + German = 1, + French = 2, + Italian = 3, + Korean = 4, + Spanish = 5, + SimplifiedChinese = 6, + TraditionalChinese = 7, + Russian = 8, + Thai = 9, + Japanese = 10, + Portuguese = 11, + Polish = 12, + Danish = 13, + Dutch = 14, + Finnish = 15, + Norwegian = 16, + Swedish = 17, + Hungarian = 18, + Czech = 19, + Romanian = 20, + Turkish = 21, + Brazilian = 22, + Bulgarian = 23, + Greek = 24, + Arabic = 25, + Ukrainian = 26, + LatamSpanish = 27, + Vietnamese = 28, + SteamChina_SChinese = 29, + Max = 30, +} +export interface RegisteredSteamDeck { + bRegistered: boolean; + bIgnoreRegistrationPrompt: boolean; + strSteamID: string; + strSerialNumber: string; +} + +export interface TimeZone { + utcOffset: number; + timezoneID: string; + timezoneLocalizationToken: string; + regionsLocalizationToken: string; +} + +interface Region { + nRegionID: number; + strRegionName: string; +} + +interface Hour { + nHour: number; + strDisplay: string; +} + +interface AvailableClientBeta { + nBetaID: number; + strName: string; +} + +interface SteamSettings { + bIsInClientBeta: boolean; + bIsSteamSideload: boolean; + eClientBetaState: ClientBetaState; + strSelectedBetaName: string; + nAvailableBetas: number; + bChangeBetaEnabled: boolean; + nSelectedBetaID: number; + vecAvailableClientBetas: AvailableClientBeta[]; + bIsValveEmail: boolean; + bIsInDesktopUIBeta: boolean; + bEnableSoftProcessKill: boolean; + vecValidDownloadRegions: Region[]; + vecValidAutoUpdateRestrictHours: Hour[]; + bCompatEnabled: boolean; + bCompatEnabledForOtherTitles: boolean; + strCompatTool: string; + strDisplayName: string; + bDisplayIsExternal: boolean; + flAutoDisplayScaleFactor: number; + flCurrentDisplayScaleFactor: number; + bDisplayIsUsingAutoScale: boolean; + flMinDisplayScaleFactor: number; + flMaxDisplayScaleFactor: number; + flCurrentUnderscanLevel: number; + bUnderscanEnabled: boolean; + vecNightModeScheduledHours: Hour[]; +} + +export enum ClientBetaState { + None = 0, + NoneChosen = 1, + NoneChosenNonAdmin = 2, + InBeta = 3, + InBetaNonAdmin = 4, +} + + + +/** + * CMsgMonitorInfo + */ +export interface MsgMonitorInfo extends JsPbMessage { + monitors(): Monitor[]; + + selected_display_name(): string; + + add_monitors(param0: any, param1: any): any; + + set_monitors(param0: any): any; + + set_selected_display_name(param0: any): any; +} + +/** + * @todo Doesn't work on Linux ? + */ +export interface Monitor { + monitor_device_name: string; + monitor_display_name: string; +} + +/** + * CMsgClientSettings + */ +export interface MsgClientSettings extends JsPbMessage { + always_show_user_chooser(): boolean; + + always_use_gamepadui_overlay(): boolean; + + auto_scale_factor(): number; + + bigpicture_windowed(): boolean; + + broadcast_bitrate(): number; + + broadcast_chat_corner(): number; + + broadcast_encoding_option(): BroadcastEncoderSetting; + + broadcast_output_height(): number; + + broadcast_output_width(): number; + + broadcast_permissions(): BroadcastPermission; + + broadcast_record_all_audio(): boolean; + + broadcast_record_all_video(): boolean; + + broadcast_record_microphone(): boolean; + + broadcast_show_live_reminder(): boolean; + + broadcast_show_upload_stats(): boolean; + + cef_remote_debugging_enabled(): boolean; + + cloud_enabled(): boolean; + + controller_combine_nintendo_joycons(): boolean; + controller_enable_chord(): boolean; + + controller_generic_support(): boolean; + + controller_guide_button_focus_steam(): boolean; + + controller_poll_rate(): boolean; + controller_power_off_timeout(): number; + + controller_ps_support(): number; + + controller_switch_support(): boolean; + + controller_xbox_driver(): boolean; + + controller_xbox_support(): boolean; + + default_ping_rate(): number; + + disable_all_toasts(): boolean; + + disable_toasts_in_game(): boolean; + + display_name(): string; + + download_peer_content(): number; + + download_rate_bits_per_s(): boolean; + + download_region(): number; + + download_throttle_rate(): number; + + download_throttle_while_streaming(): boolean; + + download_while_app_running(): boolean; + + enable_avif_screenshots(): boolean; + + enable_dpi_scaling(): boolean; + + enable_gpu_accelerated_webviews(): boolean; + + enable_hardware_video_decoding(): boolean; + + enable_marketing_messages(): boolean; + + enable_overlay(): boolean; + + enable_screenshot_notification(): boolean; + + enable_screenshot_sound(): boolean; + + enable_shader_background_processing(): boolean; + + enable_shader_precache(): boolean; + + enable_ui_sounds(): boolean; + + force_deck_perf_tab(): boolean; + + force_fake_mandatory_update(): boolean; + + force_oobe(): boolean; + + g_background_audio(): EGRAudio; + + g_background_a_m(): number; + + g_background_a_s(): boolean; + + g_background_path(): string; + + g_background_max_keep(): string; + + g_background_mode(): EGRMode; + + g_background_time_resolution(): number; + + g_background_mk(): Hotkey; + + g_background_tg(): Hotkey; + + g_max_fps(): number; + + gamerecording_automatic_gain_control(): boolean; + gamerecording_export_codec(): EExportCodec; + gamerecording_export_directory(): number; + gamerecording_export_limit_bitrate(): number; + gamerecording_export_limit_frame_rate(): number; + gamerecording_export_limit_height(): number; + gamerecording_export_limit_size_mb(): number; + gamerecording_export_limit_width(): number; + gamerecording_export_limit_type(): EGRExportLimitType; + gamerecording_force_mic_mono(): boolean; + gamerecording_hotkey_ic(): Hotkey; + gamerecording_ic_seconds(): number; + gamerecording_video_bitrate(): string; + gamerecording_video_maxheight(): number; + + game_notes_enable_spellcheck(): boolean; + + gamescope_allow_tearing(): boolean; + + gamescope_app_target_framerate(): number; + + gamescope_composite_debug(): boolean; + + gamescope_disable_framelimit(): boolean; + + gamescope_disable_mura_correction(): boolean; + + gamescope_display_refresh_rate(): number; + + gamescope_enable_app_target_framerate(): boolean; + + gamescope_force_composite(): boolean; + + gamescope_hdr_visualization(): HDRVisualization; + + gamescope_include_steamui_in_screenshots(): boolean; + + gamescope_use_game_refresh_rate_in_steam(): boolean; + + gamestream_enable_video_h265(): boolean; + gamestream_hardware_video_encode(): boolean; + + hdr_compat_testing(): boolean; + + in_client_beta(): boolean; + + is_external_display(): boolean; + + is_steam_sideloaded(): boolean; + + jumplist_flags(): number; + + library_disable_community_content(): boolean; + + library_display_icon_in_game_list(): boolean; + + library_display_size(): number; + + library_low_bandwidth_mode(): boolean; + + library_low_perf_mode(): boolean; + + library_whats_new_show_only_product_updates(): boolean; + + max_scale_factor(): number; + + min_scale_factor(): number; + + music_download_high_quality(): boolean; + + music_pause_on_app_start(): boolean; + + music_pause_on_voice_chat(): boolean; + + music_playlist_notification(): boolean; + + music_volume(): number; + + needs_steam_service_repair(): boolean; + + no_save_personal_info(): boolean; + + oobe_test_mode_enabled(): boolean; + + os_version_unsupported(): boolean; + + overlay_fps_counter_corner(): number; + + overlay_fps_counter_high_contrast(): boolean; + + overlay_key(): Hotkey; + + overlay_restore_browser_tabs(): boolean; + + overlay_scale_interface(): boolean; + + overlay_tabs(): string; + + overlay_toolbar_list_view(): boolean; + + override_browser_composer_mode(): number; + + play_sound_on_toast(): boolean; + + preferred_monitor(): string; + + ready_to_play_includes_streaming(): boolean; + + restrict_auto_updates(): boolean; + + restrict_auto_updates_end(): number; + + restrict_auto_updates_start(): number; + + run_at_startup(): boolean; + + save_uncompressed_screenshots(): boolean; + + screenshot_items_per_row(): number; + + screenshot_key(): Hotkey; + + screenshots_path(): string; + + server_ping_rate(): number; + + setting_validation_bool(): boolean; + + setting_validation_enum(): HDRVisualization; + + setting_validation_int32(): number; + + setting_validation_uint32(): number; + + setting_validation_uint64(): number; + + setting_validation_float(): number; + + setting_validation_string(): string; + + shader_precached_size(): string; + + show_copy_count_in_library(): boolean; + + show_family_sharing_notifications(): boolean; + + show_screenshot_manager(): boolean; + + show_steam_deck_info(): boolean; + + show_store_content_on_home(): boolean; + + show_timestamps_in_console(): boolean; + + skip_steamvr_install_dialog(): boolean; + + small_mode(): boolean; + + smooth_scroll_webviews(): boolean; + + start_in_big_picture_mode(): boolean; + + start_page(): string; + + startup_movie_id(): string; + + startup_movie_local_path(): string; + + startup_movie_shuffle(): boolean; + + startup_movie_used_for_resume(): boolean; + + steam_cef_gpu_blocklist_disabled(): boolean; + + steam_input_configurator_error_msg_enable(): boolean; + + steam_networking_share_ip(): number; + + steam_os_underscan_enabled(): boolean; + + steam_os_underscan_level(): number; + + steamos_cec_enabled(): boolean; + + steamos_cec_wake_on_resume(): boolean; + + steamos_magnifier_scale(): number; + + steamos_status_led_brightness(): number; + + steamos_tdp_limit(): number; + + steamos_tdp_limit_enabled(): boolean; + + steamos_wifi_debug(): boolean; + + steamos_wifi_force_wpa_supplicant(): boolean; + + system_bluetooth_enabled(): boolean; + + turn_off_controller_on_exit(): boolean; + + voice_mic_device_name(): string; + + voice_mic_input_gain(): number; + + voice_push_to_talk_key(): Hotkey; + + voice_push_to_talk_setting(): number; + + voice_speaker_output_gain(): number; + + web_browser_home(): string; +} + +export enum BroadcastEncoderSetting { + BestQuality = 0, + BestPerformance = 1, +} + +export enum BroadcastPermission { + Disabled = 0, + FriendsApprove = 1, + FriendsAllowed = 2, + Public = 3, + Subscribers = 4, +} + +export enum EExportCodec { + Default, + H264, + H265, +} + +export enum EGRAudio { + Game, + System, + Select, +} + +export enum EGRExportLimitType { + Native, + FileSize, + Advanced, +} + +export enum EGRMode { + Never, + Always, + Manual, +} + +export interface Hotkey { + alt_key: boolean; + ctrl_key: boolean; + display_name: string; + key_code: number; + meta_key: boolean; + shift_key: boolean; +} + +export enum HDRVisualization { + None = 0, + Heatmap = 1, + Analysis = 2, + HeatmapExtended = 3, + HeatmapClassic = 4, +} diff --git a/src/deck-components/steam-client/SharedConnection.ts b/src/deck-components/steam-client/SharedConnection.ts new file mode 100644 index 00000000..abfefe7b --- /dev/null +++ b/src/deck-components/steam-client/SharedConnection.ts @@ -0,0 +1,42 @@ +import {Unregisterable} from "./index"; +import {SteamRealm} from "./Overlay"; + +/** + * `hSharedConnection` is the number from {@link AllocateSharedConnection}. + */ +export interface SharedConnection { + AllocateSharedConnection(): Promise; + + // if no such number, sends this warning: + // src\clientdll\clientsharedconnection.cpp (154) : m_mapSharedConnections.HasElement( hSharedConnection ) + Close(hSharedConnection: number): void; + + RegisterOnBinaryMessageReceived(hSharedConnection: number, callback: (data: ArrayBuffer) => void): Unregisterable; + + RegisterOnLogonInfoChanged(hSharedConnection: number, callback: (info: LogonInfo) => void): Unregisterable; + + RegisterOnMessageReceived(hSharedConnection: number, callback: (param0: any) => void): Unregisterable; + + SendMsg: any; + SendMsgAndAwaitBinaryResponse: any; + + SubscribeToClientServiceMethod(hSharedConnection: number, param1: any): any; + + SubscribeToEMsg(hSharedConnection: number, param1: any): any; +} + +export interface LogonInfo { + /** `true` if logged on, `false otherwise. */ + bLoggedOn: boolean; + eUniverse: SteamRealm; + /** Account username. Empty if not logged on. */ + strAccountName: string; + /** URL for community content. */ + strCommunityImagesURL: string; + /** Account nickname. Empty if not logged on. */ + strPersonaName: string; + /** Steam64 ID. */ + strSteamid: string; + /** Country code. */ + strUserCountry: string; +} diff --git a/src/deck-components/steam-client/Stats.ts b/src/deck-components/steam-client/Stats.ts new file mode 100644 index 00000000..c8e81313 --- /dev/null +++ b/src/deck-components/steam-client/Stats.ts @@ -0,0 +1,10 @@ +export interface Stats { + // param0 - AppDetailsReviewSection, Showcases, LibraryReviewSpotlight + // param1 - + // AppDetailsReviewSection: PositiveClicked, NegativeClicked, NeutralClicked, PositiveReviewPosted, NegativeReviewPosted, EditClicked, ReviewCanceled + // LibraryReviewSpotlight: ReviseClicked, PositiveClicked, ReviseCloseClicked, NegativeClicked, PositiveRevisePosted, NegativeRevisePosted, ReviseCanceled, ReviewCanceled, CloseClicked + // Showcases: Delete, Save-Modify, Save-New + RecordActivationEvent(param0: string, param1: string): any; + + RecordDisplayEvent: any; +} diff --git a/src/deck-components/steam-client/SteamChina.ts b/src/deck-components/steam-client/SteamChina.ts new file mode 100644 index 00000000..d23e6c78 --- /dev/null +++ b/src/deck-components/steam-client/SteamChina.ts @@ -0,0 +1,3 @@ +export interface SteamChina { + GetCustomLauncherAppID(): Promise; +} diff --git a/src/deck-components/steam-client/Storage.ts b/src/deck-components/steam-client/Storage.ts new file mode 100644 index 00000000..aab95556 --- /dev/null +++ b/src/deck-components/steam-client/Storage.ts @@ -0,0 +1,24 @@ +import {OperationResponse} from "./index"; + +/** + * SteamClient.MachineStorage affects the "STEAMPATH/config/config.vdf" file. + * SteamClient.RoamingStorage affects the "STEAMPATH/userdata/STEAMID3/7/remote/sharedconfig.vdf" file. + * SteamClient.Storage affects the "STEAMPATH/userdata/STEAMID3/config/localconfig.vdf" file. + */ +export interface Storage { + DeleteKey(key: string): Promise; + + /** + * @remarks Use {@link SetObject} to set. + */ + GetJSON(key: string): Promise; + + GetString(key: string): Promise; + + /** + * @remarks Use {@link SetObject} to get. + */ + SetObject(key: string, value: any): Promise; + + SetString(key: string, value: string): Promise; +} diff --git a/src/deck-components/steam-client/Streaming.ts b/src/deck-components/steam-client/Streaming.ts new file mode 100644 index 00000000..6b6c9c00 --- /dev/null +++ b/src/deck-components/steam-client/Streaming.ts @@ -0,0 +1,55 @@ +import {Unregisterable} from "./index"; +import {LaunchOption} from "./App"; + +export interface Streaming { + AcceptStreamingEULA(param0: any, param1: any, param2: any): any; + + CancelStreamGame(): void; // existing stream + + /** + * Registers a callback function to be called when the streaming client finishes. + * @param callback The callback function to be called. + * @returns An object that can be used to unregister the callback. + */ + RegisterForStreamingClientFinished(callback: (code: number, result: string) => void): Unregisterable; + + /** + * Registers a callback function to be called when there is progress in the launch of the streaming client. + * @param callback The callback function to be called. + * @returns An object that can be used to unregister the callback. + */ + RegisterForStreamingClientLaunchProgress( + callback: (actionType: string, taskDetails: string, done: number, total: number) => void, + ): Unregisterable; + + /** + * Registers a callback function to be called when the streaming client is started (e.g., when clicking the stream button). + * @param callback The callback function to be called. + * @returns An object that can be used to unregister the callback. + */ + RegisterForStreamingClientStarted(callback: (appId: number) => void): Unregisterable; + + /** + * Registers a callback function to be called when the streaming launch is complete. + * @param callback The callback function to be called. + * @returns An object that can be used to unregister the callback. + * @todo `code` is likely a code, 1 being it started, 10 being host computer is updating game, `result` just returns "complete" + */ + RegisterForStreamingLaunchComplete(callback: (code: number, result: string) => void): Unregisterable; + + RegisterForStreamingShowEula(callback: (appId: number) => any): Unregisterable; + + RegisterForStreamingShowIntro(callback: (param0: any, param1: any) => any): Unregisterable; + + /** + * Registers a callback function to be called when the streaming client receives launch options from the host. + * @param callback The callback function to be called. + * @returns An object that can be used to unregister the callback. + */ + RegisterForStreamingShowLaunchOptions( + callback: (appId: number, launchOptions: LaunchOption[]) => void, + ): Unregisterable; // Callback when streaming client receives launch options from host + + StreamingContinueStreamGame(): void; // existing game running on another streaming capable device + StreamingSetLaunchOption(param0: any): any; +} diff --git a/src/deck-components/steam-client/UI.ts b/src/deck-components/steam-client/UI.ts new file mode 100644 index 00000000..4b1946b0 --- /dev/null +++ b/src/deck-components/steam-client/UI.ts @@ -0,0 +1,82 @@ +import {UIMode, Unregisterable} from "./index"; +import {OSType} from "./system"; + +export interface UI { + EnsureMainWindowCreated(): void; + + ExitBigPictureMode(): void; + + GetDesiredSteamUIWindows(): Promise; + + /** + * Gets information about whether your OS will be unsupported in the future or not. + */ + GetOSEndOfLifeInfo(): Promise; + + /** + * Retrieves the current UI mode. + * @returns A Promise that resolves to the current UI mode. + */ + GetUIMode(): Promise; + + NotifyAppInitialized(): void; + + RegisterDesiredSteamUIWindowsChanged(callback: () => void): Unregisterable; + + /** + * Registers a callback function to be called when a convar's value gets changed. + * + * Hard crashes if such a convar does not exist or if you can't set it. + * + * @param convar The ConVar to watch. + * @param callback The callback function to be called. + */ + RegisterForClientConVar(convar: string, callback: (value: string) => void): Unregisterable; + + RegisterForErrorCondition(callback: (param0: number, param1: number) => void): Unregisterable; + + RegisterForKioskModeResetSignal(callback: () => void): Unregisterable; + + RegisterForUIModeChanged(callback: (mode: UIMode) => void): Unregisterable; + + ResetErrorCondition(): void; + + /** + * Sets the UI mode to the specified value. + * @param mode The UI mode to set. + */ + SetUIMode(mode: UIMode): void; +} + +export enum EWindowType { + MainGamepadUI, + OverlayGamepadUI, + Keyboard, + ControllerConfigurator, + VR, + MainDesktopUI, + DesktopLogin, + OverlayDesktopUI, + SteamChinaReviewLauncher, +} + +export interface OSEndOfLifeInfo { + bOSWillBeUnsupported: boolean; + osType: OSType; +} + +/** + * The following might have more correct information: + * https://github.com/SteamDatabase/SteamTracking/blob/master/Protobufs/webuimessages_sharedjscontext.proto + */ +export interface SteamWindow { + appid: number; + hwndParent: number; + nBrowserID: number; + strAppName: string; + unID: number; + unPID: number; + windowType: EWindowType; + x: number; + y: number; +} diff --git a/src/deck-components/steam-client/URL.ts b/src/deck-components/steam-client/URL.ts new file mode 100644 index 00000000..cd70fad7 --- /dev/null +++ b/src/deck-components/steam-client/URL.ts @@ -0,0 +1,46 @@ +import {Unregisterable} from "./index"; + +export interface URL { + /** + * Executes a steam:// URL. + * @param url The URL to execute. + */ + ExecuteSteamURL(url: string): void; + + /** + * @remarks The array may be empty. + */ + GetSteamURLList(param0: string[]): Promise; + + GetWebSessionID(): Promise; + + /** + * Registers a callback to be called when a steam:// URL gets executed. + * @param section `rungameid`, `open`, etc. + * @param callback The callback function to be called. + * @returns An object that can be used to unregister the callback. + */ + RegisterForRunSteamURL(section: string, callback: (param0: number, url: string) => void): Unregisterable; + + RegisterForSteamURLChanges(callback: () => void): void; +} + +export interface SteamURL { + url: string; + /** + * @todo enum? + */ + feature: number; +} + +export interface SteamURLs { + CommunityImages: SteamURL; + StoreAppImages: SteamURL; + BaseURLSharedCDN: SteamURL; + ClanAssetCDN: SteamURL; + CommunityCDN: SteamURL; + AvatarBaseURL: SteamURL; + StoreCDN: SteamURL; + WebAPI: SteamURL; + LocalSSA: SteamURL; +} diff --git a/src/deck-components/steam-client/Updates.ts b/src/deck-components/steam-client/Updates.ts new file mode 100644 index 00000000..2345a89b --- /dev/null +++ b/src/deck-components/steam-client/Updates.ts @@ -0,0 +1,90 @@ +import {JsPbMessage, OperationResponse, Result, Unregisterable} from "./index"; + +export interface Updates { + ApplyUpdates(param0: string): Promise; + + CheckForUpdates(): Promise; // Checks for software updates + + GetCurrentOSBranch(): Promise; + + /** + * If `data` is deserialized, returns {@link MsgSystemUpdateState}. + * @returns A Promise that resolves to a ProtoBuf message. + */ + RegisterForUpdateStateChanges(callback: (data: ArrayBuffer) => void): Unregisterable; + + // 1 - Stable, 2 - Beta, 3 - Preview + SelectOSBranch(branch: number): any; // enum? +} + + +export interface OSBranch { + eBranch: OSBranchType; // 1 - Stable + sRawName: string; +} + +export enum OSBranchType { + Unknown = 0, + Release = 1, + ReleaseCandidate = 2, + Beta = 3, + BetaCandidate = 4, + Main = 5, + Staging = 6, +} + +/** + * CMsgSystemUpdateState + */ +export interface MsgSystemUpdateState extends JsPbMessage { + state(): UpdaterState | undefined; + + progress(): UpdateProgress | undefined; + + supports_os_updates(): boolean | undefined; + + update_apply_results(): UpdateApplyResult[]; + + update_check_results(): UpdateCheckResult[]; +} + +export interface UpdateApplyResult { + type: UpdaterType; + eresult: Result; + requires_client_restart: boolean; + requires_system_restart: boolean; +} + +export interface UpdateCheckResult { + type: UpdaterType; + eresult: Result; + rtime_checked: number; + available: boolean; +} + +export interface UpdateProgress { + stage_progress: number | undefined; + stage_size_bytes: number | undefined; + rtime_estimated_completion: number | undefined; +} + +export enum UpdaterState { + Invalid = 0, + UpToDate = 2, + Checking = 3, + Available = 4, + Applying = 5, + ClientRestartPending = 6, + SystemRestartPending = 7, +} + +export enum UpdaterType { + Invalid = 0, + Client = 1, + OS = 2, + BIOS = 3, + Aggregated = 4, + Test1 = 5, + Test2 = 6, + Dummy = 7, +} diff --git a/src/deck-components/steam-client/User.ts b/src/deck-components/steam-client/User.ts new file mode 100644 index 00000000..e3e6db8d --- /dev/null +++ b/src/deck-components/steam-client/User.ts @@ -0,0 +1,187 @@ +import {OperationResponse, Unregisterable} from "./index"; + +export interface User { + AuthorizeMicrotxn(txnId: any): any; + + CancelLogin: any; + + CancelMicrotxn(txnId: any): any; + + /** + * Tries to cancel Steam shutdown. + * @remarks Used in the "Shutting down" dialog. + */ + CancelShutdown(): void; + + /** + * Opens the "Change Account" dialog. + */ + ChangeUser(): void; + + Connect(): Promise; + + FlipToLogin(): void; + + /** + * Forces a shutdown while shutting down. + * @remarks Used in the "Shutting down" dialog. + */ + ForceShutdown(): void; + + /** + * Forgets an account's password. + * @param accountName Login of the account to forget. + * @returns A Promise that resolves to a boolean indicating whether the operation succeeded or not. + */ + ForgetPassword(accountName: string): Promise; + + /** + * Gets your country code. + * @returns A Promise that resolves to a string containing your country code. + */ + GetIPCountry(): Promise; + + GetLoginProgress(callback: (param0: number, param1: number) => void): Unregisterable; + + GetLoginUsers(): Promise; + + GoOffline(): void; + + GoOnline(): void; + + OptOutOfSurvey(): void; + + PrepareForSystemSuspend(): any; + + Reconnect(): void; + + RegisterForConnectionAttemptsThrottled(callback: (data: ConnectionAttempt) => void): Unregisterable; + + RegisterForCurrentUserChanges(callback: (user: CurrentUser) => void): void; + + RegisterForLoginStateChange(callback: (accountName: string, loginState: LoginState, loginResult: number, loginPercentage: number, param4: number) => void): Unregisterable; + + RegisterForPrepareForSystemSuspendProgress(callback: (data: any) => void): Unregisterable; + + RegisterForResumeSuspendedGamesProgress: Unregisterable; + + RegisterForShutdownDone(callback: () => void): Unregisterable; + + RegisterForShutdownFailed: Unregisterable; + + /** + * Register a function to be executed when a shutdown start is detected. + * @param callback The function to be executed on shutdown start. + */ + RegisterForShutdownStart(callback: () => void): Unregisterable; + + RegisterForShutdownState: Unregisterable; + + /** + * Removes an account from remembered users. + * @param accountName The account to remove. + */ + RemoveUser(accountName: string): void; + + RequestSupportSystemReport(reportId: string): Promise<{ + bSuccess: boolean; + }>; + + ResumeSuspendedGames(param0: boolean): any; + + // Hardware survey information + RunSurvey(callback: (surveySections: SurveySection[]) => void): void; + + SendSurvey: any; + + SetAsyncNotificationEnabled(appId: number, enable: boolean): any; + + /** + * Sets given login credentials, but don't log in to that account. + * @param accountName Account name. + * @param password Account password. + * @param rememberMe Whether to remember that account. + */ + SetLoginCredentials(accountName: string, password: string, rememberMe: boolean): void; + + SetOOBEComplete(): void; + + ShouldShowUserChooser(): Promise; + + /** + * Signs out and restarts Steam. + */ + SignOutAndRestart(): void; + + StartLogin(): void; + + // is param0 offline mode? + StartOffline(param0: boolean): any; + + /** + * Restarts the Steam client. + */ + StartRestart(): any; + + StartShutdown(flag: boolean): any; +} + +export interface ConnectionAttempt { + rtCooldownExpiration: number; +} + +export interface CurrentUser { + NotificationCounts: { + async_game_updates: number; + comments: number; + gifts: number; + help_request_replies: number; + inventory_items: number; + invites: number; + moderator_messages: number; + offline_messages: number; + trade_offers: number; + }; + bHWSurveyPending: boolean; + bIsLimited: boolean; + bIsOfflineMode: boolean; + bPromptToChangePassword: boolean; + bSupportAckOnlyMessages: boolean; + bSupportAlertActive: boolean; + bSupportPopupMessage: boolean; + clientinstanceid: string; + strAccountBalance: string; + strAccountBalancePending: string; + strAccountName: string; + strFamilyGroupID: string; + strSteamID: string; +} + +export enum LoginState { + None = 0, + WelcomeDialog = 1, + WaitingForCreateUser = 2, + WaitingForCredentials = 3, + WaitingForNetwork = 4, + WaitingForServerResponse = 5, + WaitingForLibraryReady = 6, + Success = 7, + Quit = 8, +} + +export interface LoginUser { + personaName: string; + accountName: string; + rememberPassword: boolean; + avatarUrl: string; +} + +export interface SurveyEntry { + strName: string; + vecArgs: string[]; +} + +export interface SurveySection { + strSectionName: string; + vecEntries: SurveyEntry[]; +} diff --git a/src/deck-components/steam-client/WebChat.ts b/src/deck-components/steam-client/WebChat.ts new file mode 100644 index 00000000..12b99140 --- /dev/null +++ b/src/deck-components/steam-client/WebChat.ts @@ -0,0 +1,158 @@ +import {OverlayBrowserInfo} from "./Overlay"; +import {UIMode, Unregisterable} from "./index"; + +export interface WebChat { + BSuppressPopupsInRestore(): Promise; + + /** + * Gets your Steam3 ID. + * @returns A Promise that resolves to a Steam3 ID. + */ + GetCurrentUserAccountID(): Promise; + + /** + * Gets the current user's 64x64 avatar as a data URL. + * @returns A Promise that resolves to the data URL. + */ + GetLocalAvatarBase64(): Promise; + + /** + * Gets the current user's nickname. + * @returns A Promise that resolves to the nickname. + */ + GetLocalPersonaName(): Promise; + + GetOverlayChatBrowserInfo(): Promise; + + // param0 - appid ? + GetPrivateConnectString(param0: number): Promise; + + /** + * Gets information about push-to-Talk. + * @returns + */ + GetPushToTalkEnabled(): Promise; + + /** + * Gets the "Sign in to friends when Steam starts" option value. + * @returns A Promise that resolves to a boolean indicating whether the option is enabled or not. + */ + GetSignIntoFriendsOnStart(): Promise; + + /** + * Retrieves the current UI mode. + * @returns A Promise that resolves to the current UI mode. + */ + GetUIMode(): Promise; + + OnGroupChatUserStateChange(chatGroupId: any, accountId: any, action: any): any; + + OnNewGroupChatMsgAdded( + groupId: number, + chatId: number, + accountId: number, + timestamp: number, + param4: number, + message: string, + ): any; + + // Opens the URL in default web browser, despite what the name says ? + OpenURLInClient(url: string, pid: number, forceExternal: boolean): void; + + /** + * Registers a callback function to be called when the computer's active state changes. + * @param callback The callback function to be called. + * @returns An object that can be used to unregister the callback. + * @todo Changes to 2 after 10 seconds? + * @todo Does not affect the keyboard? + */ + RegisterForComputerActiveStateChange( + callback: (state: ComputerActiveState, time: number) => void, + ): Unregisterable; + + /** + * @todo WebChat.ShowFriendChatDialog does this. + */ + RegisterForFriendPostMessage(callback: (data: FriendChatDialogData) => void): Unregisterable; + + /** + * To unregister, use {@link UnregisterForMouseXButtonDown}. + */ + RegisterForMouseXButtonDown(callback: any): void; + + /** + * Registers a callback function to be called when the push-to-talk state changes. + * @param callback The callback function to be called. + * @returns An object that can be used to unregister the callback. + */ + RegisterForPushToTalkStateChange(callback: (state: boolean) => void): Unregisterable; + + /** + * Registers a callback function to be called when the UI mode is changed. + * @param callback The callback function to be called. + * @returns An object that can be used to unregister the callback. + */ + RegisterForUIModeChange(callback: (mode: UIMode) => void): Unregisterable; + + RegisterOverlayChatBrowserInfoChanged(callback: any): Unregisterable; + + SetActiveClanChatIDs(clanChatIds: any[]): any; + + SetNumChatsWithUnreadPriorityMessages(size: number): void; + + SetPersonaName: any; + + SetPushToMuteEnabled(value: boolean): any; + + SetPushToTalkEnabled(value: boolean): any; + + SetPushToTalkHotKey(param0: number): void; + + SetPushToTalkMouseButton(param0: number): void; + + SetVoiceChatActive: any; + SetVoiceChatStatus: any; + ShowChatRoomGroupDialog: any; + + /** + * @todo Does not actually show the dialog. + */ + ShowFriendChatDialog(steamid: string): void; + + /** + * @todo does this take any args at all lol + */ + UnregisterForMouseXButtonDown(callback: any): void; +} + +export enum ComputerActiveState { + Invalid = 0, + Active = 1, + Idle = 2, +} + +export interface FriendChatDialog { + browserid: number; + btakefocus: string; + command: string; + pid: number; + steamid: string; +} + +export interface FriendChatDialogData { + data: FriendChatDialog; +} + +export interface PushToTalkInfo { + /** Indicates whether push-to-talk is enabled. */ + bEnabled: boolean; + /** Indicates whether push-to-mute is in use instead. */ + bPushToMute: boolean; + /** + * Push-to-talk hotkey. + * @todo enum? this is not EHIDKeyboardKey + */ + vkHotKey: number; + /** Push-to-talk hotkey name. */ + strKeyName: string; +} diff --git a/src/deck-components/steam-client/WebUITransport.ts b/src/deck-components/steam-client/WebUITransport.ts new file mode 100644 index 00000000..79289f4b --- /dev/null +++ b/src/deck-components/steam-client/WebUITransport.ts @@ -0,0 +1,21 @@ +import { OperationResponse } from "./index"; + +export interface WebUITransport { + GetTransportInfo(): Promise; + + /** + * *Possibly* notifies websocket of failure and tries to reconnect to it. + * + * The responsible message for this is `CMsgWebUITransportFailure`. + * + * @param serializedBase64 Serialized ProtoBuf message. + */ + NotifyTransportFailure(serializedBase64: string): Promise; +} + +export interface TransportInfo { + authKeyClientdll: string; + authKeySteamUI: string; + portClientdll: number; + portSteamUI: number; +} diff --git a/src/deck-components/steam-client/Window.ts b/src/deck-components/steam-client/Window.ts new file mode 100644 index 00000000..69e32872 --- /dev/null +++ b/src/deck-components/steam-client/Window.ts @@ -0,0 +1,235 @@ +import {UIComposition} from "./Overlay"; + +/** + * Represents functionality for managing Steam's windows. + * + * "Restore details" here refers to a string that is similiar to + * `1&x=604&y=257&w=1010&h=600`, which is usable with certain + * `window.open()` parameters and methods from here. + * + * Note that methods here have to be called from the + * window you want to use (not SharedJSContext). + */ +export interface Window { + BringToFront(forceOS?: WindowBringToFront): void; + + /** + * Closes the window. + */ + Close(): void; + + /** + * @returns the window's fullscreen state. + */ + DefaultMonitorHasFullscreenWindow(): Promise; + + /** + * Flashes the window in the taskbar. + */ + FlashWindow(): void; + + GetDefaultMonitorDimensions(): Promise; + + /** + * @returns the mouse position's restore details. + */ + GetMousePositionDetails(): Promise; + + /** + * @returns the window's details. + */ + GetWindowDetails(): Promise; + + /** + * @returns the window's dimensions. + */ + GetWindowDimensions(): Promise; + + /** + * @returns the window's restore details. + */ + GetWindowRestoreDetails(): Promise; + + /** + * Hides the window. + */ + HideWindow(): void; + + /** + * @returns the window's maximized state. + */ + IsWindowMaximized(): Promise; + + /** + * @returns the window's minimized state. + */ + IsWindowMinimized(): Promise; + + MarkLastFocused(): void; + + /** + * Minimizes the window. + */ + Minimize(): void; + + /** + * Moves the window to given coordinates. + * @param x Window X position. + * @param y Window Y position. + * @param dpi Screen DPI. + */ + MoveTo(x: number, y: number, dpi: number | undefined): void; + + /** + * Moves the window to a given location. + * @param location Window location. + * @param offset X/Y offset. + */ + MoveToLocation(location: WindowLocation, offset: number | undefined): void; + + /** + * Moves the window relatively to given details. + * @param details Window restore details string from {@link GetWindowRestoreDetails}. + * @param x Window X position. + * @param y Window Y position. + * @param width Window width. + * @param height Window height. + * + * @example + * Move the window to bottom right by 50 pixels: + * ``` + * SteamClient.Window.GetWindowRestoreDetails((e) => { + * SteamClient.Window.PositionWindowRelative(e, 50, 50, 0, 0); + * }); + * ``` + */ + PositionWindowRelative(details: string, x: number, y: number, width: number, height: number): void; + + /** + * @returns true if yje naun [tpcess od about to shut down.] + */ + ProcessShuttingDown(): Promise; + + /** + * Resizes the window to given dimension. + * The window has to be created with the resizable flag. + * @param width Window width. + * @param height Window height. + * @param applyBrowserScaleOrDPIValue + */ + ResizeTo(width: number, height: number, applyBrowserScaleOrDPIValue: boolean | number): void; + + /** + * Moves the window to given details. + * @param details Window details string from `Window.GetWindowRestoreDetails`. + */ + RestoreWindowSizeAndPosition(details: string): void; + + SetAutoDisplayScale(value: boolean): void; + + SetComposition(mode: UIComposition, appIdCompositionQueue: number[], windowId: number): void; + + /** + * Makes the window hide, but not close on pressing the close button. + * @param value Hide on close? + */ + SetHideOnClose(value: boolean): void; + + SetKeyFocus(value: boolean): void; + + SetManualDisplayScaleFactor(displayScaleFactor: number): void; + + /** + * Sets the window's max size. + * @param width Window's max width. + * @param height Window's max height. + */ + SetMaxSize(width: number, height: number): void; + + /** + * Sets the window's min size. + * @param width Window's max width. + * @param height Window's max height. + */ + SetMinSize(width: number, height: number): void; + + SetModal(value: boolean): void; + + /** + * Sets the window's resize grip size. + * The window has to be created with the resizable flag for this to take any effect. + * @param width Resize grip width. + * @param height Resize grip height. + */ + SetResizeGrip(width: number, height: number): void; + + /** + * Set the window's icon. + * @param icon The window icon to be used. + */ + SetWindowIcon(icon: WindowIcon): void; + + /** + * Shows the window. + */ + ShowWindow(): void; + + /** + * Stops the window's taskbar flashing. + */ + StopFlashWindow(): void; + + /** + * Toggles the window's fullscreen state. + */ + ToggleFullscreen(): void; + + /** + * Toggles the window's maximized state. + */ + ToggleMaximize(): void; +} + +export enum WindowBringToFront { + Invalid = 0, + ForceOS = 1, + WithoutForcingOS = 2, +} + +export type WindowLocation = + | 'upper-left' + | 'lower-left' + | 'center-top' + | 'center-bottom' + | 'upper-right' + | 'lower-right'; + +export type WindowIcon = 'steam' | 'messages' | 'voice'; + +/** + * "Usable" here refers to space that is not taken by the taskbar. + */ +export interface MonitorDimensions { + flHorizontalScale: number; + flVerticalScale: number; + nFullHeight: number; + nFullLeft: number; + nFullTop: number; + nFullWidth: number; + nUsableHeight: number; + nUsableLeft: number; + nUsableTop: number; + nUsableWidth: number; +} + +export interface WindowDetails { + bGPUEnabled: boolean; + bUnderlaySupported: boolean; +} + +export interface WindowDimensions { + x: number; + y: number; + width: number; + height: number; +} diff --git a/src/deck-components/steam-client/browser-view/BrowserViewPopup.ts b/src/deck-components/steam-client/browser-view/BrowserViewPopup.ts new file mode 100644 index 00000000..a7110773 --- /dev/null +++ b/src/deck-components/steam-client/browser-view/BrowserViewPopup.ts @@ -0,0 +1,375 @@ +import {TouchGestureType} from "../Browser"; + +export interface BrowserViewPopup { + /** + * Blur the popup. + * @param enabled Is the blur enabled? + * @param backgroundColor + * @param blur + * @todo backgroundColor is a bool? Whatever that means + */ + AddGlass(enabled: boolean, backgroundColor: boolean, blur: boolean): void; + + /** + * Indicates whether you can go backward in history or not. + * @returns true if you can go backward in history, false otherwise. + */ + CanGoBackward(): boolean; + + /** + * Indicates whether you can go forward in history or not. + * @returns true if you can go forward in history, false otherwise. + */ + CanGoForward(): boolean; + + // alert() i assume + DialogResponse(param0: boolean): void; + + EnableSteamInput(): void; + + /** + * Find a string in the page. + * @param input The string to find. + * @param param1 Additional parameter (exact usage may vary). + * @param previous `true` for previous match, `false` for next match. + */ + FindInPage(input: string, param1: boolean, previous: boolean): void; + + /** + * Get the current popup position. + * @returns The window position. + */ + GetBounds(): BrowserViewBounds; + + /** + * Go back in history. + */ + GoBack(): void; + + /** + * Go forward in history. + */ + GoForward(): void; + + /** + * @remarks `| number` is used for `BrowserViewContextMenu.custom_commands`. + */ + HandleContextMenuCommand(command: BrowserViewContextMenuCommand | number, param2: BrowserViewContextMenu): void; + + /** + * Load the specified URL. + * @param url The URL to go to. + */ + LoadURL(url: string): void; + + NotifyUserActivation(): void; + + /** + * Paste the current clipboard selection. + */ + Paste(): void; + + PostMessage(message: string, args: string): boolean; + + /** + * Reload the page. + */ + Reload(): void; + + /** + * Load the specified URL, but don't save history. + * @param url The URL to go to. + */ + ReplaceURL(url: string): void; + + /** + * Define blocked protocols, like https, etc. + * @param protocols The protocols to block, separated by a semicolon. + */ + SetBlockedProtocols(protocols: string): void; + + /** + * Sets the browser window position. + * @param x Browser window X position. + * @param y Browser window Y position. + * @param width Browser window width. + * @param height Browser window height. + */ + SetBounds(x: number, y: number, width: number, height: number): void; + + /** + * Sets the browser window focus state. + * @param value Is the window focused? + */ + SetFocus(value: boolean): void; + + SetName(browserName: string): void; + + /** + * Registers a callback to be called when a context menu is shown. + * @param callback The callback function to be called. + */ + SetShowContextMenuCallback(callback: (data: BrowserViewContextMenu) => void): void; + + /** + * Registers a callback to be called when a steam:// protocol URL is loaded. + */ + SetSteamURLCallback(callback: (steamURL: string) => void): void; + + /** + * @todo unconfirmed + */ + SetTouchGesturesToCancel(gestures: TouchGestureType[]): void; + + SetVRKeyboardVisibility(value: boolean): void; + + SetVisible(value: boolean): void; + + SetWindowStackingOrder(order: EWindowStackingOrder): void; + + /** + * Stop the "find in page" function. + */ + StopFindInPage(): void; + + /** + * Stop listening for an event. + * @param event The event to stop listening to. + * @param callback The callback function to be called. + */ + off(event: BrowserViewEvent, callback: (args: any) => void): void; + + /** + * Start listening for an event. + * @param event The event to start listening to. + * @param callback The callback function to be called. + */ + on(event: BrowserViewEvent, callback: (args: any) => void): void; + + /** + * Fires when an `alert()` dialog appears. + */ + on(event: 'alert-dialog', callback: (message: string) => void): void; + + /** + * Fires when the browser is about to get destroyed. + */ + on(event: 'before-close', callback: () => void): void; + + /** + * Fires when a URL gets blocked. + * @todo not SetBlockedProtocols, maybe only steam links + */ + on(event: 'blocked-request', callback: (blockedURL: string) => void): void; + + /** + * Fires when `CanGoBack() or `CanGoForward()` state changes. + */ + on(event: 'can-go-back-forward-changed', callback: (canGoBackward: boolean, canGoForward: boolean) => void): void; + + /** + * Fires when a `confirm()` dialog appears. + */ + on(event: 'confirm-dialog', callback: (message: string) => void): void; + + /** + * Fires when the browser's favicon changes. + */ + on(event: 'favicon-urls-changed', callback: (faviconURLs: string[]) => void): void; + + /** + * Fires when "Find in page" gets its results. + */ + on(event: 'find-in-page-results', callback: (results: number, activeResultIndex: number) => void): void; + + /** + * Fires when the page finishes loading. + */ + on(event: 'finished-request', callback: (currentURL: string, previousURL: string) => void): void; + + /** + * Fires when the browser goes focused or vice versa. + */ + on(event: 'focus-changed', callback: (focused: boolean) => void): void; + + /** + * Fires when the browser goes fullscreen or vice versa. + */ + on(event: 'full-screen', callback: (fullscreen: boolean) => void): void; + + /** + * Fires when history changes occur. + */ + on(event: 'history-changed', callback: (history: BrowserViewHistory) => void): void; + + /** + * Fires when the URL fails to load. + */ + on(event: 'load-error', callback: (errorCode: number, errorURL: string, errorDescription: string) => void): void; + + /** + * @todo Same as PostMessage? + */ + on(event: 'message', callback: (args: any) => void): void; + + on(event: 'new-tab', callback: (args: any) => void): void; + + /** + * Fires when a node gets focused. + */ + on( + event: 'node-has-focus', + callback: ( + elementIdOrTagName: string, + elementTag: string, + param2: any, + param3: string, + param4: boolean, + ) => void, + ): void; + + on(event: 'page-security', callback: (url: string, pageSecurity: BrowserViewPageSecurity) => void): void; + + /** + * Fires when the page's `` changes. + */ + on(event: 'set-title', callback: (title: string) => void): void; + + /** + * Fires when the page starts loading. + */ + on(event: 'start-loading', callback: (url: string, param1: boolean) => void): void; + + /** + * Fires when the page starts loading. + */ + on(event: 'start-request', callback: (url: string) => void): void; + + /** + * Fires when "Find in page" gets toggled. + */ + on(event: 'toggle-find-in-page', callback: () => void): void; +} + + +export interface BrowserViewBounds { + x: number; + y: number; + width: number; + height: number; +} + +export interface BrowserViewContextMenu { + /** + * Mouse X position inside the browser view. + */ + coord_x: number; + /** + * Mouse Y position inside the browser view. + */ + coord_y: number; + custom_commands: BrowserViewContextMenuCustomCommand[]; + /** + * Bitmask representing edit state. + * @remarks Appears on editable elements like `<input>`, etc. + * @example + * May be used with BrowserViewContextMenuEditFlag: + * ```js + * edit_state_flags & BrowserViewContextMenuEditFlag.CanCut != 0 // Can cut text + * ``` + */ + edit_state_flags?: number; + /** + * The misspelled word the cursor is on. + * @remarks Appears on an editable element with text. + */ + misspelled_word?: string; + /** + * Browser page URL. + * @todo Appears when there is selected text? + */ + link_url?: string; + /** + * Browser page URL. + */ + page_url: string; + /** + * Selected text. + * @remarks Appears when there is selected text. + */ + selection_text?: string; + /** + * Bitmask representing context menu type. + * @example + * May be used with BrowserViewContextMenuTypeFlag: + * ```js + * type_flags & BrowserViewContextMenuTypeFlag.Selection != 0 // Selected text present + * ``` + */ + type_flags: number; + /** + * Browser page URL. + * @todo Appears when there is selected text? + */ + unfiltered_link_url?: string; +} + +export interface BrowserViewContextMenuCustomCommand { + id: number; + label: string; +} + +export enum BrowserViewContextMenuCommand { + Close = -1, + OpenDevTools = 26500, + CloseDevTools = 26501, + InspectElement = 26502, + OpenLinkInNewTab = 26503, +} + +export enum EWindowStackingOrder { + Bottom, + Top, +} + +export type BrowserViewEvent = + | 'alert-dialog' + | 'before-close' + | 'blocked-request' + | 'can-go-back-forward-changed' + | 'confirm-dialog' + | 'favicon-urls-changed' + | 'find-in-page-results' + | 'finished-request' + | 'focus-changed' + | 'full-screen' + | 'history-changed' + | 'load-error' + | 'message' + | 'new-tab' + | 'node-has-focus' + | 'page-security' + | 'set-title' + | 'start-loading' + | 'start-request' + | 'toggle-find-in-page'; + + +export interface BrowserViewHistory { + index: number; + entries: BrowserViewHistoryEntry[]; +} + +export interface BrowserViewHistoryEntry { + url: string; +} + +export interface BrowserViewPageSecurity { + bHasCertError: boolean; + bIsEVCert: boolean; + bIsSecure: boolean; + certExpiry: number; + certName: string; + issuerName: string; + nCertBits: number; +} diff --git a/src/deck-components/steam-client/browser-view/index.ts b/src/deck-components/steam-client/browser-view/index.ts new file mode 100644 index 00000000..0af2a749 --- /dev/null +++ b/src/deck-components/steam-client/browser-view/index.ts @@ -0,0 +1,27 @@ +import {BrowserViewPopup} from "./BrowserViewPopup"; + +export interface BrowserView { + Create(browser?: BrowserViewInit): BrowserViewPopup; + + CreatePopup(browser?: BrowserViewInit): { + /** + * URL for usage with `window.open()`. + */ + strCreateURL: string; + browserView: BrowserViewPopup; + }; + + Destroy(browser: BrowserViewInit): void; + + PostMessageToParent(message: string, args: string): void; +} + +export interface BrowserViewInit { + bOnlyAllowTrustedPopups?: boolean; + parentPopupBrowserID?: number; + /** Initial URL to go to. */ + strInitialURL?: string; + strUserAgentIdentifier?: string; + strUserAgentOverride?: string; + strVROverlayKey?: string; +} diff --git a/src/deck-components/steam-client/index.ts b/src/deck-components/steam-client/index.ts new file mode 100644 index 00000000..ee8ce104 --- /dev/null +++ b/src/deck-components/steam-client/index.ts @@ -0,0 +1,608 @@ +import {AppDetails, Apps, Shortcut} from "./App"; +import {Auth} from "./Auth"; +import {Broadcast} from "./Broadcast"; +import {Browser} from "./Browser"; +import {BrowserView} from "./browser-view"; +import {ClientNotifications} from "./ClientNotifications"; +import {Cloud} from "./Cloud"; +import {CommunityItems} from "./CommunityItems"; +import {Console} from "./Console"; +import {Customization} from "./Customization"; +import {Downloads} from "./Downloads"; +import {FamilySharing} from "./FamilySharing"; +import {FriendSettings} from "./FriendSettings"; +import {Friends} from "./Friends"; +import {GameNotes} from "./GameNotes"; +import {GameRecording} from "./GameRecording"; +import {GameSessions} from "./GameSessions"; +import {Input} from "./Input"; +import {InstallFolder} from "./InstallFolder"; +import {Installs} from "./Installs"; +import {Messaging} from "./Messaging"; +import {Music} from "./Music"; +import {Notifications} from "./Notifications"; +import {OpenVR} from "./OpenVR"; +import {Overlay} from "./Overlay"; +import {Storage} from "./Storage"; +import {Parental} from "./Parental"; +import {RemotePlay} from "./RemotePlay"; +import {ServerBrowser} from "./ServerBrowser"; +import {Screenshots} from "./Screenshots"; +import {Settings} from "./Settings"; +import {SharedConnection} from "./SharedConnection"; +import {Stats} from "./Stats"; +import {SteamChina} from "./SteamChina"; +import {Streaming} from "./Streaming"; +import {System} from "./system"; +import {UI} from "./UI"; +import {Updates} from "./Updates"; +import {User} from "./User"; +import {WebChat} from "./WebChat"; +import {WebUITransport} from "./WebUITransport"; +import {Window} from "./Window"; +import {Device} from "./system/network/Device"; + +export interface SteamClient { + Apps: Apps; + Auth: Auth; + Broadcast: Broadcast; + Browser: Browser; + BrowserView: BrowserView; + ClientNotifications: ClientNotifications; + Cloud: Cloud; + CommunityItems: CommunityItems; + Console: Console; + Customization: Customization; + Downloads: Downloads; + FamilySharing: FamilySharing; + Friends: Friends; + FriendSettings: FriendSettings; + GameNotes: GameNotes; + GameRecording: GameRecording; + GameSessions: GameSessions; + Input: Input; + InstallFolder: InstallFolder; + Installs: Installs; + MachineStorage: Storage; + Messaging: Messaging; + Music: Music; + Notifications: Notifications; + OpenVR: OpenVR; + Overlay: Overlay; + Parental: Parental; + RemotePlay: RemotePlay; + RoamingStorage: Storage; + Screenshots: Screenshots; + ServerBrowser: ServerBrowser; + Settings: Settings; + SharedConnection: SharedConnection; + Stats: Stats; + SteamChina: SteamChina; + Storage: Storage; + Streaming: Streaming; + System: System; + UI: UI; + URL: URL; + Updates: Updates; + User: User; + WebChat: WebChat; + WebUITransport: WebUITransport; + Window: Window; +} + +export enum Result { + OK = 1, + Fail = 2, + NoConnection = 3, + InvalidPassword = 5, + LoggedInElsewhere = 6, + InvalidProtocolVer = 7, + InvalidParam = 8, + FileNotFound = 9, + Busy = 10, + InvalidState = 11, + InvalidName = 12, + InvalidEmail = 13, + DuplicateName = 14, + AccessDenied = 15, + Timeout = 16, + Banned = 17, + AccountNotFound = 18, + InvalidSteamID = 19, + ServiceUnavailable = 20, + NotLoggedOn = 21, + Pending = 22, + EncryptionFailure = 23, + InsufficientPrivilege = 24, + LimitExceeded = 25, + Revoked = 26, + Expired = 27, + AlreadyRedeemed = 28, + DuplicateRequest = 29, + AlreadyOwned = 30, + IPNotFound = 31, + PersistFailed = 32, + LockingFailed = 33, + LogonSessionReplaced = 34, + ConnectFailed = 35, + HandshakeFailed = 36, + IOFailure = 37, + RemoteDisconnect = 38, + ShoppingCartNotFound = 39, + Blocked = 40, + Ignored = 41, + NoMatch = 42, + AccountDisabled = 43, + ServiceReadOnly = 44, + AccountNotFeatured = 45, + AdministratorOK = 46, + ContentVersion = 47, + TryAnotherCM = 48, + PasswordRequiredToKickSession = 49, + AlreadyLoggedInElsewhere = 50, + Suspended = 51, + Cancelled = 52, + DataCorruption = 53, + DiskFull = 54, + RemoteCallFailed = 55, + PasswordUnset = 56, + ExternalAccountUnlinked = 57, + PSNTicketInvalid = 58, + ExternalAccountAlreadyLinked = 59, + RemoteFileConflict = 60, + IllegalPassword = 61, + SameAsPreviousValue = 62, + AccountLogonDenied = 63, + CannotUseOldPassword = 64, + InvalidLoginAuthCode = 65, + AccountLogonDeniedNoMail = 66, + HardwareNotCapableOfIPT = 67, + IPTInitError = 68, + ParentalControlRestricted = 69, + FacebookQueryError = 70, + ExpiredLoginAuthCode = 71, + IPLoginRestrictionFailed = 72, + AccountLockedDown = 73, + AccountLogonDeniedVerifiedEmailRequired = 74, + NoMatchingURL = 75, + BadResponse = 76, + RequirePasswordReEntry = 77, + ValueOutOfRange = 78, + UnexpectedError = 79, + Disabled = 80, + InvalidCEGSubmission = 81, + RestrictedDevice = 82, + RegionLocked = 83, + RateLimitExceeded = 84, + AccountLoginDeniedNeedTwoFactor = 85, + ItemDeleted = 86, + AccountLoginDeniedThrottle = 87, + TwoFactorCodeMismatch = 88, + TwoFactorActivationCodeMismatch = 89, + AccountAssociatedToMultiplePartners = 90, + NotModified = 91, + NoMobileDevice = 92, + TimeNotSynced = 93, + SmsCodeFailed = 94, + AccountLimitExceeded = 95, + AccountActivityLimitExceeded = 96, + PhoneActivityLimitExceeded = 97, + RefundToWallet = 98, + EmailSendFailure = 99, + NotSettled = 100, + NeedCaptcha = 101, + GSLTDenied = 102, + GSOwnerDenied = 103, + InvalidItemType = 104, + IPBanned = 105, + GSLTExpired = 106, + InsufficientFunds = 107, + TooManyPending = 108, + NoSiteLicensesFound = 109, + WGNetworkSendExceeded = 110, + AccountNotFriends = 111, + LimitedUserAccount = 112, +} + +export enum EBrowserType { + /** + * No window is created (like SharedJSContext). + */ + OffScreen, + OpenVROverlay, + OpenVROverlay_Dashboard, + /** + * A normal window. + */ + DirectHWND, + /** + * A borderless window. + */ + DirectHWND_Borderless, + /** + * An initially hidden window. + * May be shown with {@link SteamClient.Window.ShowWindow}. + */ + DirectHWND_Hidden, + ChildHWNDNative, + Offscreen_SteamUI = 12, + OpenVROverlay_Subview, +} + +export enum UIMode { + Unknown = -1, + GamePad = 4, + Desktop = 7, +} + +export interface BrowserContext { + /** + * Window type. + */ + m_eBrowserType?: EBrowserType; + /** + * The UI mode in use. + */ + m_eUIMode?: UIMode; + /** + * @todo Appears when EBrowserType == 0 ? + */ + m_gameID?: string; + /** + * @todo Same as `SteamClient.Browser.GetBrowserID()` ? + */ + m_nBrowserID: number; + /** + * Game's app ID. + */ + m_unAppID?: number; + /** + * If overlay, game's PID. + */ + m_unPID: number; +} + +/** + * Represents the response of an operation. It appears to be not necessary to await for this operation response. It is only used to indicate the result of an operation. + */ +export interface OperationResponse { + /** + * The result code of the operation. + */ + result: Result; + + /** + * A message describing the result of the operation. + */ + message: string; +} + +export interface Unregisterable { + /** + * Unregister the callback. + */ + unregister(): void; +} + +/** + * JsPb message class. + */ +export interface JsPbMessageClass { + /** + * @todo Returns {@link JsPbMessage}, but not sure how to do it for the messages. + */ + deserializeBinary(data: ArrayBuffer): any; +} + +/** + * Deserialized JsPb message. + */ +export interface JsPbMessage { + getClassName(): string; + + serializeBase64String(): string; + + serializeBinary(): Uint8Array; + + /** + * Converts the message to an object. + */ + toObject(includeJsPbInstance: boolean): any; +} + + + + + + +//todo: Organize the interfaces below +export interface SteamShortcut { + appid: number; + data: Shortcut; +} + +export interface AppData { + details: AppDetails; + // more +} + +export interface SteamDatagramLinkInstantaneousStats { + out_packets_per_sec_x10: number | undefined; + out_bytes_per_sec: number | undefined; + in_packets_per_sec_x10: number | undefined; + in_bytes_per_sec: number | undefined; + ping_ms: number | undefined; + packets_dropped_pct: number | undefined; + packets_weird_sequence_pct: number | undefined; + peak_jitter_usec: number | undefined; +} + +export interface SteamDatagramLinkLifetimeStats { + connected_seconds: number | undefined; + packets_sent: number | undefined; + kb_sent: number | undefined; + packets_recv: number | undefined; + kb_recv: number | undefined; + packets_recv_sequenced: number | undefined; + packets_recv_dropped: number | undefined; + packets_recv_out_of_order: number | undefined; + packets_recv_out_of_order_corrected: number | undefined; + packets_recv_duplicate: number | undefined; + packets_recv_lurch: number | undefined; + multipath_packets_recv_sequenced: number[]; + multipath_packets_recv_later: number[]; + multipath_send_enabled: number | undefined; + quality_histogram_100: number | undefined; + quality_histogram_99: number | undefined; + quality_histogram_97: number | undefined; + quality_histogram_95: number | undefined; + quality_histogram_90: number | undefined; + quality_histogram_75: number | undefined; + quality_histogram_50: number | undefined; + quality_histogram_1: number | undefined; + quality_histogram_dead: number | undefined; + quality_ntile_2nd: number | undefined; + quality_ntile_5th: number | undefined; + quality_ntile_25th: number | undefined; + quality_ntile_50th: number | undefined; + ping_histogram_25: number | undefined; + ping_histogram_50: number | undefined; + ping_histogram_75: number | undefined; + ping_histogram_100: number | undefined; + ping_histogram_125: number | undefined; + ping_histogram_150: number | undefined; + ping_histogram_200: number | undefined; + ping_histogram_300: number | undefined; + ping_histogram_max: number | undefined; + ping_ntile_5th: number | undefined; + ping_ntile_50th: number | undefined; + ping_ntile_75th: number | undefined; + ping_ntile_95th: number | undefined; + ping_ntile_98th: number | undefined; + jitter_histogram_negligible: number | undefined; + jitter_histogram_1: number | undefined; + jitter_histogram_2: number | undefined; + jitter_histogram_5: number | undefined; + jitter_histogram_10: number | undefined; + jitter_histogram_20: number | undefined; + txspeed_max: number | undefined; + txspeed_histogram_16: number | undefined; + txspeed_histogram_32: number | undefined; + txspeed_histogram_64: number | undefined; + txspeed_histogram_128: number | undefined; + txspeed_histogram_256: number | undefined; + txspeed_histogram_512: number | undefined; + txspeed_histogram_1024: number | undefined; + txspeed_histogram_max: number | undefined; + txspeed_ntile_5th: number | undefined; + txspeed_ntile_50th: number | undefined; + txspeed_ntile_75th: number | undefined; + txspeed_ntile_95th: number | undefined; + txspeed_ntile_98th: number | undefined; + rxspeed_max: number | undefined; + rxspeed_histogram_16: number | undefined; + rxspeed_histogram_32: number | undefined; + rxspeed_histogram_64: number | undefined; + rxspeed_histogram_128: number | undefined; + rxspeed_histogram_256: number | undefined; + rxspeed_histogram_512: number | undefined; + rxspeed_histogram_1024: number | undefined; + rxspeed_histogram_max: number | undefined; + rxspeed_ntile_5th: number | undefined; + rxspeed_ntile_50th: number | undefined; + rxspeed_ntile_75th: number | undefined; + rxspeed_ntile_95th: number | undefined; + rxspeed_ntile_98th: number | undefined; +} + +export interface SteamDatagramConnectionQuality { + instantaneous: SteamDatagramLinkInstantaneousStats | undefined; + lifetime: SteamDatagramLinkLifetimeStats | undefined; +} + +export interface SteamNetworkingICESessionSummary { + failure_reason_code: number | undefined; + local_candidate_types: number | undefined; + remote_candidate_types: number | undefined; + initial_route_kind: number | undefined; + initial_ping: number | undefined; + initial_score: number | undefined; + negotiation_ms: number | undefined; + best_route_kind: number | undefined; + best_ping: number | undefined; + best_score: number | undefined; + best_time: number | undefined; + selected_seconds: number | undefined; + user_settings: number | undefined; + ice_enable_var: number | undefined; + local_candidate_types_allowed: number | undefined; +} + +export interface SteamNetworkingP2PSDRRoutingSummary { + initial_ping: number | undefined; + initial_ping_front_local: number | undefined; + initial_ping_front_remote: number | undefined; + initial_score: number | undefined; + initial_pop_local: number | undefined; + initial_pop_remote: number | undefined; + best_ping: number | undefined; + best_ping_front_local: number | undefined; + best_ping_front_remote: number | undefined; + best_score: number | undefined; + best_pop_local: number | undefined; + best_pop_remote: number | undefined; + best_time: number | undefined; + negotiation_ms: number | undefined; + selected_seconds: number | undefined; +} + +export interface SteamDatagramP2PRoutingSummary { + ice: SteamNetworkingICESessionSummary | undefined; + sdr: SteamNetworkingP2PSDRRoutingSummary | undefined; +} + + +/** + * CMsgNetworkDevicesData + */ +export interface MsgNetworkDevicesData extends JsPbMessage { + devices(): Device[]; + + is_wifi_enabled(): boolean; + + is_wifi_scanning_enabled(): boolean; +} + + +/** + * CGameNetworkingUI_ConnectionState + */ +export interface GameNetworkingUI_ConnectionState extends JsPbMessage { + connection_key(): string; + + appid(): number; + + connection_id_local(): number; + + identity_local(): string; + + identity_remote(): string; + + connection_state(): number; + + start_time(): number; + + close_time(): number; + + close_reason(): number; + + close_message(): string; + + status_loc_token(): string; + + transport_kind(): number; + + sdrpopid_local(): string; + + sdrpopid_remote(): string; + + address_remote(): string; + + p2p_routing(): SteamDatagramP2PRoutingSummary; + + ping_interior(): number; + + ping_remote_front(): number; + + ping_default_internet_route(): number; + + e2e_quality_local(): SteamDatagramConnectionQuality; + + e2e_quality_remote(): SteamDatagramConnectionQuality; + + e2e_quality_remote_instantaneous_time(): string; + + e2e_quality_remote_lifetime_time(): string; + + front_quality_local(): SteamDatagramConnectionQuality; + + front_quality_remote(): SteamDatagramConnectionQuality; + + front_quality_remote_instantaneous_time(): string; + + front_quality_remote_lifetime_time(): string; +} + +/** + * CMsgHotkey + */ +export interface MsgHotkey extends JsPbMessage { + key_code(): number; + + alt_key(): boolean; + + shift_key(): boolean; + + ctrl_key(): boolean; + + meta_key(): boolean; + + display_name(): string; +} + +export enum ControllerRumbleSetting { + ControllerPreference = 0, + Off = 1, + On = 2, +} + +export enum MusicRepeatStatus { + None = 0, + All = 1, + Once = 2, + Max = 3, +} + +export enum BrowserViewContextMenuTypeFlag { + None = 0, + Page = 1 << 0, + Frame = 1 << 1, + Link = 1 << 2, + Media = 1 << 3, + Selection = 1 << 4, + Editable = 1 << 5, +} + +export enum BrowserViewContextMenuEditFlag { + None = 0, + CanUndo = 1 << 0, + CanRedo = 1 << 1, + CanCut = 1 << 2, + CanCopy = 1 << 3, + CanPaste = 1 << 4, + CanDelete = 1 << 5, + CanSelectAll = 1 << 6, + CanTranslate = 1 << 7, +} + +/** + * @todo May be useful for ParentalSettings.feature ? + */ +export enum ParentalFeature { + Invalid = 0, + Store = 1, + Community = 2, + Profile = 3, + Friends = 4, + News = 5, + Trading = 6, + Settings = 7, + Console = 8, + Browser = 9, + ParentalSetup = 10, + Library = 11, + Test = 12, + SiteLicense = 13, + KioskMode = 14, + Max = 15, +} diff --git a/src/deck-components/steam-client/system/Audio.ts b/src/deck-components/steam-client/system/Audio.ts new file mode 100644 index 00000000..f9031967 --- /dev/null +++ b/src/deck-components/steam-client/system/Audio.ts @@ -0,0 +1,206 @@ +import {OperationResponse, Unregisterable} from "../index"; + +/** + * Represents various functions related to Steam system audio. + */ +export interface Audio { + /** + * Clears the default device override for a specified audio type. + * @param audioType The audio type (0 for input, 1 for output). + * @returns A Promise indicating the result of the operation. + */ + ClearDefaultDeviceOverride(audioType: number): Promise<OperationResponse>; + + /** + * Retrieves information about audio applications. + * @returns A Promise that resolves to information about audio applications. + */ + GetApps(): Promise<ApplicationsAudio>; + + /** + * Retrieves information about audio devices. + * @returns A Promise that resolves to information about audio devices. + */ + GetDevices(): Promise<AudioDeviceInfo>; + + /** + * Registers a callback to be called when a new audio application is added. + * @param callback The callback function to be called. + * @returns An object that can be used to unregister the callback. + */ + RegisterForAppAdded(callback: (appAudioAdded: ApplicationAudio) => void): Unregisterable; + + /** + * Registers a callback to be called when an audio application is removed. + * @param callback The callback function to be called. + * @returns An object that can be used to unregister the callback. + */ + RegisterForAppRemoved(callback: (appAudioId: number) => void): Unregisterable; + + /** + * Registers a callback to be called when the volume of an audio application changes. + * @param callback The callback function to be called. + * @returns An object that can be used to unregister the callback. + */ + RegisterForAppVolumeChanged(callback: (appAudioId: number, volume: number) => void): Unregisterable; + + /** + * Registers a callback to be called when a new audio device is added. + * @param callback The callback function to be called. + * @returns An object that can be used to unregister the callback. + */ + RegisterForDeviceAdded(callback: (audioDevice: Device) => void): Unregisterable; + + /** + * Registers a callback to be called when an audio device is removed. + * @param callback The callback function to be called. + * @returns An object that can be used to unregister the callback. + */ + RegisterForDeviceRemoved(callback: (audioDeviceId: number) => void): Unregisterable; + + /** + * Registers a callback to be called when the volume of an audio device changes. + * @param callback The callback function to be called. + * @returns An object that can be used to unregister the callback. + */ + RegisterForDeviceVolumeChanged(callback: (audioDeviceId: number, audioType: number, volume: number) => void): Unregisterable; + + RegisterForServiceConnectionStateChanges(callback: (param0: any) => void): Unregisterable; + + /** + * Registers a callback to be called when volume buttons are pressed. + * @param callback The callback function to be called. + * @returns An object that can be used to unregister the callback. + */ + RegisterForVolumeButtonPressed(callback: (volumeUpPressed: boolean) => void): Unregisterable; + + /** + * Sets the volume of an audio application. + * @param appAudioId The ID of the audio application. + * @param volume The volume level (floating point value between 0 and 1). + * @returns A Promise indicating the result of the operation. + */ + SetAppVolume(appAudioId: number, volume: number): Promise<OperationResponse>; + + /** + * Sets the default device override for a specified audio type. + * @param audioDeviceId The ID of the audio device. + * @param audioType The audio type (0 for input, 1 for output). + * @returns A Promise indicating the result of the operation. + */ + SetDefaultDeviceOverride(audioDeviceId: number, audioType: number): Promise<OperationResponse>; + + /** + * Sets the volume of an audio device. + * @param audioDeviceId The ID of the audio device. + * @param audioType The audio type (0 for input, 1 for output). + * @param volume The volume level (floating point value between 0 and 1). + * @returns A Promise indicating the result of the operation. + */ + SetDeviceVolume(audioDeviceId: number, audioType: number, volume: number): Promise<OperationResponse>; +} + +/** + * Represents details about an array of application audio sessions. + */ +export interface ApplicationsAudio { + /** + * An array of application audio sessions. + */ + apps: ApplicationAudio[]; +} + +/** + * Represents details about an application audio session. + */ +export interface ApplicationAudio { + /** + * The ID of the application audio. + */ + id: number; + + /** + * The name of the application (e.g., Spotify, YouTube from a browser, etc.). + */ + strName: string; + + /** + * The volume level of the application (floating point value between 0 and 1). + */ + flVolume: number; +} + +/** + * Represents details about audio devices and information about the active audio device. + */ +export interface AudioDeviceInfo { + /** + * The ID of the active output audio device. + */ + activeOutputDeviceId: number; + + /** + * The ID of the active input audio device. + */ + activeInputDeviceId: number; + + /** + * The ID of the overridden output audio device (-1 if not overridden). + */ + overrideOutputDeviceId: number; + + /** + * The ID of the overridden input audio device (-1 if not overridden). + */ + overrideInputDeviceId: number; + + /** + * An array of audio devices. + */ + vecDevices: Device[]; +} + +/** + * Represents details about an audio device. + */ +export interface Device { + /** + * The identifier of the audio device. + */ + id: number; + + /** + * The name of the audio device. + */ + sName: string; + + /** + * Indicates if the device has audio output. + */ + bHasOutput: boolean; + + /** + * Indicates if the device is the default output device. + */ + bIsDefaultOutputDevice: boolean; + + /** + * The volume level of the audio output device (floating point value between 0 and 1). + */ + flOutputVolume: number; + + /** + * Indicates if the device has audio input. + */ + bHasInput: boolean; + + /** + * Indicates if the device is the default input device. + */ + bIsDefaultInputDevice: boolean; + + /** + * The volume level of the audio input device (floating point value between 0 and 1). + */ + flInputVolume: number; +} diff --git a/src/deck-components/steam-client/system/AudioDevice.ts b/src/deck-components/steam-client/system/AudioDevice.ts new file mode 100644 index 00000000..8aadef12 --- /dev/null +++ b/src/deck-components/steam-client/system/AudioDevice.ts @@ -0,0 +1,116 @@ +import {JsPbMessage, Unregisterable} from "../index"; + +export interface AudioDevice { + /** + * If `data` is deserialized, returns {@link MsgSystemAudioManagerState}. + * @returns An object that can be used to unregister the callback. + */ + RegisterForStateChanges(callback: (data: ArrayBuffer) => void): Unregisterable; + + UpdateSomething(param0: any): any; // e.UpdateSomething(t.serializeBase64String()) +} + +/** + * CMsgSystemAudioManagerState + */ +export interface MsgSystemAudioManagerState extends JsPbMessage { + counter(): number | undefined; + + hw(): MsgSystemAudioManagerStateHW | undefined; + + rtime_filter(): number | undefined; +} + +export interface MsgSystemAudioManagerStateHW { + devices: MsgSystemAudioManagerDevice[]; + nodes: MsgSystemAudioManagerNode[]; + ports: MsgSystemAudioManagerPort[]; + links: MsgSystemAudioManagerLink[]; +} + +export interface MsgSystemAudioManagerDevice { + base: MsgSystemAudioManagerObject | undefined; + name: string | undefined; + nick: string | undefined; + description: string | undefined; + api: string | undefined; +} + +export interface MsgSystemAudioManagerNode { + base: MsgSystemAudioManagerObject | undefined; + device_id: number | undefined; + name: string | undefined; + nick: string | undefined; + description: string | undefined; + edirection: SystemAudioDirection | undefined; + volume: MsgSystemAudioVolume | undefined; +} + +export interface MsgSystemAudioManagerPort { + base: MsgSystemAudioManagerObject | undefined; + node_id: number | undefined; + name: string | undefined; + alias: string | undefined; + etype: SystemAudioPortType | undefined; + edirection: SystemAudioPortDirection | undefined; + is_physical: boolean | undefined; + is_terminal: boolean | undefined; + is_control: boolean | undefined; + is_monitor: boolean | undefined; +} + +export interface MsgSystemAudioVolume { + entries: MsgSystemAudioVolumeChannelEntry[] | undefined; + is_muted: boolean | undefined; +} + +export interface MsgSystemAudioVolumeChannelEntry { + echannel: SystemAudioChannel | undefined; + volume: number | undefined; +} + +export interface MsgSystemAudioManagerLink { + base: MsgSystemAudioManagerObject | undefined; + output_node_id: number | undefined; + output_port_id: number | undefined; + input_node_id: number | undefined; + input_port_id: number | undefined; +} + +export interface MsgSystemAudioManagerObject { + id: number | undefined; + rtime_last_update: number | undefined; +} + +export enum SystemAudioDirection { + Invalid = 0, + Input = 1, + Output = 2, +} + +export enum SystemAudioPortDirection { + Invalid = 0, + Input = 1, + Output = 2, +} + +export enum SystemAudioPortType { + Invalid = 0, + Unknown = 1, + Audio32f = 2, + Midi8b = 3, + Video32RGBA = 4, +} + +export enum SystemAudioChannel { + Invalid = 0, + Aggregated = 1, + FrontLeft = 2, + FrontRight = 3, + LFE = 4, + BackLeft = 5, + BackRight = 6, + FrontCenter = 7, + Unknown = 8, + Mono = 9, +} diff --git a/src/deck-components/steam-client/system/Bluetooth.ts b/src/deck-components/steam-client/system/Bluetooth.ts new file mode 100644 index 00000000..35d885cd --- /dev/null +++ b/src/deck-components/steam-client/system/Bluetooth.ts @@ -0,0 +1,178 @@ +import {OperationResponse, Unregisterable} from "../index"; + +/** + * Provides functionality for managing Bluetooth devices and interactions. + */ +export interface Bluetooth { + /** + * Cancels an ongoing pairing request with a Bluetooth device. + * @param adapterId The ID of the Bluetooth adapter. + * @param deviceId The ID of the Bluetooth device to cancel pairing with. + * @returns A Promise that resolves with the result of the cancellation. + */ + CancelPairing(adapterId: number, deviceId: number): Promise<OperationResponse>; + + /** + * Connects to a paired Bluetooth device using the specified adapter. + * @param adapterId The ID of the Bluetooth adapter. + * @param deviceId The ID of the paired Bluetooth device to connect to. + * @returns A Promise that resolves with the result of the connection attempt. + */ + Connect(adapterId: number, deviceId: number): Promise<OperationResponse>; + + /** + * Disconnects from a currently connected Bluetooth device using the specified adapter. + * @param adapterId The ID of the Bluetooth adapter. + * @param deviceId The ID of the connected Bluetooth device to disconnect from. + * @returns A Promise that resolves with the result of the disconnection. + */ + Disconnect(adapterId: number, deviceId: number): Promise<OperationResponse>; + + /** + * Initiates pairing with a Bluetooth device using the specified adapter. + * @param adapterId The ID of the Bluetooth adapter. + * @param deviceId The ID of the Bluetooth device to initiate pairing with. + * @returns A Promise that resolves with the result of the pairing attempt. + */ + Pair(adapterId: number, deviceId: number): Promise<OperationResponse>; + + /** + * Registers a callback function to be called when the Bluetooth state changes. + * @param callback The callback function to be called. + * @returns An object that can be used to unregister the callback. + */ + RegisterForStateChanges(callback: (bluetoothStateChange: BluetoothStateChange) => void): Unregisterable; + + /** + * Sets whether the Bluetooth adapter should be in discovering mode. + * @param adapterId The ID of the Bluetooth adapter. + * @param value `true` to enable discovering mode, `false` to disable it. + * @returns A Promise that resolves with the result of the operation. + */ + SetAdapterDiscovering(adapterId: number, value: boolean): Promise<OperationResponse>; + + /** + * Enables or disables Bluetooth functionality. + * @param bluetooth `true` to enable Bluetooth, `false` to disable it. + * @returns A Promise that resolves with the result of the operation. + */ + SetEnabled(bluetooth: boolean): Promise<OperationResponse>; + + /** + * Unpairs a Bluetooth device from the adapter. + * @param adapterId The ID of the Bluetooth adapter. + * @param deviceId The ID of the Bluetooth device to unpair with. + * @returns A Promise that resolves with the result of the unpairing request. + */ + UnPair(adapterId: number, deviceId: number): Promise<OperationResponse>; +} + +/** + * Represents a change in the state of Bluetooth adapters and devices. + */ +export interface BluetoothStateChange { + /** + * An array of Bluetooth adapters with their current state. + */ + vecAdapters: BluetoothAdapter[]; + + /** + * An array of Bluetooth devices with their current state. + */ + vecDevices: BluetoothDevice[]; + + /** + * Indicates whether Bluetooth is enabled (`true`) or disabled (`false`). + */ + bEnabled: boolean; +} + +/** + * Represents information about a Bluetooth adapter. + */ +export interface BluetoothAdapter { + /** + * The unique identifier of the Bluetooth adapter. + */ + nId: number; + + /** + * The MAC address of the Bluetooth adapter. + */ + sMAC: string; + + /** + * The name of the Bluetooth adapter. + */ + sName: string; + + /** + * Indicates whether the Bluetooth adapter is enabled. + */ + bEnabled: boolean; + + /** + * Indicates whether the Bluetooth adapter is in discovering mode. + */ + bDiscovering: boolean; +} + +/** + * Represents information about a Bluetooth device. + */ +export interface BluetoothDevice { + /** + * The unique identifier of the Bluetooth device. + */ + nId: number; + + /** + * The ID of the Bluetooth adapter to which this device is discovered by / connected to. + */ + nAdapterId: number; + + /** + * The type of the Bluetooth device (e.g., headphones, mouse, keyboard). + */ + eType: BluetoothDeviceType; + + /** + * The MAC address of the Bluetooth device. + */ + sMAC: string; + + /** + * The name of the Bluetooth device. + */ + sName: string; + + /** + * Indicates whether the Bluetooth device is currently connected to the adapter. + */ + bConnected: boolean; + + /** + * Indicates whether the Bluetooth device is paired to the adapter. + */ + bPaired: boolean; + + /** + * The raw signal strength of the Bluetooth device. + */ + nStrengthRaw: number; +} + +export enum BluetoothDeviceType { + Invalid = 0, + Unknown = 1, + Phone = 2, + Computer = 3, + Headset = 4, + Headphones = 5, + Speakers = 6, + OtherAudio = 7, + Mouse = 8, + Joystick = 9, + Gamepad = 10, + Keyboard = 11, +} diff --git a/src/deck-components/steam-client/system/Devkit.ts b/src/deck-components/steam-client/system/Devkit.ts new file mode 100644 index 00000000..242643d7 --- /dev/null +++ b/src/deck-components/steam-client/system/Devkit.ts @@ -0,0 +1,11 @@ +import {Unregisterable} from "../index"; + +export interface Devkit { + DeveloperModeChanged(state: boolean): any; + + RegisterForPairingPrompt(callback: (param0: any) => any): Unregisterable; + + RespondToPairingPrompt(param0: any, param1: any): any; + + SetPairing(param0: any): any; +} diff --git a/src/deck-components/steam-client/system/Display.ts b/src/deck-components/steam-client/system/Display.ts new file mode 100644 index 00000000..3272292c --- /dev/null +++ b/src/deck-components/steam-client/system/Display.ts @@ -0,0 +1,15 @@ +import {Unregisterable} from "../index"; + +export interface Display { + EnableUnderscan(param0: boolean): any; + + RegisterForBrightnessChanges(callback: (brightnessChanges: BrightnessChange) => void): Unregisterable; + + SetBrightness(brightness: number): any; + + SetUnderscanLevel(param0: any): any; +} + +export interface BrightnessChange { + flBrightness: number; +} diff --git a/src/deck-components/steam-client/system/DisplayManager.ts b/src/deck-components/steam-client/system/DisplayManager.ts new file mode 100644 index 00000000..dd6d49f9 --- /dev/null +++ b/src/deck-components/steam-client/system/DisplayManager.ts @@ -0,0 +1,16 @@ +import {Unregisterable} from "../index"; + +// CMsgSystemDisplayManagerState, CMsgSystemDisplayManagerSetMode +export interface DisplayManager { + ClearModeOverride(displayId: any): any; + + GetState: any; + + RegisterForStateChanges(callback: () => void): Unregisterable; + + SetCompatibilityMode(displayId: any): any; + + SetGamescopeInternalResolution(width: number, height: number): any; + + SetMode(base64: string): any; // +} diff --git a/src/deck-components/steam-client/system/Dock.ts b/src/deck-components/steam-client/system/Dock.ts new file mode 100644 index 00000000..cc683ce7 --- /dev/null +++ b/src/deck-components/steam-client/system/Dock.ts @@ -0,0 +1,32 @@ +import {JsPbMessage, Unregisterable} from "../index"; +import {UpdaterState} from "../Updates"; + +// CMsgSystemDockUpdateFirmware, CMsgSystemDockState +export interface Dock { + DisarmSafetyNet(): void; + + /** + * If `data` is deserialized, returns {@link MsgSystemDockState}. + * @returns An object that can be used to unregister the callback. + */ + RegisterForStateChanges(callback: (data: ArrayBuffer) => void): Unregisterable; + + UpdateFirmware(base64String: string): any; // serialize base64 string +} + +/** + * CMsgSystemDockState + */ +export interface MsgSystemDockState extends JsPbMessage { + update_state(): SystemDockUpdateState | undefined; +} + +export interface SystemDockUpdateState { + state: UpdaterState | undefined; + rtime_last_checked: number | undefined; + version_current: string | undefined; + version_available: string | undefined; + stage_progress: number | undefined; + rtime_estimated_completion: number | undefined; + old_fw_workaround: number | undefined; +} diff --git a/src/deck-components/steam-client/system/Perf.ts b/src/deck-components/steam-client/system/Perf.ts new file mode 100644 index 00000000..594e77c1 --- /dev/null +++ b/src/deck-components/steam-client/system/Perf.ts @@ -0,0 +1,196 @@ +import {JsPbMessage, Unregisterable} from "../index"; + +// CMsgSystemPerfUpdateSettings, CMsgSystemPerfState, CMsgSystemPerfSettings +export interface Perf { + /** + * If `data` is deserialized, returns {@link MsgSystemPerfDiagnosticInfo}. + * @returns An object that can be used to unregister the callback. + */ + RegisterForDiagnosticInfoChanges(callback: (data: ArrayBuffer) => void): Unregisterable; + + /** + * If `data` is deserialized, returns {@link MsgSystemPerfState}. + * @returns An object that can be used to unregister the callback. + */ + RegisterForStateChanges(callback: (data: ArrayBuffer) => void): Unregisterable; + + UpdateSettings(base64: string): any; // serialize +} + +/** + * CMsgSystemPerfDiagnosticInfo + */ +export interface MsgSystemPerfDiagnosticInfo extends JsPbMessage { + battery_temp_c(): number | undefined; + + entries(): SystemPerfDiagnosticEntry[] | undefined; + + interfaces(): SystemPerfNetworkInterface[] | undefined; +} + +export interface SystemPerfDiagnosticEntry { + name: string | undefined; + value: string | undefined; +} + +export interface SystemPerfNetworkInterface { + name: string | undefined; + timestamp: number | undefined; + tx_bytes_total: number | undefined; + rx_bytes_total: number | undefined; + tx_bytes_per_sec: number | undefined; + rx_bytes_per_sec: number | undefined; +} + +/** + * CMsgSystemPerfState + */ +export interface MsgSystemPerfState extends JsPbMessage { + active_profile_game_id(): string | undefined; + + current_game_id(): string | undefined; + + limits(): SystemPerfLimits | undefined; + + settings(): SystemPerfSettings | undefined; +} + +export interface SystemPerfLimits { + cpu_governor_manual_min_mhz: number | undefined; + cpu_governor_manual_max_mhz: number | undefined; + fsr_sharpness_min: number | undefined; + fsr_sharpness_max: number | undefined; + gpu_performance_manual_min_mhz: number | undefined; + gpu_performance_manual_max_mhz: number | undefined; + perf_overlay_is_standalone: boolean | undefined; + is_dynamic_vrs_available: boolean | undefined; + is_manual_display_refresh_rate_available: boolean | undefined; + gpu_performance_levels_available: GPUPerformanceLevel[]; + display_refresh_manual_hz_min: number | undefined; + display_refresh_manual_hz_max: number | undefined; + fps_limit_options: number[] | undefined; + tdp_limit_min: number | undefined; + tdp_limit_max: number | undefined; + is_nis_supported: boolean | undefined; + nis_sharpness_min: number | undefined; + nis_sharpness_max: number | undefined; + display_external_refresh_manual_hz_min: number | undefined; + display_external_refresh_manual_hz_max: number | undefined; + fps_limit_options_external: number[] | undefined; + is_tearing_supported: boolean | undefined; + is_vrr_supported: boolean | undefined; + is_dynamic_refresh_rate_in_steam_supported: boolean | undefined; + is_split_scaling_and_filtering_supported: boolean | undefined; + split_scaling_filters_available: SplitScalingFilter[]; + split_scaling_scalers_available: SplitScalingScaler[]; + is_hdr_supported: boolean | undefined; + display_refresh_manual_hz_oc_max: number | undefined; + disable_refresh_rate_management: boolean | undefined; +} + +export enum GPUPerformanceLevel { + Invalid = 0, + Auto = 1, + Manual = 2, + Low = 3, + High = 4, + Profiling = 5, +} + +export enum SplitScalingFilter { + Invalid = 0, + Linear = 1, + Nearest = 2, + FSR = 3, + NIS = 4, +} + +export enum SplitScalingScaler { + Invalid = 0, + Auto = 1, + Integer = 2, + Fit = 3, + Fill = 4, + Stretch = 5, +} + +export interface SystemPerfSettings { + global: SystemPerfSettingsGlobal | undefined; + per_app: SystemPerfSettingsPerApp | undefined; +} + +export interface SystemPerfSettingsGlobal { + diagnostic_update_rate: number; + system_trace_service_state: SystemServiceState; + graphics_profiling_service_state: SystemServiceState; + perf_overlay_service_state: SystemServiceState; + perf_overlay_level: GraphicsPerfOverlayLevel; + is_show_perf_overlay_over_steam_enabled: boolean; + is_advanced_settings_enabled: boolean; + allow_external_display_refresh_control: boolean; + is_hdr_enabled: boolean; + hdr_on_sdr_tonemap_operator: HDRToneMapOperator; + is_hdr_debug_heatmap_enabled: boolean; + force_hdr_wide_gammut_for_sdr: boolean; + allow_experimental_hdr: boolean; + sdr_to_hdr_brightness: number; + debug_force_hdr_support: boolean; + force_hdr_10pq_output_debug: boolean; + is_display_oc_enabled: boolean; + is_color_management_enabled: boolean; +} + +export enum SystemServiceState { + Unavailable = 0, + Disabled = 1, + Enabled = 2, +} + +export enum GraphicsPerfOverlayLevel { + Hidden = 0, + Basic = 1, + Medium = 2, + Full = 3, + Minimal = 4, +} + +export enum HDRToneMapOperator { + Invalid = 0, + Uncharted = 1, + Reinhard = 2, +} + +export interface SystemPerfSettingsPerApp { + gpu_performance_manual_mhz: number | undefined; + fps_limit: number | undefined; + is_variable_resolution_enabled: boolean | undefined; + is_dynamic_refresh_rate_enabled: boolean | undefined; + tdp_limit: number | undefined; + cpu_governor: CPUGovernor | undefined; + cpu_governor_manual_mhz: number | undefined; + scaling_filter: number | undefined; + fsr_sharpness: number | undefined; + is_fps_limit_enabled: boolean | undefined; + is_tdp_limit_enabled: boolean | undefined; + is_low_latency_mode_enabled: boolean | undefined; + display_refresh_manual_hz: number | undefined; + is_game_perf_profile_enabled: boolean | undefined; + gpu_performance_level: GPUPerformanceLevel | undefined; + nis_sharpness: number | undefined; + display_external_refresh_manual_hz: number | undefined; + fps_limit_external: number | undefined; + is_tearing_enabled: boolean | undefined; + is_vrr_enabled: boolean | undefined; + is_composite_debug_enabled: boolean | undefined; + force_composite: boolean | undefined; + use_dynamic_refresh_rate_in_steam: boolean | undefined; + split_scaling_filter: SplitScalingFilter | undefined; + split_scaling_scaler: SplitScalingScaler | undefined; +} + +export enum CPUGovernor { + Invalid = 0, + Perf = 1, + Powersave = 2, + Manual = 3, +} diff --git a/src/deck-components/steam-client/system/Report.ts b/src/deck-components/steam-client/system/Report.ts new file mode 100644 index 00000000..bb51c7bf --- /dev/null +++ b/src/deck-components/steam-client/system/Report.ts @@ -0,0 +1,40 @@ +import {JsPbMessage, OperationResponse} from "../index"; + +export interface Report { + /** + * Generates a system report located in /tmp/steamXXXXXX (https://steamloopback.host/systemreports). + * @throws OperationResponse + */ + GenerateSystemReport(): Promise<SystemReportReply | OperationResponse>; + + /** + * Saves a report in the Desktop directory. + * @param reportId The report ID (file name) to save. + */ + SaveToDesktop(reportId: string): Promise<OperationResponse>; + + /** + * @param reportId The report ID (file name) to submit. + * @todo times out ({@link Result.Timeout}) + */ + Submit(reportId: string): Promise<OperationResponse>; +} + +export interface SystemReportReply extends OperationResponse { + /** + * If deserialized, returns {@link MsgGenerateSystemReportReply}. + */ + reply: ArrayBuffer; +} + +/** + * CMsgGenerateSystemReportReply + */ +export interface MsgGenerateSystemReportReply extends JsPbMessage { + /** + * The report file name. + */ + report_id(): string | undefined; + + set_report_id(param0: any): any; +} diff --git a/src/deck-components/steam-client/system/UI.ts b/src/deck-components/steam-client/system/UI.ts new file mode 100644 index 00000000..ea4c1fde --- /dev/null +++ b/src/deck-components/steam-client/system/UI.ts @@ -0,0 +1,33 @@ +import {Unregisterable} from "../index"; + +export interface UI { + CloseGameWindow(appId: number, windowId: number): void; + + GetGameWindowsInfo(appId: number, windowIds: number[]): Promise<GameWindowInfo>; + + RegisterForFocusChangeEvents(callback: (event: FocusChangeEvent) => void): Unregisterable; + + // appId is 0 if unknown app is focused + RegisterForOverlayGameWindowFocusChanged(callback: (appId: number, param1: number) => void): Unregisterable; + + //event.eKey, event.nControllerIndex + RegisterForSystemKeyEvents(callback: (event: any) => void): Unregisterable; // eKey +} + +export interface FocusChangeEvent { + focusedApp: FocusedApp; + rgFocusable: FocusedApp[]; +} + +export interface FocusedApp { + appid: number; + pid: number; + windowid: number; + strExeName: string; +} + +export interface GameWindowInfo { + bCanClose: boolean; + strTitle: string; + windowid: number; +} diff --git a/src/deck-components/steam-client/system/index.ts b/src/deck-components/steam-client/system/index.ts new file mode 100644 index 00000000..308d807f --- /dev/null +++ b/src/deck-components/steam-client/system/index.ts @@ -0,0 +1,371 @@ +import {JsPbMessage, OperationResponse, Unregisterable} from "../index"; +import {Audio} from "./Audio"; +import {AudioDevice} from "./AudioDevice"; +import {Bluetooth} from "./Bluetooth"; +import {Devkit} from "./Devkit"; +import {Display} from "./Display"; +import {DisplayManager} from "./DisplayManager"; +import {Dock} from "./Dock"; +import {Network} from "./network"; +import {Perf} from "./Perf"; +import {Report} from "./Report"; +import {UI} from "./UI"; + +export interface System { + Audio: Audio; + AudioDevice: AudioDevice; + Bluetooth: Bluetooth; + + /** + * @returns a boolean indicating whether the operation succeeded. + */ + CopyFile(target: string, destination: string): Promise<boolean>; + + /** + * Copies specified files to clipboard. + * Does not throw if not found. + * @param paths File paths to copy. + */ + CopyFilesToClipboard(paths: string[]): void; + + /** + * Creates a temporary folder. + * @param path The folder to create. + * @returns The created path. + * @todo Does this support relative paths ? this has some weird behavior + */ + CreateTempPath(path: string): Promise<string>; + + Devkit: Devkit; + Display: Display; + DisplayManager: DisplayManager; + Dock: Dock; + + ExitFakeCaptivePortal(): any; + + FactoryReset(): any; + + FormatStorage(forceFormat: boolean): any; + + GetOSType(): Promise<OSType>; + + GetSystemInfo(): Promise<SystemInfo>; + + IsDeckFactoryImage(): Promise<boolean>; + + IsSteamInTournamentMode(): Promise<boolean>; + + /** + * Moves a file. + * @param target Target file/folder. + * @param destination Destination path. + * @remarks Does not throw on error. + */ + MoveFile(target: string, destination: string): void; + + Network: Network; + + NotifyGameOverlayStateChanged(latestAppOverlayStateActive: boolean, appId: number): any; + + /** + * Open a dialog for choosing a file. + * @param prefs Dialog preferences. + * @returns A Promise that resolves to the selected file name. + * @throws Throws if no file was selected. + */ + OpenFileDialog(prefs: FileDialog): Promise<string | OperationResponse>; + + /** + * Open a URL in the default web browser. + */ + OpenInSystemBrowser(url: string): void; + + OpenLocalDirectoryInSystemExplorer(directory: string): void; // Opens local directory in system explorer + Perf: Perf; + + RebootToAlternateSystemPartition(): any; + + RebootToFactoryTestImage(param0: any): any; + + RegisterForAirplaneModeChanges(callback: (airplaneModeChange: AirplaneModeChange) => void): Unregisterable; + + RegisterForBatteryStateChanges(callback: (batteryStateChange: BatteryStateChange) => void): Unregisterable; + + RegisterForFormatStorageProgress(callback: () => void): Unregisterable; // {"flProgress":0,"rtEstimatedCompletionTime":0,"eStage":1} + + RegisterForOnResumeFromSuspend(callback: () => void): Unregisterable; + + RegisterForOnSuspendRequest(callback: () => void): Unregisterable; + + /** + * @returns A Promise that resolves to a ProtoBuf message. If deserialized, returns {@link MsgSystemManagerSettings}. + */ + RegisterForSettingsChanges(callback: (data: ArrayBuffer) => void): Unregisterable; + + Report: Report; + + /** + * Restarts the system. + */ + RestartPC(): any; + + SetAirplaneMode(value: boolean): void; + + ShutdownPC(): any; + + SteamRuntimeSystemInfo(): Promise<string>; + + /** + * Suspends the system. + */ + SuspendPC(): any; + + /** + * Switches to desktop mode. + */ + SwitchToDesktop(): any; + + UI: UI; + UpdateSettings: any; + + VideoRecordingDriverCheck(): any; +} + +export interface AirplaneModeChange { + bEnabled: boolean; +} + +export interface BatteryStateChange { + bHasBattery: boolean; + eACState: ACState; + eBatteryState: BatteryState; + flLevel: number; // Battery Percentage in floating point 0-1 + nSecondsRemaining: number; // Appears to be charge time remaining or time remaining on battery + bShutdownRequested: boolean; +} + +export enum ACState { + Unknown = 0, + Disconnected = 1, + Connected = 2, + ConnectedSlow = 3, +} + +export enum BatteryState { + Unknown = 0, + Discharging = 1, + Charging = 2, + Full = 3, +} + +export interface FileDialog { + /** Whether to choose a directory instead. */ + bChooseDirectory?: boolean; + /** + * Array of file filters. + * @example + * Example from the "Add a Non-Steam Game" dialog: + * ``` + * [ + * { + * strFileTypeName: LocalizationManager.LocalizeString("#AddNonSteam_Filter_Exe_Linux"), + * rFilePatterns: [ "*.application", "*.exe", "*.sh", "*.AppImage" ], + * bUseAsDefault: true, + * }, + * { + * strFileTypeName: LocalizationManager.LocalizeString("#AddNonSteam_Filter_All"), + * rFilePatterns: [ "*" ], + * } + * ] + * ``` + */ + rgFilters?: FileDialogFilter[]; + /** Initially selected file. */ + strInitialFile?: string; + /** Window title. */ + strTitle?: string; +} + +export interface FileDialogFilter { + /** A localization string for the file type. */ + strFileTypeName: string; + /** + * File patterns. + * @example [ "*.application", "*.exe", "*.sh", "*.AppImage" ] + */ + rFilePatterns: string[]; + /** Whether to use this filter by default. */ + bUseAsDefault?: boolean; +} + +export enum OSType { + Web = -700, + Ios = -600, + Android = -500, + Android6 = -499, + Android7 = -498, + Android8 = -497, + Android9 = -496, + Ps3os = -300, + Linux = -203, + Linux22 = -202, + Linux24 = -201, + Linux26 = -200, + Linux32 = -199, + Linux35 = -198, + Linux36 = -197, + Linux310 = -196, + Linux316 = -195, + Linux318 = -194, + Linux3x = -193, + Linux4x = -192, + Linux41 = -191, + Linux44 = -190, + Linux49 = -189, + Linux414 = -188, + Linux419 = -187, + Linux5x = -186, + Linux54 = -185, + Linux6x = -184, + Linux7x = -183, + Linux510 = -182, + Macos = -102, + Macos104 = -101, + Macos105 = -100, + Macos1058 = -99, + Macos106_unused1 = -98, + Macos106_unused2 = -97, + Macos106_unused3 = -96, + Macos106 = -95, + Macos1063 = -94, + Macos1064_slgu = -93, + Macos1067 = -92, + Macos1067_unused = -91, + Macos107 = -90, + Macos108 = -89, + Macos109 = -88, + Macos1010 = -87, + Macos1011 = -86, + Macos1012 = -85, + Macos1013 = -84, + Macos1014 = -83, + Macos1015 = -82, + Macos1016 = -81, + Macos11 = -80, + Macos111 = -79, + Macos1017 = -78, + Macos12 = -77, + Macos1018 = -76, + Macos13 = -75, + Macos1019 = -74, + Macos14 = -73, + Macos1020 = -72, + Macos15 = -71, + Unknown = -1, + Windows = 0, + Win311 = 1, + Win95 = 2, + Win98 = 3, + WinME = 4, + WinNT = 5, + Win200 = 6, + WinXP = 7, + Win2003 = 8, + WinVista = 9, + Win7 = 10, + Win2008 = 11, + Win2012 = 12, + Win8 = 13, + Win81 = 14, + Win2012R2 = 15, + Win10 = 16, + Win2016 = 17, + Win2019 = 18, + Win2022 = 19, + Win11 = 20, +} + +export interface SystemInfo { + sOSName: string; + sKernelVersion: string; + sBIOSVersion: string; + sHostname: string; + sOSCodename: string; + sOSVariantId: string; + sOSVersionId: string; + sOSBuildId: string; + nSteamVersion: number; + sSteamBuildDate: string; + sSteamAPI: string; + sCPUVendor: string; + sCPUName: string; + nCPUHz: number; + nCPUPhysicalCores: number; + nCPULogicalCores: number; + nSystemRAMSizeMB: number; + sVideoCardName: string; + sVideoDriverVersion: string; + nVideoRAMSizeMB: number; + bIsUnsupportedPrototypeHardware: boolean; +} + +/** + * CMsgSystemManagerSettings + */ +export interface MsgSystemManagerSettings extends JsPbMessage { + display_adaptive_brightness_enabled(): boolean; + + display_colorgamut(): number; + + display_colorgamut_labelset(): number; + + display_colortemp(): number; + + display_colortemp_default(): number; + + display_colortemp_enabled(): boolean; + + display_diagnostics_enabled(): boolean; + + display_nightmode_blend(): number; + + display_nightmode_enabled(): boolean; + + display_nightmode_maxhue(): number; + + display_nightmode_maxsat(): number; + + display_nightmode_schedule_enabled(): boolean; + + display_nightmode_schedule_endtime(): number; + + display_nightmode_schedule_starttime(): number; + + display_nightmode_tintstrength(): number; + + display_nightmode_uiexp(): number; + + fan_control_mode(): number; + + idle_backlight_dim_ac_seconds(): number; + + idle_backlight_dim_battery_seconds(): number; + + idle_suspend_ac_seconds(): number; + + idle_suspend_battery_seconds(): number; + + idle_suspend_supressed(): boolean; + + is_adaptive_brightness_available(): boolean; + + is_display_brightness_available(): boolean; + + is_display_colormanagement_available(): boolean; + + is_display_colortemp_available(): boolean; + + is_fan_control_available(): boolean; + + is_wifi_powersave_enabled(): boolean; +} diff --git a/src/deck-components/steam-client/system/network/Device.ts b/src/deck-components/steam-client/system/network/Device.ts new file mode 100644 index 00000000..a0e84fb3 --- /dev/null +++ b/src/deck-components/steam-client/system/network/Device.ts @@ -0,0 +1,12 @@ +export interface Device { + Connect(param0: any): any; // some base64 serialized string + Disconnect(deviceId: any): Promise<any>; + + WirelessNetwork: WirelessNetwork; +} + +export interface WirelessNetwork { + Forget(deviceId: any, deviceWapId: any): any; + + SetAutoconnect(deviceId: any, deviceWapId: any, autoConnect: boolean): any; +} diff --git a/src/deck-components/steam-client/system/network/index.ts b/src/deck-components/steam-client/system/network/index.ts new file mode 100644 index 00000000..dcddd073 --- /dev/null +++ b/src/deck-components/steam-client/system/network/index.ts @@ -0,0 +1,195 @@ +import {JsPbMessage, OperationResponse, Unregisterable} from "../../index"; +import {Device} from "./Device"; + + +export interface Network { + Device: Device; + + ForceRefresh(): Promise<OperationResponse>; + + ForceTestConnectivity(): void; + + GetProxyInfo(): Promise<ProxyInfo>; + + // data.nAppID, data.serializedMsg + RegisterForAppSummaryUpdate(callback: (data: any) => any): Unregisterable; + + /** + * @todo {@link GameNetworkingUI_ConnectionState}, unconfirmed + */ + RegisterForConnectionStateUpdate: Unregisterable; + + RegisterForConnectivityTestChanges( + callback: (connectivityTestChange: ConnectivityTestChange) => void, + ): Unregisterable; + + /** + * If `data` is deserialized, returns {@link MsgNetworkDevicesData}. + * @returns An object that can be used to unregister the callback. + */ + RegisterForDeviceChanges(callback: (data: ArrayBuffer) => void): Unregisterable; + + SetFakeLocalSystemState(state: NetFakeLocalSystemState): void; + + SetProxyInfo(mode: number, address: string, port: number, excludeLocal: boolean): void; + + SetWifiEnabled(value: boolean): Promise<OperationResponse>; + + StartScanningForNetworks(): Promise<OperationResponse>; + + StopScanningForNetworks(): Promise<OperationResponse>; +} + +export interface ConnectivityTestChange { + eConnectivityTestResult: ConnectivityTestResult; + eFakeState: NetFakeLocalSystemState; + bChecking: boolean; +} + +export enum ConnectivityTestResult { + Unknown = 0, + Connected = 1, + CaptivePortal = 2, + TimedOut = 3, + Failed = 4, + WifiDisabled = 5, + NoLAN = 6, +} + +export interface ProxyInfo { + proxy_mode: number; + address: string; + port: number; + exclude_local: boolean; +} + +export enum NetFakeLocalSystemState { + Normal = 0, + NoLAN = 1, + CaptivePortal_Redirected = 2, + CaptivePortal_InPlace = 3, + NoInternet = 4, + NoSteam = 5, +} + +/** + * CMsgNetworkDevicesData + */ +export interface MsgNetworkDevicesData extends JsPbMessage { + devices(): NetworkDevice[]; + + is_wifi_enabled(): boolean; + + is_wifi_scanning_enabled(): boolean; +} + +export interface NetworkDevice_Wireless { + aps: WirelessAP[]; + /** + * @remarks Not present if wired. + * @todo enum + */ + esecurity_supported?: number; +} + +export interface WirelessAP { + esecurity: WirelessAPSecurityFlags; + estrength: WirelessAPStrength; + id: number; + is_active: boolean; + is_autoconnect: boolean; + password: string; + ssid: string; + strength_raw: number; + user_name?: string; +} + +export enum WirelessAPSecurityFlags { + None = 0, + StaticWep = 1, + DynamicWep = 2, + Wpa = 4, + WpaEnterprise = 8, + Wpa2 = 16, + Wpa2Enterprise = 32, + /** + * Special value to indicate that this platform does not support + * the security methods required to connect to an access point + */ + Unsupported = 32768, +} + +export interface NetworkDevice_Wired { + friendly_name: string; + is_cable_present: boolean; + speed_mbit: number; +} + +export interface NetworkDevice { + estate: NetworkDeviceState; + etype: NetworkDeviceType; + id: number; + ipv4: NetworkDeviceIPv4; + ipv6: NetworkDeviceIPv6; + mac: string; + product: string; + vendor: string; + /** + * @remarks Present only if wired. + */ + wired?: NetworkDevice_Wired; + /** + * @remarks Present even if wired. + */ + wireless: NetworkDevice_Wireless; +} + +export interface NetworkDeviceIPv4Address { + ip: number; + netmask: number; +} + +export interface NetworkDeviceIPv6Address { + ip: string; +} + +export interface NetworkDeviceIP { + dns_ip: number[]; + gateway_ip: number; + is_default_route: boolean; + is_dhcp_enabled: boolean; + is_enabled: boolean; +} + +export interface NetworkDeviceIPv4 extends NetworkDeviceIP { + addresses: NetworkDeviceIPv4Address[]; +} + +export interface NetworkDeviceIPv6 extends NetworkDeviceIP { + addresses: NetworkDeviceIPv6Address[]; +} + +export enum NetworkDeviceState { + NotPresent = 0, + Failed = 1, + Disconnected = 2, + Disconnecting = 3, + Connecting = 4, + Connected = 5, + Retrying = 6, +} + +export enum NetworkDeviceType { + Unknown = 0, + Wired = 1, + Wireless = 2, + Virtual = 3, +} + +export enum WirelessAPStrength { + None = 0, + Weak = 1, + Ok = 2, + Good = 3, + Excellent = 4, +} diff --git a/src/globals/SteamClient.ts b/src/globals/SteamClient.ts index 0c657077..d45e1754 100644 --- a/src/globals/SteamClient.ts +++ b/src/globals/SteamClient.ts @@ -1,321 +1,5 @@ -declare global { - var SteamClient: SteamClient; -} - -export interface Apps { - RegisterForAppOverviewChanges: any; - RegisterForAppDetails: any; - RegisterForLocalizationChanges: any; - RegisterForWorkshopChanges: any; - RegisterForWorkshopItemDownloads: any; - GetLibraryBootstrapData: any; - RegisterForAchievementChanges: any; - GetFriendAchievementsForApp: any; - GetMyAchievementsForApp: any; - AddUserTagToApps: any; - RemoveUserTagFromApps: any; - ClearUserTagsOnApps: any; - ClearAndSetUserTagsOnApp: any; - SetAppHidden: any; - ResetHiddenState: any; - SetAppLaunchOptions: any; - SetAppResolutionOverride: any; - SetAppCurrentLanguage: any; - SetAppAutoUpdateBehavior: any; - SetAppBackgroundDownloadsBehavior: any; - ToggleAppFamilyBlockedState: any; - ToggleAppSteamCloudEnabled: any; - ToggleAppSteamCloudSyncOnSuspendEnabled: any; - ToggleOverrideResolutionForInternalDisplay: any; - ToggleEnableSteamOverlayForApp: any; - ToggleEnableDesktopTheatreForApp: any; - BrowseLocalFilesForApp: any; - BrowseScreenshotsForApp: any; - BrowseScreenshotForApp: any; - BackupFilesForApp: any; - VerifyFilesForApp: any; - CreateDesktopShortcutForApp: any; - JoinAppContentBeta: any; - JoinAppContentBetaByPassword: any; - GetAchievementsInTimeRange: any; - GetSubscribedWorkshopItems: any; - SubscribeWorkshopItem: any; - GetDownloadedWorkshopItems: any; - DownloadWorkshopItem: any; - SetLocalScreenshotCaption: any; - SetLocalScreenshotSpoiler: any; - GetDetailsForScreenshotUpload: any; - UploadLocalScreenshot: any; - DeleteLocalScreenshot: any; - GetScreenshotsInTimeRange: any; - GetFriendsWhoPlay: any; - RequestLegacyCDKeysForApp: any; - GetSoundtrackDetails: any; - GetStoreTagLocalization: any; - GetLaunchOptionsForApp: any; - GetResolutionOverrideForApp: any; - ScanForShortcuts: any; - GetAllShortcuts: any; - GetShortcutData: any; - AddShortcut: any; - RemoveShortcut: any; - InstallFlatpakAppAndCreateShortcut: any; - ListFlatpakApps: any; - UninstallFlatpakApp: any; - ShowControllerConfigurator: any; - SetThirdPartyControllerConfiguration: any; - ToggleAllowDesktopConfiguration: any; - SetControllerRumblePreference: any; - GetCachedAppDetails: any; - SetCachedAppDetails: any; - ReportLibraryAssetCacheMiss: any; - SaveAchievementProgressCache: any; - SetStreamingClientForApp: any; - SetCustomArtworkForApp: any; - ClearCustomArtworkForApp: any; - SetCustomLogoPositionForApp: any; - ClearCustomLogoPositionForApp: any; - RequestIconDataForApp: any; - SpecifyCompatTool: any; - GetAvailableCompatTools: any; - SetShortcutName: any; - SetShortcutExe: any; - SetShortcutStartDir: any; - SetShortcutLaunchOptions: any; - SetShortcutIsVR: any; - PromptToChangeShortcut: any; - PromptToSelectShortcutIcon: any; - InstallApp: any; - RunGame: any; - VerifyApp: any; - StreamGame: any; - CancelLaunch: any; - TerminateApp: any; - UninstallApps: any; - ShowStore: any; - SetDLCEnabled: any; - ContinueGameAction: any; - CancelGameAction: any; - GetActiveGameActions: any; - GetGameActionDetails: any; - GetGameActionForApp: any; - SkipShaderProcessing: any; - MarkEulaAccepted: any; - MarkEulaRejected: any; - LoadEula: any; - GetConflictingFileTimestamps: any; - GetCloudPendingRemoteOperations: any; - ClearProton: any; - RegisterForMarketingMessages: any; - FetchMarketingMessages: any; - MarkMarketingMessageSeen: any; - ReportMarketingMessageSeen: any; - RegisterForGameActionStart: any; - RegisterForGameActionEnd: any; - RegisterForGameActionTaskChange: any; - RegisterForGameActionUserRequest: any; - RegisterForGameActionShowError: any; - RegisterForGameActionShowUI: any; - OpenAppSettingsDialog: any; -} - -export interface Window { - RegisterForExternalDisplayChanged: any; - SetManualDisplayScaleFactor: any; - SetAutoDisplayScale: any; - Minimize: any; - ProcessShuttingDown: any; - ToggleMaximize: any; - MoveTo: any; - ResizeTo: any; - SetMinSize: any; - SetResizeGrip: any; - SetComposition: any; - GamescopeBlur: any; - BringToFront: any; - SetForegroundWindow: any; - SetKeyFocus: any; - FlashWindow: any; - StopFlashWindow: any; - ShowWindow: any; - HideWindow: any; - SetWindowIcon: any; - GetWindowDimensions: any; - GetWindowRestoreDetails: any; - PositionWindowRelative: any; - GetMousePositionDetails: any; - IsWindowMinimized: any; - GetBrowserID: any; -} - -export interface SteamClient { - Apps: Apps; - Browser: any; - BrowserView: any; - ClientNotifications: any; - Cloud: any; - Console: any; - Downloads: any; - FamilySharing: any; - FriendSettings: any; - Friends: any; - GameSessions: any; - Input: any; - InstallFolder: any; - Installs: any; - MachineStorage: any; - Messaging: any; - Notifications: any; - OpenVR: any; - Overlay: any; - Parental: any; - RegisterIFrameNavigatedCallback: any; - RemotePlay: any; - RoamingStorage: any; - Screenshots: any; - Settings: any; - SharedConnection: any; - Stats: any; - Storage: any; - Streaming: any; - System: any; - UI: any; - URL: any; - Updates: any; - User: any; - WebChat: any; - Window: Window; -} - -export interface SteamShortcut { - appid: number; - data: { - bIsApplication: boolean; - strAppName: string; - strExePath: string; - strArguments: string; - strShortcutPath: string; - strSortAs: string; - }; -} - -/** - * @prop unAppID is not properly set by Steam for non-steam game shortcuts, so it defaults to 0 for them - */ -export interface LifetimeNotification { - unAppID: number; - nInstanceID: number; - bRunning: boolean; -} +import {SteamClient} from "../deck-components/steam-client"; -export type AppAchievements = { - nAchieved: number; - nTotal: number; - vecAchievedHidden: any[]; - vecHighlight: any[]; - vecUnachieved: any[]; -}; - -export type AppLanguages = { - strDisplayName: string; - strShortName: string; -}; - -export type LogoPinPositions = 'BottomLeft' | 'UpperLeft' | 'CenterCenter' | 'UpperCenter' | 'BottomCenter'; - -export interface LogoPosition { - pinnedPosition: LogoPinPositions; - nWidthPct: number; - nHeightPct: number; -} - -export interface AppDetails { - achievements: AppAchievements; - bCanMoveInstallFolder: boolean; - bCloudAvailable: boolean; - bCloudEnabledForAccount: boolean; - bCloudEnabledForApp: boolean; - bCloudSyncOnSuspendAvailable: boolean; - bCloudSyncOnSuspendEnabled: boolean; - bCommunityMarketPresence: boolean; - bEnableAllowDesktopConfiguration: boolean; - bFreeRemovableLicense: boolean; - bHasAllLegacyCDKeys: boolean; - bHasAnyLocalContent: boolean; - bHasLockedPrivateBetas: boolean; - bIsExcludedFromSharing: boolean; - bIsSubscribedTo: boolean; - bOverlayEnabled: boolean; - bOverrideInternalResolution: boolean; - bRequiresLegacyCDKey: boolean; - bShortcutIsVR: boolean; - bShowCDKeyInMenus: boolean; - bShowControllerConfig: boolean; - bSupportsCDKeyCopyToClipboard: boolean; - bVRGameTheatreEnabled: boolean; - bWorkshopVisible: boolean; - eAppOwnershipFlags: number; - eAutoUpdateValue: number; - eBackgroundDownloads: number; - eCloudSync: number; - eControllerRumblePreference: number; - eDisplayStatus: number; - eEnableThirdPartyControllerConfiguration: number; - eSteamInputControllerMask: number; - iInstallFolder: number; - lDiskUsageBytes: number; - lDlcUsageBytes: number; - nBuildID: number; - nCompatToolPriority: number; - nPlaytimeForever: number; - nScreenshots: number; - rtLastTimePlayed: number; - rtLastUpdated: number; - rtPurchased: number; - selectedLanguage: { - strDisplayName: string; - strShortName: string; - }; - strCloudBytesAvailable: string; - strCloudBytesUsed: string; - strCompatToolDisplayName: string; - strCompatToolName: string; - strDeveloperName: string; - strDeveloperURL: string; - strDisplayName: string; - strExternalSubscriptionURL: string; - strFlatpakAppID: string; - strHomepageURL: string; - strLaunchOptions: string; - strManualURL: string; - strOwnerSteamID: string; - strResolutionOverride: string; - strSelectedBeta: string; - strShortcutExe: string; - strShortcutLaunchOptions: string; - strShortcutStartDir: string; - strSteamDeckBlogURL: string; - unAppID: number; - vecBetas: any[]; - vecDLC: any[]; - vecDeckCompatTestResults: any[]; - vecLanguages: AppLanguages[]; - vecLegacyCDKeys: any[]; - vecMusicAlbums: any[]; - vecPlatforms: string[]; - vecScreenShots: any[]; - libraryAssets?: { - logoPosition?: LogoPosition; - }; -} - -export interface SteamAppOverview { - display_name: string; - gameid: string; - appid: number; - icon_hash: string; - third_party_mod?: boolean; - selected_clientid?: string; - BIsModOrShortcut: () => boolean; - BIsShortcut: () => boolean; -} +declare global { + var SteamClient: SteamClient; +} \ No newline at end of file diff --git a/src/globals/stores.ts b/src/globals/stores.ts index fafbafa0..33f760b6 100644 --- a/src/globals/stores.ts +++ b/src/globals/stores.ts @@ -1,5 +1,7 @@ import { WindowRouter } from '../modules/Router'; -import { AppDetails, LogoPosition, SteamAppOverview } from './SteamClient'; +import { AppDetails, LogoPosition, SteamAppOverview } from "../deck-components/steam-client/App"; +import {AppData} from "../deck-components/steam-client"; + declare global { interface Window { LocalizationManager: { @@ -43,6 +45,7 @@ declare global { GetIconURLForApp: (app: SteamAppOverview) => string; }; appDetailsStore: { + GetAppData: (appId: number) => AppData | null; GetAppDetails: (appId: number) => AppDetails | null; GetCustomLogoPosition: (app: SteamAppOverview) => LogoPosition | null; SaveCustomLogoPosition: (app: SteamAppOverview, logoPositions: LogoPosition) => any; diff --git a/src/modules/Router.ts b/src/modules/Router.ts index 1a766124..53f1db7c 100644 --- a/src/modules/Router.ts +++ b/src/modules/Router.ts @@ -1,5 +1,6 @@ import Logger from '../logger'; import { Export, findModuleExport } from '../webpack'; +import {DisplayStatus} from "../deck-components/steam-client/App"; export enum SideMenu { None, @@ -19,45 +20,6 @@ export enum QuickAccessTab { Decky = 999, } -export enum DisplayStatus { - Invalid = 0, - Launching = 1, - Uninstalling = 2, - Installing = 3, - Running = 4, - Validating = 5, - Updating = 6, - Downloading = 7, - Synchronizing = 8, - ReadyToInstall = 9, - ReadyToPreload = 10, - ReadyToLaunch = 11, - RegionRestricted = 12, - PresaleOnly = 13, - InvalidPlatform = 14, - PreloadComplete = 16, - BorrowerLocked = 17, - UpdatePaused = 18, - UpdateQueued = 19, - UpdateRequired = 20, - UpdateDisabled = 21, - DownloadPaused = 22, - DownloadQueued = 23, - DownloadRequired = 24, - DownloadDisabled = 25, - LicensePending = 26, - LicenseExpired = 27, - AvailForFree = 28, - AvailToBorrow = 29, - AvailGuestPass = 30, - Purchase = 31, - Unavailable = 32, - NotLaunchable = 33, - CloudError = 34, - CloudOutOfDate = 35, - Terminating = 36, -} - export type AppOverview = { appid: string; display_name: string;