Steamworks-dokumentation
Oversigt over Steamworks-API

Oversigt

Steamworks-API'en gør det muligt for dit spil at udnytte mulighederne ved Steam bedst muligt ved at få adgang til alle de underliggende systemer, som leveres gennem API'en. Dette inkluderer ting såsom at sætte dit spil på pause, når brugeren åbner Steam-overlayet, invitere venner til at spille, lade spillere låse op for Steam-præstationer, lade spillere konkurrere på Steam-førertavlerne og meget mere.

Referencedokumentation til Steamworks-API'en dokumenterer alle grænseflader, funktioner, tilbagekald og typer, som er understøttet i API'en.

Integrering med Steamworks-APIen er aldrig et krav for at udgive dit produkt på Steam, men det anbefales kraftigt, fordi det gør det muligt for dig at udføre mange interaktioner, som Steam-brugere forventer.

Sådan kommer du i gang

BEMÆRK: Steamworks-API'en understøtter officielt C++ ved hjælp af Microsoft Visual Studio 2008+ på Microsoft Windows, GCC 4.6+ og Clang 3.0+ på macOS og SteamOS/Linux. Hvis du bruger en tredjepartsmotor eller et andet programmeringssprog end C++, bør du først kigge på Commercial engine and non-C++ language support for at se, om der er nogle mere specifikke instruktioner til at komme i gang med din valgte motor eller sprog. I nogle tilfælde kan du muligvis springe over mange af disse trin.

  • Hvis du ikke allerede har gjort det, skal du downloade Steamworks-SDK'en og pakke den ud.
  • Kopier Steamworks-API-headermappen public/steam til et passende sted i dit applikationskildetræ.
  • Copy the relevant redistributable files from redistributable_bin into an appropriate place in your project folder.
    • Windows
      You must have steam_api[64].lib linking in your visual studio project. This can be linked to either the primary executable or a module that uses Steam. This allows you to access the functionality contained in steam_api[64].dll which is exposed via the Steamworks API headers. Additional Reading: Linking an Executable to a DLL (MSDN)

      You must also ship the steam_api[64].dll in your run-time directory (next to your programs executable, or in your dll search path).
    • macOS
      libsteam_api.dylib provides both the x86 and x64 version of the Steam API. You must link to this in your Xcode project and you must ship this along side your executable.
      Additional Reading: Using Dynamic Libraries
    • Linux
      libsteam_api.so You must both link to and ship this along side your executable.

Initialisering og lukning

SteamAPI_Init

Når du har sat Steamworks-API'en op i dit projekt, kan du begynde at bruge den ved at kalde SteamAPI_Init-funktionen for at initialisere API'en. Dette vil indstille den globale tilstand og udfylde grænseflademarkørerne, som er tilgængelige via globale funktioner, som passer til navnet på grænsefladen. Dette SKAL kaldes og returneres, før Steamworks-grænseflader tilgås!

Steamworks-API'en bliver ikke initaliseret, hvis den ikke kender app-ID'et til dit spil. Når du starter din app fra selve Steam, vil den automatisk have app-ID'et. Under udviklingsarbejdet skal du give Steam besked om dette med en tekstfil. Opret en tekstfil kaldet steam_appid.txt ved siden af din eksekverbare fil, som kun indeholder app-ID'et og intet andet. Dette overskriver værdien, som Steam giver. Du bør ikke udgive dette med dine builds. Eksempel:
480

Hvis false returneres, indikerer det en af de følgende tilstande:
  • Steam-klienten kører ikke. Der kræves en kørende Steam-klient for at give implementeringer af forskellige Steamworks-grænseflader.
  • Steam-klienten kunne ikke bestemme spillets app-ID. Hvis du kører din applikation fra den eksekverbare fil eller direkte fra fejlfinderen, skal du have en steam_appid.txt i din spilmappe ved siden af den eksekverbare fil sammen med dit app-ID og intet andet. Steam kigger efter denne fil i den nuværende arbejdsmappe. Hvis du kører din eksekverbare fil fra en anden mappe, kan du blive nødt til at flytte steam_appid.txt-filen.
  • Din applikation kører ikke under den samme OS-brugerkontekst som Steam-klienten, såsom en anden bruger eller administrationsadgangsniveau.
  • Du skal sikre dig, at du ejer en licens for app-ID'et på den nuværende aktive Steam-konto. Dit spil skal dukke op i dit Steam-bibliotek.
  • Dit app-ID er ikke helt sat op, for eksempel i Release State: Unavailable, eller det mangler standardpakker.
