Documentación de Steamworks
Steamworks API Overview

Descripción general

La API de Steamworks permite a tu juego aprovechar Steam al máximo, accediendo a todos los sistemas subyacentes proporcionados a través de la API. Esto incluye cosas como pausar tu juego cuando el usuario abre Steam Overlay, invitando a los amigos a jugar, permitiendo a los jugadores desbloquear Logros de Steam, dejar que los jugadores compitan en Steam Leaderboards y mucho más.

Referencia de la API de Steamworks cataloga y documenta todas las interfaces, funciones, funciones callback y tipos admitidos en la API.

La integración con la API de Steamworks nunca es un requisito para publicar tu producto en Steam, aunque se recomienda encarecidamente que se procure, ya que permite muchas interacciones que los usuarios de Steam esperan.

Creación de nuevos eventos

NOTA: La API de Steamworks admite oficialmente C++, el uso de Microsoft Visual Studio 2008+ en Microsoft Windows, GCC 4.6+ y Clang 3.0+ en macOS, y SteamOS/Linux. Si utilizas un motor de terceros o un lenguaje de programación distinto de C++, consulta Compatibilidad con motores comerciales o lenguajes distintos a C++ para ver si hay más instrucciones específicas antes de ponerte en marcha con tu motor o lenguaje preferido. En muchos casos es posible saltarse muchos de estos pasos.

  • Si aún no lo has hecho, descarga el Steamworks SDK y descomprime.
  • Copia la carpeta de encabezados de la API de Steamworks public/steam en un lugar apropiado en el árbol de fuentes de tu aplicación.
  • Copia los archivos redistribuibles relevantes de redistributable_bin en un lugar apropiado en su carpeta de proyecto.
    • Windows
      Debe tener steam_api[64].lib en tu proyecto de estudio visual. Se puede vincular al ejecutable principal o a un módulo que utilice Steam. Esto te permite acceder a la funcionalidad contenida en steam_api[64].dll que se expone a través de los encabezados API de Steamworks. Lectura adicional: Vinculación de un ejecutable a una DLL (MSDN)

      También debes enviar el steam_api[64].dll en su directorio de tiempo de ejecución (al lado de tu ejecutable de programas o en su ruta de búsqueda de DLL).
    • macOS
      libsteam_api.dylib proporciona las versiones x86 y x64 de la API de Steam.. Debes vincular esto en tu proyecto Xcode y debes enviarlo junto con tu ejecutable.
      Lectura complementaria: Uso de bibliotecas dinámicas.
    • Linux
      libsteam_api.so Debes vincular y enviar esto junto con tu ejecutable.

Inicialización y cierre

SteamAPI_Init

Una vez que tienes la API de Steamworks configurada dentro de tu proyecto, puedes empezar a usarla realizando llamadas a la función SteamAPI_Init para inicializar la API. Esto establecerá el estado global y rellenará los punteros de la interfaz que sean accesibles mediante las funciones globales y concuerden con el nombre la interfaz. ¡Este DEBE ser llamado y regresará exitosamente antes de acceder a cualquiera de las Interfaces de Steamworks!

La API de Steamworks no se inicializará si no conoce el id. de aplicación de tu juego. Cuando inicias tu aplicación desde el propio Steam, el id. de aplicación está disponible automáticamente. Durante el desarrollo hay que indicar esto a Steam mediante un archivo de texto. Crea un archivo de texto llamado steam_appid.txt junto a tu ejecutable que contiene solo el id. de la aplicación y nada más. Este valor tiene preferencia sobre el que Steam proporciona. Este archivo no debe incluirse en las compilaciones. Para más información sobre cómo garantizar la seguridad de tu cuenta de Steam, consulta la guía
480

Un retorno de false indica una de las siguientes condiciones:
  • El cliente de Steam no se está ejecutando. Se requiere un cliente de Steam en ejecución para aportar implementaciones de las diversas interfaces de Steamworks.
  • El cliente de Steam no pudo determinar el id. de aplicación del juego. Si estás ejecutando tu aplicación desde el ejecutable o el depurador directamente, debes tener un steam_appid.txt en tu directorio de juegos al lado del ejecutable, con tu id. de aplicación y nada más. Steam buscará este archivo en el directorio actual de trabajo. Si estás ejecutando tu ejecutable desde un directorio diferente, es posible que debsa reubicar el archivo steam_appid.txt.
  • La aplicación no se está ejecutando bajo el mismo contexto de usuario del SO que el cliente de Steam, por ejemplo, bajo un usuario distinto o un nivel de acceso administrativo diferente.
  • Es necesario asegurarse de que se posee una licencia para el id. de aplicación en la cuenta de Steam activa actualmente. El juego que se quiere ejecutar debe aparecer en la biblioteca de Steam.
  • Tu id. de aplicación no está completamente configurada, es decir, en Estado de la versión: no disponible, o faltan paquetes predeterminados.
