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.",
+ },
},
});