Documentation Steamworks
Présentation de l'API Steamworks

Présentation

L'API Steamworks permet à votre jeu de tirer pleinement parti de Steam en accédant à tous les systèmes sous-jacents proposés via l'API. Ceci inclut des éléments tels que mettre en pause votre jeu lorsque quelqu'un ouvre l'overlay Steam, inviter des contacts à jouer, autoriser les joueurs et joueuses à débloquer des succès Steam, permettre à la communauté de s'affronter pour une place dans les classements Steam et plus encore.

L'article Références de l'API Steamworks catalogue et documente chaque interface, fonction, rappel et type pris en charge par l'API.

L'intégration à l'API Steamworks n'est jamais obligatoire pour la publication de votre produit sur Steam, mais elle est fortement recommandée, car elle vous permet de mettre en œuvre de nombreuses interactions auxquelles s'attendent les utilisateurs et utilisatrices de Steam.

C'est parti

REMARQUE : L'API Steamworks prend officiellement en charge le C++, à l'aide de Microsoft Visual Studio 2008+ sur Microsoft Windows, de GCC 4.6+ et de Clang 3.0+ sur macOS et SteamOS/Linux. Si vous utilisez un moteur tiers ou un langage de programmation différent du C++, vous devriez alors jeter un œil à l'article Moteur du commerce et prise en charge des langages non C++ afin de voir si d'autres instructions spécifiques sont disponibles pour vous aider à démarrer avec le moteur ou le langage de votre choix. Dans certains cas, il est possible que vous puissiez passer un bon nombre de ces étapes.

  • Si vous ne l'avez pas déjà fait, téléchargez le SDK Steamworks et décompressez-le.
  • Copiez le dossier d'entêtes de l'API Steamworks public/steam dans un endroit approprié de l'arborescence source de votre application.
  • Copiez les fichiers redistribuables concernés de redistributable_bin dans un endroit approprié dans le dossier de votre projet.
    • Windows
      Vous devez avoir steam_api[64].lib associé à votre projet Visual Studio. Il peut être associé soit à l'exécutable principal, soit à un module utilisant Steam. Cela vous permet d'accéder à la fonctionnalité contenue dans steam_api[64].dll exposée via les entêtes de l'API Steamworks. Lecture complémentaire : associer un exécutable à une DLL (MSDN)

      Vous devez également publier steam_api[64].dll dans votre répertoire d'exécution (à côté de votre exécutable de programmes ou dans le chemin d'accès à vos dll).
    • macOS
      libsteam_api.dylib fournit à la fois la version x86 et x64 de l'API Steam. Vous devez relier ceci à votre projet XCode et le livrer en même temps que votre exécutable.
      Lecture complémentaire :
      Utiliser les bibliothèques dynamiques.
    • Linux
      libsteam_api.so : vous devez l'associer et l'envoyer en même temps que votre exécutable.

Initialisation et arrêt

SteamAPI_Init

Une fois l'API Steamworks configurée au sein de votre projet, vous pouvez l'utiliser en appelant la fonction SteamAPI_Init afin d'initialiser l'API. Ceci définira le statut global et remplira les pointeurs d'interface accessibles via les fonctions globales correspondant au nom de l'interface. Cette fonction DOIT être appelée et renvoyée avec succès avant l'accès à une des Interfaces Steamworks !

L'API Steamworks ne s'initialisera pas si elle ne connait pas l'AppID de votre jeu. Lorsque vous lancez votre application depuis la plateforme Steam elle-même, elle disposera automatiquement de l'AppID disponible. Pendant le développement, vous devrez le suggérer à Steam à l'aide d'un fichier texte. Créez le fichier texte nommé steam_appid.txt à côté de votre exécutable ne contenant que l'AppID et rien d'autre. Celui-ci se substituera à la valeur fournie par Steam. Vous ne devez pas le livrer avec vos versions. Exemple :
480

