steamworks-ffi-node 0.3.1 → 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.
- package/README.md +32 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/dist/internal/SteamAPICore.d.ts +32 -9
- package/dist/internal/SteamAPICore.d.ts.map +1 -1
- package/dist/internal/SteamAPICore.js +46 -15
- package/dist/internal/SteamAPICore.js.map +1 -1
- package/dist/internal/SteamAchievementManager.d.ts +25 -25
- package/dist/internal/SteamAchievementManager.js +26 -26
- package/dist/internal/SteamAchievementManager.js.map +1 -1
- package/dist/internal/SteamCallbackPoller.d.ts +68 -0
- package/dist/internal/SteamCallbackPoller.d.ts.map +1 -0
- package/dist/internal/SteamCallbackPoller.js +134 -0
- package/dist/internal/SteamCallbackPoller.js.map +1 -0
- package/dist/internal/SteamLeaderboardManager.d.ts +338 -0
- package/dist/internal/SteamLeaderboardManager.d.ts.map +1 -0
- package/dist/internal/SteamLeaderboardManager.js +734 -0
- package/dist/internal/SteamLeaderboardManager.js.map +1 -0
- package/dist/internal/SteamLibraryLoader.d.ts +15 -0
- package/dist/internal/SteamLibraryLoader.d.ts.map +1 -1
- package/dist/internal/SteamLibraryLoader.js +26 -0
- package/dist/internal/SteamLibraryLoader.js.map +1 -1
- package/dist/internal/SteamStatsManager.d.ts +57 -45
- package/dist/internal/SteamStatsManager.d.ts.map +1 -1
- package/dist/internal/SteamStatsManager.js +146 -101
- package/dist/internal/SteamStatsManager.js.map +1 -1
- package/dist/steam.d.ts +169 -9
- package/dist/steam.d.ts.map +1 -1
- package/dist/steam.js +178 -0
- package/dist/steam.js.map +1 -1
- package/dist/types.d.ts +91 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +34 -0
- package/dist/types.js.map +1 -1
- package/package.json +4 -3
|
@@ -82,13 +82,14 @@ class SteamStatsManager {
|
|
|
82
82
|
* that track player progress and can be used for leaderboards and analytics.
|
|
83
83
|
*
|
|
84
84
|
* @param statName - Name of the stat to retrieve (as defined in Steamworks Partner site)
|
|
85
|
-
* @returns
|
|
85
|
+
* @returns SteamStat object with name, value, and type, or null if not found or on error
|
|
86
86
|
*
|
|
87
87
|
* @example
|
|
88
88
|
* ```typescript
|
|
89
|
-
* const
|
|
90
|
-
* if (
|
|
91
|
-
* console.log(`
|
|
89
|
+
* const killsStat = await statsManager.getStatInt('total_kills');
|
|
90
|
+
* if (killsStat) {
|
|
91
|
+
* console.log(`[Steamworks] ${killsStat.name}: ${killsStat.value}`);
|
|
92
|
+
* // Access value directly: killsStat.value
|
|
92
93
|
* }
|
|
93
94
|
* ```
|
|
94
95
|
*
|
|
@@ -96,13 +97,14 @@ class SteamStatsManager {
|
|
|
96
97
|
* - Returns null if Steam API is not initialized
|
|
97
98
|
* - Stat names are case-sensitive and must match Steamworks configuration
|
|
98
99
|
* - Use getStatFloat() for decimal values
|
|
100
|
+
* - Returns structured SteamStat object with full metadata
|
|
99
101
|
*
|
|
100
102
|
* Steamworks SDK Functions:
|
|
101
103
|
* - `SteamAPI_ISteamUserStats_GetStatInt32()` - Get int32 stat value
|
|
102
104
|
*/
|
|
103
105
|
async getStatInt(statName) {
|
|
104
106
|
if (!this.apiCore.isInitialized()) {
|
|
105
|
-
console.warn('
|
|
107
|
+
console.warn('[Steamworks] Steam API not initialized');
|
|
106
108
|
return null;
|
|
107
109
|
}
|
|
108
110
|
try {
|
|
@@ -111,16 +113,20 @@ class SteamStatsManager {
|
|
|
111
113
|
const success = this.libraryLoader.SteamAPI_ISteamUserStats_GetStatInt32(userStatsInterface, statName, valueOut);
|
|
112
114
|
if (success) {
|
|
113
115
|
const value = koffi.decode(valueOut, 'int32');
|
|
114
|
-
console.log(
|
|
115
|
-
return
|
|
116
|
+
console.log(`[Steamworks] Got stat "${statName}": ${value}`);
|
|
117
|
+
return {
|
|
118
|
+
name: statName,
|
|
119
|
+
value,
|
|
120
|
+
type: 'int'
|
|
121
|
+
};
|
|
116
122
|
}
|
|
117
123
|
else {
|
|
118
|
-
console.warn(
|
|
124
|
+
console.warn(`[Steamworks] Failed to get stat: ${statName}`);
|
|
119
125
|
return null;
|
|
120
126
|
}
|
|
121
127
|
}
|
|
122
128
|
catch (error) {
|
|
123
|
-
console.error(
|
|
129
|
+
console.error(`[Steamworks] Error getting stat "${statName}":`, error.message);
|
|
124
130
|
return null;
|
|
125
131
|
}
|
|
126
132
|
}
|
|
@@ -131,26 +137,27 @@ class SteamStatsManager {
|
|
|
131
137
|
* require decimal precision (e.g., average accuracy, distance traveled).
|
|
132
138
|
*
|
|
133
139
|
* @param statName - Name of the stat to retrieve (as defined in Steamworks Partner site)
|
|
134
|
-
* @returns
|
|
140
|
+
* @returns SteamStat object with name, value, and type, or null if not found or on error
|
|
135
141
|
*
|
|
136
142
|
* @example
|
|
137
143
|
* ```typescript
|
|
138
|
-
* const
|
|
139
|
-
* if (
|
|
140
|
-
* console.log(`
|
|
144
|
+
* const accuracyStat = await statsManager.getStatFloat('shooting_accuracy');
|
|
145
|
+
* if (accuracyStat) {
|
|
146
|
+
* console.log(`[Steamworks] ${accuracyStat.name}: ${(accuracyStat.value * 100).toFixed(2)}%`);
|
|
141
147
|
* }
|
|
142
148
|
* ```
|
|
143
149
|
*
|
|
144
150
|
* @remarks
|
|
145
151
|
* - Returns null if Steam API is not initialized
|
|
146
152
|
* - Use getStatInt() for whole number values
|
|
153
|
+
* - Returns structured SteamStat object with full metadata
|
|
147
154
|
*
|
|
148
155
|
* Steamworks SDK Functions:
|
|
149
156
|
* - `SteamAPI_ISteamUserStats_GetStatFloat()` - Get float stat value
|
|
150
157
|
*/
|
|
151
158
|
async getStatFloat(statName) {
|
|
152
159
|
if (!this.apiCore.isInitialized()) {
|
|
153
|
-
console.warn('
|
|
160
|
+
console.warn('[Steamworks] Steam API not initialized');
|
|
154
161
|
return null;
|
|
155
162
|
}
|
|
156
163
|
try {
|
|
@@ -159,16 +166,20 @@ class SteamStatsManager {
|
|
|
159
166
|
const success = this.libraryLoader.SteamAPI_ISteamUserStats_GetStatFloat(userStatsInterface, statName, valueOut);
|
|
160
167
|
if (success) {
|
|
161
168
|
const value = koffi.decode(valueOut, 'float');
|
|
162
|
-
console.log(
|
|
163
|
-
return
|
|
169
|
+
console.log(`[Steamworks] Got stat "${statName}": ${value}`);
|
|
170
|
+
return {
|
|
171
|
+
name: statName,
|
|
172
|
+
value,
|
|
173
|
+
type: 'float'
|
|
174
|
+
};
|
|
164
175
|
}
|
|
165
176
|
else {
|
|
166
|
-
console.warn(
|
|
177
|
+
console.warn(`[Steamworks] Failed to get stat: ${statName}`);
|
|
167
178
|
return null;
|
|
168
179
|
}
|
|
169
180
|
}
|
|
170
181
|
catch (error) {
|
|
171
|
-
console.error(
|
|
182
|
+
console.error(`[Steamworks] Error getting stat "${statName}":`, error.message);
|
|
172
183
|
return null;
|
|
173
184
|
}
|
|
174
185
|
}
|
|
@@ -188,7 +199,7 @@ class SteamStatsManager {
|
|
|
188
199
|
* const currentKills = await statsManager.getStatInt('total_kills') || 0;
|
|
189
200
|
* const success = await statsManager.setStatInt('total_kills', currentKills + 1);
|
|
190
201
|
* if (success) {
|
|
191
|
-
* console.log('Kill count updated!');
|
|
202
|
+
* console.log('[Steamworks] Kill count updated!');
|
|
192
203
|
* }
|
|
193
204
|
* ```
|
|
194
205
|
*
|
|
@@ -205,7 +216,7 @@ class SteamStatsManager {
|
|
|
205
216
|
*/
|
|
206
217
|
async setStatInt(statName, value) {
|
|
207
218
|
if (!this.apiCore.isInitialized()) {
|
|
208
|
-
console.warn('
|
|
219
|
+
console.warn('[Steamworks] Steam API not initialized');
|
|
209
220
|
return false;
|
|
210
221
|
}
|
|
211
222
|
try {
|
|
@@ -215,23 +226,23 @@ class SteamStatsManager {
|
|
|
215
226
|
// Store the stats to Steam servers
|
|
216
227
|
const stored = this.libraryLoader.SteamAPI_ISteamUserStats_StoreStats(userStatsInterface);
|
|
217
228
|
if (stored) {
|
|
218
|
-
console.log(
|
|
229
|
+
console.log(`[Steamworks] Set stat "${statName}" to ${value}`);
|
|
219
230
|
// Process callbacks
|
|
220
231
|
this.libraryLoader.SteamAPI_RunCallbacks();
|
|
221
232
|
return true;
|
|
222
233
|
}
|
|
223
234
|
else {
|
|
224
|
-
console.warn(
|
|
235
|
+
console.warn(`[Steamworks] Failed to store stat: ${statName}`);
|
|
225
236
|
return false;
|
|
226
237
|
}
|
|
227
238
|
}
|
|
228
239
|
else {
|
|
229
|
-
console.warn(
|
|
240
|
+
console.warn(`[Steamworks] Failed to set stat: ${statName}`);
|
|
230
241
|
return false;
|
|
231
242
|
}
|
|
232
243
|
}
|
|
233
244
|
catch (error) {
|
|
234
|
-
console.error(
|
|
245
|
+
console.error(`[Steamworks] Error setting stat "${statName}":`, error.message);
|
|
235
246
|
return false;
|
|
236
247
|
}
|
|
237
248
|
}
|
|
@@ -266,7 +277,7 @@ class SteamStatsManager {
|
|
|
266
277
|
*/
|
|
267
278
|
async setStatFloat(statName, value) {
|
|
268
279
|
if (!this.apiCore.isInitialized()) {
|
|
269
|
-
console.warn('
|
|
280
|
+
console.warn('[Steamworks] Steam API not initialized');
|
|
270
281
|
return false;
|
|
271
282
|
}
|
|
272
283
|
try {
|
|
@@ -276,23 +287,23 @@ class SteamStatsManager {
|
|
|
276
287
|
// Store the stats to Steam servers
|
|
277
288
|
const stored = this.libraryLoader.SteamAPI_ISteamUserStats_StoreStats(userStatsInterface);
|
|
278
289
|
if (stored) {
|
|
279
|
-
console.log(
|
|
290
|
+
console.log(`[Steamworks] Set stat "${statName}" to ${value}`);
|
|
280
291
|
// Process callbacks
|
|
281
292
|
this.libraryLoader.SteamAPI_RunCallbacks();
|
|
282
293
|
return true;
|
|
283
294
|
}
|
|
284
295
|
else {
|
|
285
|
-
console.warn(
|
|
296
|
+
console.warn(`[Steamworks] Failed to store stat: ${statName}`);
|
|
286
297
|
return false;
|
|
287
298
|
}
|
|
288
299
|
}
|
|
289
300
|
else {
|
|
290
|
-
console.warn(
|
|
301
|
+
console.warn(`[Steamworks] Failed to set stat: ${statName}`);
|
|
291
302
|
return false;
|
|
292
303
|
}
|
|
293
304
|
}
|
|
294
305
|
catch (error) {
|
|
295
|
-
console.error(
|
|
306
|
+
console.error(`[Steamworks] Error setting stat "${statName}":`, error.message);
|
|
296
307
|
return false;
|
|
297
308
|
}
|
|
298
309
|
}
|
|
@@ -329,7 +340,7 @@ class SteamStatsManager {
|
|
|
329
340
|
*/
|
|
330
341
|
async updateAvgRateStat(statName, countThisSession, sessionLength) {
|
|
331
342
|
if (!this.apiCore.isInitialized()) {
|
|
332
|
-
console.warn('
|
|
343
|
+
console.warn('[Steamworks] Steam API not initialized');
|
|
333
344
|
return false;
|
|
334
345
|
}
|
|
335
346
|
try {
|
|
@@ -339,23 +350,23 @@ class SteamStatsManager {
|
|
|
339
350
|
// Store the stats to Steam servers
|
|
340
351
|
const stored = this.libraryLoader.SteamAPI_ISteamUserStats_StoreStats(userStatsInterface);
|
|
341
352
|
if (stored) {
|
|
342
|
-
console.log(
|
|
353
|
+
console.log(`[Steamworks] Updated avg rate stat "${statName}": ${countThisSession} over ${sessionLength}s`);
|
|
343
354
|
// Process callbacks
|
|
344
355
|
this.libraryLoader.SteamAPI_RunCallbacks();
|
|
345
356
|
return true;
|
|
346
357
|
}
|
|
347
358
|
else {
|
|
348
|
-
console.warn(
|
|
359
|
+
console.warn(`[Steamworks] Failed to store stat: ${statName}`);
|
|
349
360
|
return false;
|
|
350
361
|
}
|
|
351
362
|
}
|
|
352
363
|
else {
|
|
353
|
-
console.warn(
|
|
364
|
+
console.warn(`[Steamworks] Failed to update avg rate stat: ${statName}`);
|
|
354
365
|
return false;
|
|
355
366
|
}
|
|
356
367
|
}
|
|
357
368
|
catch (error) {
|
|
358
|
-
console.error(
|
|
369
|
+
console.error(`[Steamworks] Error updating avg rate stat "${statName}":`, error.message);
|
|
359
370
|
return false;
|
|
360
371
|
}
|
|
361
372
|
}
|
|
@@ -384,7 +395,7 @@ class SteamStatsManager {
|
|
|
384
395
|
*
|
|
385
396
|
* // Now get the friend's stats
|
|
386
397
|
* const friendKills = await statsManager.getUserStatInt(friendSteamId, 'total_kills');
|
|
387
|
-
* console.log(`Friend has ${friendKills} kills`);
|
|
398
|
+
* console.log(`[Steamworks] Friend has ${friendKills} kills`);
|
|
388
399
|
* }
|
|
389
400
|
* ```
|
|
390
401
|
*
|
|
@@ -399,7 +410,7 @@ class SteamStatsManager {
|
|
|
399
410
|
*/
|
|
400
411
|
async requestUserStats(steamId) {
|
|
401
412
|
if (!this.apiCore.isInitialized()) {
|
|
402
|
-
console.warn('
|
|
413
|
+
console.warn('[Steamworks] Steam API not initialized');
|
|
403
414
|
return false;
|
|
404
415
|
}
|
|
405
416
|
try {
|
|
@@ -407,16 +418,16 @@ class SteamStatsManager {
|
|
|
407
418
|
const steamIdBigInt = typeof steamId === 'string' ? BigInt(steamId) : steamId;
|
|
408
419
|
const callHandle = this.libraryLoader.SteamAPI_ISteamUserStats_RequestUserStats(userStatsInterface, steamIdBigInt);
|
|
409
420
|
if (callHandle !== BigInt(0)) {
|
|
410
|
-
console.log(
|
|
421
|
+
console.log(`[Steamworks] Requested stats for user: ${steamId}`);
|
|
411
422
|
return true;
|
|
412
423
|
}
|
|
413
424
|
else {
|
|
414
|
-
console.warn(
|
|
425
|
+
console.warn(`[Steamworks] Failed to request user stats: ${steamId}`);
|
|
415
426
|
return false;
|
|
416
427
|
}
|
|
417
428
|
}
|
|
418
429
|
catch (error) {
|
|
419
|
-
console.error(
|
|
430
|
+
console.error(`[Steamworks] Error requesting user stats:`, error.message);
|
|
420
431
|
return false;
|
|
421
432
|
}
|
|
422
433
|
}
|
|
@@ -428,7 +439,7 @@ class SteamStatsManager {
|
|
|
428
439
|
*
|
|
429
440
|
* @param steamId - Steam ID of the user
|
|
430
441
|
* @param statName - Name of the stat to retrieve
|
|
431
|
-
* @returns
|
|
442
|
+
* @returns UserStat object with steamId, name, value, and type, or null if not found or on error
|
|
432
443
|
*
|
|
433
444
|
* @example
|
|
434
445
|
* ```typescript
|
|
@@ -437,23 +448,26 @@ class SteamStatsManager {
|
|
|
437
448
|
* await statsManager.requestUserStats(friendId);
|
|
438
449
|
* await new Promise(resolve => setTimeout(resolve, 100));
|
|
439
450
|
*
|
|
440
|
-
* const
|
|
441
|
-
* const
|
|
451
|
+
* const myStat = await statsManager.getStatInt('total_kills');
|
|
452
|
+
* const friendStat = await statsManager.getUserStatInt(friendId, 'total_kills');
|
|
442
453
|
*
|
|
443
|
-
*
|
|
454
|
+
* if (myStat && friendStat) {
|
|
455
|
+
* console.log(`[Steamworks] You: ${myStat.value}, Friend: ${friendStat.value}`);
|
|
456
|
+
* }
|
|
444
457
|
* ```
|
|
445
458
|
*
|
|
446
459
|
* @remarks
|
|
447
460
|
* - Must call requestUserStats() first
|
|
448
461
|
* - Wait 50-100ms after requesting before calling this
|
|
449
462
|
* - Returns null if stats haven't arrived yet or user's stats are private
|
|
463
|
+
* - Returns structured UserStat object with full metadata including steamId
|
|
450
464
|
*
|
|
451
465
|
* Steamworks SDK Functions:
|
|
452
466
|
* - `SteamAPI_ISteamUserStats_GetUserStatInt32()` - Get user's int32 stat value
|
|
453
467
|
*/
|
|
454
468
|
async getUserStatInt(steamId, statName) {
|
|
455
469
|
if (!this.apiCore.isInitialized()) {
|
|
456
|
-
console.warn('
|
|
470
|
+
console.warn('[Steamworks] Steam API not initialized');
|
|
457
471
|
return null;
|
|
458
472
|
}
|
|
459
473
|
try {
|
|
@@ -463,16 +477,21 @@ class SteamStatsManager {
|
|
|
463
477
|
const success = this.libraryLoader.SteamAPI_ISteamUserStats_GetUserStatInt32(userStatsInterface, steamIdBigInt, statName, valueOut);
|
|
464
478
|
if (success) {
|
|
465
479
|
const value = koffi.decode(valueOut, 'int32');
|
|
466
|
-
console.log(
|
|
467
|
-
return
|
|
480
|
+
console.log(`[Steamworks] Got user stat "${statName}" for ${steamId}: ${value}`);
|
|
481
|
+
return {
|
|
482
|
+
steamId: typeof steamId === 'string' ? steamId : steamId.toString(),
|
|
483
|
+
name: statName,
|
|
484
|
+
value,
|
|
485
|
+
type: 'int'
|
|
486
|
+
};
|
|
468
487
|
}
|
|
469
488
|
else {
|
|
470
|
-
console.warn(
|
|
489
|
+
console.warn(`[Steamworks] Failed to get user stat: ${statName}`);
|
|
471
490
|
return null;
|
|
472
491
|
}
|
|
473
492
|
}
|
|
474
493
|
catch (error) {
|
|
475
|
-
console.error(
|
|
494
|
+
console.error(`[Steamworks] Error getting user stat "${statName}":`, error.message);
|
|
476
495
|
return null;
|
|
477
496
|
}
|
|
478
497
|
}
|
|
@@ -484,7 +503,7 @@ class SteamStatsManager {
|
|
|
484
503
|
*
|
|
485
504
|
* @param steamId - Steam ID of the user
|
|
486
505
|
* @param statName - Name of the stat to retrieve
|
|
487
|
-
* @returns
|
|
506
|
+
* @returns UserStat object with steamId, name, value, and type, or null if not found or on error
|
|
488
507
|
*
|
|
489
508
|
* @example
|
|
490
509
|
* ```typescript
|
|
@@ -493,9 +512,9 @@ class SteamStatsManager {
|
|
|
493
512
|
* await statsManager.requestUserStats(friendId);
|
|
494
513
|
* await new Promise(resolve => setTimeout(resolve, 100));
|
|
495
514
|
*
|
|
496
|
-
* const
|
|
497
|
-
* if (
|
|
498
|
-
* console.log(`Friend accuracy: ${(
|
|
515
|
+
* const friendStat = await statsManager.getUserStatFloat(friendId, 'shooting_accuracy');
|
|
516
|
+
* if (friendStat) {
|
|
517
|
+
* console.log(`[Steamworks] Friend accuracy: ${(friendStat.value * 100).toFixed(2)}%`);
|
|
499
518
|
* }
|
|
500
519
|
* ```
|
|
501
520
|
*
|
|
@@ -503,13 +522,14 @@ class SteamStatsManager {
|
|
|
503
522
|
* - Must call requestUserStats() first
|
|
504
523
|
* - Wait 50-100ms after requesting before calling this
|
|
505
524
|
* - Returns null if stats haven't arrived yet or user's stats are private
|
|
525
|
+
* - Returns structured UserStat object with full metadata including steamId
|
|
506
526
|
*
|
|
507
527
|
* Steamworks SDK Functions:
|
|
508
528
|
* - `SteamAPI_ISteamUserStats_GetUserStatFloat()` - Get user's float stat value
|
|
509
529
|
*/
|
|
510
530
|
async getUserStatFloat(steamId, statName) {
|
|
511
531
|
if (!this.apiCore.isInitialized()) {
|
|
512
|
-
console.warn('
|
|
532
|
+
console.warn('[Steamworks] Steam API not initialized');
|
|
513
533
|
return null;
|
|
514
534
|
}
|
|
515
535
|
try {
|
|
@@ -519,16 +539,21 @@ class SteamStatsManager {
|
|
|
519
539
|
const success = this.libraryLoader.SteamAPI_ISteamUserStats_GetUserStatFloat(userStatsInterface, steamIdBigInt, statName, valueOut);
|
|
520
540
|
if (success) {
|
|
521
541
|
const value = koffi.decode(valueOut, 'float');
|
|
522
|
-
console.log(
|
|
523
|
-
return
|
|
542
|
+
console.log(`[Steamworks] Got user stat "${statName}" for ${steamId}: ${value}`);
|
|
543
|
+
return {
|
|
544
|
+
steamId: typeof steamId === 'string' ? steamId : steamId.toString(),
|
|
545
|
+
name: statName,
|
|
546
|
+
value,
|
|
547
|
+
type: 'float'
|
|
548
|
+
};
|
|
524
549
|
}
|
|
525
550
|
else {
|
|
526
|
-
console.warn(
|
|
551
|
+
console.warn(`[Steamworks] Failed to get user stat: ${statName}`);
|
|
527
552
|
return null;
|
|
528
553
|
}
|
|
529
554
|
}
|
|
530
555
|
catch (error) {
|
|
531
|
-
console.error(
|
|
556
|
+
console.error(`[Steamworks] Error getting user stat "${statName}":`, error.message);
|
|
532
557
|
return null;
|
|
533
558
|
}
|
|
534
559
|
}
|
|
@@ -555,7 +580,7 @@ class SteamStatsManager {
|
|
|
555
580
|
* await new Promise(resolve => setTimeout(resolve, 100));
|
|
556
581
|
*
|
|
557
582
|
* const totalKills = await statsManager.getGlobalStatInt('total_kills');
|
|
558
|
-
* console.log(`All players combined: ${totalKills} kills`);
|
|
583
|
+
* console.log(`[Steamworks] All players combined: ${totalKills} kills`);
|
|
559
584
|
* ```
|
|
560
585
|
*
|
|
561
586
|
* @remarks
|
|
@@ -570,7 +595,7 @@ class SteamStatsManager {
|
|
|
570
595
|
*/
|
|
571
596
|
async requestGlobalStats(historyDays = 0) {
|
|
572
597
|
if (!this.apiCore.isInitialized()) {
|
|
573
|
-
console.warn('
|
|
598
|
+
console.warn('[Steamworks] Steam API not initialized');
|
|
574
599
|
return false;
|
|
575
600
|
}
|
|
576
601
|
try {
|
|
@@ -579,16 +604,16 @@ class SteamStatsManager {
|
|
|
579
604
|
const userStatsInterface = this.libraryLoader.SteamAPI_SteamUserStats_v013();
|
|
580
605
|
const callHandle = this.libraryLoader.SteamAPI_ISteamUserStats_RequestGlobalStats(userStatsInterface, days);
|
|
581
606
|
if (callHandle !== BigInt(0)) {
|
|
582
|
-
console.log(
|
|
607
|
+
console.log(`[Steamworks] Requested global stats with ${days} days of history`);
|
|
583
608
|
return true;
|
|
584
609
|
}
|
|
585
610
|
else {
|
|
586
|
-
console.warn(
|
|
611
|
+
console.warn(`[Steamworks] Failed to request global stats`);
|
|
587
612
|
return false;
|
|
588
613
|
}
|
|
589
614
|
}
|
|
590
615
|
catch (error) {
|
|
591
|
-
console.error(
|
|
616
|
+
console.error(`[Steamworks] Error requesting global stats:`, error.message);
|
|
592
617
|
return false;
|
|
593
618
|
}
|
|
594
619
|
}
|
|
@@ -599,7 +624,7 @@ class SteamStatsManager {
|
|
|
599
624
|
* Must call requestGlobalStats() first and wait for the data to arrive.
|
|
600
625
|
*
|
|
601
626
|
* @param statName - Name of the global stat to retrieve
|
|
602
|
-
* @returns
|
|
627
|
+
* @returns GlobalStat object with name, value, and type, or null if not found or on error
|
|
603
628
|
*
|
|
604
629
|
* @example
|
|
605
630
|
* ```typescript
|
|
@@ -607,24 +632,25 @@ class SteamStatsManager {
|
|
|
607
632
|
* await statsManager.requestGlobalStats();
|
|
608
633
|
* await new Promise(resolve => setTimeout(resolve, 100));
|
|
609
634
|
*
|
|
610
|
-
* const
|
|
611
|
-
* if (
|
|
612
|
-
* console.log(`
|
|
635
|
+
* const globalStat = await statsManager.getGlobalStatInt('total_kills');
|
|
636
|
+
* if (globalStat) {
|
|
637
|
+
* console.log(`[Steamworks] ${globalStat.name}: ${globalStat.value}`);
|
|
613
638
|
* }
|
|
614
639
|
* ```
|
|
615
640
|
*
|
|
616
641
|
* @remarks
|
|
617
|
-
* - Returns BigInt for large numbers (can exceed JavaScript's safe integer range)
|
|
618
642
|
* - Must call requestGlobalStats() first
|
|
619
643
|
* - Wait 50-100ms after requesting before calling this
|
|
620
644
|
* - Useful for tracking game-wide statistics
|
|
645
|
+
* - Returns structured GlobalStat object with full metadata
|
|
646
|
+
* - Value is number (BigInt converted to number for consistency)
|
|
621
647
|
*
|
|
622
648
|
* Steamworks SDK Functions:
|
|
623
649
|
* - `SteamAPI_ISteamUserStats_GetGlobalStatInt64()` - Get global int64 stat value
|
|
624
650
|
*/
|
|
625
651
|
async getGlobalStatInt(statName) {
|
|
626
652
|
if (!this.apiCore.isInitialized()) {
|
|
627
|
-
console.warn('
|
|
653
|
+
console.warn('[Steamworks] Steam API not initialized');
|
|
628
654
|
return null;
|
|
629
655
|
}
|
|
630
656
|
try {
|
|
@@ -633,16 +659,20 @@ class SteamStatsManager {
|
|
|
633
659
|
const success = this.libraryLoader.SteamAPI_ISteamUserStats_GetGlobalStatInt64(userStatsInterface, statName, valueOut);
|
|
634
660
|
if (success) {
|
|
635
661
|
const value = koffi.decode(valueOut, 'int64');
|
|
636
|
-
console.log(
|
|
637
|
-
return
|
|
662
|
+
console.log(`[Steamworks] Got global stat "${statName}": ${value}`);
|
|
663
|
+
return {
|
|
664
|
+
name: statName,
|
|
665
|
+
value: Number(value),
|
|
666
|
+
type: 'int64'
|
|
667
|
+
};
|
|
638
668
|
}
|
|
639
669
|
else {
|
|
640
|
-
console.warn(
|
|
670
|
+
console.warn(`[Steamworks] Failed to get global stat: ${statName}`);
|
|
641
671
|
return null;
|
|
642
672
|
}
|
|
643
673
|
}
|
|
644
674
|
catch (error) {
|
|
645
|
-
console.error(
|
|
675
|
+
console.error(`[Steamworks] Error getting global stat "${statName}":`, error.message);
|
|
646
676
|
return null;
|
|
647
677
|
}
|
|
648
678
|
}
|
|
@@ -654,7 +684,7 @@ class SteamStatsManager {
|
|
|
654
684
|
* Use this for averages or stats requiring decimal precision.
|
|
655
685
|
*
|
|
656
686
|
* @param statName - Name of the global stat to retrieve
|
|
657
|
-
* @returns
|
|
687
|
+
* @returns GlobalStat object with name, value, and type, or null if not found or on error
|
|
658
688
|
*
|
|
659
689
|
* @example
|
|
660
690
|
* ```typescript
|
|
@@ -662,9 +692,9 @@ class SteamStatsManager {
|
|
|
662
692
|
* await statsManager.requestGlobalStats();
|
|
663
693
|
* await new Promise(resolve => setTimeout(resolve, 100));
|
|
664
694
|
*
|
|
665
|
-
* const
|
|
666
|
-
* if (
|
|
667
|
-
* console.log(`
|
|
695
|
+
* const avgStat = await statsManager.getGlobalStatDouble('average_accuracy');
|
|
696
|
+
* if (avgStat) {
|
|
697
|
+
* console.log(`[Steamworks] ${avgStat.name}: ${(avgStat.value * 100).toFixed(2)}%`);
|
|
668
698
|
* }
|
|
669
699
|
* ```
|
|
670
700
|
*
|
|
@@ -673,13 +703,14 @@ class SteamStatsManager {
|
|
|
673
703
|
* - Must call requestGlobalStats() first
|
|
674
704
|
* - Wait 50-100ms after requesting before calling this
|
|
675
705
|
* - Perfect for calculating game-wide averages
|
|
706
|
+
* - Returns structured GlobalStat object with full metadata
|
|
676
707
|
*
|
|
677
708
|
* Steamworks SDK Functions:
|
|
678
709
|
* - `SteamAPI_ISteamUserStats_GetGlobalStatDouble()` - Get global double stat value
|
|
679
710
|
*/
|
|
680
711
|
async getGlobalStatDouble(statName) {
|
|
681
712
|
if (!this.apiCore.isInitialized()) {
|
|
682
|
-
console.warn('
|
|
713
|
+
console.warn('[Steamworks] Steam API not initialized');
|
|
683
714
|
return null;
|
|
684
715
|
}
|
|
685
716
|
try {
|
|
@@ -688,16 +719,20 @@ class SteamStatsManager {
|
|
|
688
719
|
const success = this.libraryLoader.SteamAPI_ISteamUserStats_GetGlobalStatDouble(userStatsInterface, statName, valueOut);
|
|
689
720
|
if (success) {
|
|
690
721
|
const value = koffi.decode(valueOut, 'double');
|
|
691
|
-
console.log(
|
|
692
|
-
return
|
|
722
|
+
console.log(`[Steamworks] Got global stat "${statName}": ${value}`);
|
|
723
|
+
return {
|
|
724
|
+
name: statName,
|
|
725
|
+
value,
|
|
726
|
+
type: 'double'
|
|
727
|
+
};
|
|
693
728
|
}
|
|
694
729
|
else {
|
|
695
|
-
console.warn(
|
|
730
|
+
console.warn(`[Steamworks] Failed to get global stat: ${statName}`);
|
|
696
731
|
return null;
|
|
697
732
|
}
|
|
698
733
|
}
|
|
699
734
|
catch (error) {
|
|
700
|
-
console.error(
|
|
735
|
+
console.error(`[Steamworks] Error getting global stat "${statName}":`, error.message);
|
|
701
736
|
return null;
|
|
702
737
|
}
|
|
703
738
|
}
|
|
@@ -709,7 +744,7 @@ class SteamStatsManager {
|
|
|
709
744
|
*
|
|
710
745
|
* @param statName - Name of the global stat
|
|
711
746
|
* @param days - Number of days of history to retrieve (1-60, default: 7)
|
|
712
|
-
* @returns
|
|
747
|
+
* @returns GlobalStatHistory object with name, history array, and type, or null if error
|
|
713
748
|
*
|
|
714
749
|
* @example
|
|
715
750
|
* ```typescript
|
|
@@ -719,10 +754,10 @@ class SteamStatsManager {
|
|
|
719
754
|
*
|
|
720
755
|
* const history = await statsManager.getGlobalStatHistoryInt('total_kills', 7);
|
|
721
756
|
* if (history) {
|
|
722
|
-
* console.log(
|
|
723
|
-
* history.forEach((kills, index) => {
|
|
757
|
+
* console.log(`[Steamworks] ${history.name} history (${history.type}):`);
|
|
758
|
+
* history.history.forEach((kills, index) => {
|
|
724
759
|
* const daysAgo = index === 0 ? 'today' : `${index} days ago`;
|
|
725
|
-
* console.log(`
|
|
760
|
+
* console.log(`[Steamworks] ${daysAgo}: ${kills} kills`);
|
|
726
761
|
* });
|
|
727
762
|
* }
|
|
728
763
|
* ```
|
|
@@ -730,7 +765,8 @@ class SteamStatsManager {
|
|
|
730
765
|
* @remarks
|
|
731
766
|
* - Array index [0] = today, [1] = yesterday, etc.
|
|
732
767
|
* - Must call requestGlobalStats(days) first with same or greater number of days
|
|
733
|
-
* - Returns
|
|
768
|
+
* - Returns structured GlobalStatHistory object with full metadata
|
|
769
|
+
* - Values are numbers (BigInt converted to number for consistency)
|
|
734
770
|
* - Maximum 60 days of history (automatically clamped)
|
|
735
771
|
* - Perfect for trend analysis and visualizations
|
|
736
772
|
*
|
|
@@ -739,7 +775,7 @@ class SteamStatsManager {
|
|
|
739
775
|
*/
|
|
740
776
|
async getGlobalStatHistoryInt(statName, days = 7) {
|
|
741
777
|
if (!this.apiCore.isInitialized()) {
|
|
742
|
-
console.warn('
|
|
778
|
+
console.warn('[Steamworks] Steam API not initialized');
|
|
743
779
|
return null;
|
|
744
780
|
}
|
|
745
781
|
try {
|
|
@@ -751,18 +787,22 @@ class SteamStatsManager {
|
|
|
751
787
|
if (elementsReturned > 0) {
|
|
752
788
|
const history = [];
|
|
753
789
|
for (let i = 0; i < elementsReturned; i++) {
|
|
754
|
-
history.push(koffi.decode(historyOut, 'int64', i));
|
|
790
|
+
history.push(Number(koffi.decode(historyOut, 'int64', i))); // Convert BigInt to number
|
|
755
791
|
}
|
|
756
|
-
console.log(
|
|
757
|
-
return
|
|
792
|
+
console.log(`[Steamworks] Got ${elementsReturned} days of history for "${statName}"`);
|
|
793
|
+
return {
|
|
794
|
+
name: statName,
|
|
795
|
+
history,
|
|
796
|
+
type: 'int64'
|
|
797
|
+
};
|
|
758
798
|
}
|
|
759
799
|
else {
|
|
760
|
-
console.warn(
|
|
800
|
+
console.warn(`[Steamworks] Failed to get global stat history: ${statName}`);
|
|
761
801
|
return null;
|
|
762
802
|
}
|
|
763
803
|
}
|
|
764
804
|
catch (error) {
|
|
765
|
-
console.error(
|
|
805
|
+
console.error(`[Steamworks] Error getting global stat history "${statName}":`, error.message);
|
|
766
806
|
return null;
|
|
767
807
|
}
|
|
768
808
|
}
|
|
@@ -775,7 +815,7 @@ class SteamStatsManager {
|
|
|
775
815
|
*
|
|
776
816
|
* @param statName - Name of the global stat
|
|
777
817
|
* @param days - Number of days of history to retrieve (1-60, default: 7)
|
|
778
|
-
* @returns
|
|
818
|
+
* @returns GlobalStatHistory object with name, history array, and type, or null if error
|
|
779
819
|
*
|
|
780
820
|
* @example
|
|
781
821
|
* ```typescript
|
|
@@ -785,10 +825,10 @@ class SteamStatsManager {
|
|
|
785
825
|
*
|
|
786
826
|
* const history = await statsManager.getGlobalStatHistoryDouble('average_accuracy', 30);
|
|
787
827
|
* if (history) {
|
|
788
|
-
* console.log(
|
|
789
|
-
* history.forEach((accuracy, index) => {
|
|
828
|
+
* console.log(`[Steamworks] ${history.name} trend (${history.type}):`);
|
|
829
|
+
* history.history.forEach((accuracy, index) => {
|
|
790
830
|
* if (index % 7 === 0) { // Weekly intervals
|
|
791
|
-
* console.log(`
|
|
831
|
+
* console.log(`[Steamworks] Week ${index/7}: ${(accuracy * 100).toFixed(2)}%`);
|
|
792
832
|
* }
|
|
793
833
|
* });
|
|
794
834
|
* }
|
|
@@ -797,6 +837,7 @@ class SteamStatsManager {
|
|
|
797
837
|
* @remarks
|
|
798
838
|
* - Array index [0] = today, [1] = yesterday, etc.
|
|
799
839
|
* - Must call requestGlobalStats(days) first with same or greater number of days
|
|
840
|
+
* - Returns structured GlobalStatHistory object with full metadata
|
|
800
841
|
* - Returns floating-point values for decimal precision
|
|
801
842
|
* - Maximum 60 days of history (automatically clamped)
|
|
802
843
|
* - Perfect for tracking averages, rates, and percentages over time
|
|
@@ -806,7 +847,7 @@ class SteamStatsManager {
|
|
|
806
847
|
*/
|
|
807
848
|
async getGlobalStatHistoryDouble(statName, days = 7) {
|
|
808
849
|
if (!this.apiCore.isInitialized()) {
|
|
809
|
-
console.warn('
|
|
850
|
+
console.warn('[Steamworks] Steam API not initialized');
|
|
810
851
|
return null;
|
|
811
852
|
}
|
|
812
853
|
try {
|
|
@@ -820,16 +861,20 @@ class SteamStatsManager {
|
|
|
820
861
|
for (let i = 0; i < elementsReturned; i++) {
|
|
821
862
|
history.push(koffi.decode(historyOut, 'double', i));
|
|
822
863
|
}
|
|
823
|
-
console.log(
|
|
824
|
-
return
|
|
864
|
+
console.log(`[Steamworks] Got ${elementsReturned} days of history for "${statName}"`);
|
|
865
|
+
return {
|
|
866
|
+
name: statName,
|
|
867
|
+
history,
|
|
868
|
+
type: 'double'
|
|
869
|
+
};
|
|
825
870
|
}
|
|
826
871
|
else {
|
|
827
|
-
console.warn(
|
|
872
|
+
console.warn(`[Steamworks] Failed to get global stat history: ${statName}`);
|
|
828
873
|
return null;
|
|
829
874
|
}
|
|
830
875
|
}
|
|
831
876
|
catch (error) {
|
|
832
|
-
console.error(
|
|
877
|
+
console.error(`[Steamworks] Error getting global stat history "${statName}":`, error.message);
|
|
833
878
|
return null;
|
|
834
879
|
}
|
|
835
880
|
}
|