steamworks-ffi-node 0.3.0 → 0.4.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.
Files changed (38) hide show
  1. package/README.md +86 -10
  2. package/dist/index.d.ts +2 -2
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +6 -1
  5. package/dist/index.js.map +1 -1
  6. package/dist/internal/SteamAPICore.d.ts +221 -8
  7. package/dist/internal/SteamAPICore.d.ts.map +1 -1
  8. package/dist/internal/SteamAPICore.js +234 -14
  9. package/dist/internal/SteamAPICore.js.map +1 -1
  10. package/dist/internal/SteamAchievementManager.d.ts +602 -31
  11. package/dist/internal/SteamAchievementManager.d.ts.map +1 -1
  12. package/dist/internal/SteamAchievementManager.js +601 -32
  13. package/dist/internal/SteamAchievementManager.js.map +1 -1
  14. package/dist/internal/SteamCallbackPoller.d.ts +68 -0
  15. package/dist/internal/SteamCallbackPoller.d.ts.map +1 -0
  16. package/dist/internal/SteamCallbackPoller.js +134 -0
  17. package/dist/internal/SteamCallbackPoller.js.map +1 -0
  18. package/dist/internal/SteamLeaderboardManager.d.ts +338 -0
  19. package/dist/internal/SteamLeaderboardManager.d.ts.map +1 -0
  20. package/dist/internal/SteamLeaderboardManager.js +734 -0
  21. package/dist/internal/SteamLeaderboardManager.js.map +1 -0
  22. package/dist/internal/SteamLibraryLoader.d.ts +15 -0
  23. package/dist/internal/SteamLibraryLoader.d.ts.map +1 -1
  24. package/dist/internal/SteamLibraryLoader.js +42 -5
  25. package/dist/internal/SteamLibraryLoader.js.map +1 -1
  26. package/dist/internal/SteamStatsManager.d.ts +357 -50
  27. package/dist/internal/SteamStatsManager.d.ts.map +1 -1
  28. package/dist/internal/SteamStatsManager.js +444 -106
  29. package/dist/internal/SteamStatsManager.js.map +1 -1
  30. package/dist/steam.d.ts +169 -9
  31. package/dist/steam.d.ts.map +1 -1
  32. package/dist/steam.js +178 -0
  33. package/dist/steam.js.map +1 -1
  34. package/dist/types.d.ts +91 -0
  35. package/dist/types.d.ts.map +1 -1
  36. package/dist/types.js +34 -0
  37. package/dist/types.js.map +1 -1
  38. package/package.json +4 -3
@@ -36,15 +36,62 @@ Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.SteamAchievementManager = void 0;
37
37
  const koffi = __importStar(require("koffi"));
38
38
  /**
39
- * Manages all Steam achievement operations
39
+ * SteamAchievementManager
40
+ *
41
+ * Manages all Steam achievement operations including:
42
+ * - Core operations (get, unlock, clear, check status)
43
+ * - Visual features (icons, progress notifications)
44
+ * - Progress tracking (get limits for progress bars)
45
+ * - Friend comparisons (see friend achievements)
46
+ * - Global statistics (unlock percentages, popularity sorting)
47
+ * - Testing tools (reset stats/achievements)
48
+ *
49
+ * @example
50
+ * ```typescript
51
+ * const achievementManager = new SteamAchievementManager(libraryLoader, apiCore);
52
+ * const achievements = await achievementManager.getAllAchievements();
53
+ * await achievementManager.unlockAchievement('ACH_WIN_ONE_GAME');
54
+ * ```
40
55
  */
41
56
  class SteamAchievementManager {
57
+ /**
58
+ * Creates a new SteamAchievementManager instance
59
+ *
60
+ * @param libraryLoader - The Steam library loader for FFI calls
61
+ * @param apiCore - The Steam API core for lifecycle management
62
+ */
42
63
  constructor(libraryLoader, apiCore) {
43
64
  this.libraryLoader = libraryLoader;
44
65
  this.apiCore = apiCore;
45
66
  }
46
67
  /**
47
68
  * Get all achievements from Steam
69
+ *
70
+ * Retrieves complete achievement data including unlock status and timestamps.
71
+ * Automatically runs Steam callbacks to ensure latest data is available.
72
+ *
73
+ * @returns Promise resolving to array of all achievements, or empty array on error
74
+ *
75
+ * @example
76
+ * ```typescript
77
+ * const achievements = await achievementManager.getAllAchievements();
78
+ * console.log(`[Steamworks] Found ${achievements.length} achievements`);
79
+ * achievements.forEach(ach => {
80
+ * console.log(`[Steamworks] ${ach.displayName}: ${ach.unlocked ? 'Unlocked' : 'Locked'}`);
81
+ * });
82
+ * ```
83
+ *
84
+ * @remarks
85
+ * - Returns empty array if Steam API is not initialized
86
+ * - Includes display name, description, unlock status, and unlock time
87
+ * - Unlock time is a Unix timestamp (seconds since epoch)
88
+ *
89
+ * Steamworks SDK Functions:
90
+ * - `SteamAPI_RunCallbacks()` - Process Steam callbacks
91
+ * - `SteamAPI_ISteamUserStats_GetNumAchievements()` - Get total achievement count
92
+ * - `SteamAPI_ISteamUserStats_GetAchievementName()` - Get achievement API name
93
+ * - `SteamAPI_ISteamUserStats_GetAchievementDisplayAttribute()` - Get display attributes
94
+ * - `SteamAPI_ISteamUserStats_GetAchievementAndUnlockTime()` - Get unlock status and time
48
95
  */
49
96
  async getAllAchievements() {
50
97
  if (!this.apiCore.isInitialized()) {
@@ -87,7 +134,7 @@ class SteamAchievementManager {
87
134
  });
88
135
  }
89
136
  catch (error) {
90
- console.warn(`Failed to get achievement ${i}:`, error.message);
137
+ console.warn(`[Steamworks] Failed to get achievement ${i}:`, error.message);
91
138
  }
92
139
  }
