Не партнёр

Главная Документация и помощь
Документация Steamworks
Обзор API Steamworks

Введение

API Steamworks предоставляет играм все преимущества Steam благодаря доступу ко всем основным системам с помощью API. Сюда входят, к примеру, постановка игры на паузу в момент открытия пользователем оверлея Steam, приглашение друзей в игру, достижения Steam, соревнование игроков в списках лидеров Steam и так далее.

В разделе Справочник по API Steamworks задокументированы все интерфейсы, функции, обратные вызовы и типы, поддерживаемые в API.

Интеграция с API Steamworks не требуется для доставки продуктов пользователям Steam, но мы рекомендуем её реализацию, поскольку она позволяет удовлетворить ожидания пользователей Steam.

С чего начать

ВНИМАНИЕ: API Steamworks официально поддерживает C++, использование Microsoft Visual Studio 2008+ на Microsoft Windows, GCC 4.6+ и Clang 3.0+ на macOS и SteamOS / Linux. Если вы используете сторонние движки или отличные от C++ языки программирования, вам следует ознакомиться с разделом Поддержка коммерческих движков и языков, отличных от C++, где могут быть изложены инструкции, относящиеся к вашему движку или выбранному языку. В некоторых случаях у вы пропустить некоторые из нижеследующих инструкций.

  • Если вы этого ещё не сделали, скачайте SDK Steamworks и распакуйте zip-файл.
  • Скопируйте папку заголовочных файлов public/steam в подходящее место в исходном дереве кода вашего приложения.
  • Включите один из следующих заголовочных файлов в ваш проект C++.
    • steam_api.h. Включает все остальные заголовки Steamworks и является точкой входа для инициализации API Steamworks.
    • steam_gameserver.h. Это файл необходимо включить, только если вы используете API игровых серверов Steam. Он включает в себя steam_api.h, так что оба использовать не нужно.
  • Скопируйте нужные файлы из папки redistributable_bin в подходящее место в папке проекта.
    • Windows
      В проекте Visual Studio файл steam_api[64].lib необходимо связать либо с первичным исполняемым файлом, либо с модулем, который использует Steam. Это позволяет получить доступ к функциям, содержащимся в библиотеке steam_api[64].dll. Они предоставляются через заголовочные файлы API Steamworks. Дополнительное чтение: «Связывание исполняемого файла с библиотекой DLL».

      Также файл steam_api[64].dll должен располагаться в папке среды выполнения (вместе с исполняемым файлом программы, либо в папке, куда указывается при поиске dll-файлов.
    • macOS
      В libsteam_api.dylib представлены версии API Steam как для архитектуры x86, так и для x64. Вы должны связать его в своём XCode-проекте и должны отправить его вместе с исполняемым файлом.
      Дополнительное чтение: «Использование динамических библиотек».
    • Linux
      libsteam_api.so Вы должны как привязать его к исполняемому файлу, так и отправить их вместе.

Инициализация и завершение работы

SteamAPI_Init

После того, как вы настроите API Steamworks в своём проекте, вы можете начать использовать его, вызывая SteamAPI_Init для инициализации. Это настроит глобальное состояние и заполнит его указателями интерфейсов, доступных с помощью глобальных функций, соответствующих названиям интерфейсов. Вызов SteamAPI_Init и получение сообщения о его успехе ОБЯЗАТЕЛЬНЫ до выполнения вызовов к другим интерфейсам!

API Steamworks не будет инициализирован, если ему не будет известен номер вашего приложения (App ID). При запуске приложения в Steam он автоматически получит номер приложения. Во время разработки вы должны сообщить его в виде текстового файла. Создайте текстовый файл steam_appid.txt, который будет содержать исключительно номер приложения, в папке с исполняемым файлом. Это число будет иметь приоритет над тем значением, которое предоставляется Steam. Нельзя отправлять этот файл с вашими сборками. К примеру:
480

Возвращает false при следующих условиях:
  • Не запущен клиент Steam. Запуск клиента Steam обязателен для корректной работы интерфейсов Steamworks.
  • Клиенту Steam не удалось определить App ID игры. Если вы запускаете приложение напрямую из исполняемого файла или отладчика, в папке игры должен находится файл steam_appid.txt, в котором должен присутствовать исключительно номер приложения. Steam попытается найти этот файл в текущей папке. Если вы запускаете исполняемый файл из другой папки, вам может потребоваться переместить steam_appid.txt.
  • Ваше приложение запущено не с тем же пользовательским контекстом в операционной системе, что и клиент Steam, к примеру, одно запущено под обычным пользователем, а второе — с правами администратора.
  • Убедитесь, что активный аккаунт Steam владеет приложением. Игру должно быть видно в вашей библиотеке Steam.
  • Приложение не настроено полностью, к примеру, Release State: Unavailable, или в нём отсутствуют комплекты по умолчанию.
Если у вас возникают трудности, прочтите раздел «Отладка API Steamworks».

SteamAPI_RestartAppIfNecessary

SteamAPI_RestartAppIfNecessary проверяет, запущен ли исполняемый файл через Steam, и если нет, перезапускает его в Steam.

Это необязательно, но крайне рекомендуется, поскольку контекст Steam (включая номер приложения) не будет настроен, если пользователь запустит исполняемый файл напрямую. Если это случится, вызов SteamAPI_Init не состоится, и вы не сможете использовать API Steamworks.
Если вы решите его использовать, это должен быть первый вызов Steamworks, выполняемый непосредственно перед SteamAPI_Init.

Если возвращается true, будет запущен клиент Steam (если это необходимо), а затем через клиент и игра. Вы должны завершить свой процесс как можно скорее. В этот момент запускается steam://run/<AppID>, так что необязательно будет запущен тот исполняемый файл, который вызвал эту функцию (к примеру, если вы запускали из отладчика). Всегда будет перезапускаться версия, установленная в папке с библиотекой Steam.

Если же будет возвращено значение false, игра была запущена клиентом, и никаких действий предпринимать не нужно. В то же время, если файл steam_appid.txt имеется в наличии, этот вызов всегда будет возвращать false. Это позволяет разрабатывать и тестировать игру без необходимости запускать её из клиента. Не забудьте удалить steam_appid.txt перед отправкой игры в хранилище Steam!

ВНИМАНИЕ: если вы используете оболочку DRM для первичного исполняемого файла, эта проверка необязательна, поскольку оболочка выполнит её самостоятельно.

SteamAPI_Shutdown

Когда вы завершите использование API Steamworks вы должны вызвать SteamAPI_Shutdown, чтобы освободить ресурсы, используемые приложением в Steam. Если возможно, вы должны сделать этот вызов при завершении процесса.

Этот вызов не отключит оверлей от приложения, поскольку нет гарантии, что ваш API выведения изображений перестал его использовать.

Интерфейсы Steamworks

API Steamworks состоит из множества интерфейсов, которые предоставляют ограниченную, конкретную функциональность.

После того, как API был успешно инициализирован, вы можете получить доступ интерфейсам с помощью их глобальных функций. Названия функций всегда соответствуют названиям интерфейсов. Так, вы можете получить доступ к ISteamApps с помощью SteamApps() и к ISteamFriends с помощью SteamFriends().

Вы можете использовать интерфейсы для подобных вызовов:
// Получить имена профилей Steam текущих пользователей. const char *name = SteamFriends()->GetPersonaName();

Вы можете увидеть полный список интерфейсов здесь или изучив заголовочные файлы API Steamworks.

Обратные вызовы

Обратные вызовы — один из самых важных элементов Steamworks, который позволяет получать данные из Steam асинхронно, без необходимости блокировать игру. Цель обратных вызовов в том, чтобы предоставить простой, легкий, типобезопасный, потокобезопасный метод представления событий любому объекту, зарегистрированному в качестве слушателя.

Обратные вызовы обычно срабатывают, когда то или иное событие происходит в Steam, к примеру когда друг входит в сеть или выходит из неё, или в результате функций API. Каждый обратный вызов состоит из структуры (struct), содержащей уникальный идентификатор и небольшой набор данных. Обратные вызовы объявлены в заголовочных файлах ISteam*.h и сгруппированы по интерфейсам, которым они принадлежат в наибольшей степени.

Чтобы слушать обратный вызов, структура или класс должны иметь в объявлении следующий макрос: STEAM_CALLBACK( :classname, :functionname, :callbackname ).
  • :classname — название структуры или класса, где определяется вызов (к примеру, CGameManager).
  • :functionname — название функции, получающей обратный вызов (к примеру, OnGameOverlayActivated).
  • :callbackname — название обратного вызова (к примеру, GameOverlayActivated_t).
Это определяет локальную функцию-член данного класса, которая автоматически получает прототип void :functionname( :callbackname *pCallback ). Создание нового экземпляра данного объекта приведёт к регистрации функции-члена как слушателя в API Steamworks. Уничтожение объекта приведет к отмене регистрации.

ВНИМАНИЕ: Обратите внимание: вы должны убедиться, что Steam инициализирован до того, как создавать объекты, которые слушают обратные вызовы.

Чтобы подготовить отправку обратных вызовов зарегистрированным слушателям, необходимо вызывать SteamAPI_RunCallbacks. Лучше всего делать это часто, поскольку чем больше времени проходит между вызовами, тем больше задержка между получением событий и результатами от API Steamworks. Большинство игр вызывают это один раз за одну отрисовку кадра. Рекомендуется вызывать как минимум раз в секунду. Во время вызова будут вызваны все функции, зарегистрированные как слушатели в контексте потока, где был отправлен вызов SteamAPI_RunCallbacks.

Пример

Один из обратных вызовов, который вы, скорее всего, будете использовать, — это ISteamFriends::GameOverlayActivated_t. Как и подразумевает его название, он отправляется всякий раз, когда пользователь открывает или закрывает оверлей.

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

ISteamFriends::GameOverlayActivated_t часто используется для того, чтобы при открытии оверлея поставить игру на паузу.

Результаты вызова

Многие методы Steamworks используют результаты вызова вместо обратных вызовов для отправки асинхронных результатов вызова функции. Разница между обратным вызовов и результатом вызова состоит в том, что обратные вызовы транслируются всем слушателям, а результаты вызова — только определённому слушателю. Как и в случае с обратными вызовами, игре необходимо вызвать SteamAPI_RunCallbacks для подготовки отправки результатов вызовов их слушателям.

Вы можете понять, что функция возвращает результат вызова, изучив возвращаемое значение. Если она возвращает SteamAPICall_t и обладает атрибутом CALL_RESULT(), значит нужно зарегистрировать объект для получения результата вызова.

ВНИМАНИЕ: Обратите внимание: обратные вызовы и результаты вызова не взаимозаменимы. Вы получите информацию о событии только так или иначе, но не с помощью обоих средств. Вы должны убедиться, что слушатель зарегистрирован для нужного типа события!

Результаты вызова должны быть созданы в качестве члена в структуре или классе при помощи типа CCallResult.
void func( :callresultname *pCallback, bool bIOFailure ); CCallResult< :classname, :callresultname > m_callresultname;
  • :classname — название структуры или класса, где определяется вызов (к примеру, CGameManager).
  • :callresultname — название обратного вызова (к примеру, NumberOfCurrentPlayers_t).

Вы можете назвать функцию, параметры функции и тип CCallResult так, как вам угодно.

Пример

Далее приведён пример использования функции ISteamUserStats::GetNumberOfCurrentPlayers, которая производит результат вызова ISteamUserStats::NumberOfCurrentPlayers_t.
// В определении класса class CGameManager { public: void GetNumberOfCurrentPlayers(); private: void OnGetNumberOfCurrentPlayers( NumberOfCurrentPlayers_t *pCallback, bool bIOFailure ); CCallResult< CGameManager, NumberOfCurrentPlayers_t > m_NumberOfCurrentPlayersCallResult; }; // Сделайте асинхронный запрос на получение числа активных игроков. void CGameManager::GetNumberOfCurrentPlayers() { printf( "Getting Number of Current Players\n" ); SteamAPICall_t hSteamAPICall = SteamUserStats()->GetNumberOfCurrentPlayers(); m_NumberOfCurrentPlayersCallResult.Set( hSteamAPICall, this, &CGameManager::OnGetNumberOfCurrentPlayers ); } // Вызывается, когда SteamUserStats()->GetNumberOfCurrentPlayers() возвращается асинхронно, после вызова 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 ); }

ВНИМАНИЕ: если вы не можете использовать систему CCallResult, вы можете воспользоваться вызовами ISteamUtils::IsAPICallCompleted, ISteamUtils::GetAPICallResult и ISteamUtils::GetAPICallFailureReason для отслеживания состояния результата вызова.

Игровые серверы Steam

API Steamworks поддерживает игровые серверы равно как и обычные клиенты. В терминах API Steamworks игровой сервер — это системная сущность, к которой нормальные пользователи подключаются для того, чтобы играть в многопользовательские игры. Это может выглядеть как подключение к удалённому игровому серверу по интернету, так и к локальному игровому серверу, на котором запущен тот же процесс, что и на клиенте. Игровые серверы обладают своими функциями API, а также собственными идентификаторами Steam ID, по которым их находят другие пользователи.

Для использования API игровых серверов требуется включить steam_gameserver.h вместо steam_api.h.

Инициализация и использование API игровых серверов похоже на обычные API:

После инициализации игрового сервера у вас будет доступ к двум интерфейсам, предназначенным только для серверов: ISteamGameServer и ISteamGameServerStats.

Также с игрового сервера можно получить доступ к следующим обычным интерфейсам:
  • ISteamClient — с помощью глобального интерфейса SteamGameServerClient()
  • ISteamUtils — с помощью глобального интерфейса SteamGameServerUtils()
  • ISteamNetworking — с помощью глобального интерфейса SteamGameServerNetworking()
  • ISteamHTTP — с помощью глобального интерфейса SteamGameServerHTTP()
  • ISteamInventory — с помощью глобального интерфейса SteamGameServerInventory()
  • ISteamUGC — с помощью глобального интерфейса SteamGameServerUGC()
  • ISteamApps — с помощью глобального интерфейса SteamGameServerApps()

Если у вас запущен выделенный игровой сервер (такой, на котором нет клиентской составляющей), вам потребуется инициализировать API игровых серверов, вам не обязательно инициализировать API обычных пользователей.

См. раздел «Приложение-образец с API Steamworks (SpaceWar)», где представлена полностью работоспособная версия API игровых серверов.

Поддержка коммерческих движков и языков, отличных от C++

Если вы используете коммерческий игровой движок или язык, отличный от C или C++, вам необходимо понимать, какой уровень поддержки предоставляется для них в API Steamworks.
Некоторые движки предоставляют встроенную поддержку, для других потребуется стороннее решение.

Если у вашего движка нет встроенной поддержки, вы можете использовать веб-API Steam для доступа к функциям, поддерживающимся в Steam.

Вне зависимости от того, как SDK Steamworks реализован в вашем движке, для отправки приложения в Steam вам потребуется последняя версия SDK Steamworks.

ВНИМАНИЕ: если часть программного обеспечения, которое вы отправляете в Steam, находится под ограничительной открытой лицензией, пожалуйста, ознакомьтесь с разделом «Распространение приложений с открытым кодом в Steam».

Далее перечислены несколько наиболее распространённых движков, используемых для отправки игр в Steam, а также приводятся ссылки на документацию о том, как их использовать вместе с SDK Steamworks.

ВНИМАНИЕ: Valve никоим образом не даёт рекомендаций по использованию этих движков или сторонних решений. Этот список отсортирован по алфавиту, не является исчерпывающим, и существует только как отправная точка. Перечислены только те движки, которые имеют встроенную поддержку или стороннее решение, соответствующее требованиям. Сторонние решения перечислены только в том случае, если они достаточно часто обновляются, свободно доступны под разрешительной лицензией (см. раздел «Распространение приложений с открытым кодом в Steam»), а также имеют свою ветку на форуме разработчиков Steamworks. Мы рекомендуем посоветоваться с сообществом, чтобы увидеть, какая опция может подойти именно вам.

Движки:

ДвижокВстроенная поддержка?Информация
CRYENGINE ✔️
GameMaker Studio 2 ✔️ Использование SDK Steamworks с GameMaker: Studio
Godot Сторонняя: GodotSteamфорум разработчиков Steamworks
Haxe Сторонняя: SteamWrapфорум разработчиков Steamworks
Leadwerks Game Engine ✔️ Leadwerks API Reference › Steamworks
RPG Maker MV Сторонняя: Greenworksфорум разработчиков Steamworks
Source 2013 ✔️ Распространение игр на движке Source
Unity Сторонняя: Facepunch.Steamworks - форум разработчиков Steamworks
Сторонняя: http://steamworks.github.io - форум разработчиков Steamworks
Unreal Engine 4 ✔️ Steam, использование SDK Steam во время разработки
Visionaire Studio ✔️ Публикация в Steam

Языки:

Технические детали

Steam использует множество техник для предоставления функциональности приложению. Понимание того, как работает API Steamworks, ни в коем случае не требуется, но это довольно просто и может пригодиться при написании кода игры, если вы планируете интеграцию со Steam.

Когда вы связываетесь с steam_api[64][.dll/.so/dylib], она предоставляет доступ к небольшому числу функций с префиксом в виде макроса S_API, все эти функции представляются в steam_api.h и steam_gameserver.h. Сам по себе модуль steam_api очень мал, он предоставляет доступ к базовой функциональности по инициализации и выключению API Steamworks.

После инициализации API Steamworks находит активный процесс клиента Steam и загружает из этого места: steamclient.dll. steamclient.dll по сути является основным движком клиента Steam. Он содержит и поддерживает информацию, необходимую для работы Steam. Интерфейс клиента Steam использует похожий набор функций для доступа к данным, предоставленными steamclient.dll. Поскольку эти данные находятся в процессе Steam, все вызовы API Steam прозрачно маршализуются и отправляются с помощью механизма RPC/IPC. (Кросс-процессный канал, ISteamClient::HSteamPipe).

Процесс Steam поддерживает постоянное соединение с внутренними серверами Steam с помощью steamclient.dll. Благодаря этому соединению происходит аутентификация, подбор игр, управление списком друзей и сообщение с системой VAC. Соединение может быть сброшено, если у пользователя возникнет проблема с сетью, или если сервер, к которому он подключён, получит обновление. Любому запущенному приложению будут отправлены обратные вызовы, если соединение прерывается или восстанавливается. Клиент Steam автоматически попробует переподключиться, и те клиенты, на которых есть запущены приложения, так что обычно соединение восстанавливается менее 10 секунд, хотя в редких случаях это может занять до 5 минут.

API Steamworks получает версии с помощью подобного COM механизма, где название и версия интерфейса передаются в steamclient.dll, который затем возвращает корректную версию интерфейса вызывающему. steamclient.dll содержит набор адаптеров для всех выпущенных версий интерфейса, которые перенаправляет или заново интерпретирует старые вызовы в контексте последнего интерфейса. Адаптеры живут внутри клиента Steam, так что их легко обновить, если возникают какие-то проблемы.