unified_game_services_steam

Steam provider for unified_game_services, backed by the pure-Dart steamworks FFI bindings — no Flutter dependency.

Capabilities

Capability Steam API
achievements ISteamUserStats (set/clear, enumerate)
stats ISteamUserStats (int stats)
leaderboards find / upload / download (async)
cloudSave ISteamRemoteStorage
friends ISteamFriends
presence ISteamFriends rich presence

Platform support — desktop only

Steam is backed by dart:ffi, so it runs only on Windows, macOS and Linux. It is not supported on Android, iOS or web — build each store target for the platform it ships on.

Platform Behaviour
Windows / macOS / Linux Full support.
Web The package entry point exports an inert stub on web (if (dart.library.io) selects the real FFI provider). Importing the package never breaks flutter build web / dart compile js, but every member throws UnsupportedError — do not register Steam on web.
Android / iOS dart:ffi compiles, but the Steamworks runtime lib does not exist there, so the constructor throws UnsupportedError — do not register Steam on mobile.

To keep the FFI code out of a mobile/web bundle entirely (not just inert), use a per-platform entry point that never imports this package for those targets — see the per-store builds section in the facade README.

Native library — not bundled (important)

Steam is not zero-config, and this is inherent to Steamworks, not this package: pub.dev ships Dart source only, and Valve's license forbids redistributing the SDK, so the native steam_api library is never delivered with the package. Every Steamworks integration (Unity, Godot, …) requires you to add the native lib yourself.

One-time dev setup

The transitive steamworks package bundles the official redistributables. Copy the right one into your project and write a dev steam_appid.txt with:

dart run unified_game_services_steam:setup --app-id 480

Then make the dynamic loader find it at runtime (it does not search the working directory on macOS/Linux):

OS What to do
Windows Keep steam_api64.dll next to the executable / run dir (searched automatically).
macOS DYLD_LIBRARY_PATH="$PWD" dart run … or copy libsteam_api.dylib to /usr/local/lib.
Linux LD_LIBRARY_PATH="$PWD" dart run …, copy libsteam_api.so to /usr/local/lib, or set an rpath.

In an IDE, set the run config's working directory and add the DYLD_LIBRARY_PATH/LD_LIBRARY_PATH environment variable.

Also: the Steam client must be running and logged in (the signed-in user is the identity — Steam has no username/password login).

Production

For a shipped build, distribute the native lib with your app (next to the executable) under your own Steamworks agreement, and bake the app id into code (SteamProvider(appId: …), which calls RestartAppIfNecessary). Do not ship steam_appid.txt — it is a development-only override.

Never commit the native lib (steam_api64.dll / libsteam_api.dylib / libsteam_api.so) or steam_appid.txt to source control. Valve's license does not permit redistributing the SDK; each build copies the redistributable out of the local pub cache and ships it under your own Steamworks agreement. (This repo keeps them .gitignored for exactly this reason.)

Cross-platform bindings

The published steamworks ships Windows bindings; the same Dart bindings also work on macOS/Linux for the core API. If you hit ABI issues, regenerate per-platform bindings with tool/README.md and a dependency_overrides entry.

Install

dependencies:
  unified_game_services: ^0.1.0
  unified_game_services_steam: ^0.1.0

Usage

import 'package:unified_game_services/unified_game_services.dart';
import 'package:unified_game_services_steam/unified_game_services_steam.dart';

SteamProvider.registerWith(appId: 480); // 480 = Spacewar test app
final services = UnifiedGameServices(); // uses the registered provider

await services.signIn();
await services.unlockAchievement('ACH_WIN_ONE_GAME');
await services.submitScore(leaderboardId: 'Feet Traveled', score: 1500);
final board = await services.getLeaderboard('Feet Traveled');

Steam-specific API

Beyond the unified API (reach via UnifiedGameServicesPlatform.getInstance<SteamProvider>()):

  • clearAchievement(id) — clear a single achievement.
  • resetAllStats(includeAchievements: true) — reset for re-testing.
  • getSteamId64() — the signed-in user's 64-bit Steam ID (SteamUser()->GetSteamID().ConvertToUint64()) as a raw int.
  • getWebApiAuthTicket({identity})SteamAuthTicket — request a Web API auth ticket for server-side account linking (see below).
  • cancelAuthTicket(handle) — release a ticket once your backend consumed it.

Steam has no OAuth, but it offers an equivalent: a Web API auth ticket your server verifies against Valve. Use it to bind a Steam account to a row in your own database with anti-spoof trust.

Two tiers, pick by how much trust you need:

  • Local onlygetSteamId64() returns the steamID64 directly (same value as PlayerProfile.id). Fine to display or cache locally, but a client can lie about it, so never trust it on a server as proof of identity.
  • Server-verifiedgetWebApiAuthTicket() returns a SteamAuthTicket. Send its .hex to your backend; only Valve can confirm it maps to a real steamID64.
final steam = UnifiedGameServicesPlatform.getInstance<SteamProvider>();
await steam.signIn();

// 1. Client: get a ticket and send the hex to your server.
final ticket = await steam.getWebApiAuthTicket();
await http.post(myBackendUri, body: {'ticket': ticket.hex});
steam.cancelAuthTicket(ticket.handle); // release when your server is done

// 2. Server: verify with your publisher Web API key + app id.
//    GET https://api.steampowered.com/ISteamUserAuth/AuthenticateUserTicket/v1/
//        ?key=<WEB_API_KEY>&appid=<APPID>&ticket=<hex>
//    → response carries the *verified* steamid; store it on the user row.

The verified steamID64 is the link key — the client cannot forge it. This is the recommended path for "log in / link with Steam" against your own service.

Examples & tooling

License

MIT — see the LICENSE file.

This is an independent, unofficial library, not affiliated with or endorsed by Valve. Steam and Steamworks are trademarks of Valve Corporation.

This provider is a thin wrapper over the BSD-3-Clause steamworks FFI bindings (© 2022 Ahmet Enes Bayraktar). It bundles no Valve SDK or native binary: Valve's license forbids redistributing the Steamworks SDK, so the native library is copied out of your local pub cache at setup time and you must ship it under your own Steamworks agreement. Full third-party credits and trademark notices are in the repository's NOTICE.md.

Libraries

unified_game_services_steam
Steam provider for unified_game_services, backed by the pure-Dart steamworks FFI bindings.