Hvis du støder på problemer med initialisering, skal du tjekke dokumentationen Fejlfinding i Steamworks-API'en for at lære mere om de forskellige metoder til fejlfinding af Steamworks-API'en.

SteamAPI_RestartAppIfNecessary

SteamAPI_RestartAppIfNecessary tjekker, om din eksekverbare fil blev startet gennem Steam, og genstarter den gennem Steam, hvis den ikke blev startet gennem Steam første gang.

Dette er valgfrit, men anbefales kraftigt, da Steam-konteksten, som er tilknyttet din applikation (inklusive dit app-ID), ikke vil blive sat op, hvis brugeren starter den eksekverbare fil direkte. Hvis dette sker, vil SteamAPI_Init fejle, og du vil ikke være i stand til at bruge Steamworks-API'en.
Hvis du vælger at bruge denne, bør det være det første Steamworks-funktionskald, du laver lige før SteamAPI_Init.

Hvis true returneres, vil det starte Steam-klienten, hvis det er påkrævet, og starte dit spil gennem Steam. Du bør afslutte processen så snart, det er muligt. Dette kører reelt set steam://run/<AppID>, så det kan være, at det ikke genoptager den samme eksekverbare fil, som kaldte denne funktion (for eksempel hvis du kørte fra din fejlfinder). Det vil altid starte op igen fra versionen, som du har installeret i din Steam-biblioteksmappe.

Ellers hvis dette returnerer false, blev dit spil startet af Steam-klienten, og ingen handling er nødvendig. En undtagelse er, hvis en steam_appid.txt-fil findes, så vil dette returnere false uanset. Dette giver dig mulighed for at udvikle og teste uden at starte dit spil gennem Steam-klienten. Sørg for at fjerne steam_appid.txt-filen, når du uploader spillet til dit Steam-depot!

BEMÆRK: Hvis du bruger Steam DRM-wrapperen på din primære eksekverbare fil, er denne kontrol unødvendig, da DRM-wrapperen vil udføre dette internt.

SteamAPI_Shutdown

Når du er færdig med at bruge Steamworks-API'en, bør du kalde SteamAPI_Shutdown for at frigive resurserne, som bruges af din applikation internt i Steam. Du bør kalde dette under lukningsprocessen, hvis det er muligt.

Dette vil ikke fjerne tilknytningen af Steam-overlay fra dit spil, da der ikke er nogen garanti for, at din gengivelses-API er færdig med at bruge den.

Steamworks-grænseflader

Steamworks-API'en er sammensat af flere grænseflader, som alle viser en begrænset, specifik mængde af funktionalitet.

Når Steamworks er korrekt initialiseret, kan du tilgå grænsefladerne via deres globale funktioner. Funktionerne matcher altid navnet på deres grænseflade. Derfor kan du tilgå ISteamApps gennem SteamApps()-accessoren og ISteamFriends gennem SteamFriends().

Du kan bruge disse grænseflader til at foretage kald således:
// Henter den aktuelle brugers Steam-navn. const char *name = SteamFriends()->GetPersonaName();

Du kan se den komplette liste over grænseflader på Referencedokumentation til Steamworks-API'en eller ved at se på Steamworks-API-headerfilerne.

Tilbagekald

Tilbagekald er et af de vigtigste aspekter af Steamworks, da de gør det muligt for dig at hente data asynkront fra Steam uden at låse for dit spil. Formålet med tilbagekald er at give en simpel, let, type- og trådsikker metode til at hæve asynkrone hændelser på ethvert objekt, som er registreret som lytter.

Tilbagekald udløses normalt via en hændelse, der sker fra Steam, såsom når en ven logger på eller af eller asynkrone resultater fra API-funktioner. Hvert tilbagekald består af en struktur, som indeholder en unik identifikator og et mindre datasæt. Tilbagekald erklæres i ISteam*.h-headerfilerne, grupperet med grænsefladen, som kaldet hører tættest til.

