steamworks-ffi-node 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Artur Khutak
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,266 @@
1
+ # Steamworks FFI - Real Steam Integration
2
+
3
+ A production-ready TypeScript/JavaScript wrapper for the Steamworks SDK using Koffi FFI, designed for Node.js and Electron applications with **real Steam client integration**.
4
+
5
+ > ✅ **No C++ Compilation Required**: Uses Koffi FFI for seamless installation without Visual Studio Build Tools!
6
+
7
+ ## 🎯 Features
8
+
9
+ - **Real Steam Integration**: Direct FFI calls to Steamworks C++ SDK
10
+ - **Cross-Platform**: Windows, macOS, and Linux support
11
+ - **Electron Ready**: Perfect for Electron applications
12
+ - **Production Ready**: Full Steam client connection and API access
13
+ - **TypeScript Support**: Complete TypeScript definitions included
14
+ - **Achievement System**: Full CRUD operations for Steam achievements
15
+
16
+ ## 🚀 Quick Start
17
+
18
+ ### Prerequisites
19
+
20
+ **Before using, you need:**
21
+
22
+ 1. **Steamworks SDK**: Download from [Steam Partner Portal](https://partner.steamgames.com/) and place in `steamworks_sdk/` directory
23
+
24
+ 2. **Steam Client**: Must be running and logged in for real integration
25
+
26
+ ### Installation
27
+
28
+ ```bash
29
+ # Install dependencies (using Koffi FFI - no C++ compilation required!)
30
+ npm install
31
+
32
+ # Build TypeScript
33
+ npm run build
34
+ ```
35
+
36
+ ### Basic Usage
37
+
38
+ ```typescript
39
+ import Steam from 'steamworks-ffi';
40
+
41
+ // Initialize real Steam connection
42
+ const steam = Steam.getInstance();
43
+ const initialized = steam.init({ appId: 480 }); // Your Steam App ID
44
+
45
+ if (initialized) {
46
+ // Get achievements from Steam servers
47
+ const achievements = await steam.getAllAchievements();
48
+ console.log('Real Steam achievements:', achievements);
49
+
50
+ // Unlock achievement (permanent in Steam!)
51
+ await steam.unlockAchievement('ACH_WIN_ONE_GAME');
52
+
53
+ // Check unlock status from Steam
54
+ const isUnlocked = await steam.isAchievementUnlocked('ACH_WIN_ONE_GAME');
55
+ console.log('Achievement unlocked:', isUnlocked);
56
+ }
57
+
58
+ // Cleanup
59
+ steam.shutdown();
60
+ ```
61
+
62
+ ### JavaScript (CommonJS)
63
+
64
+ ```javascript
65
+ const Steam = require('steamworks-ffi').default;
66
+
67
+ async function example() {
68
+ const steam = Steam.getInstance();
69
+
70
+ if (steam.init({ appId: 480 })) {
71
+ const achievements = await steam.getAllAchievements();
72
+ console.log(`Found ${achievements.length} achievements`);
73
+
74
+ // Unlock first locked achievement
75
+ const locked = achievements.find(a => !a.unlocked);
76
+ if (locked) {
77
+ await steam.unlockAchievement(locked.apiName);
78
+ }
79
+ }
80
+
81
+ steam.shutdown();
82
+ }
83
+
84
+ example();
85
+ ```
86
+
87
+ ## 📚 API Reference
88
+
89
+ ### Steam Class
90
+
91
+ #### `Steam.getInstance()`
92
+ Get the singleton Steam instance.
93
+
94
+ #### `init(options: SteamInitOptions): boolean`
95
+ Initialize the Steam API.
96
+ - `options.appId`: Your Steam Application ID
97
+
98
+ #### `shutdown(): void`
99
+ Shutdown the Steam API and cleanup resources.
100
+
101
+ #### `getStatus(): SteamStatus`
102
+ Get current Steam status information.
103
+
104
+ ### Achievement Methods
105
+
106
+ #### `getAllAchievements(): Promise<SteamAchievement[]>`
107
+ Get all available achievements for the app.
108
+
109
+ #### `unlockAchievement(apiName: string): Promise<boolean>`
110
+ Unlock a specific achievement.
111
+
112
+ #### `clearAchievement(apiName: string): Promise<boolean>`
113
+ Clear/reset an achievement (for testing).
114
+
115
+ #### `isAchievementUnlocked(apiName: string): Promise<boolean>`
116
+ Check if an achievement is unlocked.
117
+
118
+ #### `getAchievement(apiName: string): Promise<SteamAchievement | null>`
119
+ Get details for a specific achievement.
120
+
121
+ #### `getTotalCount(): Promise<number>`
122
+ Get total number of achievements.
123
+
124
+ #### `getUnlockedCount(): Promise<number>`
125
+ Get number of unlocked achievements.
126
+
127
+ ### Types
128
+
129
+ ```typescript
130
+ interface SteamAchievement {
131
+ apiName: string; // Internal achievement ID
132
+ displayName: string; // User-friendly name
133
+ description: string; // Achievement description
134
+ unlocked: boolean; // Whether it's unlocked
135
+ unlockTime: number; // Unix timestamp of unlock (0 if locked)
136
+ }
137
+
138
+ interface SteamInitOptions {
139
+ appId: number; // Your Steam Application ID
140
+ }
141
+
142
+ interface SteamStatus {
143
+ initialized: boolean; // Whether Steam API is initialized
144
+ appId: number; // Current app ID
145
+ steamId: string; // Current user's Steam ID
146
+ }
147
+ ```
148
+
149
+ ## 🎮 Real Steam Integration
150
+
151
+ This library connects directly to the Steam client and Steamworks SDK:
152
+
153
+ ```javascript
154
+ // Real Steam API - no mocking!
155
+ const steam = Steam.getInstance();
156
+ steam.init({ appId: 480 }); // Connects to actual Steam
157
+
158
+ // Live achievements from Steam servers
159
+ const achievements = await steam.getAllAchievements();
160
+ console.log(achievements); // Real achievement data from your Steam app
161
+
162
+ // Permanent achievement unlock in Steam
163
+ await steam.unlockAchievement('YOUR_ACHIEVEMENT');
164
+ // ^ This shows up in Steam overlay and is saved permanently
165
+ ```
166
+
167
+ **What happens when you unlock an achievement:**
168
+ - ✅ Steam overlay notification appears
169
+ - ✅ Achievement saved to Steam servers permanently
170
+ - ✅ Syncs across all devices
171
+ - ✅ Appears in Steam profile
172
+ - ✅ Counts toward Steam statistics
173
+
174
+ ## 🖥️ Electron Integration
175
+
176
+ For Electron applications, just use it in your main process:
177
+
178
+ ```typescript
179
+ // main.ts
180
+ import { app } from 'electron';
181
+ import Steam from 'steamworks-ffi';
182
+
183
+ app.whenReady().then(() => {
184
+ const steam = Steam.getInstance();
185
+
186
+ if (steam.init({ appId: YOUR_STEAM_APP_ID })) {
187
+ console.log('Steam initialized in Electron!');
188
+
189
+ // Handle achievement unlocks from renderer process
190
+ // via IPC if needed
191
+ }
192
+ });
193
+
194
+ app.on('before-quit', () => {
195
+ Steam.getInstance().shutdown();
196
+ });
197
+ ```
198
+
199
+ ## 🏗️ Production Setup
200
+
201
+ ### Steamworks SDK Setup
202
+
203
+ 1. **Download SDK**: Get from [Steam Partner Portal](https://partner.steamgames.com/)
204
+ 2. **Extract to project**:
205
+ ```
206
+ steamworks_sdk/
207
+ ├── public/steam/ # Header files
208
+ └── redistributable_bin/ # Native libraries
209
+ ├── win64/steam_api64.dll
210
+ ├── osx/libsteam_api.dylib
211
+ └── linux64/libsteam_api.so
212
+ ```
213
+ 3. **Get Steam App ID**: Register your game on Steamworks
214
+ 4. **Create steam_appid.txt**: File with your App ID in project root
215
+
216
+ ### Testing Setup
217
+
218
+ For immediate testing, use Spacewar (App ID 480):
219
+ - Free Steam app for testing
220
+ - Add to Steam library: steam://install/480
221
+ - Requires Steam client running and logged in
222
+
223
+ ## 🔧 Requirements
224
+
225
+ ### Development
226
+ - **Node.js**: 18+
227
+ - **TypeScript**: 5.0+ (optional)
228
+ - **Visual Studio Build Tools**: C++ workload required
229
+ - **Python**: For native module compilation
230
+
231
+ ### Runtime
232
+ - **Steam Client**: Must be running and logged in
233
+ - **Steamworks SDK**: Redistributable binaries required
234
+ - **Valid Steam App ID**: From registered Steam application
235
+
236
+ ### Platform Support
237
+ - ✅ **Windows**: steam_api64.dll / steam_api.dll
238
+ - ✅ **macOS**: libsteam_api.dylib
239
+ - ✅ **Linux**: libsteam_api.so
240
+
241
+ ## 🚀 Quick Start
242
+
243
+ ```bash
244
+ # 1. Setup environment
245
+ npm run setup
246
+
247
+ # 2. Install dependencies
248
+ npm install
249
+
250
+ # 3. Build TypeScript
251
+ npm run build
252
+
253
+ # 4. Test with Steam
254
+ npm start
255
+ ```
256
+
257
+ ## 🔧 Troubleshooting
258
+
259
+ **"Library not found"**: Install Steamworks SDK to `steamworks_sdk/`
260
+ **"SteamAPI_Init failed"**: Make sure Steam client is running
261
+ **Build errors**: Install Visual Studio C++ Build Tools
262
+ **"Missing VC++ toolset"**: Add C++ workload in VS Installer
263
+
264
+ ## 📄 License
265
+
266
+ MIT License - see LICENSE file for details.
@@ -0,0 +1,6 @@
1
+ import SteamworksSDK from './steam';
2
+ import { SteamAchievement, SteamInitOptions, SteamStatus } from './types';
3
+ export { SteamAchievement, SteamInitOptions, SteamStatus };
4
+ export default SteamworksSDK;
5
+ export { SteamworksSDK as Steam };
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,aAAa,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAG1E,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,WAAW,EAAE,CAAC;AAG3D,eAAe,aAAa,CAAC;AAG7B,OAAO,EAAE,aAAa,IAAI,KAAK,EAAE,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.Steam = void 0;
7
+ const steam_1 = __importDefault(require("./steam"));
8
+ exports.Steam = steam_1.default;
9
+ // Export main Steam class
10
+ exports.default = steam_1.default;
11
+ // Example usage (commented out)
12
+ /*
13
+ // Initialize Steam
14
+ const steam = SteamFFI.getInstance();
15
+ const initialized = steam.init({ appId: 480 }); // Steam's test app
16
+
17
+ if (initialized) {
18
+ // Get achievements
19
+ steam.getAllAchievements().then(achievements => {
20
+ console.log('Achievements:', achievements);
21
+
22
+ if (achievements.length > 0) {
23
+ // Unlock first achievement
24
+ steam.unlockAchievement(achievements[0].apiName);
25
+ }
26
+ });
27
+ }
28
+ */
29
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;AAAA,oDAAoC;AAUV,gBAVnB,eAAa,CAUW;AAJ/B,0BAA0B;AAC1B,kBAAe,eAAa,CAAC;AAK7B,gCAAgC;AAChC;;;;;;;;;;;;;;;;EAgBE"}
@@ -0,0 +1,83 @@
1
+ import { SteamAchievement, SteamInitOptions, SteamStatus } from './types';
2
+ /**
3
+ * Real Steamworks SDK implementation using Koffi FFI
4
+ * This connects directly to the actual Steam client and Steamworks SDK
5
+ */
6
+ declare class SteamworksSDK {
7
+ private static instance;
8
+ private steamLib;
9
+ private initialized;
10
+ private appId;
11
+ private userStatsInterface;
12
+ private SteamAPI_Init;
13
+ private SteamAPI_Shutdown;
14
+ private SteamAPI_RunCallbacks;
15
+ private SteamAPI_IsSteamRunning;
16
+ private SteamAPI_SteamUserStats_v013;
17
+ private SteamAPI_SteamUser_v023;
18
+ private SteamAPI_ISteamUserStats_GetNumAchievements;
19
+ private SteamAPI_ISteamUserStats_GetAchievementName;
20
+ private SteamAPI_ISteamUserStats_GetAchievementDisplayAttribute;
21
+ private SteamAPI_ISteamUserStats_GetAchievement;
22
+ private SteamAPI_ISteamUserStats_SetAchievement;
23
+ private SteamAPI_ISteamUserStats_ClearAchievement;
24
+ private SteamAPI_ISteamUserStats_StoreStats;
25
+ private SteamAPI_ISteamUserStats_RequestCurrentStats;
26
+ private SteamAPI_ISteamUser_GetSteamID;
27
+ private constructor();
28
+ static getInstance(): SteamworksSDK;
29
+ /**
30
+ * Get platform-specific Steam library path
31
+ */
32
+ private getSteamLibraryPath;
33
+ /**
34
+ * Initialize Steam API with real Steamworks SDK
35
+ */
36
+ init(options: SteamInitOptions): boolean;
37
+ /**
38
+ * Shutdown Steam API
39
+ */
40
+ shutdown(): void;
41
+ /**
42
+ * Get current Steam status
43
+ */
44
+ getStatus(): SteamStatus;
45
+ /**
46
+ * Get all achievements from Steam
47
+ */
48
+ getAllAchievements(): Promise<SteamAchievement[]>;
49
+ /**
50
+ * Unlock achievement in Steam
51
+ */
52
+ unlockAchievement(apiName: string): Promise<boolean>;
53
+ /**
54
+ * Clear achievement in Steam (for testing)
55
+ */
56
+ clearAchievement(apiName: string): Promise<boolean>;
57
+ /**
58
+ * Check if achievement is unlocked
59
+ */
60
+ isAchievementUnlocked(apiName: string): Promise<boolean>;
61
+ /**
62
+ * Get achievement by API name
63
+ */
64
+ getAchievement(apiName: string): Promise<SteamAchievement | null>;
65
+ /**
66
+ * Get total number of achievements
67
+ */
68
+ getTotalCount(): Promise<number>;
69
+ /**
70
+ * Get number of unlocked achievements
71
+ */
72
+ getUnlockedCount(): Promise<number>;
73
+ /**
74
+ * Run Steam callbacks to process pending events
75
+ */
76
+ runCallbacks(): void;
77
+ /**
78
+ * Check if Steam client is running
79
+ */
80
+ isSteamRunning(): boolean;
81
+ }
82
+ export default SteamworksSDK;
83
+ //# sourceMappingURL=steam.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"steam.d.ts","sourceRoot":"","sources":["../src/steam.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE1E;;;GAGG;AACH,cAAM,aAAa;IACjB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAgB;IACvC,OAAO,CAAC,QAAQ,CAAgC;IAChD,OAAO,CAAC,WAAW,CAAkB;IACrC,OAAO,CAAC,KAAK,CAAa;IAC1B,OAAO,CAAC,kBAAkB,CAAa;IAGvC,OAAO,CAAC,aAAa,CAAuB;IAC5C,OAAO,CAAC,iBAAiB,CAAuB;IAChD,OAAO,CAAC,qBAAqB,CAAuB;IACpD,OAAO,CAAC,uBAAuB,CAAuB;IACtD,OAAO,CAAC,4BAA4B,CAAuB;IAC3D,OAAO,CAAC,uBAAuB,CAAuB;IACtD,OAAO,CAAC,2CAA2C,CAAuB;IAC1E,OAAO,CAAC,2CAA2C,CAAuB;IAC1E,OAAO,CAAC,uDAAuD,CAAuB;IACtF,OAAO,CAAC,uCAAuC,CAAuB;IACtE,OAAO,CAAC,uCAAuC,CAAuB;IACtE,OAAO,CAAC,yCAAyC,CAAuB;IACxE,OAAO,CAAC,mCAAmC,CAAuB;IAClE,OAAO,CAAC,4CAA4C,CAAuB;IAC3E,OAAO,CAAC,8BAA8B,CAAuB;IAE7D,OAAO;IAEP,MAAM,CAAC,WAAW,IAAI,aAAa;IAOnC;;OAEG;IACH,OAAO,CAAC,mBAAmB;IA6B3B;;OAEG;IACH,IAAI,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO;IAuFxC;;OAEG;IACH,QAAQ,IAAI,IAAI;IAUhB;;OAEG;IACH,SAAS,IAAI,WAAW;IAsBxB;;OAEG;IACG,kBAAkB,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;IA4DvD;;OAEG;IACG,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAqC1D;;OAEG;IACG,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAqCzD;;OAEG;IACG,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAmB9D;;OAEG;IACG,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAKvE;;OAEG;IACG,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC;IAatC;;OAEG;IACG,gBAAgB,IAAI,OAAO,CAAC,MAAM,CAAC;IAKzC;;OAEG;IACH,YAAY,IAAI,IAAI;IAUpB;;OAEG;IACH,cAAc,IAAI,OAAO;CAW1B;AAED,eAAe,aAAa,CAAC"}
package/dist/steam.js ADDED
@@ -0,0 +1,388 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ const koffi = __importStar(require("koffi"));
37
+ const path = __importStar(require("path"));
38
+ const fs = __importStar(require("fs"));
39
+ /**
40
+ * Real Steamworks SDK implementation using Koffi FFI
41
+ * This connects directly to the actual Steam client and Steamworks SDK
42
+ */
43
+ class SteamworksSDK {
44
+ constructor() {
45
+ this.steamLib = null;
46
+ this.initialized = false;
47
+ this.appId = 0;
48
+ this.userStatsInterface = null;
49
+ }
50
+ static getInstance() {
51
+ if (!SteamworksSDK.instance) {
52
+ SteamworksSDK.instance = new SteamworksSDK();
53
+ }
54
+ return SteamworksSDK.instance;
55
+ }
56
+ /**
57
+ * Get platform-specific Steam library path
58
+ */
59
+ getSteamLibraryPath() {
60
+ const platform = process.platform;
61
+ const arch = process.arch;
62
+ let libPath;
63
+ if (platform === 'win32') {
64
+ if (arch === 'x64') {
65
+ libPath = path.join(__dirname, '../steamworks_sdk/redistributable_bin/win64/steam_api64.dll');
66
+ }
67
+ else {
68
+ libPath = path.join(__dirname, '../steamworks_sdk/redistributable_bin/steam_api.dll');
69
+ }
70
+ }
71
+ else if (platform === 'darwin') {
72
+ libPath = path.join(__dirname, '../steamworks_sdk/redistributable_bin/osx/libsteam_api.dylib');
73
+ }
74
+ else if (platform === 'linux') {
75
+ libPath = path.join(__dirname, '../steamworks_sdk/redistributable_bin/linux64/libsteam_api.so');
76
+ }
77
+ else {
78
+ throw new Error(`Unsupported platform: ${platform}`);
79
+ }
80
+ // Check if the library exists
81
+ if (!fs.existsSync(libPath)) {
82
+ throw new Error(`Steamworks SDK library not found at: ${libPath}\n` +
83
+ 'Please download Steamworks SDK and place it in the steamworks_sdk/ directory.');
84
+ }
85
+ return libPath;
86
+ }
87
+ /**
88
+ * Initialize Steam API with real Steamworks SDK
89
+ */
90
+ init(options) {
91
+ try {
92
+ this.appId = options.appId;
93
+ // Set Steam App ID in environment
94
+ process.env.SteamAppId = this.appId.toString();
95
+ // Also create steam_appid.txt file (Steam requirement)
96
+ const appIdFilePath = path.join(process.cwd(), 'steam_appid.txt');
97
+ fs.writeFileSync(appIdFilePath, this.appId.toString());
98
+ console.log(`🔌 Loading Steamworks SDK for App ID: ${this.appId}`);
99
+ // Load Steam API library using Koffi
100
+ const libPath = this.getSteamLibraryPath();
101
+ console.log(`📚 Loading library: ${libPath}`);
102
+ this.steamLib = koffi.load(libPath);
103
+ // Define function signatures using Koffi
104
+ this.SteamAPI_Init = this.steamLib.func('SteamAPI_InitSafe', 'bool', []);
105
+ this.SteamAPI_Shutdown = this.steamLib.func('SteamAPI_Shutdown', 'void', []);
106
+ this.SteamAPI_RunCallbacks = this.steamLib.func('SteamAPI_RunCallbacks', 'void', []);
107
+ this.SteamAPI_IsSteamRunning = this.steamLib.func('SteamAPI_IsSteamRunning', 'bool', []);
108
+ this.SteamAPI_SteamUserStats_v013 = this.steamLib.func('SteamAPI_SteamUserStats_v013', 'void*', []);
109
+ this.SteamAPI_SteamUser_v023 = this.steamLib.func('SteamAPI_SteamUser_v023', 'void*', []);
110
+ this.SteamAPI_ISteamUserStats_GetNumAchievements = this.steamLib.func('SteamAPI_ISteamUserStats_GetNumAchievements', 'uint32', ['void*']);
111
+ this.SteamAPI_ISteamUserStats_GetAchievementName = this.steamLib.func('SteamAPI_ISteamUserStats_GetAchievementName', 'str', ['void*', 'uint32']);
112
+ this.SteamAPI_ISteamUserStats_GetAchievementDisplayAttribute = this.steamLib.func('SteamAPI_ISteamUserStats_GetAchievementDisplayAttribute', 'str', ['void*', 'str', 'str']);
113
+ this.SteamAPI_ISteamUserStats_GetAchievement = this.steamLib.func('SteamAPI_ISteamUserStats_GetAchievement', 'bool', ['void*', 'str', 'bool*']);
114
+ this.SteamAPI_ISteamUserStats_SetAchievement = this.steamLib.func('SteamAPI_ISteamUserStats_SetAchievement', 'bool', ['void*', 'str']);
115
+ this.SteamAPI_ISteamUserStats_ClearAchievement = this.steamLib.func('SteamAPI_ISteamUserStats_ClearAchievement', 'bool', ['void*', 'str']);
116
+ this.SteamAPI_ISteamUserStats_StoreStats = this.steamLib.func('SteamAPI_ISteamUserStats_StoreStats', 'bool', ['void*']);
117
+ this.SteamAPI_ISteamUserStats_RequestCurrentStats = this.steamLib.func('SteamAPI_ISteamUserStats_RequestUserStats', 'uint64', ['void*', 'uint64']);
118
+ this.SteamAPI_ISteamUser_GetSteamID = this.steamLib.func('SteamAPI_ISteamUser_GetSteamID', 'uint64', ['void*']);
119
+ console.log('🚀 Initializing Steam API...');
120
+ // Initialize Steam API
121
+ const initResult = this.SteamAPI_Init();
122
+ if (!initResult) {
123
+ throw new Error('SteamAPI_Init() failed. Make sure Steam client is running and you\'re logged in.');
124
+ }
125
+ // Check if Steam is running
126
+ const steamRunning = this.SteamAPI_IsSteamRunning();
127
+ if (!steamRunning) {
128
+ console.warn('⚠️ Steam client might not be running properly');
129
+ }
130
+ // Get UserStats interface
131
+ this.userStatsInterface = this.SteamAPI_SteamUserStats_v013();
132
+ if (!this.userStatsInterface || this.userStatsInterface === null) {
133
+ throw new Error('Failed to get SteamUserStats interface');
134
+ }
135
+ // Request current stats from Steam servers
136
+ console.log('📊 Requesting current stats from Steam...');
137
+ // Use 0 as SteamID to request stats for current user
138
+ const statsRequested = this.SteamAPI_ISteamUserStats_RequestCurrentStats(this.userStatsInterface, 0);
139
+ if (!statsRequested) {
140
+ console.warn('⚠️ Failed to request current stats from Steam servers');
141
+ }
142
+ // Run callbacks to process any pending Steam events
143
+ this.SteamAPI_RunCallbacks();
144
+ this.initialized = true;
145
+ console.log('✅ Steam API initialized successfully!');
146
+ console.log(`🎮 Connected to Steam for App ID: ${this.appId}`);
147
+ return true;
148
+ }
149
+ catch (error) {
150
+ console.error('❌ Failed to initialize Steam API:', error.message);
151
+ console.error('💡 Make sure:');
152
+ console.error(' 1. Steam client is running and you\'re logged in');
153
+ console.error(' 2. Steamworks SDK is in steamworks_sdk/ directory');
154
+ console.error(' 3. You have Visual Studio C++ Redistributable installed');
155
+ return false;
156
+ }
157
+ }
158
+ /**
159
+ * Shutdown Steam API
160
+ */
161
+ shutdown() {
162
+ if (this.steamLib && this.initialized) {
163
+ console.log('🔌 Shutting down Steam API...');
164
+ this.SteamAPI_Shutdown();
165
+ this.initialized = false;
166
+ this.userStatsInterface = null;
167
+ console.log('✅ Steam API shutdown complete');
168
+ }
169
+ }
170
+ /**
171
+ * Get current Steam status
172
+ */
173
+ getStatus() {
174
+ let steamId = '0';
175
+ if (this.initialized && this.steamLib) {
176
+ try {
177
+ const userInterface = this.SteamAPI_SteamUser_v023();
178
+ if (userInterface && userInterface !== null) {
179
+ const steamIdNum = this.SteamAPI_ISteamUser_GetSteamID(userInterface);
180
+ steamId = steamIdNum.toString();
181
+ }
182
+ }
183
+ catch (error) {
184
+ console.warn('Failed to get Steam ID:', error.message);
185
+ }
186
+ }
187
+ return {
188
+ initialized: this.initialized,
189
+ appId: this.appId,
190
+ steamId
191
+ };
192
+ }
193
+ /**
194
+ * Get all achievements from Steam
195
+ */
196
+ async getAllAchievements() {
197
+ if (!this.initialized || !this.steamLib || !this.userStatsInterface) {
198
+ console.warn('⚠️ Steam API not initialized');
199
+ return [];
200
+ }
201
+ try {
202
+ // Run callbacks to ensure we have latest data
203
+ this.SteamAPI_RunCallbacks();
204
+ const achievements = [];
205
+ const numAchievements = this.SteamAPI_ISteamUserStats_GetNumAchievements(this.userStatsInterface);
206
+ console.log(`📋 Found ${numAchievements} achievements in Steam`);
207
+ for (let i = 0; i < numAchievements; i++) {
208
+ try {
209
+ // Get achievement API name
210
+ const apiName = this.SteamAPI_ISteamUserStats_GetAchievementName(this.userStatsInterface, i);
211
+ if (!apiName)
212
+ continue;
213
+ // Get display name
214
+ const displayName = this.SteamAPI_ISteamUserStats_GetAchievementDisplayAttribute(this.userStatsInterface, apiName, 'name') || apiName;
215
+ // Get description
216
+ const description = this.SteamAPI_ISteamUserStats_GetAchievementDisplayAttribute(this.userStatsInterface, apiName, 'desc') || '';
217
+ // Check if unlocked
218
+ const unlockedPtr = koffi.alloc('bool', 1);
219
+ const hasAchievement = this.SteamAPI_ISteamUserStats_GetAchievement(this.userStatsInterface, apiName, unlockedPtr);
220
+ const unlocked = hasAchievement ? koffi.decode(unlockedPtr, 'bool') : false;
221
+ achievements.push({
222
+ apiName,
223
+ displayName,
224
+ description,
225
+ unlocked,
226
+ unlockTime: unlocked ? Date.now() : 0 // Steam doesn't provide unlock time easily
227
+ });
228
+ }
229
+ catch (error) {
230
+ console.warn(`Failed to get achievement ${i}:`, error.message);
231
+ }
232
+ }
233
+ return achievements;
234
+ }
235
+ catch (error) {
236
+ console.error('❌ Failed to get achievements:', error.message);
237
+ return [];
238
+ }
239
+ }
240
+ /**
241
+ * Unlock achievement in Steam
242
+ */
243
+ async unlockAchievement(apiName) {
244
+ if (!this.initialized || !this.steamLib || !this.userStatsInterface) {
245
+ console.warn('⚠️ Steam API not initialized');
246
+ return false;
247
+ }
248
+ try {
249
+ console.log(`🔓 Attempting to unlock achievement: ${apiName}`);
250
+ // Set the achievement
251
+ const result = this.SteamAPI_ISteamUserStats_SetAchievement(this.userStatsInterface, apiName);
252
+ if (result) {
253
+ // Store stats to commit the achievement to Steam servers
254
+ const storeResult = this.SteamAPI_ISteamUserStats_StoreStats(this.userStatsInterface);
255
+ if (storeResult) {
256
+ // Run callbacks to process the achievement unlock
257
+ this.SteamAPI_RunCallbacks();
258
+ console.log(`🏆 Achievement unlocked successfully: ${apiName}`);
259
+ return true;
260
+ }
261
+ else {
262
+ console.error(`❌ Failed to store stats for achievement: ${apiName}`);
263
+ return false;
264
+ }
265
+ }
266
+ else {
267
+ console.error(`❌ Failed to set achievement: ${apiName}`);
268
+ return false;
269
+ }
270
+ }
271
+ catch (error) {
272
+ console.error(`❌ Error unlocking achievement ${apiName}:`, error.message);
273
+ return false;
274
+ }
275
+ }
276
+ /**
277
+ * Clear achievement in Steam (for testing)
278
+ */
279
+ async clearAchievement(apiName) {
280
+ if (!this.initialized || !this.steamLib || !this.userStatsInterface) {
281
+ console.warn('⚠️ Steam API not initialized');
282
+ return false;
283
+ }
284
+ try {
285
+ console.log(`🔒 Attempting to clear achievement: ${apiName}`);
286
+ // Clear the achievement
287
+ const result = this.SteamAPI_ISteamUserStats_ClearAchievement(this.userStatsInterface, apiName);
288
+ if (result) {
289
+ // Store stats to commit the change to Steam servers
290
+ const storeResult = this.SteamAPI_ISteamUserStats_StoreStats(this.userStatsInterface);
291
+ if (storeResult) {
292
+ // Run callbacks to process the change
293
+ this.SteamAPI_RunCallbacks();
294
+ console.log(`🔒 Achievement cleared successfully: ${apiName}`);
295
+ return true;
296
+ }
297
+ else {
298
+ console.error(`❌ Failed to store stats for clearing achievement: ${apiName}`);
299
+ return false;
300
+ }
301
+ }
302
+ else {
303
+ console.error(`❌ Failed to clear achievement: ${apiName}`);
304
+ return false;
305
+ }
306
+ }
307
+ catch (error) {
308
+ console.error(`❌ Error clearing achievement ${apiName}:`, error.message);
309
+ return false;
310
+ }
311
+ }
312
+ /**
313
+ * Check if achievement is unlocked
314
+ */
315
+ async isAchievementUnlocked(apiName) {
316
+ if (!this.initialized || !this.steamLib || !this.userStatsInterface) {
317
+ return false;
318
+ }
319
+ try {
320
+ const unlockedPtr = koffi.alloc('bool', 1);
321
+ const hasAchievement = this.SteamAPI_ISteamUserStats_GetAchievement(this.userStatsInterface, apiName, unlockedPtr);
322
+ return hasAchievement ? koffi.decode(unlockedPtr, 'bool') : false;
323
+ }
324
+ catch (error) {
325
+ console.error(`❌ Error checking achievement ${apiName}:`, error.message);
326
+ return false;
327
+ }
328
+ }
329
+ /**
330
+ * Get achievement by API name
331
+ */
332
+ async getAchievement(apiName) {
333
+ const achievements = await this.getAllAchievements();
334
+ return achievements.find(a => a.apiName === apiName) || null;
335
+ }
336
+ /**
337
+ * Get total number of achievements
338
+ */
339
+ async getTotalCount() {
340
+ if (!this.initialized || !this.steamLib || !this.userStatsInterface) {
341
+ return 0;
342
+ }
343
+ try {
344
+ return this.SteamAPI_ISteamUserStats_GetNumAchievements(this.userStatsInterface);
345
+ }
346
+ catch (error) {
347
+ console.error('❌ Error getting achievement count:', error.message);
348
+ return 0;
349
+ }
350
+ }
351
+ /**
352
+ * Get number of unlocked achievements
353
+ */
354
+ async getUnlockedCount() {
355
+ const achievements = await this.getAllAchievements();
356
+ return achievements.filter(a => a.unlocked).length;
357
+ }
358
+ /**
359
+ * Run Steam callbacks to process pending events
360
+ */
361
+ runCallbacks() {
362
+ if (this.initialized && this.steamLib) {
363
+ try {
364
+ this.SteamAPI_RunCallbacks();
365
+ }
366
+ catch (error) {
367
+ console.warn('Warning: Error running Steam callbacks:', error.message);
368
+ }
369
+ }
370
+ }
371
+ /**
372
+ * Check if Steam client is running
373
+ */
374
+ isSteamRunning() {
375
+ if (this.initialized && this.steamLib) {
376
+ try {
377
+ return this.SteamAPI_IsSteamRunning();
378
+ }
379
+ catch (error) {
380
+ console.warn('Warning: Error checking if Steam is running:', error.message);
381
+ return false;
382
+ }
383
+ }
384
+ return false;
385
+ }
386
+ }
387
+ exports.default = SteamworksSDK;
388
+ //# sourceMappingURL=steam.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"steam.js","sourceRoot":"","sources":["../src/steam.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ export interface SteamAchievement {
2
+ apiName: string;
3
+ displayName: string;
4
+ description: string;
5
+ unlocked: boolean;
6
+ unlockTime: number;
7
+ }
8
+ export interface SteamInitOptions {
9
+ appId: number;
10
+ }
11
+ export interface SteamStatus {
12
+ initialized: boolean;
13
+ appId: number;
14
+ steamId: string;
15
+ }
16
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AACA,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,OAAO,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB"}
package/dist/types.js ADDED
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "steamworks-ffi-node",
3
+ "version": "0.1.1",
4
+ "description": "Real Steamworks SDK wrapper using FFI for Node.js/Electron - Full Steam Integration",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "scripts": {
8
+ "build": "tsc",
9
+ "start": "node test.js",
10
+ "test": "node test.js",
11
+ "prepublishOnly": "npm run build"
12
+ },
13
+ "dependencies": {
14
+ "koffi": "^2.8.8"
15
+ },
16
+ "devDependencies": {
17
+ "@types/node": "^20.19.20",
18
+ "typescript": "^5.0.0"
19
+ },
20
+ "files": [
21
+ "dist/**/*",
22
+ "steamworks_sdk/redistributable_bin/**/*",
23
+ "README.md",
24
+ "LICENSE"
25
+ ],
26
+ "keywords": [
27
+ "steam",
28
+ "steamworks",
29
+ "ffi",
30
+ "typescript",
31
+ "achievements",
32
+ "gaming",
33
+ "electron",
34
+ "cross-platform"
35
+ ],
36
+ "repository": {
37
+ "type": "git",
38
+ "url": "https://github.com/ArtyProf/steamworks-ffi-node.git"
39
+ },
40
+ "bugs": {
41
+ "url": "https://github.com/ArtyProf/steamworks-ffi-node/issues"
42
+ },
43
+ "homepage": "https://github.com/ArtyProf/steamworks-ffi-node#readme",
44
+ "author": "ArtyProf",
45
+ "license": "MIT",
46
+ "engines": {
47
+ "node": ">=18.0.0"
48
+ }
49
+ }
@@ -0,0 +1,82 @@
1
+ # Steamworks SDK Setup
2
+
3
+ This directory should contain the Steamworks SDK files for real Steam integration.
4
+
5
+ ## 📥 How to Get Steamworks SDK
6
+
7
+ 1. **Register as Steam Partner**: Go to https://partner.steamgames.com/
8
+ 2. **Download Steamworks SDK**: Available in the partner portal after registration
9
+ 3. **Extract SDK**: Place the extracted files in this directory
10
+
11
+ ## 📁 Required Directory Structure
12
+
13
+ ```
14
+ steamworks_sdk/
15
+ ├── public/
16
+ │ └── steam/
17
+ │ ├── steam_api.h
18
+ │ ├── isteamuserstate.h
19
+ │ └── ... (other header files)
20
+ └── redistributable_bin/
21
+ ├── win64/
22
+ │ └── steam_api64.dll # Windows 64-bit
23
+ ├── steam_api.dll # Windows 32-bit
24
+ ├── osx/
25
+ │ └── libsteam_api.dylib # macOS
26
+ └── linux64/
27
+ └── libsteam_api.so # Linux 64-bit
28
+ ```
29
+
30
+ ## 🔑 Steam App ID
31
+
32
+ You'll also need a valid Steam App ID:
33
+
34
+ 1. **Get App ID**: Register your application on Steamworks
35
+ 2. **Create steam_appid.txt**: Place your App ID in this file in the project root
36
+ 3. **Environment Variable**: The wrapper will set `SteamAppId` automatically
37
+
38
+ ## 🎮 Testing Without Real App ID
39
+
40
+ For testing purposes, you can use Steam's test App ID `480` (Spacewar), but this requires:
41
+ - Steam client running
42
+ - Being logged into Steam
43
+ - Having Spacewar in your library (it's free)
44
+
45
+ ## ⚡ Quick Setup
46
+
47
+ 1. Download Steamworks SDK from Steam Partner portal
48
+ 2. Extract to this directory maintaining the structure above
49
+ 3. Run: `npm run setup` to verify everything is configured
50
+ 4. Run: `npm install` to build FFI dependencies
51
+ 5. Run: `npm start` to test with real Steam integration
52
+
53
+ ## 🚨 Important Notes
54
+
55
+ - **Keep SDK Private**: Steamworks SDK is under NDA - don't commit it to public repos
56
+ - **Platform Specific**: Make sure to include binaries for all target platforms
57
+ - **Steam Client Required**: Real integration requires Steam client to be running
58
+ - **Valid App ID**: Production use requires a registered Steam application
59
+
60
+ ## 🔧 Troubleshooting
61
+
62
+ **"Library not found" Error**:
63
+ - Verify SDK files are in correct locations
64
+ - Check file permissions
65
+ - Ensure Visual Studio C++ Redistributable is installed
66
+
67
+ **"SteamAPI_Init failed" Error**:
68
+ - Make sure Steam client is running
69
+ - Verify you're logged into Steam
70
+ - Check that steam_appid.txt contains valid App ID
71
+ - For App ID 480, make sure Spacewar is in your Steam library
72
+
73
+ **Build Errors**:
74
+ - Install Visual Studio Build Tools with C++ workload
75
+ - Make sure Python is installed
76
+ - Try running as Administrator
77
+
78
+ ## 📚 Documentation
79
+
80
+ - **Steamworks API Reference**: https://partner.steamgames.com/doc/api
81
+ - **Steam Partner Documentation**: Available after partner registration
82
+ - **Integration Guides**: Check the official Steamworks documentation