steamworks-ffi-node 0.3.0 → 0.3.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/README.md +54 -10
- package/dist/internal/SteamAPICore.d.ts +198 -8
- package/dist/internal/SteamAPICore.d.ts.map +1 -1
- package/dist/internal/SteamAPICore.js +197 -8
- package/dist/internal/SteamAPICore.js.map +1 -1
- package/dist/internal/SteamAchievementManager.d.ts +602 -31
- package/dist/internal/SteamAchievementManager.d.ts.map +1 -1
- package/dist/internal/SteamAchievementManager.js +600 -31
- package/dist/internal/SteamAchievementManager.js.map +1 -1
- package/dist/internal/SteamLibraryLoader.d.ts.map +1 -1
- package/dist/internal/SteamLibraryLoader.js +16 -5
- package/dist/internal/SteamLibraryLoader.js.map +1 -1
- package/dist/internal/SteamStatsManager.d.ts +337 -42
- package/dist/internal/SteamStatsManager.d.ts.map +1 -1
- package/dist/internal/SteamStatsManager.js +335 -42
- package/dist/internal/SteamStatsManager.js.map +1 -1
- package/dist/steam.d.ts.map +1 -1
- package/dist/steam.js.map +1 -1
- package/package.json +1 -1
|
@@ -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
|
-
*
|
|
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(`Found ${achievements.length} achievements`);
|
|
79
|
+
* achievements.forEach(ach => {
|
|
80
|
+
* console.log(`${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()) {
|
|
@@ -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('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('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(`${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(`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
|
|
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(`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
|
|
239
|
-
*
|
|
240
|
-
* Returns
|
|
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(`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
|
-
*
|
|
264
|
-
*
|
|
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 (
|
|
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(`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 (
|
|
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(`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
|
-
*
|
|
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
|
-
*
|
|
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(`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
|
-
*
|
|
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(`${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
|
|
460
|
-
*
|
|
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(`Rare achievement! Only ${percent.toFixed(2)}% have this`);
|
|
830
|
+
* } else {
|
|
831
|
+
* console.log(`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
|
-
*
|
|
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(`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
|
|
508
|
-
*
|
|
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(`Most achieved: ${mostAchieved.apiName}`);
|
|
931
|
+
* console.log(`Unlocked by: ${mostAchieved.percent.toFixed(2)}% of players`);
|
|
932
|
+
* console.log(`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
|
|
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(`${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
|
|
571
|
-
*
|
|
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('Most to Least Achieved:');
|
|
1059
|
+
* sorted.forEach((ach, i) => {
|
|
1060
|
+
* console.log(`${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(`${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
|
-
*
|
|
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(`${ach.displayName}:`);
|
|
1208
|
+
* console.log(` Status: ${ach.unlocked ? 'Unlocked' : 'Locked'}`);
|
|
1209
|
+
* console.log(` 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();
|