For at lytte efter et tilbagekald skal en struktur bruge makroen STEAM_CALLBACK( :classname, :functionname, :callbackname ) i dens erklæring.
  • :classname skal være navnet på strukturen eller klassen, hvor du definerer dette. (for eksempel CGameManager)
  • :functionname vil være navnet på funktionen, som modtager dette tilbagekald. (for eksempel OnGameOverlayActivated)
  • :callbackname er navnet på tilbagekaldet. (for eksempel GameOverlayActivated_t)
Dette definerer en lokal medlemsfunktion for klassen, som automatisk er lavet som prototype som void :functionname( :callbackname *pCallback ). Oprettelse af en ny forekomst af objektet vil forårsage, at denne medlemsfunktion vil registrerer sig selv som lytter med Steamworks-API'en. Destruktion af objektet vil forårsage, at det vil afregistrere.

BEMÆRK: Du bør sikre, at Steam er opstartet, før du opretter objekter, som lytter efter tilbagekald.

For at forberede tilbagekald til at sende til registrerede lyttere skal du kalde SteamAPI_RunCallbacks. Det er bedst at kalde denne ofte. Jo længere tid mellem kaldene, jo større potentiel forsinkelse mellem modtagehændelser eller resultater fra Steamworks-API'en. De fleste spil kalder denne én gang pr. gengivelsesbillede. Det anbefales stærkt, at du laver dette kald mindst én gang i sekundet. Alle registrerede lyttefunktioner vil blive aktiveret under dette kald i trådkonteksten, hvor SteamAPI_RunCallbacks blev kaldt fra.

Eksempel

Et tilbagekald, som du med stor sandsynlighed ønsker at bruge, er ISteamFriends::GameOverlayActivated_t. Som navnet hentyder, sender det et tilbagekald til dig, hver gang brugeren aktiverer eller deaktiverer Steam-overlay.

class CGameManager { private: STEAM_CALLBACK( CGameManager, OnGameOverlayActivated, GameOverlayActivated_t ); }; void CGameManager::OnGameOverlayActivated( GameOverlayActivated_t* pCallback ) { if ( pCallback->m_bActive ) printf( "Steam overlay now active\n" ); else printf( "Steam overlay now inactive\n" ); }

En populær og anbefalet anvendelse af ISteamFriends::GameOverlayActivated_t-tilbagekaldet er at sætte spillet på pause, når overlayet åbner.

CallResults

Mange Steamworks-metoder bruger resultater fra kald i stedet for et tilbagekald for asynkront at returnere resultater fra et funktionskald. Forskellen mellem et tilbagekald og kaldsresultater er, at tilbagekald sendes til alle, som lytter, hvorimod kaldsresultater kun sendes til en specifik lytter. Ligesom med tilbagekald skal dit spil kalde SteamAPI_RunCallbacks for at sende kaldsresultater til lyttere.

Du kan identificere en funktion, som giver kaldsresultater ved at kigge på returværdien. Hvis SteamAPICall_t returneres og har en CALL_RESULT()-attribut, skal du registrere for at modtage kaldsresultatet.

BEMÆRK: Tilbagekalds- og kaldsresultater er ikke udskiftelige. En hændelse vil kun gå igennem det ene eller det andet, ikke begge. Du skal sørge for, at du registrerer den rigtige type hændelse!

Resultater fra kald skal oprettes som et medlem i en struktur/klasse ved at bruge CCallResult-typen, og du skal også oprette medlemsfunktionen, som vil modtage tilbagekaldet.
void func( :callresultname *pCallback, bool bIOFailure ); CCallResult< :classname, :callresultname > m_callresultname;
  • :classname skal være navnet på strukturen eller klassen, hvor du definerer dette. (for eksempel CGameManager)
  • :callresultname er navnet på tilbagekaldet. (for eksempel NumberOfCurrentPlayers_t)

Du er velkommen til at navngive funktionen, funktionsparametre og CCallResult efter eget valg.

Eksempel