Un renvoi false indique l'une des conditions suivantes.
  • Le client Steam n'est pas en cours d'exécution. Un client Steam en cours d'exécution est requis pour fournir l'implémentation des différentes interfaces Steamworks.
  • Le client Steam n'a pas pu déterminer l'AppID du jeu. Si vous exécutez votre application directement depuis l'exécutable ou le débogueur, alors vous devez avoir un fichier steam_appid.txt dans le répertoire de votre jeu, dans le même dossier que l'exécutable. Ce fichier texte ne doit contenir que l'AppID du jeu et rien d'autre. Steam va chercher ce fichier dans le répertoire de travail actuel. Si vous lancez votre exécutable depuis un répertoire différent, vous devrez peut-être déplacer le fichier steam_appid.txt.
  • Votre application ne s'exécute pas sous le même contexte d'utilisation de système d'exploitation que le client Steam. Il peut s'agir d'un niveau d'accès d'utilisation ou d'administration différent.
  • Le compte Steam actuellement actif ne possède pas de licence pour l'AppID. Assurez-vous que votre jeu s'affiche dans votre bibliothèque Steam.
  • Votre AppID n'est pas complètement paramétré (Statut de publication : indisponible), ou il lui manque des packages par défaut.
Si vous rencontrez des problèmes d'initialisation, consultez l'article Débogage de l'API Steamworks de la documentation pour en apprendre plus sur les diverses méthodes de débogage de l'API Steamworks.

SteamAPI_RestartAppIfNecessary

SteamAPI_RestartAppIfNecessary vérifie si votre exécutable a été lancé via Steam et le relance via Steam si ce n'était pas le cas.

Cette opération est optionnelle, mais fortement recommandée, car le contexte de Steam associé à votre application (dont votre AppID) ne sera pas défini si la personne lance l'exécutable directement. Si cela se produit, SteamAPI_Init échouera et vous serez incapable d'utiliser l'API Steamworks.
Si vous choisissez de l'utiliser, alors ce doit être le premier appel de fonction Steamworks que vous effectuez, avant SteamAPI_Init.

Si cette fonction renvoie true, alors elle lance le client Steam si nécessaire et lance votre jeu à nouveau via le client. Vous devrez alors demander l'arrêt du processus actuel dès que possible. La fonction exécute steam://run/<AppID>. Ainsi, l'exécutable lancé par la fonction peut ne pas être le même qui l'a appelée (par exemple, si vous l'exécutiez depuis votre débogueur). L'exécutable se relancera toujours depuis la version installée dans le dossier de votre bibliothèque Steam.

Si cette fonction renvoie false, alors votre jeu sera lancé par le client Steam et aucune action ne sera nécessaire. Une exception existe si un fichier steam_appid.txt est présent ; la fonction renverra alors false dans tous les cas. Cela vous permet de développer et de tester votre jeu sans le lancer via le client Steam. Pensez à supprimer le fichier steam_appid.txt lorsque vous mettez en ligne le jeu dans votre dépôt Steam !

REMARQUE : cette vérification n'est pas nécessaire si vous utilisez l'outil de protection DRM Steam sur votre fichier exécutable principal, car l'outil de protection DRM s'en chargera en interne.

SteamAPI_Shutdown

Lorsque vous avez terminé d'utiliser l'API Steamworks, vous devez appeler SteamAPI_Shutdown pour libérer les ressources utilisées par votre application en interne au sein de Steam. Vous devez effectuer cet appel pendant le processus de fermeture, si possible.

Cela ne supprimera pas le hook de l'overlay Steam associé à votre jeu, car il n'est pas garanti que votre API de rendu ait terminé de l'utiliser.

Interfaces Steamworks

L'API Steamworks se compose de plusieurs interfaces proposant toute une gamme limitée et spécifique de fonctionnalités.

Une fois que Steamworks s'est initialisé avec succès, vous pouvez accéder aux interfaces via leurs fonctions globales. Les fonctions correspondent toujours au nom de leur interface. De fait, vous pouvez accéder à ISteamApps via l'accesseur SteamApps() et ISteamFriends via SteamFriends().

Vous pouvez utiliser ces interfaces pour effectuer des appels comme suit :
// Récupère le nom du compte utilisant Steam. const char *name = SteamFriends()->GetPersonaName();

