Documentazione di Steamworks
Introduzione all'API di Steamworks

Introduzione

L'API di Steamworks permette al tuo gioco di trarre pieno vantaggio da Steam grazie ai sistemi di cui è dotata. Alcuni dei vantaggi includono la possibilità di mettere in pausa il gioco quando l'utente apre Steam Overlay, di invitare amici a giocare, di sbloccare gli achievement di Steam, di lasciare che i giocatori si sfidino nelle classifiche di Steam e tanto altro.

Riferimenti per l'API di Steamworks cataloga e documenta ogni interfaccia, funzione, callback e tipo supportato dall'API.

L'integrazione del tuo prodotto con l'API di Steamworks non è obbligatoria per il rilascio su Steam, ma è fortemente consigliata poiché abilita molte interazioni che gli utenti di Steam danno per scontate.

Per iniziare

NOTA: l'API di Steamworks supporta ufficialmente C++ per l'utilizzo con Microsoft Visual Studio 2008+ su Microsoft Windows e GCC 4.6+ e Clang 3.0+ per l'utilizzo su macOS e SteamOS/Linux. Se utilizzi un engine di terze parti o un linguaggio di programmazione diverso da C++, controlla se su Supporto agli engine commerciali e a linguaggi diversi da C++ sono presenti istruzioni specifiche riguardanti il tuo engine o linguaggio. In alcuni casi potrebbe essere possibile saltare diversi dei seguenti passaggi.

  • Se non l'hai ancora fatto, dscarica l'SDK di Steamworks e decomprimilo.
  • Copia la cartella dei file di intestazione dell'API di Steamworks public/steam in una posizione appropriata per i codici della tua applicazione.
  • Copia i file redistribuibili rilevanti da redistributable_bin alla cartella appropriata del tuo progetto.
    • Windows
      Devi avere steam_api[64].lib collegato al tuo progetto su Visual Studio. Può essere collegato attraverso l'eseguibile principale o un modulo che utilizza Steam. In questo modo, potrai accedere alle funzionalità presenti in steam_api[64].dll, esposta tramite le intestazioni dell'API di Steamworks. Approfondimenti: Collegare un eseguibile a una DLL (MSDN)

      Devi anche inviare la steam_api[64].dll alla tua directory run-time (accanto all'eseguibile del tuo programma o nel percorso di ricerca della tua DLL).
    • macOS
      libsteam_api.dylib fornisce sia la versione x86 che quella x64 dell'API di Steam. Dovrai collegarla nel tuo progetto XCode e inviarla insieme al tuo eseguibile.
      Approfondimento: Utilizzo delle librerie dinamiche.
    • Linux
      libsteam_api.so È necessario collegarla e inviarla insieme al tuo eseguibile.

Inizializzazione e arresto

SteamAPI_Init

Dopo avere impostato l'API di Steamworks per il tuo progetto, puoi inizializzarla effettuando una chiamata alla funzione SteamAPI_Init. Farlo, imposterà lo stato globale e popolerà i puntatori dell'interfaccia accessibili tramite le funzioni globali dal nome corrispondente. Questa chiamata DEVE essere effettuata e deve avere esito positivo per poter accedere alle Interfacce di Steamworks!

L'API di Steamworks non si avvierà se non conosce l'appID del tuo gioco. Quando lanci la tua app da Steam, la sua appID sarà automaticamente disponibile. Durante la fase di sviluppo, dovrai informare Steam dell'appID attraverso un file di testo. Crea un file di testo chiamato steam_appid.txt vicino all'eseguibile e riempilo solamente con l'appID. Ciò sovrascriverà il valore fornito da Steam. Non includere questo elemento nelle tue build. Esempio:
480

Se viene restituito false, si sono verificate una o più delle seguenti condizioni:
  • Il client di Steam non è in esecuzione. Per l'implementazione delle varie interfacce di Steamworks è necessario che sia presente un client di Steam in esecuzione.
  • Il client di Steam non è riuscito a determinare l'appID del gioco. Se stai eseguendo la tua applicazione direttamente dall'eseguibile o dal debugger, devi avere un file steam_appid.txt vicino all'eseguibile nella directory del gioco. Il file deve contenere solamente l'appID del gioco. Steam cercherà questo file nella directory di lavoro attuale. Se stai lanciando l'eseguibile da una directory diversa, potresti dover spostare il file steam_appid.txt.
  • La tua applicazione è in esecuzione in un contesto utente del sistema operativo diverso del client di Steam (ad esempio un utente diverso o diversi livelli di permesso).
  • Assicurati di avere una licenza per l'appID sull'account di Steam attualmente attivo. Il tuo gioco deve apparire sulla tua Libreria di Steam.
  • La tua appID non è interamente configurata. Ad esempio Stato di rilascio: non disponibile o mancano dei pacchetti predefiniti.
Se riscontri problemi di inizializzazione consulta, la documentazione Debugging nell'API di Steamworks per saperne di più sui vari metodi di debugging dell'API di Steamworks.

SteamAPI_RestartAppIfNecessary

SteamAPI_RestartAppIfNecessary controlla se il tuo eseguibile è stato lanciato tramite Steam e, in caso contrario, lo lancia nuovamente tramite Steam.

Non è obbligatorio ma lo consigliamo in quanto il contesto di Steam associato alla tua applicazione, nonché la tua appID, non saranno impostati se l'utente lancia direttamente l'eseguibile. Se ciò dovesse verificarsi, SteamAPI_Init fallirà e non sarai in grado di utilizzare l'API di Steamworks.
Se decidi di usare questa funzione, dovrebbe essere la prima chiamata che effettui, subito prima di SteamAPI_Init.

Se viene restituito true, si avvierà il client di Steam, se necessario, e il tuo gioco sarà lanciato nuovamente attraverso di esso. Arresta il tuo processo il più presto possibile. Questa funzione esegue steam://run/<AppID>, per cui potrebbe non lanciare lo stesso eseguibile che ha chiamato la funzione (ad esempio nel caso in cui fosse in esecuzione tramite il debugger). Il lancio avverrà sempre dalla versione installata nella tua cartella della Libreria di Steam.

In caso contrario, se viene restituito false, il tuo gioco è stato lanciato tramite il client di Steam e non sono necessarie ulteriori azioni. L'unica eccezione si verifica qualora sia presente un file steam_appid.txt. In questo caso, verrà sempre restituito false. Ciò ti permette di sviluppare e testare senza dover lanciare il tuo gioco tramite il client di Steam. Assicurati di rimuovere il file steam_appid.txt quando carichi il gioco sul tuo depot di Steam!

NOTA: se utilizzi il wrapper dello Steam DRM sul tuo file eseguibile principale, questo controllo non è necessario dato che il wrapper DRM lo eseguirà internamente.

SteamAPI_Shutdown

Quando hai finito di utilizzare l'API di Steamworks, chiama SteamAPI_Shutdown per liberare le risorse utilizzate internamente dalla tua applicazione all'interno di Steam. Se possibile, questa chiamata dovrebbe essere effettuata mentre il processo viene arrestato.

Farlo non libererà l'Overlay di Steam dal tuo gioco, poiché non è possibile sapere se l'API di rendering ha finito di usarlo.

Interfacce di Steamworks

L'API di Steamworks si compone di diverse interfacce che presentano un numero limitato e specifico di funzionalità.

Dopo la corretta inizializzazione di Steamworks, puoi accedere a queste interfacce attraverso le loro funzioni globali. Queste funzioni corrispondono sempre al nome della loro interfaccia. Potrai dunque accedere a ISteamApps attraverso SteamApps() e a ISteamFriends through SteamFriends().

Puoi utilizzare queste interfacce per effettuare chiamate come:
// Ottieni il nome di Steam attuale dell'utente. const char *name = SteamFriends()->GetPersonaName();

Puoi visualizzare la lista completa delle interfacce nel documento Riferimenti per l'API di Steamworks oppure studia direttamente i vari file di intestazione dell'API di Steamworks.

Callback

Le callback sono uno degli aspetti più importanti di Steamworks e ti consentono di recuperare dati da Steam in maniera asincrona, senza bloccare il tuo gioco. L'obiettivo delle callback è di fornire un metodo semplice, snello ed efficace di sottoporre eventi asincroni a qualunque oggetto registrato come ascoltatore.

Le callback sono solitamente causa da un evento di Steam, ad esempio un amico che esegue l'accesso o si disconnette, oppure possono essere il risultato asincrono di alcune funzioni dell'API. Ogni callback consiste di una struttura contenente un identificatore unico e un piccolo insieme di dati. Le callback sono dichiarate nei file di intestazione ISteam*.h, raggruppate con le interfacce a cui sono più vicine.

Per ascoltare una callback, le strutture e le classi devono utilizzare la macro STEAM_CALLBACK( :classname, :functionname, :callbackname ) nella loro dichiarazione.
  • :classname deve essere il nome della struttura o della classe in cui la stai definendo (ad esempio CGameManager).
  • :functionname sarà il nome della funzione che riceve questa callback. (ad esempio OnGameOverlayActivated).
  • :callbackname è il nome della callback. (ad esempio GameOverlayActivated_t).
Ciò definisce una funzione di membro locale per quella classe, che viene automaticamente resa come prototipo come void :functionname( :callbackname *pCallback ). Creare una nuova istanza dell'oggetto farà sì che la funzione membro si registri come ascoltatore all'interno dell'API di Steamworks. L'oggetto si registrerà nuovamente se viene distrutto.

NOTA: Assicurati che Steam sia stato inizializzato prima di creare oggetti che ascoltano le callback.

Per le callback da inviare ad ascoltatori registrati, chiama SteamAPI_RunCallbacks. È bene effettuare spesso questa chiamata, poiché maggiore è l'intervallo di tempo tra le chiamate, maggiore sarà la latenza fra gli eventi o i risultati ottenuti dall'API di Steamworks. La maggior parte dei giochi effettua questa chiamata una volta per ogni frame ed è consigliabile effettuarla almeno una volta al secondo. Tutti gli ascoltatori registrati per le funzioni saranno invocati durante questa chiamata, nel contesto del thread da cui è stata chiamata SteamAPI_RunCallbacks.

Esempio

Una callback che vorrai probabilmente usare è ISteamFriends::GameOverlayActivated_t. Come si può intuire dal nome, ti invia una callback ogni volta che l'utente attiva o disattiva l'Overlay di Steam.

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

Un uso diffuso e consigliato per la callback ISteamFriends::GameOverlayActivated_t è quello di mettere in pausa il gioco quando si apre l'Overlay.

Risultati di chiamata

Molti metodi di Steamworks usano i risultati di chiamata invece delle callback per restituire risultati in maniera asincrona dalla chiamata di funzione. La differenza tra una callback e un risultato di chiamata è che le callback sono trasmesse a tutti gli ascoltatori, mentre i risultati solo uno specifico ascoltatore. Come per le callback, il tuo gioco dovrà chiamare SteamAPI_RunCallbacks per inviare i risultati delle chiamate ai loro ascoltatori.

Puoi identificare una funzione che fornisce un risultato di chiamata attraverso il valore restituito. Se restituisce una SteamAPICall_t e ha un attributo CALL_RESULT(), devi registrati per ricevere il risultato di chiamata.

NOTA: Le callback e i risultati di chiamata non sono intercambiabili. Gli eventi saranno trasmessi dalle une o dagli altri, non da entrambi. Assicurati di avere effettuato la registrazione per il tipo di evento corretto!

I risultati di chiamata devono essere creati come membri di una struttura/classe utilizzando il tipo CCallResult e dovrai anche creare la funzione membro che riceverà la callback.
void func( :callresultname *pCallback, bool bIOFailure ); CCallResult< :classname, :callresultname > m_callresultname;
  • :classname deve essere il nome della struttura o della classe in cui la stai definendo (ad esempio CGameManager).
  • :callresultname è il nome della callback. (ad esempio NumberOfCurrentPlayers_t).

Puoi dare qualunque nome alla funzione, ai parametri della funzione e al tipo CCallResult.

Esempio

Ecco un esempio di come utilizzare l'API ISteamUserStats::GetNumberOfCurrentPlayers, che produce un risultato di chiamata ISteamUserStats::NumberOfCurrentPlayers_t.
// Nella tua definizione di classe class CGameManager { public: void GetNumberOfCurrentPlayers(); private: void OnGetNumberOfCurrentPlayers( NumberOfCurrentPlayers_t *pCallback, bool bIOFailure ); CCallResult< CGameManager, NumberOfCurrentPlayers_t > m_NumberOfCurrentPlayersCallResult; }; // Effettua la richiesta asincrona per ricevere il numero corrente di giocatori. void CGameManager::GetNumberOfCurrentPlayers() { printf( "Getting Number of Current Players\n" ); SteamAPICall_t hSteamAPICall = SteamUserStats()->GetNumberOfCurrentPlayers(); m_NumberOfCurrentPlayersCallResult.Set( hSteamAPICall, this, &CGameManager::OnGetNumberOfCurrentPlayers ); } // Chiamata quando SteamUserStats()->GetNumberOfCurrentPlayers() viene restituita in maniera asincrona dopo una chiamata a 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 ); }

NOTA: se non puoi utilizzare il sistema CCallResult, potresti essere in grado di utilizzare ISteamUtils::IsAPICallCompleted, ISteamUtils::GetAPICallResult e ISteamUtils::GetAPICallFailureReason per tracciare lo stato di un risultato di chiamata.

Invio callback manuale

Le classi e le macro utilizzate per registrare le callback sono comode in C++. Tuttavia, esiste anche un meccanismo di livello inferiore per gestire le callback. Tale meccanismo opera più come un ciclo di eventi di Windows. Al posto di un'unica funzione che invia tutte le callback e i risultati di chiamata agli ascoltatori attivi, recuperi la callback successiva disponibile in un ciclo e la invii utilizzando il meccanismo desiderato. La modalità di invio manuale è particolarmente utile per i livelli di associazione che espongono la SDK di Steamworks a linguaggi diversi da C++. Per ulteriori informazioni, consulta SteamAPI_ManualDispatch_Init() in steam_api.h.

Server di gioco di Steam

L'API di Steamworks include il supporto per gestire server di gioco e i normali client. Un server di gioco, dal punto di vista dell'API di Steamworks, è un'entità nel sistema a cui i normali utenti si connettono per giocare a titoli multigiocatore. La connessione può essere stabilita tramite internet con un server di gioco remoto o localmente con un server di gioco nello stesso processo del client. I server di gioco hanno i loro insiemi di funzioni API da utilizzare e il loro ID di Steam unico a cui gli altri utenti fanno riferimento.

Per usare le API dei server di gioco di Steam, devi prima includere steam_gameserver.h invece di steam_api.h.

L'avvio e l'utilizzo dell'API dei server di gioco funzionano in maniera molto simile alla normale API:

Dopo aver avviato un server di gioco, avrai accesso alle due interfacce esclusive relative: ISteamGameServer e ISteamGameServerStats.

Puoi accedere anche alle seguenti interfacce regolari dal server di gioco:
  • ISteamClient, a cui puoi accedere tramite l'interfaccia globale: SteamGameServerClient()
  • ISteamUtils, a cui puoi accedere tramite l'interfaccia globale: SteamGameServerUtils()
  • ISteamNetworking, a cui puoi accedere tramite l'interfaccia globale:SteamGameServerNetworking()
  • ISteamHTTP, a cui puoi accedere tramite l'interfaccia globale: SteamGameServerHTTP()
  • ISteamUGC, a cui puoi accedere tramite l'interfaccia globale: SteamGameServerUGC()
  • ISteamApps, a cui puoi accedere tramite l'interfaccia globale: SteamGameServerApps()

Se stai gestendo un server di gioco dedicato (uno che non ha alcuna componente client), devi solo avviare l'API dei server di gioco, non quella regolare da utente.

Vedi Esempio di applicazione dell'API di Steamworks (SpaceWar) per un esempio completo dell'utilizzo dell'API dei server di gioco.

A differenza di un gioco, un server dedicato sarà in esecuzione in un ambiente in cui non è installato il client di Steam per fornire i binari più recenti di Steamworks. Per fornire gli ultimi binari di Steam al server dedicato dovrai includere i ridistribuibili per i server dedicati nella tua applicazione. Esegui l'accesso su partner.steamgames.com e vai alle impostazioni tecniche della tua applicazione, quindi vai su "Installazione / Ridistribuibili" e attiva i ridistribuibili per i server dedicati.

Supporto agli engine commerciali e a linguaggi diversi da C++

Se stai usando un engine di gioco commerciale o un linguaggio diverso da C o C++, vorrai controllare quale livello di supporto è offerto per l'API di Steamworks.
Alcuni engine forniscono il supporto nativo, mentre altri necessitano di soluzioni di terze parti.

Se il tuo engine non è supportato in maniera nativa, puoi utilizzare l'API web di Steam per accedere a molte delle funzionalità supportate da Steam.

Indipendentemente da come l'SDK di Steamworks è implementato nel tuo engine, avrai bisogno della sua versione più recente per caricare la tua applicazione su Steam.

NOTA: se alcuni dei software che stai distribuendo su Steam sono disponibili attraverso delle licenze open source restrittive, vedi Distribuzione delle applicazioni open source su Steam.

Ecco alcuni degli engine più diffusi che vengono usati per distribuire giochi su Steam e le relative documentazioni su come iniziare a usare l'SDK di Steamworks.

NOTA: Valve non supporta ufficialmente nessuno di questi engine o di queste soluzioni di terze parti. Questa lista è ordinata per nome, non è esaustiva ed esiste solo come una guida iniziale. Sono elencati solo gli engine che includono il supporto nativo e che sono dotati di una soluzione di terze parti che rientri nelle linee guida. Le soluzioni di terze parti saranno elencate solo se vengono aggiornate in ragionevole concomitanza con l'SDK di Steamworks, sono disponibili gratuitamente con una licenza non troppo restrittiva (vedi: Distribuzione delle applicazioni open source su Steam) e sono oggetto di una discussione sulla bacheca delle discussioni di Steamworks. Ti consigliamo di consultare la comunità per capire quale sia l'opzione migliore per la tua situazione.

Engine:

NomeSupporto nativo?Informazioni
CRYENGINE ✔️
GameMaker Studio 2 ✔️ Utilizzo dell'SDK di Steamworks con GameMaker: Studio
Godot Terze parti: GodotSteam - discussioni di supporto degli sviluppatori di Steamworks
Haxe Terze parti: SteamWrap - discussioni di supporto deegli sviluppatori di Steamworks
Engine di gioco Leadwerks ✔️ Riferimenti all'API di Leadwerks › Steamworks
RPG Maker MV Terze parti: Greenworks - discussioni di supporto degli sviluppatori di Steamworks
Source 2013 ✔️ Distribuzione dei giochi e delle mod Source Engine
Unity Terze parti: Facepunch.Steamworks - discussioni di supporto degli sviluppatori di Steamworks
Third party: http://steamworks.github.io - discussioni di supporto degli sviluppatori di Steamworks
Unreal Engine 4 ✔️ Online Subsystem Steam
Visionaire Studio ✔️ Pubblicazione su Steam

Linguaggi:

Interfaccia flat per l'associazione ad altri linguaggi

L'SDK dispone di alcune funzioni per facilitare la creazione di livelli di associazione per altri linguaggi.

  • steam_api_flat.h dichiara una serie di funzioni "flat" che rispecchiano le funzionalità dell'interfaccia nell'SDK. Non è puro codice C, ma impiega un collegamento e convenzioni di denominazione nel linguaggio C di base, quindi è facile interagire con altri linguaggi. Queste funzioni sono esportate da steam_api[64][.dll/.so/dylib].
  • steam_api.json descrive (quasi tutte) le interfacce, i tipi e le funzioni dell'SDK. Questo file è destinato a essere utilizzato da un processo automatizzato per generare un livello di associazione. Ci auspichiamo che possa essere utilizzato per automatizzare il 95% del lavoro, ma ci sono ancora alcuni casi speciali che devono essere gestiti manualmente. Più specificatamente, CSteamID e CGameID richiederanno probabilmente una gestione speciale da parte del livello di associazione per renderlo efficiente.

Dettagli tecnici

Steam utilizza svariate tecniche per esporre funzionalità alla tua applicazione. Capire come funziona l'API di Steamworks non è strettamente necessario ma è piuttosto semplice e può essere utile per decidere come programmare il tuo gioco tenendo a mente la sua integrazione con Steam.

Il collegamento a steam_api[64][.dll/.so/dylib] consente di accedere a un piccolo numero di funzioni di C prefissate con la macro S_API. Queste funzioni sono tutte esposte in steam_api.h e steam_gameserver.h. Il modulo steam_api è molto piccolo ed espone solo la funzionalità di base per avviare e arrestare l'API di Steamworks.

Quando viene inizializzata, l'API di Steamworks trova il processo del client di Steam attivo al momento e carica steamclient.dll da quel percorso. steamclient.dll è essenzialmente il motore centrale del client di Steam e contiene e conserva le informazioni necessarie all'esecuzione di Steam. L'interfaccia utente del client di Steam utilizza un insieme di funzioni simili a quelle qui esposte per accedere ai dati forniti da steamclient.dll. Poiché questi dati sono contenuti nel processo di Steam, tutte le chiamate all'API di Steam sono organizzate e inviate tramite un meccanismo RPC/IPC (un processo integrato, ISteamClient::HSteamPipe).

Il processo di Steam mantiene, attraverso steamclient.dll, una connessione costante con i server back-end di Steam. Le comunicazioni con l'autenticazione, il matchmaking, la lista amici e il sistema del VAC avvengono tutte tramite questa connessione. La connessione potrebbe interrompersi se l'utente ha problemi di rete o se il server di Steam che la ospita riceve un aggiornamento. Le richiamate saranno inviate a tutte le app in esecuzione se la connessione si interrompe o viene ristabilita. Il client di Steam proverà a riconnettersi automaticamente e i client con un'applicazione in esecuzione hanno la priorità, per cui il tempo medio di riconnessione è inferiore ai 10 secondi, anche se, in rari casi, può impiegare fino a 5 minuti.

L'API di Steamworks si aggiorna tramite un meccanismo in stile COM, in cui il nome di una stringa e la versione di un'interfaccia sono passate in steamclient.dll, che a sua volta restituisce la versione corretta dell'interfaccia al caller. steamclient.dll contiene un insieme di adattatori per tutte le versioni rilasciate di un'interfaccia che redireziona o reinterpreta le vecchie chiamate nel contesto dell'interfaccia più recente. Gli adattatori si trovano all'interno del client di Steam, per cui sono semplici da aggiornare in caso di problemi.