Si tienes problemas de inicialización, consulta la documentación Depuración de la API de Steamworks para conocer los distintos métodos de depuración de la API de Steamworks.

SteamAPI_RestartAppIfNecessary

SteamAPI_RestartAppIfNecessary verifica si tu ejecutable se lanzó a través de Steam y lo reinicias a través de Steam si no se hizo así.

Esto es opcional pero se recomienda encarecidamente, ya que el contexto de Steam asociado con tu aplicación (lo que incluye el id. de aplicación) no se establecerá si el usuario lanza el ejecutable directamente. Si esto ocurre, SteamAPI_Init fallará y no podrá utilizar la API de Steamworks.
Si eliges usar esto, entonces debería ser la primera llamada a la función de Steamworks que realice, justo antes de SteamAPI_Init.

Si devuelve true, inicia el cliente de Steam si se requiere e inicia el juego a través del mismo, y se deberá abandonar el proceso lo antes posible. Esto ejecuta efectivamente steam://run/<AppID> por lo que no puede reiniciar el ejecutable exacto que llamó a esta función (por ejemplo, si estaba ejecutando desde tu depurador). Siempre volverá a iniciarse desde la versión instalada en tu carpeta de la biblioteca de Steam.

En caso contrario, si devuelve false, el juego se inició desde el cliente de Steam y no es necesario realizar otras acciones. Una excepción es si un archivo steam_appid.txt está presente, esto devolverá false independientemente. Esto permite desarrollar y testear sin iniciar el juego a través del cliente de Steam. ¡Asegúrate de eliminar el archivo steam_appid.txt cuando subas el juego a tu depósito de Steam!

NOTA: Si utilizas en encapsulador Steam DRM en tu archivo ejecutable principal, esta comprobación no es necesaria porque el contenedor DRM la realizará internamente.

SteamAPI_Shutdown

Cuando termines de usar la API de Steamworks deberías llamar a SteamAPI_Shutdown para liberar los recursos empleados por la aplicación internamente dentro de Steam. Debe llamarse a esta función durante el proceso de cierre, en caso de ser posible.

No desenlazará la Interfaz de Steam del juego, ya que no hay garantía de que la API de representación haya terminado de usarla.

Interfaces de Steamworks

La API de Steamworks está compuesta por varias interfaces, cada una de las cuales expone características específicas y limitadas.

Una vez inicializado Steamworks correctamente, puedes acceder a estas interfaces mediante las funciones globales. Las funciones siempre tienen el nombre de su interfaz. Como tal, puedes acceder a ISteamApps a través del acceso a SteamApps() y ISteamFriends a través de SteamFriends().

Estas interfaces se pueden utilizar para realizar llamadas como:
// Obtén el nombre actual de Steam de los usuarios.. const char *name = SteamFriends()->GetPersonaName();

Se puede ver una lista completa de las interfaces en la Referencia de la API de Steamworks o dentro de los archivos de encabezado de la API de Steamworks.

Callbacks

Las funciones callback son uno de los aspectos más importantes de Steamworks, ya que permiten recuperar datos de forma asíncrona de Steam sin bloquear el juego. El objetivo de las funciones callback es proporcionar un método liviano que proporciona seguridad de tipos y seguridad para uso en subprocesos y que es capaz de generar eventos asíncronos en cualquier objeto registrado como escucha.

Las funciones callback se suelen activar mediante un evento que se produce en Steam, por ejemplo, cuando un amigo inicia o cierra sesión, o como resultado asíncrono de alguna función de la API. Cada función callback consiste en una estructura que contiene un identificador exclusivo y un pequeño conjunto de datos. Las funciones callback se declaran en los archivos de encabezado ISteam*.h, agrupados con la interfaz a la que más pertenece.

Para escuchar una función callback, una estructura o clase debe usar la macro STEAM_CALLBACK( :classname, :functionname, :callbackname ) en su declaración.
  • :classname debe ser el nombre de la estructura o clase en la que está definiendo esto. (por ejemplo, CGameManager)
  • :functionname será el nombre de la función que recibe esta función callback. (por ejemplo, OnGameOverlayActivated)
  • :callbackname es el nombre de la función callback. (por ejemplo, GameOverlayActivated_t)