Vous pouvez afficher la liste complète des interfaces sur la Références de l'API Steamworks ou en consultant les fichiers d'entête de l'API Steamworks.

Rappels

Les rappels sont l'un des aspects les plus importants de Steamworks : ils vous permettent de récupérer des données de manière asynchrone depuis Steam sans bloquer votre jeu. L'objectif des rappels est de proposer une méthode simple, légère, de type sécurisé et thread-safe de déclencher des évènements asynchrones pour tout objet enregistré comme écouteur.

Les rappels sont généralement déclenchés par un évènement survenant depuis Steam, comme la connexion ou la déconnexion d'un contact, ou par le résultat asynchrone de certaines fonctions d'API. Chaque rappel se compose d'un struct contenant un identifiant unique et d'un petit ensemble de données. Les rappels sont déclarés dans les fichiers d'entête ISteam*.h, groupés avec l'interface apparentée la plus proche.

Pour écouter le déclenchement d'un rappel, une structure ou une classe doit utiliser la macro STEAM_CALLBACK( :classname, :functionname, :callbackname ) dans sa déclaration.
  • :classname doit être le nom de la classe ou de la structure dans laquelle vous le définissez. (par exemple, CGameManager)
  • :functionname sera le nom de la fonction recevant ce rappel. (par exemple, OnGameOverlayActivated)
  • :callbackname est le nom du rappel. (par exemple, GameOverlayActivated_t)
Ceci définit une fonction membre locale pour cette classe, automatiquement prototypée sous la forme void :functionname( :callbackname *pCallback ). La création d'une nouvelle instance de l'objet entrainera l'autoenregistrement de cette fonction membre comme écouteur auprès de l'API Steamworks ; la destruction de l'objet entrainera l'annulation de cet enregistrement.

REMARQUE : assurez-vous que Steam se soit bien initialisé avant de créer des objets à l'écoute des rappels.

Pour les rappels devant être dirigés vers des écouteurs enregistrés, vous devez appeler SteamAPI_RunCallbacks. Il est recommandé d'effectuer cet appel fréquemment, car plus l'intervalle entre les appels est important, plus la latence sera importante entre les évènements ou les résultats reçus depuis l'API Steamworks. La plupart des jeux effectuent cet appel une fois par image rendue. Nous vous recommandons fortement d'effectuer cet appel au moins une fois par seconde. Toutes les fonctions d'écouteurs enregistrées seront invoquées pendant cet appel, dans le contexte du thread depuis lequel SteamAPI_RunCallbacks a été rappelé.

Exemple :

Un rappel que vous souhaiterez probablement utiliser sera ISteamFriends::GameOverlayActivated_t. Comme son nom l'indique, cette fonction vous adresse un rappel chaque fois que la personne active ou désactive l'Overlay 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 cas d'utilisation populaire et recommandé du rappel ISteamFriends::GameOverlayActivated_t est la mise en pause du jeu à l'ouverture de l'overlay.

Résultats d'appel

De nombreuses méthodes Steamworks utilisent les résultats d'appel au lieu d'un rappel afin de renvoyer de manière asynchrone les résultats depuis un appel de fonction. La différence entre un rappel et les résultats d'appel est que les rappels sont émis à l'attention de tous les écouteurs, tandis que les résultats d'appel ne ciblent qu'un écouteur spécifique. Comme pour les rappels, votre jeu devra appeler SteamAPI_RunCallbacks pour diriger les résultats d'appel vers leur écouteur.

Vous pouvez identifier une fonction fournissant un résultat d'appel en inspectant sa valeur de retour ; si elle renvoie SteamAPICall_t et dispose d'un attribut CALL_RESULT(), vous devez alors vous enregistrer pour recevoir le résultat d'appel.

REMARQUE : les rappels et les résultats d'appel ne sont pas interchangeables. Un évènement ne passera que par l'un ou par l'autre canal, pas par les deux. Vous devez vous assurer de bien vous enregistrer pour le bon type d'évènement !