93
140
  return achievements;
@@ -98,7 +145,32 @@ class SteamAchievementManager {
98
145
  }
99
146
  }
100
147
  /**
101
- * Unlock achievement in Steam
148
+ * Unlock an achievement in Steam
149
+ *
150
+ * Permanently unlocks the specified achievement and syncs to Steam servers.
151
+ * Shows Steam overlay notification if enabled.
152
+ *
153
+ * @param achievementName - The API name of the achievement to unlock
154
+ * @returns Promise resolving to true if successful, false otherwise
155
+ *
156
+ * @example
157
+ * ```typescript
158
+ * const success = await achievementManager.unlockAchievement('ACH_WIN_ONE_GAME');
159
+ * if (success) {
160
+ * console.log('[Steamworks] Achievement unlocked!');
161
+ * }
162
+ * ```
163
+ *
164
+ * @remarks
165
+ * - Achievement must be configured in Steamworks Partner site
166
+ * - Changes are immediately stored to Steam servers
167
+ * - Steam overlay will show unlock notification
168
+ * - Cannot unlock already unlocked achievements (returns true)
169
+ *
170
+ * Steamworks SDK Functions:
171
+ * - `SteamAPI_ISteamUserStats_SetAchievement()` - Mark achievement as unlocked
172
+ * - `SteamAPI_ISteamUserStats_StoreStats()` - Store achievement to Steam servers
173
+ * - `SteamAPI_RunCallbacks()` - Process unlock notification
102
174
  */
