Skip to content

Workshop and Steam Integration

Deepratna Awale edited this page Oct 6, 2026 · 3 revisions

Workshop and Steam integration

How Open Wallpaper Engine talks to Steam: the Steam Web API for browsing, SteamCMD for downloads and the assets, credentials, item installation and dependencies. Code lives in Workshop/ and Library/.

Two channels

Channel Used for Components
Steam Web API (HTTPS) Browse/search (IPublishedFileService/QueryFiles, needs a key), item details (ISteamRemoteStorage/GetPublishedFileDetails), author profiles (GetPlayerSummaries with a key, else the public profile XML) WorkshopAPIService, SteamProfileXMLParser
SteamCMD (subprocess) Login, Workshop downloads (workshop_download_item 431960 <id>), the WE assets (app_update 431960) SteamCmdService, SteamCmdRunner, SteamCmdScript

Credentials (Core/Keychain, SteamCredentials)

  • The Web API key and the SteamCMD account name live in the Keychain (isolated services in dev/test copies).
  • The key is checked with Steam before saving and sent in the x-webapi-key header, never in a URL.
  • The password and Steam Guard code are piped to SteamCMD on stdin and never stored or logged. SteamCMD keeps its own login token.
  • Terminal login (SteamTerminalLoginView, SteamCmdTerminalLogin) writes a command file that opens in Terminal; "I've Signed In" then logs in with the cached session.

Running SteamCMD

  • SteamCmdRunner runs steamcmd with a script on stdin (stdin closed, so it reads EOF after quit), streams output on a background queue, supports cancellation and timeouts.
  • SteamCmdRunning is a protocol, so tests use a fake.
  • Output is parsed for status and progress (authenticating, downloading %, validating, copying).
  • Downloads are queued, retryable, and shown in the Downloads tab (DownloadsView).

Filters and search (WorkshopFilter)

  • Show Only, Rating, Type and Resolution are OR within a group; groups AND together; a group with nothing or everything checked doesn't filter.
  • Rating, Type and Resolution are exclusive categories, so the unchecked tags become excludedtags, as WE's own browser sends them.
  • QueryFiles doesn't AND several requiredtags reliably, so at most one tag is required with match_all_tags=true; further AND-ed tags are checked on the results. OR-ed genres go as requiredtags with match_all_tags=false.
  • Results checked locally are paged by WorkshopViewModel, which counts pages over what passes. Only the newest search shows its results.
  • Sort orders map to Steam's query types: Trending, Most Recent, Most Popular (vote), Most Subscribed; text search uses the text-search ranking.

Installing items (WorkshopItemInstaller)

  • SteamCMD's force_install_dir is a hidden .owe-steamcmd folder inside the storage folder. The finished item (steamapps/workshop/content/431960/<id>) is renamed into <storage>/<id> and the staging folder deleted.
  • An item the storage folder already has is kept; no second copy stays behind.
  • A preview the user applies moves from the size-capped preview cache into storage the same way.
  • A storage folder on a disconnected volume fails the download with that reason; nothing falls back elsewhere.
  • DownloadedWallpaperIndex records downloaded IDs, dates and stored Workshop tags.

Dependencies

Component Role
WorkshopDependencyResolver Finds referenced items: project.json's dependency (one ID or a list) and references in loose files (materials/workshop/<id>, JSON contents). Links each installed dependency's folders into the wallpaper (effects/workshop/<id> → <item>/effects).
WorkshopDependencyService Scans an item once per session and fetches what isn't installed; reports per-dependency status for the Details banner
WorkshopDependencyIndex A hidden file in the library marking dependency-only items
InstalledLibrary Lists what WE lists; hides asset items and dependency-only items
WorkshopDependencyCleanup After a delete, removes dependency-only items nothing left references (logged)
WorkshopAssetResolver Finds files in dependencies at load time

Installed tags (InstalledWorkshopTagSync)

For installed items whose project.json has at most one tag: read once with GetPublishedFileDetails (50 IDs per request, one request at a time, throttled), only with a key; re-read when a later time_updated is seen. Offline, stored tags are used.

User guide: Steam Workshop and SteamCMD and Steam login

Clone this wiki locally