Les résultats d'appel doivent être créés en tant que membre d'un struct/d'une classe à l'aide du type CCallResult ; vous devrez également créer la fonction membre qui recevra le rappel.
void func( :callresultname *pCallback, bool bIOFailure ); CCallResult< :classname, :callresultname > m_callresultname;
  • :classname doit être le nom de la classe ou de la structure dans laquelle vous le définissez. (par exemple, CGameManager)
  • :callresultname est le nom du rappel. (par exemple, NumberOfCurrentPlayers_t)

N'hésitez pas à donner le nom de votre choix à la fonction, aux paramètres de fonction et au type CCallResult.

Exemple :

Voici un exemple d'utilisation de l'API ISteamUserStats::GetNumberOfCurrentPlayers qui produit un résultat d'appel ISteamUserStats::NumberOfCurrentPlayers_t.
// Dans la définition de votre classe. class CGameManager { public: void GetNumberOfCurrentPlayers(); private: void OnGetNumberOfCurrentPlayers( NumberOfCurrentPlayers_t *pCallback, bool bIOFailure ); CCallResult< CGameManager, NumberOfCurrentPlayers_t > m_NumberOfCurrentPlayersCallResult; }; // Effectue la requête asynchrone pour recevoir le nombre actuel de personnes. void CGameManager::GetNumberOfCurrentPlayers() { printf( "Getting Number of Current Players\n" ); SteamAPICall_t hSteamAPICall = SteamUserStats()->GetNumberOfCurrentPlayers(); m_NumberOfCurrentPlayersCallResult.Set( hSteamAPICall, this, &CGameManager::OnGetNumberOfCurrentPlayers ); } // Appelée quand SteamUserStats()->GetNumberOfCurrentPlayers() renvoie de manière asynchrone, après un appel de 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 ); }

REMARQUE : si vous ne pouvez pas utiliser le système CCallResult, vous pouvez alors utiliser ISteamUtils::IsAPICallCompleted, ISteamUtils::GetAPICallResult et ISteamUtils::GetAPICallFailureReason pour suivre l'état d'un résultat d'appel.

Expédition des rappels manuels

Les classes et les macros utilisées pour enregistrer les rappels sont pratiques en code C++, mais il y a aussi un mécanisme de bas niveau pour gérer les rappels. Ce mécanisme opère plutôt comme une boucle évènements Windows. Au lieu d'une seule fonction qui enverrait tous les rappels et résultats d'appels aux écouteurs actifs, vous allez chercher le rappel disponible suivant en boucle et vous l'envoyez via les mécanismes que vous préférez utiliser. Le mode d'expédition manuel est particulièrement utile pour relier les couches qui exposent le SDK Steamworks à d'autres langages que C++. Référez-vous à SteamAPI_ManualDispatch_Init() dans steam_api.h pour en savoir plus.

Serveurs de jeu Steam

L'API Steamworks inclut la prise en charge nécessaire pour l'exécution de serveurs de jeu, ainsi que pour celle de clients habituels. Un serveur de jeu, en termes d'API Steamworks, est une entité du système à laquelle les personnes se connectent pour jouer à des jeux multijoueurs. Ce peut être par le biais d'une connexion via Internet à un serveur de jeu distant, ou via une connexion locale à un serveur de jeu situé dans le même processus que le client. Les serveurs de jeu disposent de leur propre ensemble de fonctions d'API et de leur propre SteamID par lequel les utilisateurs et utilisatrices peuvent les désigner.

Pour utiliser l'API Steam des serveurs de jeu, vous devez inclure steam_gameserver.h au lieu de steam_api.h.

L'initialisation et l'utilisation de l'API des serveurs de jeu sont très similaires à celles de l'API normale.

Après l'initialisation d'un serveur de jeu, vous avez accès aux deux interfaces exclusives des serveurs de jeu, ISteamGameServer et ISteamGameServerStats.

