Steamworks
SwiftlyS2 includes server-side Steam API bindings under SwiftlyS2.Shared.SteamAPI.
This page focuses on practical game-server workflows: Steam identity, authorization signals, server metadata, Workshop downloads, and async call results.
Getting Started
Import the Steam API namespace in your plugin code:
using SwiftlyS2.Shared.SteamAPI;Steam APIs are exposed as static classes, including:
SteamGameServerSteamGameServerUtilsSteamGameServerUGCSteamGameServerStats
Detecting Steam API Activation
Use Core.Event.OnSteamAPIActivated to run logic when the Steam API is ready.
private EventDelegates.OnSteamAPIActivated? _onSteamApiActivated;
public override void Load(bool hotReload)
{
_onSteamApiActivated = OnSteamApiActivated;
Core.Event.OnSteamAPIActivated += _onSteamApiActivated;
}
public override void Unload()
{
if (_onSteamApiActivated != null)
{
Core.Event.OnSteamAPIActivated -= _onSteamApiActivated;
}
}
private void OnSteamApiActivated()
{
AppId_t appId = SteamGameServerUtils.GetAppID();
Core.Logger.LogInformation("Steam API activated. AppId={AppId}", appId.m_AppId);
}Working with Steam IDs
Convert framework player IDs (ulong) into Steam API IDs (CSteamID) before Steam calls.
IPlayer? player = Core.PlayerManager.GetPlayer(playerId);
if (player == null)
{
return;
}
CSteamID steamId = new CSteamID(player.SteamID);
if (!steamId.IsValid() || !steamId.BIndividualAccount())
{
Core.Logger.LogWarning("Invalid Steam ID for playerId={PlayerId}", playerId);
return;
}
ulong steamId64 = steamId.m_SteamID;
AccountID_t accountId = steamId.GetAccountID();Steam Authorization Signals
Swiftly core events expose Steam authorization success and failure:
Core.Event.OnClientSteamAuthorizeCore.Event.OnClientSteamAuthorizeFail
Core.Event.OnClientSteamAuthorize += @event =>
{
Core.Logger.LogInformation("Steam authorize success for playerId={PlayerId}", @event.PlayerId);
};
Core.Event.OnClientSteamAuthorizeFail += @event =>
{
Core.Logger.LogWarning("Steam authorize failed for playerId={PlayerId}", @event.PlayerId);
};Server Status and Metadata
Use SteamGameServer to set server browser metadata and inspect Steam connection state.
using System.Net;
SteamGameServer.SetServerName("My Swiftly Server");
SteamGameServer.SetMapName("de_dust2");
SteamGameServer.SetMaxPlayerCount(32);
SteamGameServer.SetPasswordProtected(false);
SteamGameServer.SetGameTags("swiftly,casual");
SteamGameServer.SetGameData("region:EU;mode:retakes");
bool loggedOn = SteamGameServer.BLoggedOn();
bool secure = SteamGameServer.BSecure();
CSteamID serverSteamId = SteamGameServer.GetSteamID();
IPAddress publicIp = SteamGameServer.GetPublicIP().ToIPAddress();Ownership and License Checks
Check whether a player owns the target app or DLC with UserHasLicenseForApp.
CSteamID steamId = new CSteamID(player.SteamID);
AppId_t appId = new AppId_t(730);
EUserHasLicenseForAppResult license = SteamGameServer.UserHasLicenseForApp(steamId, appId);
if (license == EUserHasLicenseForAppResult.k_EUserHasLicenseResultHasLicense)
{
Core.Logger.LogInformation("Player owns app {AppId}", appId.m_AppId);
}
else
{
Core.Logger.LogWarning("Player missing license or auth for app {AppId}: {Result}", appId.m_AppId, license);
}Workshop Downloads with SteamGameServerUGC
Use SteamGameServerUGC (not SteamUGC) for Workshop operations in this API surface.
PublishedFileId_t fileId = new PublishedFileId_t(3070212801);
EItemState state = (EItemState)SteamGameServerUGC.GetItemState(fileId);
if ((state & EItemState.k_EItemStateInstalled) != 0)
{
Core.Logger.LogInformation("Workshop item already installed: {ItemId}", fileId.m_PublishedFileId);
}
else
{
bool started = SteamGameServerUGC.DownloadItem(fileId, true);
Core.Logger.LogInformation("Workshop download start for {ItemId}: {Started}", fileId.m_PublishedFileId, started);
}Track completion through DownloadItemResult_t:
private Callback<DownloadItemResult_t>? _downloadItemResult;
public override void Load(bool hotReload)
{
_downloadItemResult = Callback<DownloadItemResult_t>.Create(OnDownloadItemResult);
}
public override void Unload()
{
_downloadItemResult?.Dispose();
}
private void OnDownloadItemResult(DownloadItemResult_t callback)
{
if (callback.m_eResult != EResult.k_EResultOK)
{
Core.Logger.LogWarning(
"Workshop download failed for {ItemId}: {Result}",
callback.m_nPublishedFileId.m_PublishedFileId,
callback.m_eResult);
return;
}
if (SteamGameServerUGC.GetItemInstallInfo(
callback.m_nPublishedFileId,
out ulong sizeOnDisk,
out string folder,
1024,
out uint timestamp))
{
Core.Logger.LogInformation(
"Workshop item {ItemId} installed at {Folder}, size={Size}, timestamp={Timestamp}",
callback.m_nPublishedFileId.m_PublishedFileId,
folder,
sizeOnDisk,
timestamp);
}
}Async Call Results (SteamAPICall_t)
For async APIs that return SteamAPICall_t, use CallResult<T>.
private CallResult<GSStatsReceived_t>? _statsReceivedResult;
public void RequestStats(CSteamID steamId)
{
SteamAPICall_t call = SteamGameServerStats.RequestUserStats(steamId);
_statsReceivedResult?.Dispose();
_statsReceivedResult = CallResult<GSStatsReceived_t>.Create(call.m_SteamAPICall, OnStatsReceived);
}
private void OnStatsReceived(GSStatsReceived_t result, bool ioFailure)
{
if (ioFailure || result.m_eResult != EResult.k_EResultOK)
{
Core.Logger.LogWarning(
"Stats request failed for {SteamId}. IO={IoFailure}, Result={Result}",
result.m_steamIDUser.m_SteamID,
ioFailure,
result.m_eResult);
return;
}
if (SteamGameServerStats.GetUserStat(result.m_steamIDUser, "total_kills", out int kills))
{
Core.Logger.LogInformation("Stats for {SteamId}: kills={Kills}", result.m_steamIDUser.m_SteamID, kills);
}
}Auth Session APIs (Preferred)
Avoid deprecated methods SendUserConnectAndAuthenticate_DEPRECATED and SendUserDisconnect_DEPRECATED.
Prefer BeginAuthSession and EndAuthSession.
EBeginAuthSessionResult authResult = SteamGameServer.BeginAuthSession(ticket, ticket.Length, steamId);
if (authResult != EBeginAuthSessionResult.k_EBeginAuthSessionResultOK)
{
Core.Logger.LogWarning("BeginAuthSession failed for {SteamId}: {Result}", steamId.m_SteamID, authResult);
return;
}
// ... player is active ...
SteamGameServer.EndAuthSession(steamId);API Surface Quick Reference
| API | Purpose |
|---|---|
SteamGameServer | Server auth, metadata, license checks, server state |
SteamGameServerUtils | Utility data (GetAppID, GetServerRealTime, GetIPCountry) |
SteamGameServerUGC | Workshop query/download/install state |
SteamGameServerStats | Server-managed user stats and achievements |
CSteamID, AppId_t, PublishedFileId_t | Core Steam identifier and value types |
Callback<T> | Register callback handlers for Steam callback structs |
CallResult<T> | Handle SteamAPICall_t async completion results |
Reference
See Steam API index for all Steam types.
See SteamGameServer, SteamGameServerUtils, SteamGameServerUGC, and SteamGameServerStats.
See Callback<T> and CallResult<T> for async handling patterns.