Esto define una función miembro local para esa clase que se crea automáticamente como prototipo como void :functionname( :callbackname *pCallback ). Crear una nueva instancia del objeto hace que esta función miembro se registre a sí misma como escucha en la API de Steamworks; este registro se anula con la destrucción del objeto.

NOTA: Se debe asegurar que Steam se ha inicializado antes de crear objetos que escuchan funciones callback.

Para que las funciones callback se envíen a oyentes registrados, debes llamar a SteamAPI_RunCallbacks. Lo mejor es llamar a esta función con frecuencia, puesto que, a mayor tiempo entre llamadas, más latencia se produce entre los eventos de recepción o los resultados de la API de Steamworks. La mayoría de los juegos llaman a esta función una vez por cada cuadro de representación; se recomienda encarecidamente realizar al menos una llamada por segundo. Todas las funciones de escucha registradas se invocarán durante esta llamada, en el contexto del subproceso desde donde se llamó a SteamAPI_RunCallbacks.

Por ejemplo:

Una función callback que probablemente desearás usar es ISteamFriends::GameOverlayActivated_t. Como su nombre implica, envía una función callback cada vez que el usuario activa o desactiva la Interfaz de 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 caso de uso popular y recomendado para la función callback ISteamFriends::GameOverlayActivated_t es pausar el juego cuando se abre la superposición.

Resultado de llamada

Muchos métodos de Steamworks utilizan resultados de llamada en vez de funciones callback para devolver resultados de forma asíncrona ante la llamada a una función. La diferencia entre las devoluciones y los resultados de llamada es que las primeras se retransmiten a todas las escuchas, mientras que los segundos se dirigen a una escucha específica. Al igual que las funciones callback, tu juego deberá llamar a SteamAPI_RunCallbacks para enviar los resultados de las llamadas a su oyente.

Puedes identificar una función que proporciona un resultado de llamada al inspeccionar su valor de retorno; si devuelve un SteamAPICall_t y tiene un atributo CALL_RESULT(), entonces debes registrarte para recibir el resultado de la llamada.

NOTA: Las funciones callback y los resultados de llamada no son intercambiables. Los eventos llegarán a través de uno o de otro, pero no de ambos. ¡Asegúrate de registrarte para el tipo de evento correcto!

Los resultados de llamada deben crearse como miembro de una estructura o clase que use el tipo CCallResult. Además, tendrás que crear la función miembro que reciba la función callback.
void func( :callresultname *pCallback, bool bIOFailure ); CCallResult< :classname, :callresultname > m_callresultname;
  • :classname debe ser el nombre de la estructura o clase en la que está definiendo esto. (por ejemplo, CGameManager)
  • :callresultname es el nombre de la función callback. (por ejemplo, NumberOfCurrentPlayers_t)

Puedes ponerles los nombres que quieras a la función, sus parámetros y el tipo CCallResult.

Por ejemplo:

Aquí hay un ejemplo de cómo usar la API ISteamUserStats::GetNumberOfCurrentPlayers que produce el resultado de la llamada ISteamUserStats::NumberOfCurrentPlayers_t.
// En tu definición de clase class CGameManager { public: void GetNumberOfCurrentPlayers(); private: void OnGetNumberOfCurrentPlayers( NumberOfCurrentPlayers_t *pCallback, bool bIOFailure ); CCallResult< CGameManager, NumberOfCurrentPlayers_t > m_NumberOfCurrentPlayersCallResult; }; // Haz la solicitud asíncrona para recibir el número de jugadores actuales. void CGameManager::GetNumberOfCurrentPlayers() { printf( "Getting Number of Current Players\n" ); SteamAPICall_t hSteamAPICall = SteamUserStats()->GetNumberOfCurrentPlayers(); m_NumberOfCurrentPlayersCallResult.Set( hSteamAPICall, this, &CGameManager::OnGetNumberOfCurrentPlayers ); } // Llamando cuando SteamUserStats()->GetNumberOfCurrentPlayers() returns asynchronously, after a call to 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: Si no puedes usar el sistema CCallResult, entonces puedes usar ISteamUtils::IsAPICallCompleted, ISteamUtils::GetAPICallResult y ISteamUtils::GetAPICallFailureReason para rastrear el estado de un resultado de llamada.

Envío de manual de función callback

Las clases y macros utilizadas para registrar las funciones callback son convenientes en el código C++. Pero también hay un mecanismo de nivel inferior para tratar las funciones callback. Este mecanismo funciona más como un bucle de eventos de Windows. En lugar de una única función que distribuye todas las funciones callback y los resultados de la llamada a los oyentes activos, obtiene la siguiente función callback disponible en un bucle y la envía utilizando los mecanismos que quieras. El modo de envío manual es especialmente útil para capas de enlace que exponen el SDK de Steamworks a lenguajes distintos de C++. Consulta SteamAPI_ManualDispatch_Init() en steam_api.h para obtener más información.