Her er et eksempel på, hvordan du bruger ISteamUserStats::GetNumberOfCurrentPlayers-API, som producerer et ISteamUserStats::NumberOfCurrentPlayers_t-kaldsresultat.
// I din klassedefinition class CGameManager { public: void GetNumberOfCurrentPlayers(); private: void OnGetNumberOfCurrentPlayers( NumberOfCurrentPlayers_t *pCallback, bool bIOFailure ); CCallResult< CGameManager, NumberOfCurrentPlayers_t > m_NumberOfCurrentPlayersCallResult; }; // Gør, at asynkrone anmodninger modtager antallet af aktuelle spillere. void CGameManager::GetNumberOfCurrentPlayers() { printf( "Getting Number of Current Players\n" ); SteamAPICall_t hSteamAPICall = SteamUserStats()->GetNumberOfCurrentPlayers(); m_NumberOfCurrentPlayersCallResult.Set( hSteamAPICall, this, &CGameManager::OnGetNumberOfCurrentPlayers ); } // Kaldes, når SteamUserStats()->GetNumberOfCurrentPlayers() returnerer asynkront efter et kald til SteamAPI_RunCallbacks(). void CGameManager::OnGetNumberOfCurrentPlayers( NumberOfCurrentPlayers_t *pCallback, bool bIOFailure ) { if ( bIOFailure || !pCallback->m_bSuccess ) { printf( "NumberOfCurrentPlayers_t failed!\n" ); return; } printf( "Number of players currently playing: %d\n", pCallback->m_cPlayers ); }

BEMÆRK: Hvis du ikke kan bruge CCallResult-systemet, kan du muligvis bruge ISteamUtils::IsAPICallCompleted, ISteamUtils::GetAPICallResult og ISteamUtils::GetAPICallFailureReason til at spore statussen af et kaldsresultat.

Manual Callback Dispatch

Klasser og makroer til registrering af tilbagekald er praktiske i C++-kode. But there is also a lower-level mechanism for dealing with callbacks. This mechanism operates more like a windows event loop. Instead of a single function that dispatches all of the callbacks and call results to active listeners, you fetch the next available callback in a loop, and dispatch it using whatever mechanisms you want. The manual dispatch mode is especially useful for binding layers that expose the Steamworks SDK to languages other than C++. See SteamAPI_ManualDispatch_Init() in steam_api.h for more information.

Steam Game Servers

The Steamworks API includes support for running game servers as well as regular clients. A game server, in Steamworks API terms, is an entity in the system that normal users connect to to play multi-player games. This can be connecting over the Internet to a remote game server, or connecting locally to a game server that's in the same process as the client. Game servers have their own set of API functions to use, and their own unique Steam ID for other users to refer to them by.

To use the Steam Game Server API you must first include steam_gameserver.h instead of steam_api.h.

Initializing and using the game server API is very similar to the normal API:

After initializing a game server you have access to the two game server exclusive interfaces ISteamGameServer and ISteamGameServerStats.

You can also access the following regular interfaces from the game server:
  • ISteamClient, som du kan tilgå via den globale grænseflade: SteamGameServerClient()
  • ISteamUtils, som du kan tilgå via den globale grænseflade: SteamGameServerUtils()
  • ISteamNetworking, som du kan tilgå via den globale grænseflade: SteamGameServerNetworking()
  • ISteamHTTP, som du kan tilgå via den globale grænseflade: SteamGameServerHTTP()
  • ISteamUGC which you can access via the global interface: SteamGameServerUGC()
  • ISteamApps which you can access via the global interface: SteamGameServerApps()

If you're running a dedicated game server (one which has no client component), you only have to initialize the game server API's, you don't have to initialize the normal user API.

See Steamworks-API-eksempel på applikation (SpaceWar) for a fully loaded example of using the game server API.

Unlike a game, a dedicated server will usually be run in an environment where there is no Steam Client installed to provide the latest steamworks binaries. In order for the dedicated server to have the latest steam binaries, you will need to include the Dedicated Server Redistributables with your app. Log into partner.steamgames.com and navigate to the technical settings for your app. Then look under "Installation / Redistributables" and check "Dedicated Server Redistributables"

Commercial engine and non-C++ language support

If you're using a commercial game engine or a language other than C or C++ you will want to see what level of support for the Steamworks API is provided for it.
In some engines they provide native built-in support, for others you may need a third-party solution.

If your engine does not have native support you can use the Steam Web API to access many features that Steam supports.

Regardless of how the Steamworks SDK is implemented in your engine you will need to have the latest Steamworks SDK to upload your application to Steam.

