The Steamworks plugin allows integrating a project with Steam. It is currently supported with the Windows WebView2, macOS WKWebView and Linux CEF export options.
The plugin provides basic access to the user details, the Steam Overlay, achievements and DLC.
Exporting for Steam
To test your game with Steam, export it with the Windows, macOS or Linux options.
You must also have Steam installed and running on your system for the plugin features to work. Use the Is available condition to check if the plugin features are available.
For more details about getting your project running on Linux or the Steam Deck, see the guide Exporting to Linux and the Steam Deck.
During development, you must also set your Steam App ID in the plugin's App ID property, and check Development mode. This tells Steam your app ID. If Steam cannot determine the App ID it will fail to initialize and Is available will be false, so this is necessary during development to make sure Steam knows the app ID and enable Steam features. If you don't have an app ID yet, you can use the app ID 480, which is the ID for the Steamworks SDK sample "Space war".
Before publishing to Steam, be sure to uncheck Development mode, as when it is on it disables Steam's recommended "restart app if necessary" behavior.
Gamepad support
There are two quirks to be aware of regarding gamepad support when exporting to Steam.
Firstly, due to a quirk of WebView2, the browser-provided gamepad input does not work when exporting to Steam. Construct works around this by accessing GameInput directly. However support for GameInput may need to be installed on the system before it works. You should configure your Steam game to run the GameInput installer as part of the install process - refer to the Steam documentation for instructions on how to do that. To obtain the GameInput installer, download the GameInput NuGet package (click 'Download package' on the right), rename .nupkg to .zip, open the zip, and extract redist/GameInputRedist.msi.
Secondly, note that if you use app ID 480, you may find gamepad input still does not work. This is because 'Space war' uses a custom Steam Input configuration to handle gamepad input in a different way to what Construct uses. You can work around this during development by editing 'Space war' properties in Steam (which should appear when using the app ID 480), and in the 'Controller' section, choosing Disable Steam Input. Then restart the app. Alternatively if you sign up as a publisher to Steam, you can have your own app ID allocated.
Steam Overlay
The Steam in-game overlay is currently supported on Windows and the Steam Deck. The in-game overlay is not currently supported on macOS or Linux due to limitations in how Steam implements its in-game overlay. However Steam has specially designed fallbacks for when the in-game overlay is not supported - usually this means it shows the actual Steam user interface rather than displaying content inside the game.
On Windows, the Steam in-game overlay is supported using a workaround: it layers what looks to Steam like a traditional game engine transparently over the window, solely for Steam to draw its in-game overlay content in to. Note that this means some features may not work as expected, such as in-game video recording, as Steam will be capturing the transparent workaround surface rather than the actual game. However screenshots are supported (as the Steamworks SDK allows intercepting screenshots, which the plugin uses to capture the actual game surface).
To improve support for the in-game overlay, Valve will have to change the way Steam implements it. If you are interested in this, consider contacting them the following ways:
Steam Cloud
You don't actually need the Steamworks plugin to use Steam Cloud - you can use Steam Auto-Cloud with Construct's File System plugin to automatically synchronize a folder of files between systems. See the Steam Cloud documentation for more details.
The root paths for Steam auto-cloud correspond to the known folder picker tags in the File System plugin like so:
- App Install Directory: "<app>"
- WinMyDocuments: "<documents>"
- WinAppDataLocal: "<local-app-data>"
- WinAppDataRoaming: "<roaming-app-data>"
- WinSavedGames: "<saved-games>"
- MacHome: "<profile>"
- MacAppSupport: "<local-app-data>"
- MacDocuments: "<documents>"
- LinuxHome: "<profile>"
- LinuxXdgDataHome: "<local-app-data>"
Further, the SteamID64Bit expression of the Steamworks plugin corresponds to the {64BitSteamID} variable in Steam Auto-Cloud special path values. Therefore you can set up File System to write to a folder that is set up for Steam Auto-Cloud. For example on Windows you could do the following:
- Set up Steam Auto-Cloud to sync the root WinMyDocuments, path mygame/{64BitSteamId}
- Use File System to read/write to picker tag "<documents>", folder path "mygame/" & Steam.SteamID64Bit & "/file.json"
Now file.json is in the Steam Auto-Cloud folder and so Steam should sync that across different devices when closing/launching your game.
In macOS and Linux exports, note that the "<current-app-data>" picker tag corresponds to the MacAppSupport/LinuxXdgDataHome root path with a subdirectory named as the project ID (set in Project Properties), e.g. net.construct.kiwistory. You may still wish to add a further subdirectory to separate cloud files, and another for the Steam ID. For example root LinuxXdgDataHome, path net.construct.kiwistory/cloud/{64BitSteamId} corresponds to the File System picker tag "<current-app-data>", folder path "cloud/" & Steam.SteamID64Bit.
Diagnostics
Details about the Steamworks SDK, including any error messages or warnings, are logged to the developer tools console. This may help identify any problems during development. Press F12 to open the developer tools. (Remember to enable DevTools on export for this to work.)
Script interface
The Steamworks plugin exposes the following APIs that can be used from JavaScript code.
- isAvailable
- Boolean indicating if Steam features are available.
- isRunningOnSteamDeck
- Boolean indicating if the game is currently running on a Steam Deck device.
- personaName
- A string of the current user's Steam persona (display) name.
- accountId
- The current user's Steam account ID as a number.
- steamId64Bit
- The current user's Steam ID in its full 64-bit representation. Note this is a string as it may exceed the range of JavaScript numbers.
- staticAccountKey
- The current user's Steam static account key as a string. Note this is a string as it may exceed the range of JavaScript numbers.
- appOwnerAccountId
- appOwnerSteamId64Bit
- appOwnerStaticAccountKey
- As above, but for the app owner. The app owner is often the same as the current user, but in some cases may be different, such as with Family Sharing.
- playerSteamLevel
- Number representing the Steam level of the user, as shown on their Steam community profile.
- appId
- The current Steam app ID as a number.
- steamUILanguage
- currentGameLanguage
- Strings representing the current language setting for both the Steam user interface and the current game, as reported by Steam.
- getAvailableGameLanguages()
- Returns an array of strings representing available languages.
- showOverlay(optionStr)
- Request to show the Steam overlay, passing a string of the information to show, which must be one of
"friends", "community", "players", "settings", "official-game-group", "stats", "achievements".
- showOverlayURL(url, modal)
- Request to show the Steam overlay showing a web page at the given URL (string). This can optionally be made modal by passing
true for the modal parameter.
- showOverlayInviteDialog(lobbyIdStr)
- Request to show the Steam game overlay to open the invite dialog. The lobby ID must be a Steam ID in its full 64-bit representation, as a string.
- async unlockAchievement(achievement)
- Request to unlock an achievement specified by a string. Returns a Promise that resolves with a boolean, which is true if the operation completed successfully or false if it failed.
- async clearAchievement(achievement)
- Request to clear (reset) an achievement specified by a string. Returns a Promise that resolves with a boolean, which is true if the operation completed successfully or false if it failed.
- async checkDlcInstalled(appIdArray)
- Check if DLC is installed, passing an array of app IDs to check (as this method is asynchronous, this allows for checking multiple app IDs in one call). Returns a Promise that resolves with a boolean, which is true if the operation completed successfully or false if it failed. After it completes successfully,
isDlcInstalled() can be called to synchronously check the result of individual app IDs.
- isDlcInstalled(appId)
- Returns a boolean indicating if the specified DLC (given by an app ID) is installed. This is synchronous but can only be used after
checkDlcInstalled() passing the same app ID has completed successfully.
- installDlc(appId)
- uninstallDlc(appId)
- Request to initiate installation or uninstallation of DLC specified by an app ID.
- getAuthTicketForWebApi(identity)
- Retrieve an authentication ticket from the Steamworks API. For identity, pass identity of the remote service that will authenticate the ticket. Leave as an empty string if none was provided. Returns a promise that resolves with an object with the properties
authTicket and ticketHexStr.
- authTicket
- ticketHexStr
- Return the values obtained by the last call to
getAuthTicketForWebApi().
- cancelAuthTicket(authTicket)
- Cancel a previously obtained authentication ticket.
- setRichPresence(key, value)
- Set a Rich Presence key/value for the current user that is automatically shared to all friends playing the same game. For example the key "status" can be set to the user's current status. See the Steamworks SDK documentation for other possible keys. Pass an empty string for the value to remove the key.
- clearRichPresence()
- Clears all of the current user's rich presence keys and values.
- triggerScreenshot()
- Activate the Steam feature to take a screenshot. Requires the overlay to be active.