Vous pouvez également accéder aux interfaces habituelles suivantes depuis le serveur de jeu.
  • ISteamClient, à laquelle vous pouvez accéder via l'interface globale SteamGameServerClient().
  • ISteamUtils à laquelle vous pouvez accéder via l'interface globale SteamGameServerUtils().
  • ISteamNetworking à laquelle vous pouvez accéder via l'interface globale SteamGameServerNetworking().
  • ISteamHTTP à laquelle vous pouvez accéder via l'interface globale SteamGameServerHTTP().
  • ISteamUGC à laquelle vous pouvez accéder via l'interface globale SteamGameServerUGC().
  • ISteamApps à laquelle vous pouvez accéder via l'interface globale SteamGameServerApps().

Si vous exécutez un serveur de jeu dédié (un serveur sans aucun composant client), vous devez seulement initialiser l'API des serveurs de jeu, vous n'avez pas à initialiser l'API utilisateur normale.

Consultez la section Exemple d'application utilisant l'API Steamworks (Spacewar) pour un exemple en pleine charge de l'utilisation de l'API des serveurs de jeu.

Contrairement aux jeux, un serveur dédié fonctionne généralement dans un environnement où aucun client Steam n'est installé pour fournir les derniers binaires Steamworks. Pour que le serveur dédié en dispose, vous devrez inclure les redistribuables du serveur dédié avec votre application. Connectez-vous à partner.steamgames.com et allez dans les paramètres techniques de l'application. Dirigez-vous ensuite sur l'onglet « Installation/Redistribuables » et cochez l'option « Redistribuables du serveur dédié ».

Moteur du commerce et prise en charge des langages non C++

Si vous utilisez un moteur de jeu trouvé dans le commerce ou un langage autre que le C ou le C++, vous devrez vous assurer du niveau de prise en charge proposé par l'API Steamworks.
Une prise en charge intégrée est proposée dans certains moteurs, tandis que pour d'autres, vous pourriez avoir besoin d'une solution tierce.

Si votre moteur ne dispose pas d'une prise en charge native, vous pouvez utiliser l'API Web Steam pour accéder aux nombreuses fonctionnalités que Steam prend en charge.

Indépendamment de la manière dont le SDK Steamworks est implémenté dans votre moteur, vous devrez disposer de la dernière version du SDK Steamworks pour télécharger votre application vers Steam.

REMARQUE : si certains des logiciels que vous livrez sur Steam sont disponibles sous une licence open source restrictive, veuillez consulter la section Distribution d'applications open source sur Steam.

Vous trouverez ci-dessous quelques moteurs communément utilisés par les équipes de développement pour livrer des jeux sur Steam, accompagnés de la documentation pertinente expliquant comment commencer à utiliser le SDK Steamworks en conjonction avec ces moteurs.

