{"id":47397307,"url":"https://github.com/ArtyProf/steamworks-ffi-node","last_synced_at":"2026-04-01T18:01:00.661Z","repository":{"id":318721673,"uuid":"1073682146","full_name":"ArtyProf/steamworks-ffi-node","owner":"ArtyProf","description":"A TypeScript/JavaScript wrapper for the Steamworks SDK using Koffi FFI, designed for Node.js and Electron applications with Steamworks SDK integration.","archived":false,"fork":false,"pushed_at":"2026-03-20T21:35:46.000Z","size":4961,"stargazers_count":40,"open_issues_count":3,"forks_count":3,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-03-21T12:50:06.089Z","etag":null,"topics":["electron","javascript","javascript-library","nodejs","steam","steam-cloud","steam-sdk","steam-workshop","steamworks","steamworks-achievements","steamworks-js","steamworks-node","steamworks-sdk","steamworks-ts","typescript"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/steamworks-ffi-node","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ArtyProf.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-10-10T13:16:42.000Z","updated_at":"2026-03-20T21:35:50.000Z","dependencies_parsed_at":null,"dependency_job_id":"8e399e23-97c1-45c3-8d8f-80211a097454","html_url":"https://github.com/ArtyProf/steamworks-ffi-node","commit_stats":null,"previous_names":["artyprof/steamworks-ffi-node"],"tags_count":42,"template":false,"template_full_name":null,"purl":"pkg:github/ArtyProf/steamworks-ffi-node","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ArtyProf%2Fsteamworks-ffi-node","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ArtyProf%2Fsteamworks-ffi-node/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ArtyProf%2Fsteamworks-ffi-node/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ArtyProf%2Fsteamworks-ffi-node/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ArtyProf","download_url":"https://codeload.github.com/ArtyProf/steamworks-ffi-node/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ArtyProf%2Fsteamworks-ffi-node/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30790605,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-20T22:51:33.771Z","status":"online","status_checked_at":"2026-03-21T02:00:07.962Z","response_time":114,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["electron","javascript","javascript-library","nodejs","steam","steam-cloud","steam-sdk","steam-workshop","steamworks","steamworks-achievements","steamworks-js","steamworks-node","steamworks-sdk","steamworks-ts","typescript"],"created_at":"2026-03-20T07:00:30.280Z","updated_at":"2026-04-01T18:01:00.639Z","avatar_url":"https://github.com/ArtyProf.png","language":"TypeScript","readme":"[![npm](https://img.shields.io/npm/v/steamworks-ffi-node.svg)](https://www.npmjs.com/package/steamworks-ffi-node)\n[![NPM Downloads](https://img.shields.io/npm/dm/steamworks-ffi-node?color=orange)](https://www.npmjs.com/package/steamworks-ffi-node)\n[![Chat](https://img.shields.io/discord/1426518243077656699?label=Discord%20chat\u0026logo=discord)](https://discord.gg/Ruzx4Z7cKr)\n[![license](https://img.shields.io/github/license/ArtyProf/steamworks-ffi-node?color=blue)](https://github.com/ArtyProf/steamworks-ffi-node/blob/main/LICENSE)\n\n# steamworks-ffi-node - Steamworks SDK Integration for Node.js applications\n\nA TypeScript/JavaScript wrapper for the Steamworks SDK using Koffi FFI, designed for Node.js and Electron applications with **Steamworks SDK v1.64 integration**.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"assets/logo.jpeg\" alt=\"Steamworks FFI Node\" width=\"600\"\u003e\n\u003c/p\u003e\n\n---\n\n## 📑 Table of Contents\n\n- [Features](#features)\n- [Quick Start](#quick-start)\n- [API Documentation](#api-documentation)\n- [Steamworks Integration](#steamworks-integration)\n- [Electron Integration](#electron-integration)\n- [Requirements](#requirements)\n- [Troubleshooting](#troubleshooting)\n- [Projects Using This Library](#projects-using-this-library)\n- [How to Support This Project](#how-to-support-this-project)\n- [License](#license)\n\n---\n\n## Highlights\n\n\u003e ✅ **No C++ Compilation Required**: Uses Koffi FFI for seamless installation without Visual Studio Build Tools!\n\n\u003e ⚡ **Steamworks SDK v1.64**: Latest SDK with Linux ARM64, Android ARM64, and Lenovo Legion Go controller support!\n\n\u003e 📦 **16 Complete API Managers**: 100% coverage of achievements, stats, leaderboards, friends, workshop, networking, and more - see [full documentation](https://github.com/ArtyProf/steamworks-ffi-node/blob/main/docs/README.md)!\n\n\u003e 🧪 **EXPERIMENTAL: Native Overlay for Electron** - Metal (macOS), OpenGL (Windows), OpenGL 3.3 (Linux/SteamOS). [See Documentation](https://github.com/ArtyProf/steamworks-ffi-node/blob/main/docs/STEAM_OVERLAY_INTEGRATION.md)\n\n## Features\n\n- **Core API**: Essential Steam application functions\n  - ✅ Language detection (get current Steam language for localization)\n  - ✅ Steam status monitoring\n  - ✅ Callback processing\n  - ✅ Ensure app launches through Steam\n  - ✅ **Debug Mode** - Toggle detailed logging for troubleshooting **across all managers**\n  - ✅ **Centralized Logger** - `SteamLogger` utility for consistent logging across all modules\n- **Complete Achievement API**: 100% coverage of Steam Achievement functionality (20/20 functions)\n  - ✅ Core operations (get, unlock, clear, check status)\n  - ✅ Visual features (icons, progress notifications)\n  - ✅ Progress tracking (get limits for progress bars)\n  - ✅ Friend comparisons (see friend achievements)\n  - ✅ Global statistics (unlock percentages, popularity sorting)\n  - ✅ Testing tools (reset stats/achievements)\n- **Complete Stats API**: 100% coverage of Steam User Stats functionality (14/14 functions)\n  - ✅ User stats (get/set int/float, average rate tracking)\n  - ✅ Friend comparisons (compare stats with friends)\n  - ✅ Global statistics (worldwide aggregated data with history)\n- **Complete Leaderboard API**: 100% coverage of Steam Leaderboard functionality (7/7 functions)\n  - ✅ Leaderboard management (find, create, get info)\n  - ✅ Score operations (upload with optional details)\n  - ✅ Entry download (global, friends, specific users)\n  - ✅ UGC integration (attach replays/screenshots to entries)\n- **Friends \u0026 Social API**: Complete Steam friends and social features (22 functions)\n  - ✅ Current user info (persona name, online state)\n  - ✅ Friends list management (count, iterate, get all friends)\n  - ✅ Friend information (names, states, relationships, Steam levels)\n  - ✅ Friend activity (check games being played)\n  - ✅ Friend avatars (small/medium/large avatar handles)\n  - ✅ Friend groups (tags/categories management)\n  - ✅ Coplay tracking (recently played with users)\n- **Rich Presence API**: Complete Rich Presence support (6 functions)\n  - ✅ Set/clear rich presence key/value pairs\n  - ✅ Query friend rich presence data\n  - ✅ Display custom status in friends list\n  - ✅ Enable friend join functionality\n- **Overlay API**: Complete Steam overlay control (7 functions)\n  - ✅ Open overlay dialogs (friends, achievements, settings, etc.)\n  - ✅ Open user profiles, stats, and achievements\n  - ✅ Open overlay web browser to URLs\n  - ✅ Open store pages with purchase options\n  - ✅ Show invite dialogs for multiplayer sessions\n- **Cloud Storage API**: Complete Steam Cloud (Remote Storage) integration (17 functions)\n  - ✅ File operations (write, read, delete, check existence)\n  - ✅ File metadata (size, timestamp, persistence status)\n  - ✅ File listing (count, iterate, get all with details)\n  - ✅ Quota management (track storage usage and limits)\n  - ✅ Cloud settings (check/toggle cloud sync for account and app)\n  - ✅ Batch writes (atomic multi-file operations)\n- **Workshop API**: Complete Steam Workshop/UGC integration (38 functions)\n  - ✅ Subscription management (subscribe, unsubscribe, list items)\n  - ✅ Item state \u0026 information (download progress, installation info)\n  - ✅ Query operations (text search, browse, filter Workshop content)\n  - ✅ Item creation \u0026 update (create, upload, manage your Workshop items)\n  - ✅ Voting \u0026 favorites (vote on items, manage favorites)\n  - ✅ Item deletion (permanently delete your Workshop items)\n  - ✅ Content descriptors (mature content labeling)\n- **Input API**: Complete Steam Input (controller) support (35+ functions) ⚠️ _Tested with virtual gamepad only_\n  - ✅ Controller detection (Xbox, PlayStation, Switch, Steam Controller, Steam Deck)\n  - ✅ Action sets and layers (menu controls, gameplay controls, etc.)\n  - ✅ Digital actions (buttons) and analog actions (sticks/triggers)\n  - ✅ Motion data (gyro, accelerometer for supported controllers)\n  - ✅ Haptics (vibration, LED control for DualShock/DualSense)\n- **Screenshots API**: Steam Screenshots integration (9 functions)\n  - ✅ Screenshot capture (programmatic and user-triggered)\n  - ✅ Add existing images to Steam library\n  - ✅ Location and user tagging (geotag, tag friends)\n  - ✅ Workshop integration (tag published files)\n  - ✅ Screenshot hooks (intercept F12 screenshots)\n  - ✅ VR screenshot support\n- **Apps/DLC API**: Complete DLC and app ownership (28 functions)\n  - ✅ DLC ownership and installation checks\n  - ✅ Install/uninstall optional DLC\n  - ✅ App ownership verification (free weekend, Family Sharing)\n  - ✅ Beta branch management\n  - ✅ App metadata (languages, build info, install paths)\n  - ✅ Launch parameters and timed trials\n- **Matchmaking API**: Complete multiplayer lobby matchmaking (30+ functions) ⚠️ _Requires two Steam accounts for testing_\n  - ✅ Lobby creation (public, private, friends-only, invisible)\n  - ✅ Lobby searching with filters (string, numerical, distance)\n  - ✅ Lobby joining and leaving\n  - ✅ Lobby data (get/set metadata for searching and game state)\n  - ✅ Member management (list, limit, ownership transfer)\n  - ✅ Lobby chat (send/receive messages)\n  - ✅ Game server association\n- **Utils API**: Complete Steam utilities and system information (29 functions)\n  - ✅ System information (battery level, IP country, server time)\n  - ✅ Steam Deck and Big Picture mode detection\n  - ✅ Overlay notification positioning\n  - ✅ Image loading from Steam cache (avatars, achievement icons)\n  - ✅ Gamepad text input dialogs\n  - ✅ Text filtering for user-generated content\n- **Networking Utils API**: Complete Steam networking utilities (15 functions)\n  - ✅ Relay network initialization and monitoring\n  - ✅ Ping location for matchmaking (share with other players)\n  - ✅ Ping estimation between players (without sending packets)\n  - ✅ Data center (POP) information and ping times\n- **Networking Sockets API**: Complete P2P networking (34 functions) ⚠️ _Requires two Steam accounts for testing_\n  - ✅ P2P connections (connect to players via Steam ID)\n  - ✅ Listen sockets (accept incoming connections)\n  - ✅ Reliable and unreliable messaging\n  - ✅ Poll groups (efficiently handle multiple connections)\n  - ✅ Connection status (state, ping, quality metrics)\n  - ✅ High-precision local timestamps\n- **User API**: Complete user authentication and info (28 functions)\n  - ✅ Session tickets (P2P/game server authentication)\n  - ✅ Web API tickets (backend authentication)\n  - ✅ Auth session validation (server-side ticket verification)\n  - ✅ Encrypted app tickets (secure backend verification)\n  - ✅ License verification (check DLC/app ownership for authenticated users)\n  - ✅ User security info (2FA, phone verification status)\n  - ✅ Duration control (playtime limits for China compliance)\n  - ✅ Voice recording (compress, decompress, transmit voice chat)\n  - ✅ User info (Steam level, badge levels, data folder)\n- **Steamworks Integration**: Direct FFI calls to Steamworks C++ SDK\n- **Cross-Platform**: Windows, macOS, and Linux support\n- **Easy Setup**: Simple installation with clear SDK setup guide\n  - 🎉 **No steam_appid.txt file required** - Uses environment variables automatically\n  - 🎉 **Custom SDK paths** - Organize SDK in vendor/, monorepo/, or any folder structure\n  - Just pass your App ID to `init()` and you're ready!\n- **Electron Ready**: Perfect for Electron applications\n- **TypeScript Support**: Complete TypeScript definitions included\n- **No C++ Compilation**: Uses Koffi FFI for seamless installation\n\n## Quick Start\n\n### Installation\n\n```bash\n# Install the package\nnpm install steamworks-ffi-node\n```\n\n### Setup\n\n1. **Download Steamworks SDK** (required separately due to licensing):\n\n   - Visit [Steamworks Partner site](https://partner.steamgames.com/)\n   - Download the latest Steamworks SDK\n   - Extract and copy `redistributable_bin` folder to your project\n   - See [STEAMWORKS_SDK_SETUP.md](https://github.com/ArtyProf/steamworks-ffi-node/blob/main/docs/STEAMWORKS_SDK_SETUP.md) for detailed instructions\n   - Default location: `steamworks_sdk/` in project root\n   - Can now use custom locations! See `setSdkPath()` method below\n\n2. **Set your Steam App ID** - No file creation needed!\n\n   The library automatically sets the `SteamAppId` environment variable when you call `init()`.\n   \n   **For Development (Default SDK Location):**\n   ```typescript\n   const steam = SteamworksSDK.getInstance();\n   \n   // SDK at: your-project/steamworks_sdk/\n   if (steam.restartAppIfNecessary(480)) {\n     process.exit(0);\n   }\n   \n   steam.init({ appId: 480 });\n   ```\n   \n   **For Custom SDK Location:**\n   ```typescript\n   const steam = SteamworksSDK.getInstance();\n   \n   // IMPORTANT: Set SDK path BEFORE restartAppIfNecessary() or init()\n   steam.setSdkPath('vendor/steamworks_sdk');  // SDK in vendor folder\n   \n   if (steam.restartAppIfNecessary(480)) {\n     process.exit(0);\n   }\n   \n   steam.init({ appId: 480 });\n   ```\n   \n   **Custom SDK Path Examples:**\n   ```typescript\n   // SDK in vendor folder: your-project/vendor/steamworks_sdk/\n   steam.setSdkPath('vendor/steamworks_sdk');\n   \n   // SDK in nested structure: your-project/source/main/sdk/steamworks/\n   steam.setSdkPath('source/main/sdk/steamworks');\n   \n   // SDK in monorepo: monorepo/packages/game/steamworks_sdk/\n   steam.setSdkPath('packages/game/steamworks_sdk');\n   ```\n   \n   **Debug Mode (Optional):**\n   ```typescript\n   const steam = SteamworksSDK.getInstance();\n   \n   // Enable debug logs to see initialization details\n   steam.setDebug(true);\n   \n   // Set custom SDK path if needed (debug logs will show path resolution)\n   steam.setSdkPath('vendor/steamworks_sdk');\n   \n   // Check restart requirement (debug logs will show library loading)\n   if (steam.restartAppIfNecessary(480)) {\n     process.exit(0);\n   }\n   \n   // Initialize (debug logs will show initialization steps)\n   steam.init({ appId: 480 });\n   \n   // Disable debug logs after initialization\n   steam.setDebug(false);\n   ```\n   \n   \u003e **Note:** Debug mode is useful for troubleshooting SDK path issues and initialization problems.\n   \u003e Errors and warnings always display regardless of debug mode setting.\n\n   **Optional: Create `steam_appid.txt` manually** (if needed for other tools):\n   ```bash\n   echo \"480\" \u003e steam_appid.txt  # Use 480 for testing, or your Steam App ID\n   ```\n   \n   **For Production:**\n   ```typescript\n   // Check if launched through Steam, restart if necessary\n   if (steam.restartAppIfNecessary(480)) {\n     process.exit(0); // Steam will relaunch your app\n   }\n   \n   steam.init({ appId: 480 });\n   ```\n\n3. **Make sure Steam is running** and you're logged in\n\n### Basic Usage\n\n```typescript\nimport SteamworksSDK, {\n  LeaderboardSortMethod,\n  LeaderboardDisplayType,\n  LeaderboardUploadScoreMethod,\n  LeaderboardDataRequest,\n  EFriendFlags,\n  EUGCQuery,\n  EUGCMatchingUGCType,\n  EItemState,\n} from \"steamworks-ffi-node\";\n\n// Helper to auto-start callback polling\nfunction startCallbackPolling(steam: SteamworksSDK, interval: number = 1000) {\n  return setInterval(() =\u003e {\n    steam.runCallbacks();\n  }, interval);\n}\n\n// Initialize Steam connection\nconst steam = SteamworksSDK.getInstance();\nconst initialized = steam.init({ appId: 480 }); // Your Steam App ID\n\nif (initialized) {\n  // Start callback polling automatically (required for async operations)\n  const callbackInterval = startCallbackPolling(steam, 1000);\n\n  // Get current Steam language for localization\n  const language = steam.getCurrentGameLanguage();\n  console.log(\"Steam language:\", language); // e.g., 'english', 'french', 'german'\n\n  // Get achievements from Steam servers\n  const achievements = await steam.achievements.getAllAchievements();\n  console.log(\"Steam achievements:\", achievements);\n\n  // Unlock achievement (permanent in Steam!)\n  await steam.achievements.unlockAchievement(\"ACH_WIN_ONE_GAME\");\n\n  // Check unlock status from Steam\n  const isUnlocked = await steam.achievements.isAchievementUnlocked(\n    \"ACH_WIN_ONE_GAME\"\n  );\n  console.log(\"Achievement unlocked:\", isUnlocked);\n\n  // Track user statistics\n  const kills = (await steam.stats.getStatInt(\"total_kills\")) || 0;\n  await steam.stats.setStatInt(\"total_kills\", kills + 1);\n\n  // Get global statistics\n  await steam.stats.requestGlobalStats(7);\n  await new Promise((resolve) =\u003e setTimeout(resolve, 2000));\n  steam.runCallbacks();\n  const globalKills = await steam.stats.getGlobalStatInt(\"global.total_kills\");\n  console.log(\"Total kills worldwide:\", globalKills);\n\n  // Work with leaderboards\n  const leaderboard = await steam.leaderboards.findOrCreateLeaderboard(\n    \"HighScores\",\n    LeaderboardSortMethod.Descending,\n    LeaderboardDisplayType.Numeric\n  );\n\n  if (leaderboard) {\n    // Upload score\n    await steam.leaderboards.uploadLeaderboardScore(\n      leaderboard.handle,\n      1000,\n      LeaderboardUploadScoreMethod.KeepBest\n    );\n\n    // Download top 10 scores\n    const topScores = await steam.leaderboards.downloadLeaderboardEntries(\n      leaderboard.handle,\n      LeaderboardDataRequest.Global,\n      1,\n      10\n    );\n    console.log(\"Top 10 scores:\", topScores);\n  }\n\n  // Access friends and social features\n  const personaName = steam.friends.getPersonaName();\n  const friendCount = steam.friends.getFriendCount(EFriendFlags.All);\n  console.log(`${personaName} has ${friendCount} friends`);\n\n  // Get all friends with details\n  const allFriends = steam.friends.getAllFriends(EFriendFlags.All);\n  allFriends.slice(0, 5).forEach((friend) =\u003e {\n    const name = steam.friends.getFriendPersonaName(friend.steamId);\n    const state = steam.friends.getFriendPersonaState(friend.steamId);\n    const level = steam.friends.getFriendSteamLevel(friend.steamId);\n    console.log(`${name}: Level ${level}, Status: ${state}`);\n\n    // Get avatar handles\n    const smallAvatar = steam.friends.getSmallFriendAvatar(friend.steamId);\n    const mediumAvatar = steam.friends.getMediumFriendAvatar(friend.steamId);\n    if (smallAvatar \u003e 0) {\n      console.log(\n        `  Avatar handles: small=${smallAvatar}, medium=${mediumAvatar}`\n      );\n    }\n\n    // Check if playing a game\n    const gameInfo = steam.friends.getFriendGamePlayed(friend.steamId);\n    if (gameInfo) {\n      console.log(`  Playing: App ${gameInfo.gameId}`);\n    }\n  });\n\n  // Check friend groups (tags)\n  const groupCount = steam.friends.getFriendsGroupCount();\n  if (groupCount \u003e 0) {\n    const groupId = steam.friends.getFriendsGroupIDByIndex(0);\n    const groupName = steam.friends.getFriendsGroupName(groupId);\n    const members = steam.friends.getFriendsGroupMembersList(groupId);\n    console.log(`Group \"${groupName}\" has ${members.length} members`);\n  }\n\n  // Check recently played with\n  const coplayCount = steam.friends.getCoplayFriendCount();\n  if (coplayCount \u003e 0) {\n    const recentPlayer = steam.friends.getCoplayFriend(0);\n    const playerName = steam.friends.getFriendPersonaName(recentPlayer);\n    const coplayTime = steam.friends.getFriendCoplayTime(recentPlayer);\n    console.log(`Recently played with ${playerName}`);\n  }\n\n  // Set rich presence for custom status\n  steam.richPresence.setRichPresence(\"status\", \"In Main Menu\");\n  steam.richPresence.setRichPresence(\"connect\", \"+connect server:27015\");\n\n  // Open Steam overlay\n  steam.overlay.activateGameOverlay(\"Friends\"); // Open friends list\n  steam.overlay.activateGameOverlayToWebPage(\"https://example.com/wiki\"); // Open wiki\n\n  // Steam Cloud storage operations\n  const saveData = { level: 5, score: 1000, inventory: [\"sword\", \"shield\"] };\n  const buffer = Buffer.from(JSON.stringify(saveData));\n\n  // Write save file to Steam Cloud\n  const written = steam.cloud.fileWrite(\"savegame.json\", buffer);\n  if (written) {\n    console.log(\"✅ Save uploaded to Steam Cloud\");\n  }\n\n  // Check cloud quota\n  const quota = steam.cloud.getQuota();\n  console.log(\n    `Cloud storage: ${quota.usedBytes}/${\n      quota.totalBytes\n    } bytes (${quota.percentUsed.toFixed(2)}%)`\n  );\n\n  // Read save file from Steam Cloud\n  if (steam.cloud.fileExists(\"savegame.json\")) {\n    const result = steam.cloud.fileRead(\"savegame.json\");\n    if (result.success \u0026\u0026 result.data) {\n      const loadedSave = JSON.parse(result.data.toString());\n      console.log(\n        `Loaded save: Level ${loadedSave.level}, Score ${loadedSave.score}`\n      );\n    }\n  }\n\n  // List all cloud files\n  const cloudFiles = steam.cloud.getAllFiles();\n  console.log(`Steam Cloud contains ${cloudFiles.length} files:`);\n  cloudFiles.forEach((file) =\u003e {\n    const kb = (file.size / 1024).toFixed(2);\n    const status = file.persisted ? \"☁️\" : \"⏳\";\n    console.log(`${status} ${file.name} - ${kb} KB`);\n  });\n\n  // Steam Workshop operations\n  // Subscribe to a Workshop item\n  const subscribeResult = await steam.workshop.subscribeItem(123456789n);\n  if (subscribeResult.success) {\n    console.log(\"✅ Subscribed to Workshop item\");\n  }\n\n  // Get all subscribed items\n  const subscribedItems = steam.workshop.getSubscribedItems();\n  console.log(`Subscribed to ${subscribedItems.length} Workshop items`);\n\n  // Query Workshop items with text search\n  const query = steam.workshop.createQueryAllUGCRequest(\n    EUGCQuery.RankedByTextSearch,\n    EUGCMatchingUGCType.Items,\n    480, // Creator App ID\n    480, // Consumer App ID\n    1 // Page 1\n  );\n\n  if (query) {\n    // Set search text to filter results\n    steam.workshop.setSearchText(query, \"map\");\n\n    const queryResult = await steam.workshop.sendQueryUGCRequest(query);\n    if (queryResult) {\n      console.log(\n        `Found ${queryResult.numResults} Workshop items matching \"map\"`\n      );\n\n      // Get details for each item\n      for (let i = 0; i \u003c queryResult.numResults; i++) {\n        const details = steam.workshop.getQueryUGCResult(query, i);\n        if (details) {\n          console.log(`📦 ${details.title} by ${details.steamIDOwner}`);\n          console.log(\n            `   Score: ${details.score}, Downloads: ${details.numUniqueSubscriptions}`\n          );\n        }\n      }\n    }\n    steam.workshop.releaseQueryUGCRequest(query);\n  }\n\n  // Check download progress for subscribed items\n  subscribedItems.forEach((itemId) =\u003e {\n    const state = steam.workshop.getItemState(itemId);\n    const stateFlags = [];\n    if (state \u0026 EItemState.Subscribed) stateFlags.push(\"Subscribed\");\n    if (state \u0026 EItemState.NeedsUpdate) stateFlags.push(\"Needs Update\");\n    if (state \u0026 EItemState.Installed) stateFlags.push(\"Installed\");\n    if (state \u0026 EItemState.Downloading) stateFlags.push(\"Downloading\");\n\n    console.log(`Item ${itemId}: ${stateFlags.join(\", \")}`);\n\n    if (state \u0026 EItemState.Downloading) {\n      // If downloading\n      const progress = steam.workshop.getItemDownloadInfo(itemId);\n      if (progress) {\n        const percent = ((progress.downloaded / progress.total) * 100).toFixed(\n          1\n        );\n        console.log(\n          `  Download: ${percent}% (${progress.downloaded}/${progress.total} bytes)`\n        );\n      }\n    }\n\n    if (state \u0026 EItemState.Installed) {\n      // If installed\n      const info = steam.workshop.getItemInstallInfo(itemId);\n      if (info.success) {\n        console.log(`  Installed at: ${info.folder}`);\n      }\n    }\n  });\n}\n\n// Cleanup\nclearInterval(callbackInterval);\nsteam.shutdown();\n```\n\n### JavaScript\n\n```javascript\n// Option 1: ESM Named import\nimport { SteamworksSDK } from \"steamworks-ffi-node\";\n\n// Option 2: CommonJs named import (recommended - no .default needed)\nconst { SteamworksSDK } = require(\"steamworks-ffi-node\");\n\n// Option 3: CommonJs default named import (also works)\nconst SteamworksSDK = require(\"steamworks-ffi-node\").default;\n\n// Helper to auto-start callback polling\nfunction startCallbackPolling(steam, interval = 1000) {\n  return setInterval(() =\u003e {\n    steam.runCallbacks();\n  }, interval);\n}\n\nasync function example() {\n  const steam = SteamworksSDK.getInstance();\n\n  if (steam.init({ appId: 480 })) {\n    // Start callback polling automatically\n    const callbackInterval = startCallbackPolling(steam, 1000);\n\n    const achievements = await steam.achievements.getAllAchievements();\n    console.log(`Found ${achievements.length} achievements`);\n\n    // Unlock first locked achievement\n    const locked = achievements.find((a) =\u003e !a.unlocked);\n    if (locked) {\n      await steam.achievements.unlockAchievement(locked.apiName);\n    }\n\n    // Cleanup\n    clearInterval(callbackInterval);\n  }\n\n  steam.shutdown();\n}\n\nexample();\n```\n\n### Testing with Spacewar\n\nFor immediate testing, use Spacewar (App ID 480):\n\n- Free Steam app for testing Steamworks features\n- Add to Steam library: `steam://install/480` or search \"Spacewar\" in Steam\n- Launch it once, then you can test with App ID 480\n\n## API Documentation\n\nComplete documentation for all APIs is available in the [docs folder](https://github.com/ArtyProf/steamworks-ffi-node/tree/main/docs):\n\n➡️ **[View Complete Documentation](https://github.com/ArtyProf/steamworks-ffi-node/blob/main/docs/README.md)**\n\n### API Guides:\n\n- **[Steam API Core](https://github.com/ArtyProf/steamworks-ffi-node/blob/main/docs/STEAM_API_CORE.md)** - Core initialization, shutdown, and lifecycle management\n- **[Achievement Manager](https://github.com/ArtyProf/steamworks-ffi-node/blob/main/docs/ACHIEVEMENT_MANAGER.md)** - Complete achievement system (20 functions)\n- **[Stats Manager](https://github.com/ArtyProf/steamworks-ffi-node/blob/main/docs/STATS_MANAGER.md)** - User and global statistics (14 functions)\n- **[Leaderboard Manager](https://github.com/ArtyProf/steamworks-ffi-node/blob/main/docs/LEADERBOARD_MANAGER.md)** - Leaderboard operations (7 functions)\n- **[Friends Manager](https://github.com/ArtyProf/steamworks-ffi-node/blob/main/docs/FRIENDS_MANAGER.md)** - Friends and social features (22 functions)\n- **[Rich Presence Manager](https://github.com/ArtyProf/steamworks-ffi-node/blob/main/docs/RICH_PRESENCE_MANAGER.md)** - Custom status display and join functionality (6 functions)\n- **[Overlay Manager](https://github.com/ArtyProf/steamworks-ffi-node/blob/main/docs/OVERLAY_MANAGER.md)** - Steam overlay control (7 functions)\n- **[Cloud Storage Manager](https://github.com/ArtyProf/steamworks-ffi-node/blob/main/docs/CLOUD_MANAGER.md)** - Steam Cloud file operations (14 functions)\n- **[Workshop Manager](https://github.com/ArtyProf/steamworks-ffi-node/blob/main/docs/WORKSHOP_MANAGER.md)** - Steam Workshop/UGC operations (38 functions)\n- **[Input Manager](https://github.com/ArtyProf/steamworks-ffi-node/blob/main/docs/INPUT_MANAGER.md)** - Steam Input controller support (35+ functions) ⚠️ _Virtual gamepad testing only_\n- **[Apps Manager](https://github.com/ArtyProf/steamworks-ffi-node/blob/main/docs/APPS_MANAGER.md)** - DLC and app ownership (28 functions)\n- **[Screenshot Manager](https://github.com/ArtyProf/steamworks-ffi-node/blob/main/docs/SCREENSHOT_MANAGER.md)** - Steam Screenshots integration (9 functions)\n- **[Matchmaking Manager](https://github.com/ArtyProf/steamworks-ffi-node/blob/main/docs/MATCHMAKING_MANAGER.md)** - Multiplayer lobby matchmaking (30+ functions) ⚠️ _Requires two Steam accounts_\n- **[Utils Manager](https://github.com/ArtyProf/steamworks-ffi-node/blob/main/docs/UTILS_MANAGER.md)** - System info, Steam Deck detection, image loading (29 functions)\n- **[Networking Utils Manager](https://github.com/ArtyProf/steamworks-ffi-node/blob/main/docs/NETWORKING_UTILS_MANAGER.md)** - Ping location, relay network, data centers (15 functions)\n- **[Networking Sockets Manager](https://github.com/ArtyProf/steamworks-ffi-node/blob/main/docs/NETWORKING_SOCKETS_MANAGER.md)** - P2P connections, reliable messaging (34 functions) ⚠️ _Requires two Steam accounts_\n- **[User Manager](https://github.com/ArtyProf/steamworks-ffi-node/blob/main/docs/USER_MANAGER.md)** - User authentication, security, voice chat (28 functions)\n- **[Steam Overlay Integration](https://github.com/ArtyProf/steamworks-ffi-node/blob/main/docs/STEAM_OVERLAY_INTEGRATION.md)** - Native overlay for Electron apps (macOS/Windows/Linux) 🧪 _Experimental_\n\n## Steamworks Integration\n\nThis library connects directly to the Steam client and Steamworks SDK:\n\n```javascript\n// Steamworks API\nconst steam = SteamworksSDK.getInstance();\nsteam.init({ appId: 480 }); // Connects to actual Steam\n\n// Live achievements from Steam servers\nconst achievements = await steam.achievements.getAllAchievements();\nconsole.log(achievements); // Achievement data from your Steam app\n\n// Permanent achievement unlock in Steam\nawait steam.achievements.unlockAchievement(\"YOUR_ACHIEVEMENT\");\n// ^ This shows up in Steam overlay and is saved permanently\n```\n\n**What happens when you unlock an achievement:**\n\n- ✅ Steam overlay notification appears\n- ✅ Achievement saved to Steam servers permanently\n- ✅ Syncs across all devices\n- ✅ Appears in Steam profile\n- ✅ Counts toward Steam statistics\n\n## Electron Integration\n\nFor Electron applications, use it in your main process:\n\n```typescript\n// main.ts\nimport { app } from \"electron\";\nimport SteamworksSDK from \"steamworks-ffi-node\";\n\napp.whenReady().then(() =\u003e {\n  const steam = SteamworksSDK.getInstance();\n\n  if (steam.init({ appId: YOUR_STEAM_APP_ID })) {\n    console.log(\"Steam initialized in Electron!\");\n\n    // Handle achievement unlocks from renderer process\n    // via IPC if needed\n  }\n});\n\napp.on(\"before-quit\", () =\u003e {\n  const steam = SteamworksSDK.getInstance();\n  steam.shutdown();\n});\n```\n\n### 📦 Electron Packaging\n\n\u003e ⚠️ **ASAR packaging will break the library.** Two native components must live on the real filesystem — they cannot be loaded from inside an `.asar` archive:\n\u003e - `steamworks_sdk/redistributable_bin/` — loaded by the OS dynamic linker (`dlopen` / `LoadLibrary`)\n\u003e - `prebuilds/\u003cplatform\u003e/steam-overlay.node` — a native Node addon (`require()` cannot load `.node` files from `.asar`)\n\nThe recommended approach for games is to unpack the entire library. This covers all required components with a single rule and keeps configuration simple:\n\n#### electron-builder\n\n```json\n{\n  \"build\": {\n    \"asarUnpack\": [\n      \"node_modules/steamworks-ffi-node/**\",\n      \"steamworks_sdk/redistributable_bin/**\"\n    ]\n  }\n}\n```\n\n#### electron-forge\n\n```js\n// forge.config.js\nmodule.exports = {\n  packagerConfig: {\n    asar: {\n      unpack: \"*(steamworks_sdk/**|**/steamworks-ffi-node/**)\"\n    }\n  }\n};\n```\n\nNo code changes are needed in your app — just the packager config above. The `asarUnpack` setting is what physically places the files outside the archive so the OS loader and Node's native addon loader can access them.\n\n## Requirements\n\n- **Node.js**: 18+\n- **Steam Client**: Must be running and logged in\n- **Steam App ID**: Get yours at [Steamworks Partner](https://partner.steamgames.com/) and pass to `steam.init({ appId: YOUR_APP_ID })`\n- No file creation required - library uses environment variables automatically\n- Optional: You can manually create `steam_appid.txt` if needed for other Steam tools\n\n### Platform Support\n\n- ✅ **Windows**: steam_api64.dll / steam_api.dll\n- ✅ **macOS**: libsteam_api.dylib\n- ✅ **Linux x64**: libsteam_api.so\n- ✅ **Linux x86**: libsteam_api.so\n- ✅ **Linux ARM64**: libsteam_api.so (SDK 1.63+)\n- ✅ **Android ARM64**: libsteam_api.so (SDK 1.63+)\n\n**Steamworks SDK Version**: v1.64 (Latest)\n\n_Note: You must download and install the SDK redistributables separately as described in the Setup section above._\n\n## Troubleshooting\n\n### \"SteamAPI_Init failed\"\n\n- ❌ Steam client not running → **Solution**: Start Steam and log in\n- ❌ No App ID specified → **Solution**: Pass App ID to `steam.init({ appId: 480 })` (library sets environment variable automatically)\n- ❌ Invalid App ID → **Solution**: Use 480 for testing, or your registered App ID from Steamworks Partner\n- ℹ️ **Note**: The library automatically handles App ID via environment variables - no file creation needed!\n\n### \"Cannot find module 'steamworks-ffi-node'\"\n\n- ❌ Package not installed → **Solution**: Run `npm install steamworks-ffi-node`\n\n### Achievement operations not working\n\n- ❌ Not initialized → **Solution**: Call `steam.init({ appId })` first\n- ❌ No achievements configured → **Solution**: Configure achievements in Steamworks Partner site\n- ❌ Using Spacewar → **Note**: Spacewar may not have achievements, use your own App ID\n\n### Electron-specific issues\n\n- ❌ Initialized in renderer → **Solution**: Only initialize in main process\n- ❌ Not cleaning up → **Solution**: Call `shutdown()` in `before-quit` event\n- ❌ \"Steamworks SDK library not found\" in packaged app → **Solution**: Include SDK redistributables in your build (see Electron Packaging section above)\n- ❌ Native module errors in packaged app → **Solution**: Ensure Steamworks SDK files are properly included in your app bundle\n\n---\n\n## Projects Using This Library\n\nHere are some projects and applications built with `steamworks-ffi-node`:\n\n### Bulletail\n**[Steam Store Page](https://store.steampowered.com/app/4087020/)**\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://store.steampowered.com/app/4087020/\"\u003e\n    \u003cimg src=\"assets/4087020.jpg\" alt=\"Bulletail Game\" width=\"600\"\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\nSnake-meets-bullet-hell roguelike where your tail is your ammo. Eat bullets to grow, spend length to shoot, and survive escalating waves, enemies, and bosses.\n\n---\n\n### DekaDuck\n**[Steam Store Page](https://store.steampowered.com/app/3715040/)**\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://store.steampowered.com/app/3715040/\"\u003e\n    \u003cimg src=\"assets/3715040.jpg\" alt=\"DekaDuck\" width=\"600\"\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\nDekaDuck is a 2D action platformer, featuring fully hand-drawn art and animation. Fight enemies using their own abilities and quirks to solve puzzles and defeat bosses, in a sci-fi world full of conspiracies!\n\n---\n\n### Falling Face Fragments\n**[Steam Store Page](https://store.steampowered.com/app/3905510/Falling_Face_Fragments/)**\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://store.steampowered.com/app/3905510/\"\u003e\n    \u003cimg src=\"assets/3905510.jpg\" alt=\"Falling Face Fragments\" width=\"600\"\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\nFalling Face Fragments is a falling block puzzle game where you must assemble faces correctly and clear them on a button press. The more faces you have on screen when you choose to clear them, the higher you will score! Three fun modes of play; arcade mode, mission mode, and local 2-player! \n\n---\n\n### Idle Looter\n**[Steam Store Page](https://store.steampowered.com/app/4118640/)**\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://store.steampowered.com/app/4118640/\"\u003e\n    \u003cimg src=\"assets/4118640.jpg\" alt=\"Idle Looter\" width=\"600\"\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\nSlay endless monsters for legendary loot. Master deep crafting and prestige systems to grow infinitely. Collect an army of companions and conquer the unknown. Do you have what it takes to become a hero?\n\n---\n\n### Maldhalla\n**[Steam Store Page](https://store.steampowered.com/app/4385780/)** \n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://store.steampowered.com/app/4385780/\"\u003e\n    \u003cimg src=\"assets/4385780.jpg\" alt=\"Maldhalla\" width=\"600\"\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\nCrush endless waves of creatures and become absurdly overpowered! Grab loot, level up, unlock characters, and upgrade weapons to craft insane builds that obliterate everything on screen.\n\n---\n\n### Realms of Conflict\n**[Steam Store Page](https://store.steampowered.com/app/4072610/)** \n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://store.steampowered.com/app/4072610/\"\u003e\n    \u003cimg src=\"assets/4072610.jpg\" alt=\"Realms of Conflict\" width=\"600\"\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\nPrepare for adventure in Realms of Conflict, the ultimate top down, open world indie role playing adventure game!\n\n---\n\n### Add Your Project\n\nUsing `steamworks-ffi-node` in your project? We'd love to showcase it here!\n\n**To add your project:**\n1. Create an issue\n2. Add there your project details to share in this section:\n   - Project name and brief description\n   - Links (Steam page, GitHub, website)\n\nYour project helps demonstrate the library's capabilities and inspires other developers!\n\n---\n\n## How to Support This Project\n\n- ⭐ **[Star this repository](https://github.com/ArtyProf/steamworks-ffi-node)** — it helps others discover the library and motivates further development!\n\nYou can also support by wishlisting, subscribing, and purchasing the app **AFK Companion** on Steam:\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://store.steampowered.com/app/2609100/AFK_Companion/\"\u003e\n    \u003cimg src=\"assets/2609100.jpg\" alt=\"AFK Companion on Steam\" width=\"600\"\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n👉 [AFK Companion on Steam](https://store.steampowered.com/app/2609100/AFK_Companion/)\n\n- Add the app to your wishlist\n- Subscribe to updates\n- Buy and run the app\n\n**AFK Companion** is built using this library! Your support helps fund further development and improvements.\n\n---\n\n## License\n\nMIT License - see LICENSE file for details.\n\n**Note**: This package requires the Steamworks SDK redistributables to be installed separately by users. Users are responsible for complying with Valve's Steamworks SDK Access Agreement when downloading and using the SDK.\n","funding_links":[],"categories":["Code","Packages"],"sub_categories":["Engines and Frameworks","Node.js"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FArtyProf%2Fsteamworks-ffi-node","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FArtyProf%2Fsteamworks-ffi-node","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FArtyProf%2Fsteamworks-ffi-node/lists"}