steamworks-ffi-node 0.6.9 → 0.7.0

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/README.md CHANGED
@@ -41,6 +41,8 @@ A TypeScript/JavaScript wrapper for the Steamworks SDK using Koffi FFI, designed
41
41
 
42
42
  > 🎉 **NEW: Workshop API** - 29 functions for complete Steam Workshop/UGC integration! [See Documentation](https://github.com/ArtyProf/steamworks-ffi-node/blob/main/docs/WORKSHOP_MANAGER.md)
43
43
 
44
+ > 🎉 **NEW: Input API** - 35+ functions for complete Steam Input (controller) support! [See Documentation](https://github.com/ArtyProf/steamworks-ffi-node/blob/main/docs/INPUT_MANAGER.md) ⚠️ Tested with virtual gamepad only
45
+
44
46
  ## Features
45
47
 
46
48
  - **Core API**: Essential Steam application functions
@@ -94,6 +96,12 @@ A TypeScript/JavaScript wrapper for the Steamworks SDK using Koffi FFI, designed
94
96
  - ✅ Query operations (text search, browse, filter Workshop content)
95
97
  - ✅ Item creation & update (create, upload, manage your Workshop items)
96
98
  - ✅ Voting & favorites (vote on items, manage favorites)
99
+ - **Input API**: Complete Steam Input (controller) support (35+ functions) ⚠️ _Tested with virtual gamepad only_
100
+ - ✅ Controller detection (Xbox, PlayStation, Switch, Steam Controller, Steam Deck)
101
+ - ✅ Action sets and layers (menu controls, gameplay controls, etc.)
102
+ - ✅ Digital actions (buttons) and analog actions (sticks/triggers)
103
+ - ✅ Motion data (gyro, accelerometer for supported controllers)
104
+ - ✅ Haptics (vibration, LED control for DualShock/DualSense)
97
105
  - **Steamworks Integration**: Direct FFI calls to Steamworks C++ SDK
98
106
  - **Cross-Platform**: Windows, macOS, and Linux support
99
107
  - **Easy Setup**: Simple installation with clear SDK setup guide
@@ -113,23 +121,26 @@ npm install steamworks-ffi-node
113
121
  ### Setup
114
122
 
115
123
  1. **Download Steamworks SDK** (required separately due to licensing):
124
+
116
125
  - Visit [Steamworks Partner site](https://partner.steamgames.com/)
117
126
  - Download the latest Steamworks SDK
118
127
  - Extract and copy `redistributable_bin` folder to your project
119
128
  - See [STEAMWORKS_SDK_SETUP.md](https://github.com/ArtyProf/steamworks-ffi-node/blob/main/docs/STEAMWORKS_SDK_SETUP.md) for detailed instructions
120
129
 
121
130
  2. **Create `steam_appid.txt` (optional)** in your project root:
131
+
122
132
  ```bash
123
133
  echo "480" > steam_appid.txt # Use 480 for testing, or your Steam App ID
124
134
  ```
125
- *Note: You can skip this file and pass the App ID directly to `steam.init(appId)` instead*
135
+
136
+ _Note: You can skip this file and pass the App ID directly to `steam.init(appId)` instead_
126
137
 
127
138
  3. **Make sure Steam is running** and you're logged in
128
139
 
129
140
  ### Basic Usage
130
141
 
131
142
  ```typescript
132
- import SteamworksSDK from 'steamworks-ffi-node';
143
+ import SteamworksSDK from "steamworks-ffi-node";
133
144
 
134
145
  // Helper to auto-start callback polling
135
146
  function startCallbackPolling(steam: SteamworksSDK, interval: number = 1000) {
@@ -139,54 +150,56 @@ function startCallbackPolling(steam: SteamworksSDK, interval: number = 1000) {
139
150
  }
140
151
 
141
152
  // Initialize Steam connection
142
- const steam = new SteamworksSDK();
153
+ const steam = SteamworksSDK.getInstance();
143
154
  const initialized = steam.init({ appId: 480 }); // Your Steam App ID
144
155
 
145
156
  if (initialized) {
146
157
  // Start callback polling automatically (required for async operations)
147
158
  const callbackInterval = startCallbackPolling(steam, 1000);
148
-
159
+
149
160
  // Get current Steam language for localization
150
161
  const language = steam.getCurrentGameLanguage();
151
- console.log('Steam language:', language); // e.g., 'english', 'french', 'german'
152
-
162
+ console.log("Steam language:", language); // e.g., 'english', 'french', 'german'
163
+
153
164
  // Get achievements from Steam servers
154
165
  const achievements = await steam.achievements.getAllAchievements();
155
- console.log('Steam achievements:', achievements);
156
-
166
+ console.log("Steam achievements:", achievements);
167
+
157
168
  // Unlock achievement (permanent in Steam!)
158
- await steam.achievements.unlockAchievement('ACH_WIN_ONE_GAME');
159
-
169
+ await steam.achievements.unlockAchievement("ACH_WIN_ONE_GAME");
170
+
160
171
  // Check unlock status from Steam
161
- const isUnlocked = await steam.achievements.isAchievementUnlocked('ACH_WIN_ONE_GAME');
162
- console.log('Achievement unlocked:', isUnlocked);
163
-
172
+ const isUnlocked = await steam.achievements.isAchievementUnlocked(
173
+ "ACH_WIN_ONE_GAME"
174
+ );
175
+ console.log("Achievement unlocked:", isUnlocked);
176
+
164
177
  // Track user statistics
165
- const kills = await steam.stats.getStatInt('total_kills') || 0;
166
- await steam.stats.setStatInt('total_kills', kills + 1);
167
-
178
+ const kills = (await steam.stats.getStatInt("total_kills")) || 0;
179
+ await steam.stats.setStatInt("total_kills", kills + 1);
180
+
168
181
  // Get global statistics
169
182
  await steam.stats.requestGlobalStats(7);
170
- await new Promise(resolve => setTimeout(resolve, 2000));
183
+ await new Promise((resolve) => setTimeout(resolve, 2000));
171
184
  steam.runCallbacks();
172
- const globalKills = await steam.stats.getGlobalStatInt('global.total_kills');
173
- console.log('Total kills worldwide:', globalKills);
174
-
185
+ const globalKills = await steam.stats.getGlobalStatInt("global.total_kills");
186
+ console.log("Total kills worldwide:", globalKills);
187
+
175
188
  // Work with leaderboards
176
189
  const leaderboard = await steam.leaderboards.findOrCreateLeaderboard(
177
- 'HighScores',
190
+ "HighScores",
178
191
  1, // Descending (higher is better)
179
- 0 // Numeric display
192
+ 0 // Numeric display
180
193
  );
181
-
194
+
182
195
  if (leaderboard) {
183
196
  // Upload score
184
197
  await steam.leaderboards.uploadLeaderboardScore(
185
198
  leaderboard.handle,
186
199
  1000,
187
- 1 // Keep best score
200
+ 1 // Keep best score
188
201
  );
189
-
202
+
190
203
  // Download top 10 scores
191
204
  const topScores = await steam.leaderboards.downloadLeaderboardEntries(
192
205
  leaderboard.handle,
@@ -194,36 +207,38 @@ if (initialized) {
194
207
  0,
195
208
  9
196
209
  );
197
- console.log('Top 10 scores:', topScores);
210
+ console.log("Top 10 scores:", topScores);
198
211
  }
199
-
212
+
200
213
  // Access friends and social features
201
214
  const personaName = steam.friends.getPersonaName();
202
215
  const friendCount = steam.friends.getFriendCount(4); // All friends
203
216
  console.log(`${personaName} has ${friendCount} friends`);
204
-
217
+
205
218
  // Get all friends with details
206
219
  const allFriends = steam.friends.getAllFriends(4); // All friends
207
- allFriends.slice(0, 5).forEach(friend => {
220
+ allFriends.slice(0, 5).forEach((friend) => {
208
221
  const name = steam.friends.getFriendPersonaName(friend.steamId);
209
222
  const state = steam.friends.getFriendPersonaState(friend.steamId);
210
223
  const level = steam.friends.getFriendSteamLevel(friend.steamId);
211
224
  console.log(`${name}: Level ${level}, Status: ${state}`);
212
-
225
+
213
226
  // Get avatar handles
214
227
  const smallAvatar = steam.friends.getSmallFriendAvatar(friend.steamId);
215
228
  const mediumAvatar = steam.friends.getMediumFriendAvatar(friend.steamId);
216
229
  if (smallAvatar > 0) {
217
- console.log(` Avatar handles: small=${smallAvatar}, medium=${mediumAvatar}`);
230
+ console.log(
231
+ ` Avatar handles: small=${smallAvatar}, medium=${mediumAvatar}`
232
+ );
218
233
  }
219
-
234
+
220
235
  // Check if playing a game
221
236
  const gameInfo = steam.friends.getFriendGamePlayed(friend.steamId);
222
237
  if (gameInfo) {
223
238
  console.log(` Playing: App ${gameInfo.gameId}`);
224
239
  }
225
240
  });
226
-
241
+
227
242
  // Check friend groups (tags)
228
243
  const groupCount = steam.friends.getFriendsGroupCount();
229
244
  if (groupCount > 0) {
@@ -232,7 +247,7 @@ if (initialized) {
232
247
  const members = steam.friends.getFriendsGroupMembersList(groupId);
233
248
  console.log(`Group "${groupName}" has ${members.length} members`);
234
249
  }
235
-
250
+
236
251
  // Check recently played with
237
252
  const coplayCount = steam.friends.getCoplayFriendCount();
238
253
  if (coplayCount > 0) {
@@ -241,107 +256,123 @@ if (initialized) {
241
256
  const coplayTime = steam.friends.getFriendCoplayTime(recentPlayer);
242
257
  console.log(`Recently played with ${playerName}`);
243
258
  }
244
-
259
+
245
260
  // Set rich presence for custom status
246
- steam.richPresence.setRichPresence('status', 'In Main Menu');
247
- steam.richPresence.setRichPresence('connect', '+connect server:27015');
248
-
261
+ steam.richPresence.setRichPresence("status", "In Main Menu");
262
+ steam.richPresence.setRichPresence("connect", "+connect server:27015");
263
+
249
264
  // Open Steam overlay
250
- steam.overlay.activateGameOverlay('Friends'); // Open friends list
251
- steam.overlay.activateGameOverlayToWebPage('https://example.com/wiki'); // Open wiki
252
-
265
+ steam.overlay.activateGameOverlay("Friends"); // Open friends list
266
+ steam.overlay.activateGameOverlayToWebPage("https://example.com/wiki"); // Open wiki
267
+
253
268
  // Steam Cloud storage operations
254
- const saveData = { level: 5, score: 1000, inventory: ['sword', 'shield'] };
269
+ const saveData = { level: 5, score: 1000, inventory: ["sword", "shield"] };
255
270
  const buffer = Buffer.from(JSON.stringify(saveData));
256
-
271
+
257
272
  // Write save file to Steam Cloud
258
- const written = steam.cloud.fileWrite('savegame.json', buffer);
273
+ const written = steam.cloud.fileWrite("savegame.json", buffer);
259
274
  if (written) {
260
- console.log('✅ Save uploaded to Steam Cloud');
275
+ console.log("✅ Save uploaded to Steam Cloud");
261
276
  }
262
-
277
+
263
278
  // Check cloud quota
264
279
  const quota = steam.cloud.getQuota();
265
- console.log(`Cloud storage: ${quota.usedBytes}/${quota.totalBytes} bytes (${quota.percentUsed.toFixed(2)}%)`);
266
-
280
+ console.log(
281
+ `Cloud storage: ${quota.usedBytes}/${
282
+ quota.totalBytes
283
+ } bytes (${quota.percentUsed.toFixed(2)}%)`
284
+ );
285
+
267
286
  // Read save file from Steam Cloud
268
- if (steam.cloud.fileExists('savegame.json')) {
269
- const result = steam.cloud.fileRead('savegame.json');
287
+ if (steam.cloud.fileExists("savegame.json")) {
288
+ const result = steam.cloud.fileRead("savegame.json");
270
289
  if (result.success && result.data) {
271
290
  const loadedSave = JSON.parse(result.data.toString());
272
- console.log(`Loaded save: Level ${loadedSave.level}, Score ${loadedSave.score}`);
291
+ console.log(
292
+ `Loaded save: Level ${loadedSave.level}, Score ${loadedSave.score}`
293
+ );
273
294
  }
274
295
  }
275
-
296
+
276
297
  // List all cloud files
277
298
  const cloudFiles = steam.cloud.getAllFiles();
278
299
  console.log(`Steam Cloud contains ${cloudFiles.length} files:`);
279
- cloudFiles.forEach(file => {
300
+ cloudFiles.forEach((file) => {
280
301
  const kb = (file.size / 1024).toFixed(2);
281
- const status = file.persisted ? '☁️' : '';
302
+ const status = file.persisted ? "☁️" : "";
282
303
  console.log(`${status} ${file.name} - ${kb} KB`);
283
304
  });
284
-
305
+
285
306
  // Steam Workshop operations
286
307
  // Subscribe to a Workshop item
287
308
  const subscribeResult = await steam.workshop.subscribeItem(123456789n);
288
309
  if (subscribeResult.success) {
289
- console.log('✅ Subscribed to Workshop item');
310
+ console.log("✅ Subscribed to Workshop item");
290
311
  }
291
-
312
+
292
313
  // Get all subscribed items
293
314
  const subscribedItems = steam.workshop.getSubscribedItems();
294
315
  console.log(`Subscribed to ${subscribedItems.length} Workshop items`);
295
-
316
+
296
317
  // Query Workshop items with text search
297
318
  const query = steam.workshop.createQueryAllUGCRequest(
298
- 11, // RankedByTextSearch - for text search queries
299
- 0, // Items
300
- 480, // Creator App ID
301
- 480, // Consumer App ID
302
- 1 // Page 1
319
+ 11, // RankedByTextSearch - for text search queries
320
+ 0, // Items
321
+ 480, // Creator App ID
322
+ 480, // Consumer App ID
323
+ 1 // Page 1
303
324
  );
304
-
325
+
305
326
  if (query) {
306
327
  // Set search text to filter results
307
- steam.workshop.setSearchText(query, 'map');
308
-
328
+ steam.workshop.setSearchText(query, "map");
329
+
309
330
  const queryResult = await steam.workshop.sendQueryUGCRequest(query);
310
331
  if (queryResult) {
311
- console.log(`Found ${queryResult.numResults} Workshop items matching "map"`);
312
-
332
+ console.log(
333
+ `Found ${queryResult.numResults} Workshop items matching "map"`
334
+ );
335
+
313
336
  // Get details for each item
314
337
  for (let i = 0; i < queryResult.numResults; i++) {
315
338
  const details = steam.workshop.getQueryUGCResult(query, i);
316
339
  if (details) {
317
340
  console.log(`📦 ${details.title} by ${details.steamIDOwner}`);
318
- console.log(` Score: ${details.score}, Downloads: ${details.numUniqueSubscriptions}`);
341
+ console.log(
342
+ ` Score: ${details.score}, Downloads: ${details.numUniqueSubscriptions}`
343
+ );
319
344
  }
320
345
  }
321
346
  }
322
347
  steam.workshop.releaseQueryUGCRequest(query);
323
348
  }
324
-
349
+
325
350
  // Check download progress for subscribed items
326
- subscribedItems.forEach(itemId => {
351
+ subscribedItems.forEach((itemId) => {
327
352
  const state = steam.workshop.getItemState(itemId);
328
353
  const stateFlags = [];
329
- if (state & 1) stateFlags.push('Subscribed');
330
- if (state & 4) stateFlags.push('Needs Update');
331
- if (state & 8) stateFlags.push('Installed');
332
- if (state & 16) stateFlags.push('Downloading');
333
-
334
- console.log(`Item ${itemId}: ${stateFlags.join(', ')}`);
335
-
336
- if (state & 16) { // If downloading
354
+ if (state & 1) stateFlags.push("Subscribed");
355
+ if (state & 4) stateFlags.push("Needs Update");
356
+ if (state & 8) stateFlags.push("Installed");
357
+ if (state & 16) stateFlags.push("Downloading");
358
+
359
+ console.log(`Item ${itemId}: ${stateFlags.join(", ")}`);
360
+
361
+ if (state & 16) {
362
+ // If downloading
337
363
  const progress = steam.workshop.getItemDownloadInfo(itemId);
338
364
  if (progress) {
339
- const percent = (progress.downloaded / progress.total * 100).toFixed(1);
340
- console.log(` Download: ${percent}% (${progress.downloaded}/${progress.total} bytes)`);
365
+ const percent = ((progress.downloaded / progress.total) * 100).toFixed(
366
+ 1
367
+ );
368
+ console.log(
369
+ ` Download: ${percent}% (${progress.downloaded}/${progress.total} bytes)`
370
+ );
341
371
  }
342
372
  }
343
-
344
- if (state & 8) { // If installed
373
+
374
+ if (state & 8) {
375
+ // If installed
345
376
  const info = steam.workshop.getItemInstallInfo(itemId);
346
377
  if (info.success) {
347
378
  console.log(` Installed at: ${info.folder}`);
@@ -355,10 +386,17 @@ clearInterval(callbackInterval);
355
386
  steam.shutdown();
356
387
  ```
357
388
 
358
- ### JavaScript (CommonJS)
389
+ ### JavaScript
359
390
 
360
391
  ```javascript
361
- const SteamworksSDK = require('steamworks-ffi-node').default;
392
+ // Option 1: ESM Named import
393
+ import { SteamworksSDK } from "steamworks-ffi-node";
394
+
395
+ // Option 2: CommonJs named import (recommended - no .default needed)
396
+ const { SteamworksSDK } = require("steamworks-ffi-node");
397
+
398
+ // Option 3: CommonJs default named import (also works)
399
+ const SteamworksSDK = require("steamworks-ffi-node").default;
362
400
 
363
401
  // Helper to auto-start callback polling
364
402
  function startCallbackPolling(steam, interval = 1000) {
@@ -368,25 +406,25 @@ function startCallbackPolling(steam, interval = 1000) {
368
406
  }
369
407
 
370
408
  async function example() {
371
- const steam = new SteamworksSDK();
372
-
409
+ const steam = SteamworksSDK.getInstance();
410
+
373
411
  if (steam.init({ appId: 480 })) {
374
412
  // Start callback polling automatically
375
413
  const callbackInterval = startCallbackPolling(steam, 1000);
376
-
414
+
377
415
  const achievements = await steam.achievements.getAllAchievements();
378
416
  console.log(`Found ${achievements.length} achievements`);
379
-
417
+
380
418
  // Unlock first locked achievement
381
- const locked = achievements.find(a => !a.unlocked);
419
+ const locked = achievements.find((a) => !a.unlocked);
382
420
  if (locked) {
383
421
  await steam.achievements.unlockAchievement(locked.apiName);
384
422
  }
385
-
423
+
386
424
  // Cleanup
387
425
  clearInterval(callbackInterval);
388
426
  }
389
-
427
+
390
428
  steam.shutdown();
391
429
  }
392
430
 
@@ -396,6 +434,7 @@ example();
396
434
  ### Testing with Spacewar
397
435
 
398
436
  For immediate testing, use Spacewar (App ID 480):
437
+
399
438
  - Free Steam app for testing Steamworks features
400
439
  - Add to Steam library: `steam://install/480` or search "Spacewar" in Steam
401
440
  - Launch it once, then you can test with App ID 480
@@ -407,14 +446,16 @@ Complete documentation for all APIs is available in the [docs folder](https://gi
407
446
  ➡️ **[View Complete Documentation](https://github.com/ArtyProf/steamworks-ffi-node/blob/main/docs/README.md)**
408
447
 
409
448
  ### API Guides:
449
+
410
450
  - **[Achievement Manager](https://github.com/ArtyProf/steamworks-ffi-node/blob/main/docs/ACHIEVEMENT_MANAGER.md)** - Complete achievement system (20 functions)
411
451
  - **[Stats Manager](https://github.com/ArtyProf/steamworks-ffi-node/blob/main/docs/STATS_MANAGER.md)** - User and global statistics (14 functions)
412
452
  - **[Leaderboard Manager](https://github.com/ArtyProf/steamworks-ffi-node/blob/main/docs/LEADERBOARD_MANAGER.md)** - Leaderboard operations (7 functions)
413
453
  - **[Friends Manager](https://github.com/ArtyProf/steamworks-ffi-node/blob/main/docs/FRIENDS_MANAGER.md)** - Friends and social features (22 functions)
414
454
  - **[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)
415
455
  - **[Overlay Manager](https://github.com/ArtyProf/steamworks-ffi-node/blob/main/docs/OVERLAY_MANAGER.md)** - Steam overlay control (7 functions)
416
- - **[Cloud Storage Manager](https://github.com/ArtyProf/steamworks-ffi-node/blob/main/docs/CLOUD_STORAGE_MANAGER.md)** - Steam Cloud file operations (14 functions)
456
+ - **[Cloud Storage Manager](https://github.com/ArtyProf/steamworks-ffi-node/blob/main/docs/CLOUD_MANAGER.md)** - Steam Cloud file operations (14 functions)
417
457
  - **[Workshop Manager](https://github.com/ArtyProf/steamworks-ffi-node/blob/main/docs/WORKSHOP_MANAGER.md)** - Steam Workshop/UGC operations (29 functions)
458
+ - **[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_
418
459
 
419
460
  ## Steamworks Integration
420
461
 
@@ -422,7 +463,7 @@ This library connects directly to the Steam client and Steamworks SDK:
422
463
 
423
464
  ```javascript
424
465
  // Steamworks API
425
- const steam = new SteamworksSDK();
466
+ const steam = SteamworksSDK.getInstance();
426
467
  steam.init({ appId: 480 }); // Connects to actual Steam
427
468
 
428
469
  // Live achievements from Steam servers
@@ -430,11 +471,12 @@ const achievements = await steam.achievements.getAllAchievements();
430
471
  console.log(achievements); // Achievement data from your Steam app
431
472
 
432
473
  // Permanent achievement unlock in Steam
433
- await steam.achievements.unlockAchievement('YOUR_ACHIEVEMENT');
474
+ await steam.achievements.unlockAchievement("YOUR_ACHIEVEMENT");
434
475
  // ^ This shows up in Steam overlay and is saved permanently
435
476
  ```
436
477
 
437
478
  **What happens when you unlock an achievement:**
479
+
438
480
  - ✅ Steam overlay notification appears
439
481
  - ✅ Achievement saved to Steam servers permanently
440
482
  - ✅ Syncs across all devices
@@ -447,22 +489,22 @@ For Electron applications, use it in your main process:
447
489
 
448
490
  ```typescript
449
491
  // main.ts
450
- import { app } from 'electron';
451
- import SteamworksSDK from 'steamworks-ffi-node';
492
+ import { app } from "electron";
493
+ import SteamworksSDK from "steamworks-ffi-node";
452
494
 
453
495
  app.whenReady().then(() => {
454
- const steam = new SteamworksSDK();
455
-
496
+ const steam = SteamworksSDK.getInstance();
497
+
456
498
  if (steam.init({ appId: YOUR_STEAM_APP_ID })) {
457
- console.log('Steam initialized in Electron!');
458
-
499
+ console.log("Steam initialized in Electron!");
500
+
459
501
  // Handle achievement unlocks from renderer process
460
502
  // via IPC if needed
461
503
  }
462
504
  });
463
505
 
464
- app.on('before-quit', () => {
465
- const steam = new SteamworksSDK();
506
+ app.on("before-quit", () => {
507
+ const steam = SteamworksSDK.getInstance();
466
508
  steam.shutdown();
467
509
  });
468
510
  ```
@@ -475,42 +517,46 @@ The library searches for the SDK in standard locations within your Electron app
475
517
 
476
518
  ## Requirements
477
519
 
478
- - **Node.js**: 18+
520
+ - **Node.js**: 18+
479
521
  - **Steam Client**: Must be running and logged in
480
522
  - **Steam App ID**: Get yours at [Steamworks Partner](https://partner.steamgames.com/)
481
523
  - **steam_appid.txt**: Optional - create in your project root OR pass to `steam.init(appId)`
482
524
 
483
525
  ### Platform Support
526
+
484
527
  - ✅ **Windows**: steam_api64.dll / steam_api.dll
485
- - ✅ **macOS**: libsteam_api.dylib
528
+ - ✅ **macOS**: libsteam_api.dylib
486
529
  - ✅ **Linux**: libsteam_api.so
487
530
 
488
531
  **Steamworks SDK Version**: v1.62 (Latest)
489
532
 
490
- *Note: You must download and install the SDK redistributables separately as described in the Setup section above.*
533
+ _Note: You must download and install the SDK redistributables separately as described in the Setup section above._
491
534
 
492
535
  ## Troubleshooting
493
536
 
494
537
  ### "SteamAPI_Init failed"
538
+
495
539
  - ❌ Steam client not running → **Solution**: Start Steam and log in
496
540
  - ❌ No App ID specified → **Solution**: Create `steam_appid.txt` in project root OR pass App ID to `steam.init(appId)`
497
541
  - ❌ Invalid App ID → **Solution**: Use 480 for testing, or your registered App ID
498
542
 
499
543
  ### "Cannot find module 'steamworks-ffi-node'"
544
+
500
545
  - ❌ Package not installed → **Solution**: Run `npm install steamworks-ffi-node`
501
546
 
502
547
  ### Achievement operations not working
548
+
503
549
  - ❌ Not initialized → **Solution**: Call `steam.init({ appId })` first
504
550
  - ❌ No achievements configured → **Solution**: Configure achievements in Steamworks Partner site
505
551
  - ❌ Using Spacewar → **Note**: Spacewar may not have achievements, use your own App ID
506
552
 
507
553
  ### Electron-specific issues
554
+
508
555
  - ❌ Initialized in renderer → **Solution**: Only initialize in main process
509
556
  - ❌ Not cleaning up → **Solution**: Call `shutdown()` in `before-quit` event
510
557
  - ❌ "Steamworks SDK library not found" in packaged app → **Solution**: Include SDK redistributables in your build (see Electron Packaging section above)
511
558
  - ❌ Native module errors in packaged app → **Solution**: Ensure Steamworks SDK files are properly included in your app bundle
512
559
 
513
-
514
560
  ## How to Support This Project
515
561
 
516
562
  You can support the development of this library by wishlisting, subscribing, and purchasing the app **AFK Companion** on Steam:
package/dist/index.d.ts CHANGED
@@ -9,4 +9,5 @@ export { SteamCloudManager } from './internal/SteamCloudManager';
9
9
  export { SteamWorkshopManager } from './internal/SteamWorkshopManager';
10
10
  export * from './types';
11
11
  export default SteamworksSDK;
12
+ export { SteamworksSDK };
12
13
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,aAAa,MAAM,SAAS,CAAC;AAGpC,OAAO,EAAE,uBAAuB,EAAE,MAAM,oCAAoC,CAAC;AAC7E,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,uBAAuB,EAAE,MAAM,oCAAoC,CAAC;AAC7E,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,wBAAwB,EAAE,MAAM,qCAAqC,CAAC;AAC/E,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAGvE,cAAc,SAAS,CAAC;AAGxB,eAAe,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,aAAa,MAAM,SAAS,CAAC;AAGpC,OAAO,EAAE,uBAAuB,EAAE,MAAM,oCAAoC,CAAC;AAC7E,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,uBAAuB,EAAE,MAAM,oCAAoC,CAAC;AAC7E,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,wBAAwB,EAAE,MAAM,qCAAqC,CAAC;AAC/E,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAGvE,cAAc,SAAS,CAAC;AAGxB,eAAe,aAAa,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,CAAC"}
package/dist/index.js CHANGED
@@ -17,8 +17,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
17
17
  return (mod && mod.__esModule) ? mod : { "default": mod };
18
18
  };
19
19
  Object.defineProperty(exports, "__esModule", { value: true });
20
- exports.SteamWorkshopManager = exports.SteamCloudManager = exports.SteamOverlayManager = exports.SteamRichPresenceManager = exports.SteamFriendsManager = exports.SteamLeaderboardManager = exports.SteamStatsManager = exports.SteamAchievementManager = void 0;
20
+ exports.SteamworksSDK = exports.SteamWorkshopManager = exports.SteamCloudManager = exports.SteamOverlayManager = exports.SteamRichPresenceManager = exports.SteamFriendsManager = exports.SteamLeaderboardManager = exports.SteamStatsManager = exports.SteamAchievementManager = void 0;
21
21
  const steam_1 = __importDefault(require("./steam"));
22
+ exports.SteamworksSDK = steam_1.default;
22
23
  // Export manager classes for advanced usage
23
24
  var SteamAchievementManager_1 = require("./internal/SteamAchievementManager");
24
25
  Object.defineProperty(exports, "SteamAchievementManager", { enumerable: true, get: function () { return SteamAchievementManager_1.SteamAchievementManager; } });
@@ -38,6 +39,6 @@ var SteamWorkshopManager_1 = require("./internal/SteamWorkshopManager");
38
39
  Object.defineProperty(exports, "SteamWorkshopManager", { enumerable: true, get: function () { return SteamWorkshopManager_1.SteamWorkshopManager; } });
39
40
  // Export all types from organized structure
40
41
  __exportStar(require("./types"), exports);
41
- // Export main Steam class
42
+ // Export main Steam class as both default and named export
42
43
  exports.default = steam_1.default;
43
44
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA,oDAAoC;AAEpC,4CAA4C;AAC5C,8EAA6E;AAApE,kIAAA,uBAAuB,OAAA;AAChC,kEAAiE;AAAxD,sHAAA,iBAAiB,OAAA;AAC1B,8EAA6E;AAApE,kIAAA,uBAAuB,OAAA;AAChC,sEAAqE;AAA5D,0HAAA,mBAAmB,OAAA;AAC5B,gFAA+E;AAAtE,oIAAA,wBAAwB,OAAA;AACjC,sEAAqE;AAA5D,0HAAA,mBAAmB,OAAA;AAC5B,kEAAiE;AAAxD,sHAAA,iBAAiB,OAAA;AAC1B,wEAAuE;AAA9D,4HAAA,oBAAoB,OAAA;AAE7B,4CAA4C;AAC5C,0CAAwB;AAExB,0BAA0B;AAC1B,kBAAe,eAAa,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA,oDAAoC;AAiB3B,wBAjBF,eAAa,CAiBE;AAftB,4CAA4C;AAC5C,8EAA6E;AAApE,kIAAA,uBAAuB,OAAA;AAChC,kEAAiE;AAAxD,sHAAA,iBAAiB,OAAA;AAC1B,8EAA6E;AAApE,kIAAA,uBAAuB,OAAA;AAChC,sEAAqE;AAA5D,0HAAA,mBAAmB,OAAA;AAC5B,gFAA+E;AAAtE,oIAAA,wBAAwB,OAAA;AACjC,sEAAqE;AAA5D,0HAAA,mBAAmB,OAAA;AAC5B,kEAAiE;AAAxD,sHAAA,iBAAiB,OAAA;AAC1B,wEAAuE;AAA9D,4HAAA,oBAAoB,OAAA;AAE7B,4CAA4C;AAC5C,0CAAwB;AAExB,2DAA2D;AAC3D,kBAAe,eAAa,CAAC"}