BEMÆRK: If some of the software you are shipping on steam is available under a restrictive open source license then please see Distribuering af open source-applikationer på Steam.

Here are some common engines that people routinely use to ship games on Steam and the relevant documentation on how to get started using the Steamworks SDK with them.

BEMÆRK: Valve does not in any way endorse any of these engines or the third-party solutions. This list is sorted exclusively by name, and is in no way comprehensive, it exists solely as a starting guide. Engines will only be listed if they include native support or have a third-party solution that fits the guidelines. Third-party solutions will only be listed if they are kept reasonably up to date with the Steamworks SDK, are freely available under a permissive license (See: Distribuering af open source-applikationer på Steam), and have a thread on the Steamworks Discussion Board. We recommend that you consult the community to see which option would work best for your specific setup.

Motorer:

MotorIndbygget understøttelse?Oplysninger
CRYENGINE ✔️
GameMaker Studio 2 ✔️ Brug af Steamworks-SDK med GameMaker: Studio
Godot Third Party: GodotSteam - Steamworks Developer Discussions support thread
Haxe Tredjepart: SteamWrap - Steamworks-udviklerdiskussioner – supporttråd
Leadwerks Game Engine ✔️ Leadwerks API Reference › Steamworks
RPG Maker MV Tredjepart: Greenworks - Steamworks-udviklerdiskussioner – supporttråd
Source 2013 ✔️ Distribuering af Source Engine-spil/-mods
Unity Tredjepart: Facepunch.Steamworks - Steamworks-udviklerdiskussioner – supporttråd
Tredjepart: http://steamworks.github.io - Steamworks-udviklerdiskussioner – supporttråd
Unreal Engine 4 ✔️ Online Subsystem Steam
Visionaire Studio ✔️ Udgiv på Steam

Sprog:

Flat interface for binding to other languages

The SDK has a few features to facilitate the creation of binding layers for other languages.

  • steam_api_flat.h declares a set of "flat" functions that mirror the interface functions in the SDK. This is not pure C code, but it does use plain C linkage and calling conventions, so it is easy to interop with other languages. These functions are exported by steam_api[64][.dll/.so/dylib].
  • steam_api.json describes (almost all of) the interfaces, types, and functions in the SDK. It is intended that this file be used by an automated process to generate binding layer. We hope that this can be used to automate 95% of the work, but there are still a few special cases that need to be handled manually. In particular, CSteamID and CGameID will probably require special handling by your binding layer to make it efficient.

Technical Details

Steam uses a variety of techniques to expose functionality to your application. It's by no means critical to understand exactly how the Steamworks API works but it's fairly simple and can be useful in planning out how to code your game with Steam integration in mind.

When you link to steam_api[64][.dll/.so/dylib] it provides access to a small number of C functions which are prefixed with the S_API macro, these functions are all exposed in steam_api.h and steam_gameserver.h. The steam_api module itself is very small, it only exposes the base functionality to initialize and shutdown the Steamworks API.

When the Steamworks API initializes it finds the actively running steam client process and loads steamclient.dll from that path. steamclient.dll is essentially the core engine of the Steam client. It contains and maintains the information necessary to run Steam. The Steam client UI uses a similar set of functions as exposed here to access the data provided by steamclient.dll. Since this data is in the Steam process, all Steam API calls are transparently marshaled and sent via an RPC/IPC mechanism. (A cross-process pipe, ISteamClient::HSteamPipe).

The Steam process, via steamclient.dll maintains a constant connection to the Steam back-end servers. Through this connection all authentication, matchmaking, friends list and VAC communication occurs. This connection may drop if the user has a network issue, or if the Steam server they are connected to receives an update. Callbacks will be posted to any running app if the connection drops or re-establishes. The Steam client will automatically try to reconnect, and clients running an app receive priority, so the typical reconnect time is under 10 seconds, although in some rare cases may be up to 5 minutes.

The Steamworks API is versioned through a COM-like mechanism, where a string name and version of an interface are passed into steamclient.dll which then returns the correct version of the interface to the caller. steamclient.dll contains a set of adapters for all released versions of an interface which redirect or re-interpret the old calls in the context of the latest interface. The adapters live inside the steam client so that they are easy to update if any issues arise.