.claude/skills/steam-module/SKILL.md
SteamModule reference — Steamworks.NET integration for achievements, stats, leaderboards, cloud saves, inventory, friends, DLC, input, screenshots, timeline, and utils. Use when working with Steam API.
npx skillsauth add punkfuncgames/tetris-clone steam-moduleInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Package: com.punkfuncgames.steam | Define: PUNKFUNC_STEAM
Location: Packages/com.punkfuncgames.steam/Runtime/PunkFuncGames.Steam/
Namespace: PunkFuncGames.Steam
Conditional: #if STEAMWORKS_NET — graceful no-op when not available
Coordinator Pattern: SteamCoreService owns lifecycle + implements ISteamCoreProvider. Domain services take ISteamCoreProvider as dependency for shared state (IsInitialized, StatsReceived, AppId).
Services: 11 focused services registered via SteamInstaller.Install().
bool IsInitializedReadOnlyReactiveProperty<bool> IsConnected, IsLoggedInulong SteamId, string PersonaName, uint AppIdUniTask<Texture2D> GetAvatarAsync(ct)string GetCurrentGameLanguage()RunCallbacks(), UniTask InitializeAsync(ct)ISteamCoreProvider (internal shared state): bool IsInitialized, bool StatsReceived, uint AppId
UniTask<bool> UnlockAchievementAsync(string id, ct)UniTask<bool> IsAchievementUnlockedAsync(string id, ct)UniTask<IReadOnlyList<SteamAchievementData>> GetAllAchievementsAsync(ct)UniTask<bool> ClearAchievementAsync(string id, ct)UniTask<float> GetAchievementProgressAsync(string id, ct)UniTask<bool> SetAchievementProgressAsync(string id, int current, int max, ct)SteamAchievementData: Id, Name, Description, IsUnlocked, Progress
bool SetStat(string name, int/float value)int GetStatInt(string), float GetStatFloat(string)UniTask<bool> StoreStatsAsync(ct), RequestStatsAsync(ct), ResetAllStatsAsync(bool, ct)UniTask<LeaderboardUploadResult> UploadLeaderboardScoreAsync(string, int, LeaderboardUploadMethod, ct)UniTask<IReadOnlyList<LeaderboardEntry>> GetLeaderboardEntriesAsync(string, LeaderboardRequestType, int, int, ct)bool IsCloudEnabled, IsCloudEnabledForApplong QuotaAvailable, QuotaTotal, QuotaUsedUniTask<bool> UploadAsync(string fileName, byte[] data, ct)UniTask<byte[]> DownloadAsync(string fileName, ct)UniTask<bool> DeleteAsync(string fileName, ct)bool FileExists(string), int GetFileSize(string), long GetFileTimestamp(string)IReadOnlyList<SteamCloudFileInfo> GetAllFiles()ReadOnlyReactiveProperty<bool> IsInventoryLoadedUniTask<bool> LoadInventoryAsync(ct), TriggerItemDropAsync(int defId, ct), GrantPromoItemsAsync(ct)UniTask<IReadOnlyList<SteamInventoryItem>> GetAllItemsAsync(ct), GetItemsByDefinitionAsync(int, ct)UniTask<SteamInventoryResult> ExchangeItemsAsync(inputs, outputs, ct)UniTask<bool> ConsumeItemAsync(ulong instanceId, int qty, ct), TransferItemQuantityAsync(...)UniTask<IReadOnlyList<SteamItemDefinition>> GetAllItemDefinitionsAsync(ct)UniTask<SteamItemPrice> GetItemPriceAsync(int, ct), UniTask<IReadOnlyList<SteamItemPrice>> GetAllItemPricesAsync(ct)UniTask<bool> StartPurchaseAsync(IReadOnlyList<SteamItemPurchaseRequest>, ct)bool HasItemDropCooldown(int), UniTask<TimeSpan> GetTimeUntilNextDropAsync(int, ct)Models: SteamInventoryItem, SteamItemDefinition, SteamItemPrice, SteamInventoryExchangeInput/Output, SteamItemPurchaseRequest, SteamInventoryResult
int FriendCountUniTask<IReadOnlyList<SteamFriendInfo>> GetFriendsAsync(ct), GetOnlineFriendsAsync(ct)UniTask<SteamFriendInfo> GetFriendInfoAsync(ulong, ct)UniTask<Texture2D> GetFriendAvatarAsync(ulong, ct)bool SetRichPresence(string key, string value), ClearRichPresence()string GetFriendRichPresence(ulong steamId, string key)void ActivateOverlayToUser(string action, ulong), ActivateOverlayToStore(uint), ActivateOverlayToWebPage(string), ActivateOverlayInviteDialog(ulong)bool IsUserInGame(ulong), UniTask<FriendGameInfo> GetFriendGamePlayedAsync(ulong, ct)int GetClanCount(), UniTask<IReadOnlyList<SteamClanInfo>> GetClansAsync(ct)Models: SteamFriendInfo, SteamFriendState (enum), FriendGameInfo, SteamClanInfo
bool IsSubscribed, IsLowViolence, IsCybercafe, IsVACBannedstring CurrentBetaName, InstallDirectory, CurrentGameLanguageuint BuildIdIReadOnlyList<string> AvailableGameLanguagesbool IsDlcInstalled(uint), InstallDlc(uint), IsAppInstalled(uint), IsSubscribedToApp(uint)void UninstallDlc(uint)UniTask<IReadOnlyList<SteamDlcInfo>> GetAllDlcAsync(ct)string GetAppInstallDirectory(uint), GetLaunchCommandLine()ulong GetAppOwner()Models: SteamDlcInfo
uint SecondsSinceAppActive, SecondsSinceComputerActive, ServerRealTimestring IpCountrybool IsOverlayEnabled, IsSteamRunningOnSteamDeck, IsSteamInBigPictureMode, IsVRModeSteamPlatform CurrentPlatformUniTask<Texture2D> GetImageFromHandleAsync(int, ct)void SetOverlayNotificationPosition(SteamNotificationPosition), SetOverlayNotificationInset(int, int)UniTask<SteamTextFilterResult> FilterTextAsync(string, ct)bool ShowFloatingGamepadTextInput(SteamFloatingGamepadTextInputMode, int, int, int, int), DismissFloatingGamepadTextInput()string GetSteamUILanguage()Models: SteamPlatform, SteamNotificationPosition, SteamFloatingGamepadTextInputMode (enums), SteamTextFilterResult
bool IsInputInitialized, int ConnectedControllerCountUniTask<bool> InitializeInputAsync(ct)IReadOnlyList<ulong> GetConnectedControllers()SteamInputType GetInputTypeForController(ulong)bool ActivateActionSet(ulong, string), ActivateActionSetLayer(ulong, string), DeactivateActionSetLayer(ulong, string)ulong GetCurrentActionSetHandle(ulong)UniTask<Texture2D> GetGlyphForActionAsync(ulong, string, SteamGlyphSize, ct)string GetStringForAction(ulong, string)bool ShowBindingPanel(ulong)void TriggerHapticPulse(ulong, SteamControllerPad, int), TriggerRepeatedHapticPulse(ulong, SteamControllerPad, int, int, int)void RunFrame(), ShutdownInput()Models: SteamInputType, SteamGlyphSize, SteamControllerPad (enums)
bool IsScreenshotsHookedvoid TriggerScreenshot()uint AddScreenshotToLibrary(string filename, string thumbnailFilename, int width, int height)bool SetLocation(uint handle, string location), TagUser(uint handle, ulong steamId)void HookScreenshots(bool hook)void SetTimelineState(string description, float timeDelta)void AddTimelineEvent(string icon, string title, string description, uint priority, float startOffset, float duration, SteamTimelineEventClipPriority)void SetTimelineGameMode(SteamTimelineGameMode)void ClearTimelineState(float timeDelta)Models: SteamTimelineEventClipPriority, SteamTimelineGameMode (enums)
SteamSettings (ScriptableObject): Thin wrapper with public SteamSettingsData data;
Access fields via _settings.data.fieldName.
SteamSettingsData ([Serializable] public struct, camelCase fields):
| Field | Default | Section |
|-------|---------|---------|
| uint appId | 480 | Steam Configuration |
| bool enableOverlay | true | Steam Configuration |
| bool enableCloudSave | true | Cloud Save |
| string cloudSaveFileName | "savegame.dat" | Cloud Save |
| bool autoSyncOnSave | true | Cloud Save |
| bool enableAchievementNotifications | true | Achievements |
| bool enableInventory | false | Inventory |
| bool autoLoadInventory | true | Inventory |
| float dropCooldownCheckInterval | 60f | Inventory |
| bool enableRichPresence | true | Rich Presence |
| string richPresenceStatusKey | "status" | Rich Presence |
| uint[] dlcAppIds | empty | DLC |
| bool enableSteamInput | false | Input |
| string defaultActionSet | "GameControls" | Input |
| bool enableDebugLogging | false | Debug |
| bool offlineMode | false | Debug |
| Event | Key Fields |
|-------|------------|
| SteamInitializedEvent | Success, ErrorMessage |
| SteamOverlayActivatedEvent | IsActive |
| SteamConnectionChangedEvent | IsConnected |
| SteamAchievementUnlockedEvent | AchievementId, AchievementName |
| SteamStatsReceivedEvent | Success, SteamId |
| SteamStatsStoredEvent | Success |
| SteamCloudSyncEvent | Success, SyncType, FileName |
| SteamInventoryLoadedEvent | Success, ItemCount |
| SteamInventoryItemDroppedEvent | Success, DefinitionId, InstanceId, ItemName |
| SteamInventoryItemConsumedEvent | InstanceId, QuantityConsumed, QuantityRemaining |
| SteamInventoryExchangeCompletedEvent | Success, ResultItems |
| SteamInventoryPurchaseCompletedEvent | Success, TransactionId |
| SteamFriendPersonaChangedEvent | SteamId, PersonaName |
| SteamFriendRichPresenceChangedEvent | SteamId |
| SteamGameRichPresenceJoinRequestedEvent | SteamId, ConnectString |
| SteamDlcInstalledEvent | AppId |
| SteamNewUrlLaunchParametersEvent | (none) |
| SteamGamepadTextInputDismissedEvent | Submitted, SubmittedText |
| SteamFloatingGamepadTextInputDismissedEvent | (none) |
| SteamInputDeviceConnectedEvent | ControllerHandle, InputType |
| SteamInputDeviceDisconnectedEvent | ControllerHandle |
| SteamInputConfigurationLoadedEvent | ControllerHandle |
| SteamScreenshotReadyEvent | ScreenshotHandle, Success |
| SteamScreenshotRequestedEvent | (none) |
SteamInstaller.Install(builder, options, steamSettings);
// Registers: SteamCoreService as EntryPoint + ISteamCoreProvider
// Services: Achievement, Stats, Cloud, Inventory, Friends, Apps, Utils, Input, Screenshot, Timeline
// Events: 24 message brokers
// Inventory — item drops (Banana-style)
await _inventoryService.TriggerItemDropAsync(itemDefId, ct);
IReadOnlyList<SteamInventoryItem> items = await _inventoryService.GetAllItemsAsync(ct);
// Rich Presence — show status to friends
_friendsService.SetRichPresence("status", "Earning $1M/sec");
// DLC check
if (_appsService.IsDlcInstalled(dlcAppId)) { /* unlock content */ }
// Steam Deck detection
if (_utilsService.IsSteamRunningOnSteamDeck) { /* adjust UI */ }
// Controller glyphs
Texture2D glyph = await _inputService.GetGlyphForActionAsync(handle, "Jump", SteamGlyphSize.Medium, ct);
// Timeline events
_timelineService.AddTimelineEvent("star", "Prestige!", "Player prestiged", 1, 0f, 10f,
SteamTimelineEventClipPriority.Featured);
// Screenshots
_screenshotService.HookScreenshots(true);
_screenshotService.TriggerScreenshot();
SteamCallResultHelper (internal): WaitForCallResultAsync<T>(SteamAPICall_t, ct) — shared utility for async Steam API calls using UniTaskCompletionSource.
All services have fallback tests in Packages/com.punkfuncgames.steam/Tests/EditMode/:
SteamCoreServiceTests.cs, SteamAchievementServiceTests.cs, SteamStatsServiceTests.csSteamCloudServiceTests.cs, SteamInventoryServiceTests.cs, SteamFriendsServiceTests.csSteamAppsServiceTests.cs, SteamUtilsServiceTests.cs, SteamInputServiceTests.csSteamScreenshotServiceTests.cs, SteamTimelineServiceTests.csdevelopment
WalletModule reference — currency management with BigDouble support, reactive properties, caps, lifetime stats, and persistence. Use when working with currencies, wallets, or financial systems.
development
UnlockConditionModule reference — composable unlock conditions using ScriptableObjects with AND/OR/NOT logic, stat/currency/upgrade/prestige/gamestate/boolean checks, reactive service layer with progress tracking. Use when implementing unlock systems, gating, or progression requirements.
development
UndoModule reference — command pattern with undo/redo stacks, command merging, and reactive state. Use when implementing undo/redo, undoable actions, or command patterns.
tools
Unity UI Toolkit reference — UXML documents, USS styling, MVVM pattern (ViewModel + Presenter), custom VisualElements, responsive layout, animations, performance guidelines, and complete Figma-to-UI-Toolkit property mapping. Use when building or modifying UI with UI Toolkit, creating UXML/USS files, writing ViewModels or Presenters, designing screens/panels/components, or converting Figma designs to UI Toolkit.