Servidores de juego de Steam

La API de Steamworks puede gestionar tanto servidores de juego como clientes normales. Por lo que a esta API se refiere, un servidor de juego es una entidad del sistema a la que se conectan los usuarios normales para jugar partidas multijugador. Esto se puede hacer tanto conectándose por Internet a un servidor de juego remoto como haciéndolo en local a uno que esté en el mismo proceso que el cliente. Los servidores de juego cuentan con sus propias funciones de API, así como un id. de Steam de cara a los demás usuarios.

Para utilizar la API del servidor de juego de Steam, primero debes incluir steam_gameserver.h en lugar de steam_api.h.

Iniciar y usar la API de los servidores de juego se parece mucho a hacerlo con la API normal:

Tras iniciar un servidor de juego, tienes acceso a las dos interfaces exclusivas para ellos: ISteamGameServer y ISteamGameServerStats.

También puedes acceder a las siguientes interfaces normales desde el servidor de juego:
  • ISteamClient al que puedes acceder a través de la interfaz global: SteamGameServerClient()
  • ISteamUtils al que puedes acceder a través de la interfaz global: SteamGameServerUtils()
  • ISteamNetworking al que puedes acceder a través de la interfaz global: SteamGameServerNetworking()
  • ISteamHTTP al que puedes acceder a través de la interfaz global: SteamGameServerHTTP()
  • ISteamUGC al que puedes acceder a través de la interfaz global: SteamGameServerUGC()
  • ISteamApps, a la que puedes acceder a través de la interfaz global: SteamGameServerApps()

Si tienes un servidor de juego dedicado (sin cliente), solo debes ejecutar la API de dicho servidor de juego, no la de los usuarios normales.

Consulta Ejemplo de aplicación de la API de Steamworks (Spacewar!) para un ejemplo completamente cargado de usar la API del servidor de juegos.

A diferencia de un juego, un servidor dedicado normalmente se ejecutará en un entorno en el que no hay instalado un cliente de Steam que proporcione las versiones más recientes de los archivos binarios de Steamworks. Para que el servidor dedicado tenga los binarios más recientes de Steam, tendrás que incluir los redistribuibles de servidores dedicados con tu aplicación. Para ello, inicia sesión en partner.steamgames.com y ve a la sección de herramientas técnicas de tu aplicación. Luego mira en Instalación > Redistribuibles y marca "Redistribuibles de servidores dedicados".

Compatibilidad con motores comerciales o lenguajes distintos a C++

Si estás usando un motor de juego comercial o un lenguaje que no sea C o C++, te interesa ver qué nivel de compatibilidad con la API de Steamworks se proporciona para él.
Algunos motores incorporan compatibilidad nativa, mientras que otros pueden requerir una solución externa.

Si tu motor no cuenta con compatibilidad nativa, puedes usar la Web de API de Steam para acceder a muchas de las características de Steam.

Independientemente de cómo esté implementado el SDK de Steamworks en tu motor, deberás tener la versión más reciente de dicho SDK para subir tu aplicación a Steam.

NOTA: Si alguno de los programas que vas a distribuir a través de Steam está disponible bajo una licencia de código abierto restrictiva, por favor, consulta el artículo Distribución de aplicaciones de código abierto en Steam.

He aquí algunos motores utilizados habitualmente en los juegos que se publican en Steam y la documentación pertinente sobre cómo empezar a usar el SDK de Steamworks con ellos.

NOTA: Valve no avala de ninguna manera ninguno de estos motores o soluciones externas. Esta lista está ordenada alfabéticamente, no es exhaustiva y sirve únicamente como guía inicial. Solo incluye motores con compatibilidad nativa integrada o que cuentan con una solución externa ajustada a las directrices. Las soluciones externas solo aparecerán en la lista si se mantienen razonablemente actualizadas respecto al SDK de Steamworks, están disponibles gratuitamente bajo una licencia permisiva (ver Distribución de aplicaciones de código abierto en Steam) y tienen un hilo en el panel de discusiones de Steamworks. Te recomendamos que consultes con la comunidad para ver qué opción funcionaría mejor con tu configuración específica.

Motores:

[/table]

Idiomas:

  • ActionScript (Adobe Flash, AIR)
    • [url]Hilos de discusión
    [/url]
