diff --git a/README.md b/README.md index edcdd93..2e8e7dc 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ A plugin that integrate with Pipelab
Author: Armaldio
Website: https://github.com/CynToolkit/construct-plugin
Addon Url: https://github.com/CynToolkit/construct-plugin
-Download Latest Version : [Version: 2.2.0](https://github.com/CynToolkit/construct-plugin/releases/latest)
+Download Latest Version : [Version: 2.3.0](https://github.com/CynToolkit/construct-plugin/releases/latest)
Made using [c3ide2-framework](https://github.com/ConstructFund/c3ide2-framework)
## Table of Contents @@ -145,6 +145,10 @@ When Download type is Around the user, the offsets are the amount of entries aro | Download scores | Download scores from a leaderboard When Download type is Regular, offset are absolute. When Download type is Around the user, the offsets are the amount of entries around the user to fetch. | Leaderboard *(string)*
Download type *(combo)*
Start *(number)*
End *(number)*
Output *(object)*
| +| Activate Steam overlay to web page (synchronous) | Activates Steam Overlay web browser directly to the specified URL (synchronous) | URL *(string)*
Mode *(combo)*
Tag *(string)*
| +| Activate Steam overlay to web page | Activates Steam Overlay web browser directly to the specified URL | URL *(string)*
Mode *(combo)*
| +| Activate Steam overlay to store (synchronous) | Activates the Steam Overlay to the Steam store page for the provided app (synchronous) | App ID *(number)*
Flag *(combo)*
Tag *(string)*
| +| Activate Steam overlay to store | Activates the Steam Overlay to the Steam store page for the provided app | App ID *(number)*
Flag *(combo)*
| --- @@ -335,7 +339,16 @@ When Download type is Around the user, the offsets are the amount of entries aro | On any "LeaderboardDownloadScore" success | Trigger when any of the "LeaderboardDownloadScore" are executed with success. | | | On "LeaderboardDownloadScore" error | Trigger when the "LeaderboardDownloadScore" failed to execute. | Tag *(string)*
| | On any "LeaderboardDownloadScore" error | Trigger when any of the "LeaderboardDownloadScore" failed to execute. | | +| On "ActivateToWebPage" success | Trigger when the "ActivateToWebPage" is executed with success. | Tag *(string)*
| +| On any "ActivateToWebPage" success | Trigger when any of the "ActivateToWebPage" are executed with success. | | +| On "ActivateToWebPage" error | Trigger when the "ActivateToWebPage" failed to execute. | Tag *(string)*
| +| On any "ActivateToWebPage" error | Trigger when any of the "ActivateToWebPage" failed to execute. | | +| On "ActivateToStore" success | Trigger when the "ActivateToStore" is executed with success. | Tag *(string)*
| +| On any "ActivateToStore" success | Trigger when any of the "ActivateToStore" are executed with success. | | +| On "ActivateToStore" error | Trigger when the "ActivateToStore" failed to execute. | Tag *(string)*
| +| On any "ActivateToStore" error | Trigger when any of the "ActivateToStore" failed to execute. | | | Is engine | Return true if the engine running the app is the one selected | Engine *(combo)*
| +| Is initialized | Returns true if the Pipelab integration has been initialized | | | Is full screen | Returns true if the window is in full screen mode. | State *(combo)*
| | Last checked path exists | Returns true if the last checked path exists. | | @@ -436,6 +449,10 @@ When Download type is Around the user, the offsets are the amount of entries aro | LeaderboardUploadScoreWithMetadataResult | The result of the "LeaderboardUploadScoreWithMetadata last call" | string | | | LeaderboardDownloadScoreError | The error of the "LeaderboardDownloadScore last call" | string | | | LeaderboardDownloadScoreResult | The result of the "LeaderboardDownloadScore last call" | string | | +| ActivateToWebPageError | The error of the "ActivateToWebPage last call" | string | | +| ActivateToWebPageResult | The result of the "ActivateToWebPage last call" | string | | +| ActivateToStoreError | The error of the "ActivateToStore last call" | string | | +| ActivateToStoreResult | The result of the "ActivateToStore last call" | string | | | ArgumentAt | Get the argument at the given index. | string | Index *(number)*
| | ArgumentCount | Get the number of arguments. | number | | | AppFolderURL | Return the URL of the folder of the current app. | string | | @@ -480,6 +497,7 @@ When Download type is Around the user, the offsets are the amount of entries aro | SteamLevel | Get the Steam level. | number | | | SteamIpCountry | Get the Steam IP country. | string | | | SteamIsRunningOnSteamDeck | Return true if the app is running on a Steam Deck. | number | | +| SteamAppId | Get the currently used Steam App ID. | number | | ## Paths **ProjectFilesFolder**: Direct path to your games's content diff --git a/src/instance.js b/src/instance.js index c2cc338..8733f42 100644 --- a/src/instance.js +++ b/src/instance.js @@ -223,6 +223,17 @@ const defaultSteamId = { steamId64: '', } +// Simple path utility for POSIX-style path operations +const posixPath = { + dirname: (path) => { + const lastSlash = path.lastIndexOf('/'); + return lastSlash === -1 ? '.' : path.substring(0, lastSlash); + }, + join: (dirname, filename) => { + return dirname.endsWith('/') ? dirname + filename : dirname + '/' + filename; + } +}; + let DOM_COMPONENT_ID = '' //<-- DOM_COMPONENT_ID --> @@ -355,11 +366,24 @@ function getInstanceJs(parentClass, addonTriggers, C3) { /** @type {string} */ _arch = '' + /** @type {number} */ + _steam_AppId = -1 + /** @type {string} */ _ListFilesErrorValue = '' /** @type {import("@pipelab/core").FileFolder[]} */ _ListFilesResultValue = [] + /** @type {string} */ + _ActivateToWebPageErrorValue = '' + /** @type {boolean} */ + _ActivateToWebPageResultValue = false + + /** @type {string} */ + _ActivateToStoreErrorValue = '' + /** @type {boolean} */ + _ActivateToStoreResultValue = false + /** * Description * @param {ISDKInstanceBase_} inst @@ -681,6 +705,20 @@ function getInstanceJs(parentClass, addonTriggers, C3) { this._arch = response?.body.arch ?? ""; }) + promises.push(async () => { + /** @type {import('@pipelab/core').MakeInputOutput, 'input'>} */ + const order = { + url: '/steam/raw', + body: { + namespace: 'utils', + method: 'getAppId', + args: [], + }, + }; + const response = await this.ws?.sendAndWaitForResponse(order); + this._steam_AppId = response?.body.data ?? -1; + }) + const results = await Promise.allSettled(promises.map(x => x())) // ----------------------------------------------------------------------- @@ -2136,6 +2174,94 @@ function getInstanceJs(parentClass, addonTriggers, C3) { _DiscordSetActivitySync = this._DiscordSetActivityBase _DiscordSetActivity = this._DiscordSetActivityBase + _ActivateToWebPageBase = this.wrap(super._ActivateToWebPage, async ( + /** @type {string} */ url, + /** @type {number} */ mode, + /** @type {Tag} */ tag + ) => { + try { + // Map Construct3 combo values to Steam constants + // 0 = "default", 1 = "modal" + const steamMode = mode === 1 ? 1 : 0; // k_EActivateGameOverlayToWebPageMode_Modal : k_EActivateGameOverlayToWebPageMode_Default + + /** @type {import('@pipelab/core').MakeInputOutput, 'input'>} */ + const order = { + url: '/steam/raw', + body: { + namespace: 'overlay', + method: 'activateToWebPage', + args: [url, steamMode], + }, + }; + const answer = await this.ws?.sendAndWaitForResponse(order); + if (answer?.body.success === false) { + throw new Error('Failed') + } + this._ActivateToWebPageResultValue = answer?.body.success + this._ActivateToWebPageErrorValue = '' + + await this.trigger(tag, [ + C3.Plugins.pipelabv2.Cnds.OnActivateToWebPageSuccess, + C3.Plugins.pipelabv2.Cnds.OnAnyActivateToWebPageSuccess + ]) + } catch (e) { + if (e instanceof Error) { + this._ActivateToWebPageErrorValue = e.message + this._ActivateToWebPageResultValue = false + await this.trigger(tag, [ + C3.Plugins.pipelabv2.Cnds.OnActivateToWebPageError, + C3.Plugins.pipelabv2.Cnds.OnAnyActivateToWebPageError + ]) + } + } + }, this.unsupportedEngine) + _ActivateToWebPage = this._ActivateToWebPageBase + _ActivateToWebPageSync = this._ActivateToWebPageBase + + _ActivateToStoreBase = this.wrap(super._ActivateToStore, async ( + /** @type {number} */ appId, + /** @type {number} */ flag, + /** @type {Tag} */ tag + ) => { + try { + // Map Construct3 combo values to Steam constants + // 0 = "none", 1 = "addToCartAndShow" + const steamFlag = flag === 1 ? 2 : 0; // k_EOverlayToStoreFlag_AddToCartAndShow : k_EOverlayToStoreFlag_None + + /** @type {import('@pipelab/core').MakeInputOutput, 'input'>} */ + const order = { + url: '/steam/raw', + body: { + namespace: 'overlay', + method: 'activateToStore', + args: [appId, steamFlag], + }, + }; + const answer = await this.ws?.sendAndWaitForResponse(order); + if (answer?.body.success === false) { + throw new Error('Failed') + } + this._ActivateToStoreResultValue = answer?.body.success + this._ActivateToStoreErrorValue = '' + + await this.trigger(tag, [ + C3.Plugins.pipelabv2.Cnds.OnActivateToStoreSuccess, + C3.Plugins.pipelabv2.Cnds.OnAnyActivateToStoreSuccess + ]) + } catch (e) { + if (e instanceof Error) { + this._ActivateToStoreErrorValue = e.message + this._ActivateToStoreResultValue = false + await this.trigger(tag, [ + C3.Plugins.pipelabv2.Cnds.OnActivateToStoreError, + C3.Plugins.pipelabv2.Cnds.OnAnyActivateToStoreError + ]) + } + } + }, this.unsupportedEngine) + _ActivateToStore = this._ActivateToStoreBase + _ActivateToStoreSync = this._ActivateToStoreBase + // #region Cnds _OnInitializeSuccess = this.wrap(super._OnInitializeSuccess, (/** @type {Tag} */ tag) => { return this._currentTag === tag; @@ -2500,6 +2626,16 @@ function getInstanceJs(parentClass, addonTriggers, C3) { return true }) + _OnActivateToWebPageSuccess = this.wrap(super._OnActivateToWebPageSuccess, (/** @type {Tag} */ tag) => this._currentTag === tag) + _OnAnyActivateToWebPageSuccess = this.wrap(super._OnAnyActivateToWebPageSuccess, () => true) + _OnActivateToWebPageError = this.wrap(super._OnActivateToWebPageError, (/** @type {Tag} */ tag) => this._currentTag === tag) + _OnAnyActivateToWebPageError = this.wrap(super._OnAnyActivateToWebPageError, () => true) + + _OnActivateToStoreSuccess = this.wrap(super._OnActivateToStoreSuccess, (/** @type {Tag} */ tag) => this._currentTag === tag) + _OnAnyActivateToStoreSuccess = this.wrap(super._OnAnyActivateToStoreSuccess, () => true) + _OnActivateToStoreError = this.wrap(super._OnActivateToStoreError, (/** @type {Tag} */ tag) => this._currentTag === tag) + _OnAnyActivateToStoreError = this.wrap(super._OnAnyActivateToStoreError, () => true) + _IsFullScreen = this.wrap(super._IsFullScreen, (state) => { return this._fullscreenState === state }, () => false) @@ -2507,6 +2643,10 @@ function getInstanceJs(parentClass, addonTriggers, C3) { _LastCheckedPathExists = this.wrap(super._LastCheckedPathExists, (state) => { return this._CheckIfPathExistErrorValue === '' }, () => false) + + _IsInitialized = this.wrap(super._IsInitialized, () => { + return this._isInitialized + }, () => false) // #endregion // #region Exps @@ -2674,6 +2814,9 @@ function getInstanceJs(parentClass, addonTriggers, C3) { _SteamIsRunningOnSteamDeck = this.exprs(super._SteamIsRunningOnSteamDeck, () => { return this._steam_IsRunningOnSteamDeck ? 1 : 0 }) + _SteamAppId = this.exprs(super._SteamAppId, () => { + return this._steam_AppId + }) _InitializeError = this.exprs(super._InitializeError, () => { return this._InitializeErrorValue @@ -2956,6 +3099,20 @@ function getInstanceJs(parentClass, addonTriggers, C3) { return this._DiscordSetActivityResultValue }) + _ActivateToWebPageError = this.exprs(super._ActivateToWebPageError, () => { + return this._ActivateToWebPageErrorValue + }) + _ActivateToWebPageResult = this.exprs(super._ActivateToWebPageResult, () => { + return this._ActivateToWebPageResultValue + }) + + _ActivateToStoreError = this.exprs(super._ActivateToStoreError, () => { + return this._ActivateToStoreErrorValue + }) + _ActivateToStoreResult = this.exprs(super._ActivateToStoreResult, () => { + return this._ActivateToStoreResultValue + }) + // _saveToJson() { diff --git a/src/pluginConfig.js b/src/pluginConfig.js index 8ba75e8..1c9f770 100644 --- a/src/pluginConfig.js +++ b/src/pluginConfig.js @@ -1149,6 +1149,62 @@ const DiscordSetActivity = ACEGenerator("DiscordSetActivity", /** @type {const} description: "Set the discord activity (aka Rich presence).", })) +const ActivateToWebPage = ACEGenerator("ActivateToWebPage", /** @type {const} */ ({ + category: "steam", + highlight: false, + deprecated: false, + params: [ + { + id: 'url', + desc: "The webpage to open. A fully qualified address with the protocol is required (e.g. 'http://www.steampowered.com')", + name: "URL", + type: 'string', + initialValue: "\"\"", + }, + { + id: 'mode', + desc: "Mode for the web page.", + name: "Mode", + type: 'combo', + items: [ + { "default": "Default" }, + { "modal": "Modal" }, + ] + } + ], + listName: "Activate Steam overlay to web page", + displayText: "Activate Steam overlay to web page [b]{0}[/b] (mode: {1})", + description: "Activates Steam Overlay web browser directly to the specified URL", +})) + +const ActivateToStore = ACEGenerator("ActivateToStore", /** @type {const} */ ({ + category: "steam", + highlight: false, + deprecated: false, + params: [ + { + id: 'appId', + desc: "The app ID to show the store page of", + name: "App ID", + type: 'number', + initialValue: "0", + }, + { + id: 'flag', + desc: "Flags to modify the behavior when the page opens", + name: "Flag", + type: 'combo', + items: [ + { "none": "None" }, + { "addToCartAndShow": "Add to cart and show" }, + ] + } + ], + listName: "Activate Steam overlay to store", + displayText: "Activate Steam overlay to store for app [b]{0}[/b] (flag: {1})", + description: "Activates the Steam Overlay to the Steam store page for the provided app", +})) + /** * @satisfies {import('./sdk.js').Config} */ @@ -1329,6 +1385,8 @@ const Config = /** @type {const} */({ ...LeaderboardUploadScore.actions, ...LeaderboardUploadScoreWithMetadata.actions, ...LeaderboardDownloadScore.actions, + ...ActivateToWebPage.actions, + ...ActivateToStore.actions, }, Cnds: { ...Initialize.conditions, @@ -1377,6 +1435,8 @@ const Config = /** @type {const} */({ ...LeaderboardUploadScore.conditions, ...LeaderboardUploadScoreWithMetadata.conditions, ...LeaderboardDownloadScore.conditions, + ...ActivateToWebPage.conditions, + ...ActivateToStore.conditions, IsEngine: { category: "general", forward: "_IsEngine", @@ -1399,6 +1459,19 @@ const Config = /** @type {const} */({ listName: "Is engine", }, + IsInitialized: { + category: "general", + forward: "_IsInitialized", + highlight: false, + deprecated: false, + description: "Returns true if the Pipelab integration has been initialized", + displayText: "Is initialized", + listName: "Is initialized", + isInvertible: true, + isTrigger: false, + params: [] + }, + IsFullScreen: { category: "window", forward: "_IsFullScreen", @@ -1483,6 +1556,8 @@ const Config = /** @type {const} */({ ...LeaderboardUploadScore.expressions, ...LeaderboardUploadScoreWithMetadata.expressions, ...LeaderboardDownloadScore.expressions, + ...ActivateToWebPage.expressions, + ...ActivateToStore.expressions, // command line ArgumentAt: { @@ -1881,6 +1956,14 @@ const Config = /** @type {const} */({ returnType: 'number', description: "Return true if the app is running on a Steam Deck.", }, + SteamAppId: { + category: "steam", + forward: "_SteamAppId", + highlight: false, + deprecated: false, + returnType: 'number', + description: "Get the currently used Steam App ID.", + }, }, });