103
175
  async unlockAchievement(achievementName) {
104
176
  if (!this.apiCore.isInitialized()) {
@@ -139,7 +211,32 @@ class SteamAchievementManager {
139
211
  }
140
212
  }
141
213
  /**
142
- * Clear achievement in Steam (for testing)
214
+ * Clear an achievement in Steam (for testing purposes)
215
+ *
216
+ * Removes the unlock status of an achievement. Should only be used for testing.
217
+ * Changes are immediately stored to Steam servers.
218
+ *
219
+ * @param achievementName - The API name of the achievement to clear
220
+ * @returns Promise resolving to true if successful, false otherwise
221
+ *
222
+ * @example
223
+ * ```typescript
224
+ * // Clear achievement for testing
225
+ * await achievementManager.clearAchievement('ACH_WIN_ONE_GAME');
226
+ * ```
227
+ *
228
+ * @remarks
229
+ * - Only use for testing/debugging purposes
230
+ * - Achievement must be configured in Steamworks Partner site
231
+ * - Changes are immediately stored to Steam servers
232
+ * - Cannot clear already locked achievements (returns true)
233
+ *
234
+ * @warning This permanently removes the achievement unlock from user's profile
235
+ *
236
+ * Steamworks SDK Functions:
237
+ * - `SteamAPI_ISteamUserStats_ClearAchievement()` - Mark achievement as locked
238
+ * - `SteamAPI_ISteamUserStats_StoreStats()` - Store change to Steam servers
239
+ * - `SteamAPI_RunCallbacks()` - Process the change
143
240
  */
144
241
  async clearAchievement(achievementName) {
145
242
  if (!this.apiCore.isInitialized()) {
@@ -180,7 +277,28 @@ class SteamAchievementManager {
180
277
  }
181
278
  }
182
279
  /**
183
- * Check if achievement is unlocked
280
+ * Check if an achievement is unlocked
281
+ *
282
+ * Queries Steam for the current unlock status of a specific achievement.
283
+ *
284
+ * @param achievementName - The API name of the achievement to check
285
+ * @returns Promise resolving to true if unlocked, false if locked or error
286
+ *
287
+ * @example
288
+ * ```typescript
289
+ * const isUnlocked = await achievementManager.isAchievementUnlocked('ACH_WIN_ONE_GAME');
290
+ * if (isUnlocked) {
291
+ * console.log('[Steamworks] Player has already won one game');
292
+ * }
293
+ * ```
294
+ *
295
+ * @remarks
296
+ * - Returns false if Steam API is not initialized
297
+ * - Returns false if achievement doesn't exist
298
+ * - Returns false on any error (check console for details)
299
+ *
300
+ * Steamworks SDK Functions:
301
+ * - `SteamAPI_ISteamUserStats_GetAchievement()` - Get achievement unlock status
184
302
  */
185
303
  async isAchievementUnlocked(achievementName) {
186
304
  if (!this.apiCore.isInitialized()) {
@@ -202,14 +320,52 @@ class SteamAchievementManager {
202
320
  }
203
321
  }
204
322
  /**
205
- * Get achievement by API name
323
+ * Get a specific achievement by its API name
324
+ *
325
+ * Retrieves complete data for a single achievement.
326
+ *
327
+ * @param achievementName - The API name of the achievement to retrieve
328
+ * @returns Promise resolving to achievement data, or null if not found
329
+ *
330
+ * @example
331
+ * ```typescript
332
+ * const achievement = await achievementManager.getAchievementByName('ACH_WIN_ONE_GAME');
333
+ * if (achievement) {
334
+ * console.log(`[Steamworks] ${achievement.displayName}: ${achievement.description}`);
335
+ * }
336
+ * ```
337
+ *
338
+ * @remarks
339
+ * - Calls getAllAchievements() internally, so may be slower than batch operations
340
+ * - Returns null if achievement doesn't exist
341
+ * - Returns null if Steam API is not initialized
342
+ *
343
+ * Steamworks SDK Functions:
344
+ * - Uses getAllAchievements() which calls multiple SDK functions
206
345
  */
207
346
  async getAchievementByName(achievementName) {
208
347
  const achievements = await this.getAllAchievements();
209
348
  return achievements.find(a => a.apiName === achievementName) || null;
210
349
  }
211
350
  /**
212
- * Get total number of achievements
351
+ * Get the total number of achievements configured for this game
352
+ *
353
+ * Returns the count of all achievements defined in Steamworks Partner site.
354
+ *
355
+ * @returns Promise resolving to total achievement count, or 0 on error
356
+ *
357
+ * @example
358
+ * ```typescript
359
+ * const total = await achievementManager.getTotalAchievementCount();
360
+ * console.log(`[Steamworks] This game has ${total} achievements`);
361
+ * ```
362
+ *
363
+ * @remarks
364
+ * - Returns 0 if Steam API is not initialized
365
+ * - Count includes both locked and unlocked achievements
366
+ *
367
+ * Steamworks SDK Functions:
368
+ * - `SteamAPI_ISteamUserStats_GetNumAchievements()` - Get total achievement count
213
369
  */
214
370
  async getTotalAchievementCount() {
215
371
  if (!this.apiCore.isInitialized()) {
@@ -228,16 +384,56 @@ class SteamAchievementManager {
228
384
  }
229
385
  }
230
386
  /**
231
- * Get number of unlocked achievements
387
+ * Get the number of achievements the user has unlocked
388
+ *
389
+ * Counts how many achievements the current user has unlocked.
390
+ *
391
+ * @returns Promise resolving to count of unlocked achievements
392
+ *
393
+ * @example
394
+ * ```typescript
395
+ * const total = await achievementManager.getTotalAchievementCount();
396
+ * const unlocked = await achievementManager.getUnlockedAchievementCount();
397
+ * console.log(`[Steamworks] Progress: ${unlocked}/${total} (${(unlocked/total*100).toFixed(1)}%)`);
398
+ * ```
399
+ *
400
+ * @remarks
401
+ * - Calls getAllAchievements() internally to count unlocked achievements
402
+ * - Returns 0 if Steam API is not initialized
403
+ *
404
+ * Steamworks SDK Functions:
405
+ * - Uses getAllAchievements() which calls multiple SDK functions
232
406
  */
233
407
  async getUnlockedAchievementCount() {
234
408
  const achievements = await this.getAllAchievements();
235
409
  return achievements.filter(a => a.unlocked).length;
236
410
  }
237
411
  /**
238
- * Get achievement icon handle
239
- * Returns icon handle for use with ISteamUtils::GetImageRGBA()
240
- * Returns 0 if no icon set or still loading
412
+ * Get the icon handle for an achievement
413
+ *
414
+ * Returns an icon handle that can be used with ISteamUtils::GetImageRGBA()
415
+ * to retrieve the actual icon image data.
416
+ *
417
+ * @param achievementName - The API name of the achievement
418
+ * @returns Promise resolving to icon handle (0 if no icon or still loading)
419
+ *
420
+ * @example
421
+ * ```typescript
422
+ * const iconHandle = await achievementManager.getAchievementIcon('ACH_WIN_ONE_GAME');
423
+ * if (iconHandle > 0) {
424
+ * // Use ISteamUtils::GetImageRGBA() to get actual image data
425
+ * console.log(`[Steamworks] Icon handle: ${iconHandle}`);
426
+ * }
427
+ * ```
428
+ *
429
+ * @remarks
430
+ * - Returns 0 if no icon is set for the achievement
431
+ * - Returns 0 if icon is still being fetched from Steam
432
+ * - Wait for UserAchievementIconFetched_t callback if 0 is returned
433
+ * - Icon handle is valid until Steam API shutdown
434
+ *
435
+ * Steamworks SDK Functions:
436
+ * - `SteamAPI_ISteamUserStats_GetAchievementIcon()` - Get achievement icon handle
241
437
  */
242
438
  async getAchievementIcon(achievementName) {
243
439
  if (!this.apiCore.isInitialized()) {
@@ -260,8 +456,33 @@ class SteamAchievementManager {
260
456
  }
261
457
  }
262
458
  /**
263
- * Indicate achievement progress to user
264
- * Shows a progress notification in Steam overlay
459
+ * Show achievement progress notification to user
460
+ *
461
+ * Displays a progress notification in the Steam overlay showing current/max progress.
462
+ * Useful for achievements that require multiple steps or cumulative actions.
463
+ *
464
+ * @param achievementName - The API name of the achievement
465
+ * @param currentProgress - Current progress value
466
+ * @param maxProgress - Maximum progress value needed to unlock
467
+ * @returns Promise resolving to true if successful, false otherwise
468
+ *
469
+ * @example
470
+ * ```typescript
471
+ * // Show "Win 50 games" progress: 25/50
472
+ * await achievementManager.indicateAchievementProgress('ACH_WIN_50_GAMES', 25, 50);
473
+ *
474
+ * // Update progress when player wins another game
475
+ * await achievementManager.indicateAchievementProgress('ACH_WIN_50_GAMES', 26, 50);
476
+ * ```
477
+ *
478
+ * @remarks
479
+ * - Shows notification in Steam overlay (if enabled)
480
+ * - Does NOT unlock the achievement automatically
481
+ * - Call unlockAchievement() when currentProgress >= maxProgress
482
+ * - Notification only shows if progress has changed
483
+ *
484
+ * Steamworks SDK Functions:
485
+ * - `SteamAPI_ISteamUserStats_IndicateAchievementProgress()` - Show progress notification
265
486
  */
266
487
  async indicateAchievementProgress(achievementName, currentProgress, maxProgress) {
267
488
  if (!this.apiCore.isInitialized()) {
@@ -292,7 +513,30 @@ class SteamAchievementManager {
292
513
  }
293
514
  }
294
515
  /**
295
- * Get achievement progress limits (for integer-based progress)
516
+ * Get achievement progress limits (integer-based)
517
+ *
518
+ * Retrieves the minimum and maximum progress values for an achievement that
519
+ * uses integer-based progress tracking.
520
+ *
521
+ * @param achievementName - The API name of the achievement
522
+ * @returns Promise resolving to progress limits object, or null if not configured
523
+ *
524
+ * @example
525
+ * ```typescript
526
+ * const limits = await achievementManager.getAchievementProgressLimitsInt('ACH_WIN_50_GAMES');
527
+ * if (limits) {
528
+ * console.log(`[Steamworks] Progress range: ${limits.minProgress} to ${limits.maxProgress}`);
529
+ * }
530
+ * ```
531
+ *
532
+ * @remarks
533
+ * - Returns null if achievement has no progress tracking configured
534
+ * - Use for achievements with integer progress (e.g., "Win 50 games")
535
+ * - For float-based progress, use getAchievementProgressLimitsFloat()
536
+ * - Must be configured in Steamworks Partner site
537
+ *
538
+ * Steamworks SDK Functions:
539
+ * - `SteamAPI_ISteamUserStats_GetAchievementProgressLimitsInt32()` - Get integer progress limits
296
540
  */
297
541
  async getAchievementProgressLimitsInt(achievementName) {
298
542
  if (!this.apiCore.isInitialized()) {
@@ -322,7 +566,30 @@ class SteamAchievementManager {
322
566
  }
323
567
  }
324
568
  /**
325
- * Get achievement progress limits (for float-based progress)
569
+ * Get achievement progress limits (float-based)
570
+ *
571
+ * Retrieves the minimum and maximum progress values for an achievement that
572
+ * uses floating-point progress tracking.
573
+ *
574
+ * @param achievementName - The API name of the achievement
575
+ * @returns Promise resolving to progress limits object, or null if not configured
576
+ *
577
+ * @example
578
+ * ```typescript
579
+ * const limits = await achievementManager.getAchievementProgressLimitsFloat('ACH_TRAVEL_100KM');
580
+ * if (limits) {
581
+ * console.log(`[Steamworks] Need to travel ${limits.maxProgress}km`);
582
+ * }
583
+ * ```
584
+ *
585
+ * @remarks
586
+ * - Returns null if achievement has no progress tracking configured
587
+ * - Use for achievements with decimal progress (e.g., "Travel 100.5km")
588
+ * - For integer-based progress, use getAchievementProgressLimitsInt()
589
+ * - Must be configured in Steamworks Partner site
590
+ *
591
+ * Steamworks SDK Functions:
592
+ * - `SteamAPI_ISteamUserStats_GetAchievementProgressLimitsFloat()` - Get float progress limits
326
593
  */
327
594
  async getAchievementProgressLimitsFloat(achievementName) {
328
595
  if (!this.apiCore.isInitialized()) {
@@ -352,8 +619,37 @@ class SteamAchievementManager {
352
619
  }
353
620
  }
354
621
  /**
355
- * Request stats for another user (friend)
356
- * This is async - you need to wait for the callback before calling getUserAchievement
622
+ * Request achievement stats for another user (friend)
623
+ *
624
+ * Initiates an asynchronous request to fetch achievement data for another Steam user.
625
+ * Must be called before getUserAchievement() can return data for that user.
626
+ *
627
+ * @param steamId - The Steam ID of the user (as string, e.g., "76561197960287930")
628
+ * @returns Promise resolving to true if request sent, false on error
629
+ *
630
+ * @example
631
+ * ```typescript
632
+ * const friendId = '76561197960287930';
633
+ *
634
+ * // Request friend's stats
635
+ * await achievementManager.requestUserStats(friendId);
636
+ *
637
+ * // Wait for callback and process
638
+ * await new Promise(resolve => setTimeout(resolve, 2000));
639
+ * steam.runCallbacks();
640
+ *
641
+ * // Now can get friend's achievement
642
+ * const achievement = await achievementManager.getUserAchievement(friendId, 'ACH_WIN_ONE_GAME');
643
+ * ```
644
+ *
645
+ * @remarks
646
+ * - This is an asynchronous operation - wait for callback
647
+ * - Friend must have played the game to have stats
648
+ * - Wait 1-2 seconds and call runCallbacks() before querying
649
+ * - Request times out after some period (varies)
650
+ *
651
+ * Steamworks SDK Functions:
652
+ * - `SteamAPI_ISteamUserStats_RequestUserStats()` - Request user's achievement data
357
653
  */
358
654
  async requestUserStats(steamId) {
359
655
  if (!this.apiCore.isInitialized()) {
@@ -385,7 +681,41 @@ class SteamAchievementManager {
385
681
  }
386
682
  /**
387
683
  * Get achievement status for another user (friend)
388
- * Must call requestUserStats() first and wait for callback
684
+ *
685
+ * Retrieves complete achievement data for another Steam user, including their
686
+ * unlock status and unlock time.
687
+ *
688
+ * @param steamId - The Steam ID of the user (as string)
689
+ * @param achievementName - The API name of the achievement
690
+ * @returns Promise resolving to user achievement data, or null if not available
691
+ *
692
+ * @example
693
+ * ```typescript
694
+ * // First request the user's stats
695
+ * await achievementManager.requestUserStats('76561197960287930');
696
+ * await new Promise(resolve => setTimeout(resolve, 2000));
697
+ * steam.runCallbacks();
698
+ *
699
+ * // Now get specific achievement
700
+ * const achievement = await achievementManager.getUserAchievement(
701
+ * '76561197960287930',
702
+ * 'ACH_WIN_ONE_GAME'
703
+ * );
704
+ *
705
+ * if (achievement && achievement.unlocked) {
706
+ * const date = new Date(achievement.unlockTime * 1000);
707
+ * console.log(`[Steamworks] Friend unlocked on: ${date.toLocaleDateString()}`);
708
+ * }
709
+ * ```
710
+ *
711
+ * @remarks
712
+ * - Must call requestUserStats() first and wait for callback
713
+ * - Returns null if stats not yet loaded or achievement doesn't exist
714
+ * - Friend must have played the game
715
+ * - Includes unlock time as Unix timestamp
716
+ *
717
+ * Steamworks SDK Functions:
718
+ * - `SteamAPI_ISteamUserStats_GetUserAchievementAndUnlockTime()` - Get user's achievement status
389
719
  */
390
720
  async getUserAchievement(steamId, achievementName) {
391
721
  if (!this.apiCore.isInitialized()) {
@@ -425,8 +755,36 @@ class SteamAchievementManager {
425
755
  }
426
756
  }
427
757
  /**
428
- * Request global achievement percentages
429
- * This is async - wait for callback before calling getAchievementAchievedPercent
758
+ * Request global achievement unlock percentages
759
+ *
760
+ * Initiates an asynchronous request to fetch global achievement statistics
761
+ * (what percentage of all players have unlocked each achievement).
762
+ *
763
+ * @returns Promise resolving to true if request sent, false on error
764
+ *
765
+ * @example
766
+ * ```typescript
767
+ * // Request global percentages
768
+ * await achievementManager.requestGlobalAchievementPercentages();
769
+ *
770
+ * // Wait for callback
771
+ * await new Promise(resolve => setTimeout(resolve, 2000));
772
+ * steam.runCallbacks();
773
+ *
774
+ * // Now can get percentages
775
+ * const percent = await achievementManager.getAchievementAchievedPercent('ACH_WIN_ONE_GAME');
776
+ * console.log(`[Steamworks] ${percent}% of players have unlocked this achievement`);
777
+ * ```
778
+ *
779
+ * @remarks
780
+ * - This is an asynchronous operation - wait for callback
781
+ * - Required before calling getAchievementAchievedPercent()
782
+ * - Required before calling getAllAchievementsSortedByPopularity()
783
+ * - Wait 2-3 seconds and call runCallbacks() before querying
784
+ * - Data is cached after first successful request
785
+ *
786
+ * Steamworks SDK Functions:
787
+ * - `SteamAPI_ISteamUserStats_RequestGlobalAchievementPercentages()` - Request global percentages
430
788
  */
431
789
  async requestGlobalAchievementPercentages() {
432
790
  if (!this.apiCore.isInitialized()) {
@@ -456,8 +814,33 @@ class SteamAchievementManager {
456
814
  }
457
815
  }
458
816
  /**
459
- * Get percentage of users who unlocked a specific achievement
460
- * Must call requestGlobalAchievementPercentages() first
817
+ * Get global unlock percentage for a specific achievement
818
+ *
819
+ * Returns what percentage of all players have unlocked this achievement.
820
+ *
821
+ * @param achievementName - The API name of the achievement
822
+ * @returns Promise resolving to percentage (0-100), or null if not available
823
+ *
824
+ * @example
825
+ * ```typescript
826
+ * const percent = await achievementManager.getAchievementAchievedPercent('ACH_WIN_ONE_GAME');
827
+ * if (percent !== null) {
828
+ * if (percent < 10) {
829
+ * console.log(`[Steamworks] Rare achievement! Only ${percent.toFixed(2)}% have this`);
830
+ * } else {
831
+ * console.log(`[Steamworks] Common achievement: ${percent.toFixed(2)}% unlocked`);
832
+ * }
833
+ * }
834
+ * ```
835
+ *
836
+ * @remarks
837
+ * - Must call requestGlobalAchievementPercentages() first
838
+ * - Returns null if global stats not yet loaded
839
+ * - Percentage is between 0.0 and 100.0
840
+ * - Data represents all players across all platforms
841
+ *
842
+ * Steamworks SDK Functions:
843
+ * - `SteamAPI_ISteamUserStats_GetAchievementAchievedPercent()` - Get global unlock percentage
461
844
  */
462
845
  async getAchievementAchievedPercent(achievementName) {
463
846
  if (!this.apiCore.isInitialized()) {
@@ -485,8 +868,37 @@ class SteamAchievementManager {
485
868
  }
486
869
  }
487
870
  /**
488
- * Get all achievements with global unlock percentages
489
- * Must call requestGlobalAchievementPercentages() first and wait for callback
871
+ * Get all achievements with their global unlock percentages
872
+ *
873
+ * Combines achievement data with global statistics to show what percentage
874
+ * of players have unlocked each achievement.
875
+ *
876
+ * @returns Promise resolving to array of achievements with global stats
877
+ *
878
+ * @example
879
+ * ```typescript
880
+ * // Request global data first
881
+ * await achievementManager.requestGlobalAchievementPercentages();
882
+ * await new Promise(resolve => setTimeout(resolve, 2000));
883
+ * steam.runCallbacks();
884
+ *
885
+ * // Get all achievements with percentages
886
+ * const achievements = await achievementManager.getAllAchievementsWithGlobalStats();
887
+ *
888
+ * // Find rarest achievement
889
+ * const rarest = achievements.reduce((prev, curr) =>
890
+ * curr.globalUnlockPercentage < prev.globalUnlockPercentage ? curr : prev
891
+ * );
892
+ * console.log(`[Steamworks] Rarest: ${rarest.displayName} (${rarest.globalUnlockPercentage.toFixed(2)}%)`);
893
+ * ```
894
+ *
895
+ * @remarks
896
+ * - Must call requestGlobalAchievementPercentages() first
897
+ * - Iterates through all achievements to fetch percentages
898
+ * - May return 0% for achievements where data is unavailable
899
+ *
900
+ * Steamworks SDK Functions:
901
+ * - Uses getAllAchievements() and getAchievementAchievedPercent()
490
902
  */
491
903
  async getAllAchievementsWithGlobalStats() {
492
904
  const achievements = await this.getAllAchievements();
@@ -504,8 +916,31 @@ class SteamAchievementManager {
504
916
  return result;
505
917
  }
506
918
  /**
507
- * Get most achieved achievement info
508
- * Returns iterator for use with getNextMostAchievedAchievementInfo
919
+ * Get the most achieved achievement
920
+ *
921
+ * Returns the achievement with the highest global unlock percentage.
922
+ * Provides an iterator for use with getNextMostAchievedAchievementInfo().
923
+ *
924
+ * @returns Promise resolving to most achieved achievement data with iterator, or null
925
+ *
926
+ * @example
927
+ * ```typescript
928
+ * const mostAchieved = await achievementManager.getMostAchievedAchievementInfo();
929
+ * if (mostAchieved) {
930
+ * console.log(`[Steamworks] Most achieved: ${mostAchieved.apiName}`);
931
+ * console.log(`[Steamworks] Unlocked by: ${mostAchieved.percent.toFixed(2)}% of players`);
932
+ * console.log(`[Steamworks] You ${mostAchieved.unlocked ? 'have' : 'don\'t have'} it`);
933
+ * }
934
+ * ```
935
+ *
936
+ * @remarks
937
+ * - Must call requestGlobalAchievementPercentages() first
938
+ * - Returns -1 iterator if no data available
939
+ * - Use iterator with getNextMostAchievedAchievementInfo() to iterate
940
+ * - Ordered by highest percentage first
941
+ *
942
+ * Steamworks SDK Functions:
943
+ * - `SteamAPI_ISteamUserStats_GetMostAchievedAchievementInfo()` - Get most achieved achievement
509
944
  */
510
945
  async getMostAchievedAchievementInfo() {
511
946
  if (!this.apiCore.isInitialized()) {
@@ -536,7 +971,43 @@ class SteamAchievementManager {
536
971
  }
537
972
  }
538
973
  /**
539
- * Get next most achieved achievement info (iterate by popularity)
974
+ * Get the next most achieved achievement (iterate by popularity)
975
+ *
976
+ * Continues iteration through achievements ordered by global unlock percentage.
977
+ * Use the iterator from getMostAchievedAchievementInfo() or previous call.
978
+ *
979
+ * @param previousIterator - Iterator from previous call
980
+ * @returns Promise resolving to next achievement data with iterator, or null if end
981
+ *
982
+ * @example
983
+ * ```typescript
984
+ * // Get top 5 most achieved achievements
985
+ * const top5 = [];
986
+ * let current = await achievementManager.getMostAchievedAchievementInfo();
987
+ *
988
+ * if (current) {
989
+ * top5.push(current);
990
+ *
991
+ * for (let i = 0; i < 4; i++) {
992
+ * const next = await achievementManager.getNextMostAchievedAchievementInfo(current.iterator);
993
+ * if (!next) break;
994
+ * top5.push(next);
995
+ * current = next;
996
+ * }
997
+ * }
998
+ *
999
+ * top5.forEach((ach, i) => {
1000
+ * console.log(`[Steamworks] ${i + 1}. ${ach.apiName}: ${ach.percent.toFixed(2)}%`);
1001
+ * });
1002
+ * ```
1003
+ *
1004
+ * @remarks
1005
+ * - Must call requestGlobalAchievementPercentages() first
1006
+ * - Returns null when iteration is complete (iterator === -1)
1007
+ * - Achievements ordered from highest to lowest percentage
1008
+ *
1009
+ * Steamworks SDK Functions:
1010
+ * - `SteamAPI_ISteamUserStats_GetNextMostAchievedAchievementInfo()` - Get next achievement by popularity
540
1011
  */
541
1012
  async getNextMostAchievedAchievementInfo(previousIterator) {
542
1013
  if (!this.apiCore.isInitialized()) {
@@ -567,8 +1038,42 @@ class SteamAchievementManager {
567
1038
  }
568
1039
  }
569
1040
  /**
570
- * Get all achievements sorted by global unlock percentage (most achieved first)
571
- * Must call requestGlobalAchievementPercentages() first
1041
+ * Get all achievements sorted by global unlock percentage
1042
+ *
1043
+ * Returns complete achievement list ordered from most to least achieved.
1044
+ * Includes full achievement details with global unlock percentages.
1045
+ *
1046
+ * @returns Promise resolving to sorted array of achievements with global stats
1047
+ *
1048
+ * @example
1049
+ * ```typescript
1050
+ * // Request global data
1051
+ * await achievementManager.requestGlobalAchievementPercentages();
1052
+ * await new Promise(resolve => setTimeout(resolve, 2000));
1053
+ * steam.runCallbacks();
1054
+ *
1055
+ * // Get sorted achievements
1056
+ * const sorted = await achievementManager.getAllAchievementsSortedByPopularity();
1057
+ *
1058
+ * console.log('[Steamworks] Most to Least Achieved:');
1059
+ * sorted.forEach((ach, i) => {
1060
+ * console.log(`[Steamworks] ${i + 1}. ${ach.displayName}: ${ach.globalUnlockPercentage.toFixed(2)}%`);
1061
+ * });
1062
+ *
1063
+ * // Find rarest achievements
1064
+ * const rare = sorted.filter(a => a.globalUnlockPercentage < 5);
1065
+ * console.log(`[Steamworks] ${rare.length} rare achievements (< 5% unlock rate)`);
1066
+ * ```
1067
+ *
1068
+ * @remarks
1069
+ * - Must call requestGlobalAchievementPercentages() first
1070
+ * - Returns empty array if no global data available
1071
+ * - Sorted from highest to lowest percentage
1072
+ * - Includes display names and descriptions
1073
+ *
1074
+ * Steamworks SDK Functions:
1075
+ * - Uses getMostAchievedAchievementInfo() and getNextMostAchievedAchievementInfo()
1076
+ * - `SteamAPI_ISteamUserStats_GetAchievementDisplayAttribute()` - Get display attributes
572
1077
  */
573
1078
  async getAllAchievementsSortedByPopularity() {
574
1079
  const results = [];
@@ -613,8 +1118,41 @@ class SteamAchievementManager {
613
1118
  return results;
614
1119
  }
615
1120
  /**
616
- * Reset all stats and optionally achievements
617
- * WARNING: This clears ALL user stats and achievements!
1121
+ * Reset all user stats and optionally achievements
1122
+ *
1123
+ * Permanently clears all statistics and optionally all achievements for the current user.
1124
+ * Changes are immediately stored to Steam servers.
1125
+ *
1126
+ * @param includeAchievements - If true, also clears all achievements (default: false)
1127
+ * @returns Promise resolving to true if successful, false otherwise
1128
+ *
1129
+ * @example
1130
+ * ```typescript
1131
+ * // Reset only stats, keep achievements
1132
+ * await achievementManager.resetAllStats(false);
1133
+ *
1134
+ * // Reset everything including achievements
1135
+ * await achievementManager.resetAllStats(true);
1136
+ * ```
1137
+ *
1138
+ * @warning
1139
+ * **THIS PERMANENTLY DELETES USER DATA!**
1140
+ * - All stats are set to 0
1141
+ * - If includeAchievements=true, all achievements are locked
1142
+ * - Changes are immediately synced to Steam servers
1143
+ * - Cannot be undone
1144
+ * - Only use for testing/debugging
1145
+ *
1146
+ * @remarks
1147
+ * - Use with extreme caution - this affects user's permanent record
1148
+ * - Recommended only for development/testing accounts
1149
+ * - Does not affect other users or global statistics
1150
+ * - Changes visible immediately in Steam overlay
1151
+ *
1152
+ * Steamworks SDK Functions:
1153
+ * - `SteamAPI_ISteamUserStats_ResetAllStats()` - Reset all stats and optionally achievements
1154
+ * - `SteamAPI_ISteamUserStats_StoreStats()` - Store reset to Steam servers
1155
+ * - `SteamAPI_RunCallbacks()` - Process the reset operation
618
1156
  */
619
1157
  async resetAllStats(includeAchievements = false) {
620
1158
  if (!this.apiCore.isInitialized()) {
@@ -654,7 +1192,38 @@ class SteamAchievementManager {
654
1192
  }
655
1193
  }
656
1194
  /**
657
- * Get all achievements with icon handles
1195
+ * Get all achievements with their icon handles
1196
+ *
1197
+ * Returns complete achievement list with icon handles that can be used
1198
+ * to retrieve actual icon image data via ISteamUtils::GetImageRGBA().
1199
+ *
1200
+ * @returns Promise resolving to array of achievements with icon handles
1201
+ *
1202
+ * @example
1203
+ * ```typescript
1204
+ * const achievements = await achievementManager.getAllAchievementsWithIcons();
1205
+ *
1206
+ * achievements.forEach(ach => {
1207
+ * console.log(`[Steamworks] ${ach.displayName}:`);
1208
+ * console.log(`[Steamworks] Status: ${ach.unlocked ? 'Unlocked' : 'Locked'}`);
1209
+ * console.log(`[Steamworks] Icon Handle: ${ach.iconHandle}`);
1210
+ *
1211
+ * if (ach.iconHandle > 0) {
1212
+ * // Use ISteamUtils::GetImageRGBA() to get actual image
1213
+ * // const imageData = steamUtils.getImageRGBA(ach.iconHandle);
1214
+ * }
1215
+ * });
1216
+ * ```
1217
+ *
1218
+ * @remarks
1219
+ * - Icon handle of 0 means no icon or still loading
1220
+ * - Icon handles are valid until Steam API shutdown
1221
+ * - Use ISteamUtils interface to convert handles to image data
1222
+ * - May trigger icon fetching if not yet cached
1223
+ *
1224
+ * Steamworks SDK Functions:
1225
+ * - Uses getAllAchievements() and getAchievementIcon()
1226
+ * - `SteamAPI_ISteamUserStats_GetAchievementIcon()` - Get icon handle for each achievement
658
1227
  */
659
1228
  async getAllAchievementsWithIcons() {
660
1229
  const achievements = await this.getAllAchievements();