Motor¿Compatibilidad nativa?Información
CRYENGINE ✔️
url=https://store.steampowered.com/app/585410/]GameMaker Studio 2[/url] ✔️ Usando el SDK de Steamworks con GameMaker: Studio
Godot De un tercero:
GodotSteam - Hilo de discusión de soporte para desarrolladores de Steamworks
Haxe De un tercero:
SteamWrap - Hilo de discusión de soporte para desarrolladores de Steamworks
Motor de juego de Leadwerks ✔️ Referencia de la API de Leadwerks › Steamworks
RPG Maker MV De un tercero:
Greenworks - [/td] [/tr]
[url]Source 2013[/url] ✔️ Distribución de juegos y mods que utilizan el motor Source
[url]Unity[/url] Por un tercero: [url]Facepunch.Steamworks[/url] - [url]Steamworks Developer Discussions support thread[/url]
Por un tercero: [url]Steamworks .NET[/url] - [url]Hilo de discusión de soporte para desarrolladores de Steamworks[/url]
[url]Unreal Engine 4[/url] ✔️ [url]Online Subsystem Steam[/url]
[url]Visionaire Studio[/url] ✔️ [url]Publicar en Steam[/url]
  • C#
  • D
  • Java
  • JavaScript
  • Python
  • Rust
  • [/list]

    Interfaz plana para enlazar a otros idiomas

    El SDK tiene algunas características para facilitar la creación de capas de enlace para otros idiomas.

    • steam_api_flat.h declara un conjunto de funciones "planas" que reflejan las funciones de la interfaz en el SDK. Este no es un código C puro, pero utiliza enlaces C simples y convenciones de llamada, por lo que es fácil operar internamente con otros idiomas. Estas funciones son exportadas por steam_api[64][.dll/.so/dylib].
    • steam_api.json describe (casi todas) las interfaces, los tipos y las funciones en el SDK. Se pretende que este archivo sea utilizado por un proceso automatizado para generar una capa de enlace. Esperamos que esto pueda usarse para automatizar el 95 % del trabajo, pero todavía hay algunos casos especiales que deben manejarse manualmente. En particular, CSteamID y CGameID probablemente requerirán un manejo especial por parte de tu capa de enlace para que sea eficiente.

    Detalles técnicos

    Steam utiliza diferentes técnicas para exponer funcionalidad a tu aplicación. No es esencial entender exactamente cómo funciona la API de Steamworks, pero es bastante sencillo y puede ser útil para planificar la programación del juego teniendo en cuenta la integración con Steam.

    Cuando enlazas steam_api[64][.dll/.so/dylib], esta proporciona acceso a un pequeño número de funciones C prefijadas con la macro S_API. Todas estas funciones están expuestas en steam_api.h y steam_gameserver.h. El módulo steam_api en sí mismo es muy pequeño, y solo expone la funcionalidad base para inicializar y cerrar la API de Steamworks.

    Cuando la API de Steamworks se inicializa, busca el proceso del cliente de Steam en ejecución activa y carga steamclient.dll desde esa ruta. steamclient.dll es esencialmente el motor central del cliente de Steam. Contiene y mantiene la información necesaria para ejecutar Steam. La interfaz de usuario del cliente de Steam utiliza un conjunto similar de funciones tal como se expone aquí para acceder a los datos proporcionados por steamclient.dll. Como estos datos están en el proceso de Steam, todas las llamadas a la API de Steam se organizan y envían de manera transparente a través de un mecanismo RPC/IPC (una segmentación entre procesos, ISteamClient::HSteamPipe).

    El proceso de Steam, a través de steamclient.dll, mantiene una conexión constante con los servidores back-end de Steam. A través de esta conexión se producen todas las comunicaciones de autenticación, matchmaking, lista de amigos y VAC. La conexión puede interrumpirse si el usuario tiene un problema de red o si el servidor de Steam al que está conectado recibe una actualización. Se enviarán funciones callback a todas las aplicaciones abiertas en caso de que se interrumpa o restablezca la conexión. El cliente de Steam tratará de volver a conectar automáticamente y los clientes que están ejecutando una aplicación tienen prioridad, así que normalmente el tiempo de reconexión será inferior a 10 segundos, aunque en casos raros puede alcanzar los 5 minutos.

    La API de Steamworks se versiona a través de un mecanismo similar a COM, donde el nombre de una cadena y la versión de una interfaz se pasan a steamclient.dll, que luego devuelve la versión correcta de la interfaz a la persona que llama. steamclient.dll contiene un conjunto de adaptadores para todas las versiones publicadas de una interfaz que redirige o reinterpreta las llamadas antiguas en el contexto de la última interfaz. Estos adaptadores se encuentran dentro del cliente de Steam, de modo que es fácil actualizarlos en caso de incidencia.