REMARQUE : Valve ne soutient en aucune façon un quelconque des moteurs ou de ces solutions proposées par de tierces parties. La liste est classée exclusivement par ordre alphabétique, et n'est en aucun cas exhaustive : elle n'a pour objectif que de servir de guide de référence. Les moteurs ne figurent dans la liste que s'ils comprennent la prise en charge native ou s'ils disposent d'une solution tierce correspondant aux recommandations. Les solutions de parties tierces ne figurent dans la liste que si elles sont raisonnablement tenues à jour vis-à-vis du SDK Steamworks, qu'elles sont disponibles gratuitement sous licence permissive (voir Distribution d'applications open source sur Steam) et qu'elles disposent d'un fil dans le forum de discussion Steamworks. Nous vous recommandons de consulter la communauté pour voir quelle option fonctionnerait le mieux dans votre configuration spécifique.

Moteurs :

MoteurPrise en charge native ?Informations
CRYENGINE ✔️
GameMaker Studio 2 ✔️ Comment utiliser le SDK Steamworks avec GameMaker: Studio (lien en anglais)
Godot Partie tierce : GodotSteam. Voir le fil de support des discussions des équipes de développement Steamworks.
Haxe Partie tierce : SteamWrap. Voir le fil de support des discussions des équipes de développement Steamworks.
Leadwerks Game Engine ✔️ Leadwerks API Reference › Steamworks
RPG Maker MV Partie tierce : Greenworks. Voir le fil de support des discussions des équipes de développement Steamworks.
Source 2013 ✔️ Distribution de jeux ou mods du moteur Source
Unity Tierce partie : Facepunch.Steamworks. Voir le fil de support des discussions de développement Steamworks.
Tierce partie : http://steamworks.github.io. Voir le fil de support des discussions de développement Steamworks.
Unreal Engine 4 ✔️ Online Subsystem Steam (lien en anglais)
Visionaire Studio ✔️ Publish on Steam (lien en anglais)

Langages :

Interface plate pour l'association avec d'autres langages

Le SDK dispose de certaines fonctionnalités pour faciliter la création de couches d'associations avec d'autres langages.

  • steam_api_flat.h déclare une série de fonctions dites « plates » reflétant les fonctions de l'interface dans le SDK. Il ne contient pas de code C pur, mais utilise ses conventions d'association et d'appel, ce qui facilite l'interopérabilité avec d'autres langages. Ces fonctions sont exportées par steam_api[64][.dll/.so/dylib].
  • steam_api.json décrit presque toutes les interfaces, types et fonctions dans le SDK. Il peut être utilisé via un processus automatisé de génération de couche d'association. Nous espérons que 95 % du travail pourra ainsi être automatisé, mais il reste encore quelques cas particuliers qui doivent être traités manuellement. CSteamID et CGameID nécessiteront probablement un traitement spécial par votre couche d'association pour être efficaces.

Détails techniques

Steam emploie toute une gamme de techniques pour exposer les fonctionnalités à votre application. Il n'est absolument pas vital de comprendre avec exactitude la manière dont fonctionne l'API Steamworks, mais elle est plutôt simple et peut être utile pour planifier la façon de coder votre jeu en gardant à l'esprit l'intégration à Steam.

Lorsque vous établissez un lien vers steam_api[64][.dll/.so/dylib], l'API procure un accès à un nombre de fonctions C précédées de la macro S_API. Ces fonctions sont toutes exposées dans steam_api.h et steam_gameserver.h. Le module steam_api en lui-même est très petit et n'expose que les fonctionnalités de base nécessaires pour initialiser et arrêter l'API Steamworks.

Lorsque l'API Steamworks s'initialise, elle trouve le processus du client Steam en cours d'exécution et charge steamclient.dll depuis ce chemin. steamclient.dll est par essence le moteur cœur du client Steam. Il renferme et tient à jour les informations nécessaires à l'exécution de Steam. L'interface du client Steam utilise un ensemble similaire aux fonctions exposées ici pour accéder aux données fournies par steamclient.dll. Comme ces données sont situées dans le processus Steam, tous les appels d'API Steam sont rassemblés de manière transparente et effectués via un mécanisme RPC/IPC (un canal transprocessus, ISteamClient::HSteamPipe).

Le processus Steam, via steamclient.dll maintient une connexion constante avec les serveurs de l'interface Steam. C'est via cette connexion que s'effectuent toutes les tâches d'authentification, de matchmaking, de liste de contacts et de communication VAC. La connexion peut tomber si l'utilisateur ou l'utilisatrice souffre d'un problème réseau ou si le serveur Steam auquel il ou elle est connecté(e) reçoit une mise à jour. Les rappels seront affectés à toute application en cours d'exécution si la connexion tombe ou se rétablit. Le client Steam tentera de se reconnecter automatiquement et les clients en train d'exécuter une application seront prioritaires. Le temps de reconnexion moyen ne dépasse généralement pas la barre des 10 secondes, bien que, dans de rares cas, l'attente puisse se prolonger jusqu'à 5 minutes.

L'API Steamworks est versionnée via une procédure similaire à COM, dans laquelle un nom de chaine de caractères et la version d'une interface sont transmis à steamclient.dll qui renvoie alors la version correcte de l'interface à l'appelant. steamclient.dll : contient un ensemble d'adaptateurs pour toutes les versions publiées d'une interface, qui redirigent ou réinterprètent les anciens appels dans le contexte de la dernière interface. Les adaptateurs résident dans le client Steam, ils sont donc faciles à mettre à jour si un problème survient.