steamworks-ffi-node 0.6.10 → 0.7.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.
Files changed (50) hide show
  1. package/README.md +157 -107
  2. package/dist/internal/SteamCloudManager.d.ts +86 -1
  3. package/dist/internal/SteamCloudManager.d.ts.map +1 -1
  4. package/dist/internal/SteamCloudManager.js +142 -0
  5. package/dist/internal/SteamCloudManager.js.map +1 -1
  6. package/dist/internal/SteamInputManager.d.ts +496 -0
  7. package/dist/internal/SteamInputManager.d.ts.map +1 -0
  8. package/dist/internal/SteamInputManager.js +993 -0
  9. package/dist/internal/SteamInputManager.js.map +1 -0
  10. package/dist/internal/SteamLibraryLoader.d.ts +61 -0
  11. package/dist/internal/SteamLibraryLoader.d.ts.map +1 -1
  12. package/dist/internal/SteamLibraryLoader.js +83 -0
  13. package/dist/internal/SteamLibraryLoader.js.map +1 -1
  14. package/dist/internal/SteamScreenshotManager.d.ts +327 -0
  15. package/dist/internal/SteamScreenshotManager.d.ts.map +1 -0
  16. package/dist/internal/SteamScreenshotManager.js +459 -0
  17. package/dist/internal/SteamScreenshotManager.js.map +1 -0
  18. package/dist/internal/SteamWorkshopManager.d.ts +24 -0
  19. package/dist/internal/SteamWorkshopManager.d.ts.map +1 -1
  20. package/dist/internal/SteamWorkshopManager.js +74 -0
  21. package/dist/internal/SteamWorkshopManager.js.map +1 -1
  22. package/dist/internal/callbackTypes/SteamCallbackIds.d.ts +2 -0
  23. package/dist/internal/callbackTypes/SteamCallbackIds.d.ts.map +1 -1
  24. package/dist/internal/callbackTypes/SteamCallbackIds.js +3 -1
  25. package/dist/internal/callbackTypes/SteamCallbackIds.js.map +1 -1
  26. package/dist/internal/callbackTypes/SteamCallbackTypes.d.ts +9 -0
  27. package/dist/internal/callbackTypes/SteamCallbackTypes.d.ts.map +1 -1
  28. package/dist/steam.d.ts +99 -0
  29. package/dist/steam.d.ts.map +1 -1
  30. package/dist/steam.js +9 -0
  31. package/dist/steam.js.map +1 -1
  32. package/dist/types/cloud.d.ts +11 -11
  33. package/dist/types/cloud.d.ts.map +1 -1
  34. package/dist/types/index.d.ts +2 -0
  35. package/dist/types/index.d.ts.map +1 -1
  36. package/dist/types/index.js +4 -0
  37. package/dist/types/index.js.map +1 -1
  38. package/dist/types/input.d.ts +252 -0
  39. package/dist/types/input.d.ts.map +1 -0
  40. package/dist/types/input.js +142 -0
  41. package/dist/types/input.js.map +1 -0
  42. package/dist/types/screenshots.d.ts +63 -0
  43. package/dist/types/screenshots.d.ts.map +1 -0
  44. package/dist/types/screenshots.js +44 -0
  45. package/dist/types/screenshots.js.map +1 -0
  46. package/dist/types/workshop.d.ts +8 -0
  47. package/dist/types/workshop.d.ts.map +1 -1
  48. package/dist/types/workshop.js.map +1 -1
  49. package/docs/README.md +49 -5
  50. package/package.json +10 -2
@@ -0,0 +1,993 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SteamInputManager = void 0;
4
+ const types_1 = require("../types");
5
+ /**
6
+ * Controller type names for display
7
+ */
8
+ const CONTROLLER_TYPE_NAMES = {
9
+ [types_1.SteamInputType.Unknown]: 'Unknown',
10
+ [types_1.SteamInputType.SteamController]: 'Steam Controller',
11
+ [types_1.SteamInputType.XBox360Controller]: 'Xbox 360 Controller',
12
+ [types_1.SteamInputType.XBoxOneController]: 'Xbox One Controller',
13
+ [types_1.SteamInputType.GenericGamepad]: 'Generic Gamepad',
14
+ [types_1.SteamInputType.PS4Controller]: 'PS4 Controller',
15
+ [types_1.SteamInputType.AppleMFiController]: 'Apple MFi Controller',
16
+ [types_1.SteamInputType.AndroidController]: 'Android Controller',
17
+ [types_1.SteamInputType.SwitchJoyConPair]: 'Switch Joy-Con Pair',
18
+ [types_1.SteamInputType.SwitchJoyConSingle]: 'Switch Joy-Con Single',
19
+ [types_1.SteamInputType.SwitchProController]: 'Switch Pro Controller',
20
+ [types_1.SteamInputType.MobileTouch]: 'Mobile Touch',
21
+ [types_1.SteamInputType.PS3Controller]: 'PS3 Controller',
22
+ [types_1.SteamInputType.PS5Controller]: 'PS5 Controller',
23
+ [types_1.SteamInputType.SteamDeckController]: 'Steam Deck',
24
+ };
25
+ /**
26
+ * SteamInputManager
27
+ *
28
+ * Manages Steam Input operations for unified controller support.
29
+ * Supports Xbox, PlayStation, Nintendo Switch, Steam Controller, and more.
30
+ *
31
+ * Features:
32
+ * - Controller detection and enumeration
33
+ * - Action set management
34
+ * - Digital and analog action handling
35
+ * - Motion data (gyro, accelerometer)
36
+ * - Haptic feedback and vibration
37
+ * - LED control
38
+ * - Button glyph display
39
+ * - Configuration UI
40
+ *
41
+ * @example
42
+ * ```typescript
43
+ * const inputManager = new SteamInputManager(libraryLoader, apiCore);
44
+ *
45
+ * // Initialize
46
+ * inputManager.init();
47
+ *
48
+ * // Update every frame
49
+ * inputManager.runFrame();
50
+ *
51
+ * // Get connected controllers
52
+ * const controllers = inputManager.getConnectedControllers();
53
+ *
54
+ * // Read actions
55
+ * const jumpHandle = inputManager.getDigitalActionHandle('Jump');
56
+ * const jumpData = inputManager.getDigitalActionData(controllerHandle, jumpHandle);
57
+ * if (jumpData.state) {
58
+ * console.log('Jump pressed!');
59
+ * }
60
+ * ```
61
+ */
62
+ class SteamInputManager {
63
+ /**
64
+ * Creates a new SteamInputManager instance
65
+ *
66
+ * @param libraryLoader - The Steam library loader for FFI calls
67
+ */
68
+ constructor(libraryLoader) {
69
+ /** Cached ISteamInput interface pointer */
70
+ this.steamInputInterface = null;
71
+ this.libraryLoader = libraryLoader;
72
+ }
73
+ /**
74
+ * Get the ISteamInput interface pointer
75
+ * @private
76
+ */
77
+ getSteamInputInterface() {
78
+ if (!this.steamInputInterface) {
79
+ this.steamInputInterface = this.libraryLoader.SteamAPI_SteamInput_v006();
80
+ }
81
+ return this.steamInputInterface;
82
+ }
83
+ // ========================================
84
+ // Initialization
85
+ // ========================================
86
+ /**
87
+ * Initialize Steam Input
88
+ *
89
+ * Must be called before using any other Steam Input functions.
90
+ * Should be called after SteamAPI_Init().
91
+ *
92
+ * @param explicitlyCallRunFrame - If true, you must call runFrame() manually each frame.
93
+ * If false, Steam will automatically update input state.
94
+ * Default is true for explicit control.
95
+ * @returns True if initialization was successful
96
+ *
97
+ * @example
98
+ * ```typescript
99
+ * if (inputManager.init()) {
100
+ * console.log('Steam Input initialized successfully');
101
+ * }
102
+ * ```
103
+ */
104
+ init(explicitlyCallRunFrame = true) {
105
+ const iface = this.getSteamInputInterface();
106
+ if (!iface) {
107
+ console.error('[SteamInput] Failed to get ISteamInput interface');
108
+ return false;
109
+ }
110
+ try {
111
+ const result = this.libraryLoader.SteamAPI_ISteamInput_Init(iface, explicitlyCallRunFrame);
112
+ return result;
113
+ }
114
+ catch (error) {
115
+ console.error('[SteamInput] Init error:', error);
116
+ return false;
117
+ }
118
+ }
119
+ /**
120
+ * Shutdown Steam Input
121
+ *
122
+ * Should be called before SteamAPI_Shutdown().
123
+ *
124
+ * @returns True if shutdown was successful
125
+ */
126
+ shutdown() {
127
+ const iface = this.getSteamInputInterface();
128
+ if (!iface)
129
+ return false;
130
+ try {
131
+ const result = this.libraryLoader.SteamAPI_ISteamInput_Shutdown(iface);
132
+ return result;
133
+ }
134
+ catch (error) {
135
+ console.error('[SteamInput] Shutdown error:', error);
136
+ return false;
137
+ }
138
+ }
139
+ /**
140
+ * Set the absolute path to the Input Action Manifest file
141
+ *
142
+ * Used for games that provide their own input_actions.vdf file.
143
+ * Must be called before init().
144
+ *
145
+ * @param manifestPath - Absolute path to input_actions.vdf
146
+ * @returns True if successful
147
+ */
148
+ setInputActionManifestFilePath(manifestPath) {
149
+ const iface = this.getSteamInputInterface();
150
+ if (!iface)
151
+ return false;
152
+ try {
153
+ return this.libraryLoader.SteamAPI_ISteamInput_SetInputActionManifestFilePath(iface, manifestPath);
154
+ }
155
+ catch (error) {
156
+ console.error('[SteamInput] SetInputActionManifestFilePath error:', error);
157
+ return false;
158
+ }
159
+ }
160
+ /**
161
+ * Update input state for all controllers
162
+ *
163
+ * Must be called every frame if init() was called with explicitlyCallRunFrame=true.
164
+ * Synchronizes controller state and processes input data.
165
+ *
166
+ * @param reservedValue - Reserved for future use, should be false
167
+ *
168
+ * @example
169
+ * ```typescript
170
+ * // In your game loop
171
+ * function gameLoop() {
172
+ * inputManager.runFrame();
173
+ * // Read input state
174
+ * // Update game logic
175
+ * requestAnimationFrame(gameLoop);
176
+ * }
177
+ * ```
178
+ */
179
+ runFrame(reservedValue = false) {
180
+ const iface = this.getSteamInputInterface();
181
+ if (!iface)
182
+ return;
183
+ try {
184
+ this.libraryLoader.SteamAPI_ISteamInput_RunFrame(iface, reservedValue);
185
+ }
186
+ catch (error) {
187
+ console.error('[SteamInput] RunFrame error:', error);
188
+ }
189
+ }
190
+ // ========================================
191
+ // Controller Enumeration
192
+ // ========================================
193
+ /**
194
+ * Get all currently connected controller handles
195
+ *
196
+ * Controller handles persist across disconnects/reconnects.
197
+ *
198
+ * @returns Array of controller handles (max 16 controllers)
199
+ *
200
+ * @example
201
+ * ```typescript
202
+ * const controllers = inputManager.getConnectedControllers();
203
+ * console.log(`Found ${controllers.length} controller(s)`);
204
+ *
205
+ * controllers.forEach(handle => {
206
+ * const type = inputManager.getInputTypeForHandle(handle);
207
+ * console.log(`Controller: ${handle}, Type: ${type}`);
208
+ * });
209
+ * ```
210
+ */
211
+ getConnectedControllers() {
212
+ const iface = this.getSteamInputInterface();
213
+ if (!iface)
214
+ return [];
215
+ try {
216
+ const handlesArray = new BigUint64Array(types_1.STEAM_INPUT.MAX_COUNT);
217
+ const handleBuffer = Buffer.from(handlesArray.buffer);
218
+ const count = this.libraryLoader.SteamAPI_ISteamInput_GetConnectedControllers(iface, handleBuffer);
219
+ const handles = [];
220
+ for (let i = 0; i < count; i++) {
221
+ handles.push(handlesArray[i]);
222
+ }
223
+ return handles;
224
+ }
225
+ catch (error) {
226
+ console.error('[SteamInput] GetConnectedControllers error:', error);
227
+ return [];
228
+ }
229
+ }
230
+ /**
231
+ * Get the input type for a specific controller
232
+ *
233
+ * @param inputHandle - Controller handle
234
+ * @returns Controller type enum value
235
+ *
236
+ * @example
237
+ * ```typescript
238
+ * const type = inputManager.getInputTypeForHandle(handle);
239
+ * if (type === SteamInputType.PS5Controller) {
240
+ * console.log('DualSense detected!');
241
+ * }
242
+ * ```
243
+ */
244
+ getInputTypeForHandle(inputHandle) {
245
+ const iface = this.getSteamInputInterface();
246
+ if (!iface)
247
+ return types_1.SteamInputType.Unknown;
248
+ try {
249
+ return this.libraryLoader.SteamAPI_ISteamInput_GetInputTypeForHandle(iface, inputHandle);
250
+ }
251
+ catch (error) {
252
+ console.error('[SteamInput] GetInputTypeForHandle error:', error);
253
+ return types_1.SteamInputType.Unknown;
254
+ }
255
+ }
256
+ /**
257
+ * Get comprehensive controller information
258
+ *
259
+ * Convenience method that combines multiple queries into one object.
260
+ *
261
+ * @param inputHandle - Controller handle
262
+ * @returns Controller information object
263
+ */
264
+ getControllerInfo(inputHandle) {
265
+ const type = this.getInputTypeForHandle(inputHandle);
266
+ const gamepadIndex = this.getGamepadIndexForController(inputHandle);
267
+ return {
268
+ handle: inputHandle,
269
+ type,
270
+ typeName: CONTROLLER_TYPE_NAMES[type] || `Unknown (${type})`,
271
+ gamepadIndex,
272
+ };
273
+ }
274
+ /**
275
+ * Get the controller handle for a specific gamepad index
276
+ *
277
+ * Useful for mapping XInput indices to Steam Input handles.
278
+ *
279
+ * @param gamepadIndex - XInput gamepad index (0-3)
280
+ * @returns Controller handle, or 0n if not found
281
+ */
282
+ getControllerForGamepadIndex(gamepadIndex) {
283
+ const iface = this.getSteamInputInterface();
284
+ if (!iface)
285
+ return BigInt(0);
286
+ try {
287
+ return this.libraryLoader.SteamAPI_ISteamInput_GetControllerForGamepadIndex(iface, gamepadIndex);
288
+ }
289
+ catch (error) {
290
+ console.error('[SteamInput] GetControllerForGamepadIndex error:', error);
291
+ return BigInt(0);
292
+ }
293
+ }
294
+ /**
295
+ * Get the gamepad index for a controller handle
296
+ *
297
+ * @param inputHandle - Controller handle
298
+ * @returns XInput gamepad index (0-3), or -1 if not emulating gamepad
299
+ */
300
+ getGamepadIndexForController(inputHandle) {
301
+ const iface = this.getSteamInputInterface();
302
+ if (!iface)
303
+ return -1;
304
+ try {
305
+ return this.libraryLoader.SteamAPI_ISteamInput_GetGamepadIndexForController(iface, inputHandle);
306
+ }
307
+ catch (error) {
308
+ console.error('[SteamInput] GetGamepadIndexForController error:', error);
309
+ return -1;
310
+ }
311
+ }
312
+ // ========================================
313
+ // Action Sets
314
+ // ========================================
315
+ /**
316
+ * Get the handle for an action set by name
317
+ *
318
+ * Action sets group related actions together (e.g., "MenuControls", "GameplayControls").
319
+ * Should be queried once at startup and cached.
320
+ *
321
+ * @param actionSetName - Name of the action set from input_actions.vdf
322
+ * @returns Action set handle
323
+ *
324
+ * @example
325
+ * ```typescript
326
+ * const menuSet = inputManager.getActionSetHandle('MenuControls');
327
+ * const gameSet = inputManager.getActionSetHandle('GameplayControls');
328
+ * ```
329
+ */
330
+ getActionSetHandle(actionSetName) {
331
+ const iface = this.getSteamInputInterface();
332
+ if (!iface)
333
+ return BigInt(0);
334
+ try {
335
+ return this.libraryLoader.SteamAPI_ISteamInput_GetActionSetHandle(iface, actionSetName);
336
+ }
337
+ catch (error) {
338
+ console.error('[SteamInput] GetActionSetHandle error:', error);
339
+ return BigInt(0);
340
+ }
341
+ }
342
+ /**
343
+ * Activate an action set for a controller
344
+ *
345
+ * Only one action set can be active at a time (plus layers).
346
+ *
347
+ * @param inputHandle - Controller handle
348
+ * @param actionSetHandle - Action set handle to activate
349
+ *
350
+ * @example
351
+ * ```typescript
352
+ * const gameSet = inputManager.getActionSetHandle('GameplayControls');
353
+ * inputManager.activateActionSet(controllerHandle, gameSet);
354
+ * ```
355
+ */
356
+ activateActionSet(inputHandle, actionSetHandle) {
357
+ const iface = this.getSteamInputInterface();
358
+ if (!iface)
359
+ return;
360
+ try {
361
+ this.libraryLoader.SteamAPI_ISteamInput_ActivateActionSet(iface, inputHandle, actionSetHandle);
362
+ }
363
+ catch (error) {
364
+ console.error('[SteamInput] ActivateActionSet error:', error);
365
+ }
366
+ }
367
+ /**
368
+ * Get the currently active action set for a controller
369
+ *
370
+ * @param inputHandle - Controller handle
371
+ * @returns Currently active action set handle
372
+ */
373
+ getCurrentActionSet(inputHandle) {
374
+ const iface = this.getSteamInputInterface();
375
+ if (!iface)
376
+ return BigInt(0);
377
+ try {
378
+ return this.libraryLoader.SteamAPI_ISteamInput_GetCurrentActionSet(iface, inputHandle);
379
+ }
380
+ catch (error) {
381
+ console.error('[SteamInput] GetCurrentActionSet error:', error);
382
+ return BigInt(0);
383
+ }
384
+ }
385
+ /**
386
+ * Activate an action set layer
387
+ *
388
+ * Layers add additional actions on top of the base action set.
389
+ * Up to 16 layers can be active simultaneously.
390
+ *
391
+ * @param inputHandle - Controller handle
392
+ * @param actionSetLayerHandle - Action set layer handle
393
+ */
394
+ activateActionSetLayer(inputHandle, actionSetLayerHandle) {
395
+ const iface = this.getSteamInputInterface();
396
+ if (!iface)
397
+ return;
398
+ try {
399
+ this.libraryLoader.SteamAPI_ISteamInput_ActivateActionSetLayer(iface, inputHandle, actionSetLayerHandle);
400
+ }
401
+ catch (error) {
402
+ console.error('[SteamInput] ActivateActionSetLayer error:', error);
403
+ }
404
+ }
405
+ /**
406
+ * Deactivate an action set layer
407
+ *
408
+ * @param inputHandle - Controller handle
409
+ * @param actionSetLayerHandle - Action set layer handle
410
+ */
411
+ deactivateActionSetLayer(inputHandle, actionSetLayerHandle) {
412
+ const iface = this.getSteamInputInterface();
413
+ if (!iface)
414
+ return;
415
+ try {
416
+ this.libraryLoader.SteamAPI_ISteamInput_DeactivateActionSetLayer(iface, inputHandle, actionSetLayerHandle);
417
+ }
418
+ catch (error) {
419
+ console.error('[SteamInput] DeactivateActionSetLayer error:', error);
420
+ }
421
+ }
422
+ /**
423
+ * Deactivate all action set layers
424
+ *
425
+ * @param inputHandle - Controller handle
426
+ */
427
+ deactivateAllActionSetLayers(inputHandle) {
428
+ const iface = this.getSteamInputInterface();
429
+ if (!iface)
430
+ return;
431
+ try {
432
+ this.libraryLoader.SteamAPI_ISteamInput_DeactivateAllActionSetLayers(iface, inputHandle);
433
+ }
434
+ catch (error) {
435
+ console.error('[SteamInput] DeactivateAllActionSetLayers error:', error);
436
+ }
437
+ }
438
+ /**
439
+ * Get all currently active action set layers
440
+ *
441
+ * @param inputHandle - Controller handle
442
+ * @returns Array of active layer handles
443
+ */
444
+ getActiveActionSetLayers(inputHandle) {
445
+ const iface = this.getSteamInputInterface();
446
+ if (!iface)
447
+ return [];
448
+ try {
449
+ const layersArray = new BigUint64Array(types_1.STEAM_INPUT.MAX_ACTIVE_LAYERS);
450
+ const layerBuffer = Buffer.from(layersArray.buffer);
451
+ const count = this.libraryLoader.SteamAPI_ISteamInput_GetActiveActionSetLayers(iface, inputHandle, layerBuffer);
452
+ const layers = [];
453
+ for (let i = 0; i < count; i++) {
454
+ layers.push(layersArray[i]);
455
+ }
456
+ return layers;
457
+ }
458
+ catch (error) {
459
+ console.error('[SteamInput] GetActiveActionSetLayers error:', error);
460
+ return [];
461
+ }
462
+ }
463
+ // ========================================
464
+ // Digital Actions (Buttons)
465
+ // ========================================
466
+ /**
467
+ * Get the handle for a digital action by name
468
+ *
469
+ * Digital actions represent button presses (on/off state).
470
+ * Should be queried once at startup and cached.
471
+ *
472
+ * @param actionName - Name of the digital action from input_actions.vdf
473
+ * @returns Digital action handle
474
+ *
475
+ * @example
476
+ * ```typescript
477
+ * const jumpHandle = inputManager.getDigitalActionHandle('Jump');
478
+ * const shootHandle = inputManager.getDigitalActionHandle('Shoot');
479
+ * ```
480
+ */
481
+ getDigitalActionHandle(actionName) {
482
+ const iface = this.getSteamInputInterface();
483
+ if (!iface)
484
+ return BigInt(0);
485
+ try {
486
+ return this.libraryLoader.SteamAPI_ISteamInput_GetDigitalActionHandle(iface, actionName);
487
+ }
488
+ catch (error) {
489
+ console.error('[SteamInput] GetDigitalActionHandle error:', error);
490
+ return BigInt(0);
491
+ }
492
+ }
493
+ /**
494
+ * Get the current state of a digital action
495
+ *
496
+ * @param inputHandle - Controller handle
497
+ * @param digitalActionHandle - Digital action handle
498
+ * @returns Digital action data (state and active status)
499
+ *
500
+ * @example
501
+ * ```typescript
502
+ * const jumpData = inputManager.getDigitalActionData(controllerHandle, jumpHandle);
503
+ * if (jumpData.state && jumpData.active) {
504
+ * player.jump();
505
+ * }
506
+ * ```
507
+ */
508
+ getDigitalActionData(inputHandle, digitalActionHandle) {
509
+ const iface = this.getSteamInputInterface();
510
+ if (!iface) {
511
+ return { state: false, active: false };
512
+ }
513
+ try {
514
+ // Allocate buffer for InputDigitalActionData_t struct (bool state + bool active)
515
+ const buffer = Buffer.alloc(2);
516
+ this.libraryLoader.SteamAPI_ISteamInput_GetDigitalActionData(iface, inputHandle, digitalActionHandle, buffer);
517
+ return {
518
+ state: buffer.readUInt8(0) !== 0,
519
+ active: buffer.readUInt8(1) !== 0,
520
+ };
521
+ }
522
+ catch (error) {
523
+ console.error('[SteamInput] GetDigitalActionData error:', error);
524
+ return { state: false, active: false };
525
+ }
526
+ }
527
+ /**
528
+ * Get the localized string for a digital action name
529
+ *
530
+ * @param digitalActionHandle - Digital action handle
531
+ * @returns Localized action name, or empty string if not found
532
+ */
533
+ getStringForDigitalActionName(digitalActionHandle) {
534
+ const iface = this.getSteamInputInterface();
535
+ if (!iface)
536
+ return '';
537
+ try {
538
+ return this.libraryLoader.SteamAPI_ISteamInput_GetStringForDigitalActionName(iface, digitalActionHandle) || '';
539
+ }
540
+ catch (error) {
541
+ console.error('[SteamInput] GetStringForDigitalActionName error:', error);
542
+ return '';
543
+ }
544
+ }
545
+ // ========================================
546
+ // Analog Actions (Sticks, Triggers)
547
+ // ========================================
548
+ /**
549
+ * Get the handle for an analog action by name
550
+ *
551
+ * Analog actions represent continuous inputs like joysticks and triggers.
552
+ * Should be queried once at startup and cached.
553
+ *
554
+ * @param actionName - Name of the analog action from input_actions.vdf
555
+ * @returns Analog action handle
556
+ *
557
+ * @example
558
+ * ```typescript
559
+ * const moveHandle = inputManager.getAnalogActionHandle('Move');
560
+ * const lookHandle = inputManager.getAnalogActionHandle('Look');
561
+ * ```
562
+ */
563
+ getAnalogActionHandle(actionName) {
564
+ const iface = this.getSteamInputInterface();
565
+ if (!iface)
566
+ return BigInt(0);
567
+ try {
568
+ return this.libraryLoader.SteamAPI_ISteamInput_GetAnalogActionHandle(iface, actionName);
569
+ }
570
+ catch (error) {
571
+ console.error('[SteamInput] GetAnalogActionHandle error:', error);
572
+ return BigInt(0);
573
+ }
574
+ }
575
+ /**
576
+ * Get the current state of an analog action
577
+ *
578
+ * @param inputHandle - Controller handle
579
+ * @param analogActionHandle - Analog action handle
580
+ * @returns Analog action data (mode, x, y values, and active status)
581
+ *
582
+ * @example
583
+ * ```typescript
584
+ * const moveData = inputManager.getAnalogActionData(controllerHandle, moveHandle);
585
+ * if (moveData.active) {
586
+ * player.move(moveData.x, moveData.y);
587
+ * }
588
+ * ```
589
+ */
590
+ getAnalogActionData(inputHandle, analogActionHandle) {
591
+ const iface = this.getSteamInputInterface();
592
+ if (!iface) {
593
+ return { mode: 0, x: 0, y: 0, active: false };
594
+ }
595
+ try {
596
+ // Allocate buffer for InputAnalogActionData_t struct
597
+ // EInputSourceMode (4 bytes), float x, float y, bool active
598
+ const buffer = Buffer.alloc(13);
599
+ this.libraryLoader.SteamAPI_ISteamInput_GetAnalogActionData(iface, inputHandle, analogActionHandle, buffer);
600
+ return {
601
+ mode: buffer.readInt32LE(0),
602
+ x: buffer.readFloatLE(4),
603
+ y: buffer.readFloatLE(8),
604
+ active: buffer.readUInt8(12) !== 0,
605
+ };
606
+ }
607
+ catch (error) {
608
+ console.error('[SteamInput] GetAnalogActionData error:', error);
609
+ return { mode: 0, x: 0, y: 0, active: false };
610
+ }
611
+ }
612
+ /**
613
+ * Get the localized string for an analog action name
614
+ *
615
+ * @param analogActionHandle - Analog action handle
616
+ * @returns Localized action name, or empty string if not found
617
+ */
618
+ getStringForAnalogActionName(analogActionHandle) {
619
+ const iface = this.getSteamInputInterface();
620
+ if (!iface)
621
+ return '';
622
+ try {
623
+ return this.libraryLoader.SteamAPI_ISteamInput_GetStringForAnalogActionName(iface, analogActionHandle) || '';
624
+ }
625
+ catch (error) {
626
+ console.error('[SteamInput] GetStringForAnalogActionName error:', error);
627
+ return '';
628
+ }
629
+ }
630
+ /**
631
+ * Stop analog action momentum for trackball mode
632
+ *
633
+ * If an analog action is in trackball mode (mouse emulation),
634
+ * this stops the momentum/inertia.
635
+ *
636
+ * @param inputHandle - Controller handle
637
+ * @param analogActionHandle - Analog action handle
638
+ */
639
+ stopAnalogActionMomentum(inputHandle, analogActionHandle) {
640
+ const iface = this.getSteamInputInterface();
641
+ if (!iface)
642
+ return;
643
+ try {
644
+ this.libraryLoader.SteamAPI_ISteamInput_StopAnalogActionMomentum(iface, inputHandle, analogActionHandle);
645
+ }
646
+ catch (error) {
647
+ console.error('[SteamInput] StopAnalogActionMomentum error:', error);
648
+ }
649
+ }
650
+ // ========================================
651
+ // Motion Data
652
+ // ========================================
653
+ /**
654
+ * Get motion data from controller (gyroscope and accelerometer)
655
+ *
656
+ * Provides quaternion rotation, positional acceleration, and angular velocity.
657
+ *
658
+ * @param inputHandle - Controller handle
659
+ * @returns Motion data, or null if not supported
660
+ *
661
+ * @example
662
+ * ```typescript
663
+ * const motion = inputManager.getMotionData(controllerHandle);
664
+ * if (motion) {
665
+ * // Use gyro for aiming
666
+ * camera.rotateByGyro(motion.rotVelX, motion.rotVelY, motion.rotVelZ);
667
+ * }
668
+ * ```
669
+ */
670
+ getMotionData(inputHandle) {
671
+ const iface = this.getSteamInputInterface();
672
+ if (!iface)
673
+ return null;
674
+ try {
675
+ // Allocate buffer for InputMotionData_t struct
676
+ // 4 floats (quat) + 3 floats (posAccel) + 3 floats (rotVel) = 10 floats = 40 bytes
677
+ const buffer = Buffer.alloc(40);
678
+ this.libraryLoader.SteamAPI_ISteamInput_GetMotionData(iface, inputHandle, buffer);
679
+ return {
680
+ rotQuatX: buffer.readFloatLE(0),
681
+ rotQuatY: buffer.readFloatLE(4),
682
+ rotQuatZ: buffer.readFloatLE(8),
683
+ rotQuatW: buffer.readFloatLE(12),
684
+ posAccelX: buffer.readFloatLE(16),
685
+ posAccelY: buffer.readFloatLE(20),
686
+ posAccelZ: buffer.readFloatLE(24),
687
+ rotVelX: buffer.readFloatLE(28),
688
+ rotVelY: buffer.readFloatLE(32),
689
+ rotVelZ: buffer.readFloatLE(36),
690
+ };
691
+ }
692
+ catch (error) {
693
+ console.error('[SteamInput] GetMotionData error:', error);
694
+ return null;
695
+ }
696
+ }
697
+ // ========================================
698
+ // Haptics and Rumble
699
+ // ========================================
700
+ /**
701
+ * Trigger vibration/rumble on a controller
702
+ *
703
+ * @param inputHandle - Controller handle
704
+ * @param leftSpeed - Left motor speed (0-65535)
705
+ * @param rightSpeed - Right motor speed (0-65535)
706
+ *
707
+ * @example
708
+ * ```typescript
709
+ * // Light rumble
710
+ * inputManager.triggerVibration(handle, 10000, 10000);
711
+ *
712
+ * // Strong rumble
713
+ * inputManager.triggerVibration(handle, 65535, 65535);
714
+ *
715
+ * // Stop rumble
716
+ * inputManager.triggerVibration(handle, 0, 0);
717
+ * ```
718
+ */
719
+ triggerVibration(inputHandle, leftSpeed, rightSpeed) {
720
+ const iface = this.getSteamInputInterface();
721
+ if (!iface)
722
+ return;
723
+ try {
724
+ this.libraryLoader.SteamAPI_ISteamInput_TriggerVibration(iface, inputHandle, leftSpeed, rightSpeed);
725
+ }
726
+ catch (error) {
727
+ console.error('[SteamInput] TriggerVibration error:', error);
728
+ }
729
+ }
730
+ /**
731
+ * Trigger extended vibration with trigger motor support (Xbox controllers)
732
+ *
733
+ * @param inputHandle - Controller handle
734
+ * @param leftSpeed - Left motor speed (0-65535)
735
+ * @param rightSpeed - Right motor speed (0-65535)
736
+ * @param leftTriggerSpeed - Left trigger motor speed (0-65535)
737
+ * @param rightTriggerSpeed - Right trigger motor speed (0-65535)
738
+ */
739
+ triggerVibrationExtended(inputHandle, leftSpeed, rightSpeed, leftTriggerSpeed, rightTriggerSpeed) {
740
+ const iface = this.getSteamInputInterface();
741
+ if (!iface)
742
+ return;
743
+ try {
744
+ this.libraryLoader.SteamAPI_ISteamInput_TriggerVibrationExtended(iface, inputHandle, leftSpeed, rightSpeed, leftTriggerSpeed, rightTriggerSpeed);
745
+ }
746
+ catch (error) {
747
+ console.error('[SteamInput] TriggerVibrationExtended error:', error);
748
+ }
749
+ }
750
+ /**
751
+ * Trigger a simple haptic event (Steam Controller, Steam Deck)
752
+ *
753
+ * @param inputHandle - Controller handle
754
+ * @param hapticLocation - Left, right, or both
755
+ * @param intensity - Intensity (0-255)
756
+ * @param gainDB - Gain in decibels
757
+ * @param otherIntensity - Intensity for the other pad
758
+ * @param otherGainDB - Gain for the other pad
759
+ */
760
+ triggerSimpleHapticEvent(inputHandle, hapticLocation, intensity, gainDB, otherIntensity, otherGainDB) {
761
+ const iface = this.getSteamInputInterface();
762
+ if (!iface)
763
+ return;
764
+ try {
765
+ this.libraryLoader.SteamAPI_ISteamInput_TriggerSimpleHapticEvent(iface, inputHandle, hapticLocation, intensity, gainDB, otherIntensity, otherGainDB);
766
+ }
767
+ catch (error) {
768
+ console.error('[SteamInput] TriggerSimpleHapticEvent error:', error);
769
+ }
770
+ }
771
+ /**
772
+ * Set controller LED color (supported controllers only)
773
+ *
774
+ * @param inputHandle - Controller handle
775
+ * @param colorR - Red (0-255)
776
+ * @param colorG - Green (0-255)
777
+ * @param colorB - Blue (0-255)
778
+ * @param flags - LED flags (0 = set color, 1 = restore default)
779
+ *
780
+ * @example
781
+ * ```typescript
782
+ * // Set LED to red
783
+ * inputManager.setLEDColor(handle, 255, 0, 0, 0);
784
+ *
785
+ * // Set LED to blue
786
+ * inputManager.setLEDColor(handle, 0, 0, 255, 0);
787
+ *
788
+ * // Restore default LED color
789
+ * inputManager.setLEDColor(handle, 0, 0, 0, 1);
790
+ * ```
791
+ */
792
+ setLEDColor(inputHandle, colorR, colorG, colorB, flags = 0) {
793
+ const iface = this.getSteamInputInterface();
794
+ if (!iface)
795
+ return;
796
+ try {
797
+ this.libraryLoader.SteamAPI_ISteamInput_SetLEDColor(iface, inputHandle, colorR, colorG, colorB, flags);
798
+ }
799
+ catch (error) {
800
+ console.error('[SteamInput] SetLEDColor error:', error);
801
+ }
802
+ }
803
+ /**
804
+ * Trigger a legacy haptic pulse (Steam Controller)
805
+ *
806
+ * @param inputHandle - Controller handle
807
+ * @param targetPad - Left or right pad
808
+ * @param durationMicroSec - Duration in microseconds
809
+ */
810
+ legacyTriggerHapticPulse(inputHandle, targetPad, durationMicroSec) {
811
+ const iface = this.getSteamInputInterface();
812
+ if (!iface)
813
+ return;
814
+ try {
815
+ this.libraryLoader.SteamAPI_ISteamInput_Legacy_TriggerHapticPulse(iface, inputHandle, targetPad, durationMicroSec);
816
+ }
817
+ catch (error) {
818
+ console.error('[SteamInput] Legacy_TriggerHapticPulse error:', error);
819
+ }
820
+ }
821
+ // ========================================
822
+ // Glyphs and Localization
823
+ // ========================================
824
+ /**
825
+ * Get the path to a PNG glyph for an action origin
826
+ *
827
+ * Useful for showing button prompts in your UI.
828
+ *
829
+ * @param origin - Action origin (button)
830
+ * @param size - Glyph size (small, medium, large)
831
+ * @param flags - Glyph style flags
832
+ * @returns Path to PNG file, or empty string if not available
833
+ *
834
+ * @example
835
+ * ```typescript
836
+ * const origins = inputManager.getDigitalActionOrigins(handle, actionSet, jumpHandle);
837
+ * if (origins.length > 0) {
838
+ * const glyphPath = inputManager.getGlyphPNGForActionOrigin(
839
+ * origins[0],
840
+ * SteamInputGlyphSize.Medium,
841
+ * SteamInputGlyphStyle.Dark
842
+ * );
843
+ * // Display glyph image in UI
844
+ * }
845
+ * ```
846
+ */
847
+ getGlyphPNGForActionOrigin(origin, size, flags) {
848
+ const iface = this.getSteamInputInterface();
849
+ if (!iface)
850
+ return '';
851
+ try {
852
+ return this.libraryLoader.SteamAPI_ISteamInput_GetGlyphPNGForActionOrigin(iface, origin, size, flags) || '';
853
+ }
854
+ catch (error) {
855
+ console.error('[SteamInput] GetGlyphPNGForActionOrigin error:', error);
856
+ return '';
857
+ }
858
+ }
859
+ /**
860
+ * Get the path to an SVG glyph for an action origin
861
+ *
862
+ * @param origin - Action origin (button)
863
+ * @param flags - Glyph style flags
864
+ * @returns Path to SVG file, or empty string if not available
865
+ */
866
+ getGlyphSVGForActionOrigin(origin, flags) {
867
+ const iface = this.getSteamInputInterface();
868
+ if (!iface)
869
+ return '';
870
+ try {
871
+ return this.libraryLoader.SteamAPI_ISteamInput_GetGlyphSVGForActionOrigin(iface, origin, flags) || '';
872
+ }
873
+ catch (error) {
874
+ console.error('[SteamInput] GetGlyphSVGForActionOrigin error:', error);
875
+ return '';
876
+ }
877
+ }
878
+ /**
879
+ * Get localized string for an action origin
880
+ *
881
+ * @param origin - Action origin (button)
882
+ * @returns Localized button name (e.g., "A Button", "Cross")
883
+ */
884
+ getStringForActionOrigin(origin) {
885
+ const iface = this.getSteamInputInterface();
886
+ if (!iface)
887
+ return '';
888
+ try {
889
+ return this.libraryLoader.SteamAPI_ISteamInput_GetStringForActionOrigin(iface, origin) || '';
890
+ }
891
+ catch (error) {
892
+ console.error('[SteamInput] GetStringForActionOrigin error:', error);
893
+ return '';
894
+ }
895
+ }
896
+ // ========================================
897
+ // Utility
898
+ // ========================================
899
+ /**
900
+ * Open the Steam Input configuration UI
901
+ *
902
+ * Shows the binding panel where users can customize their controller configuration.
903
+ *
904
+ * @param inputHandle - Controller handle
905
+ * @returns True if successful
906
+ *
907
+ * @example
908
+ * ```typescript
909
+ * // In your settings menu
910
+ * if (userClicksConfigureController) {
911
+ * inputManager.showBindingPanel(controllerHandle);
912
+ * }
913
+ * ```
914
+ */
915
+ showBindingPanel(inputHandle) {
916
+ const iface = this.getSteamInputInterface();
917
+ if (!iface)
918
+ return false;
919
+ try {
920
+ return this.libraryLoader.SteamAPI_ISteamInput_ShowBindingPanel(iface, inputHandle);
921
+ }
922
+ catch (error) {
923
+ console.error('[SteamInput] ShowBindingPanel error:', error);
924
+ return false;
925
+ }
926
+ }
927
+ /**
928
+ * Get the binding revision for a device
929
+ *
930
+ * @param inputHandle - Controller handle
931
+ * @returns Device binding revision, or null if not available
932
+ */
933
+ getDeviceBindingRevision(inputHandle) {
934
+ const iface = this.getSteamInputInterface();
935
+ if (!iface)
936
+ return null;
937
+ try {
938
+ const majorBuffer = Buffer.alloc(4);
939
+ const minorBuffer = Buffer.alloc(4);
940
+ const success = this.libraryLoader.SteamAPI_ISteamInput_GetDeviceBindingRevision(iface, inputHandle, majorBuffer, minorBuffer);
941
+ if (success) {
942
+ return {
943
+ major: majorBuffer.readInt32LE(0),
944
+ minor: minorBuffer.readInt32LE(0),
945
+ };
946
+ }
947
+ return null;
948
+ }
949
+ catch (error) {
950
+ console.error('[SteamInput] GetDeviceBindingRevision error:', error);
951
+ return null;
952
+ }
953
+ }
954
+ /**
955
+ * Get the Remote Play session ID for a controller
956
+ *
957
+ * @param inputHandle - Controller handle
958
+ * @returns Session ID, or 0 if not in a Remote Play session
959
+ */
960
+ getRemotePlaySessionID(inputHandle) {
961
+ const iface = this.getSteamInputInterface();
962
+ if (!iface)
963
+ return 0;
964
+ try {
965
+ return this.libraryLoader.SteamAPI_ISteamInput_GetRemotePlaySessionID(iface, inputHandle);
966
+ }
967
+ catch (error) {
968
+ console.error('[SteamInput] GetRemotePlaySessionID error:', error);
969
+ return 0;
970
+ }
971
+ }
972
+ /**
973
+ * Get the current session input configuration settings
974
+ *
975
+ * Returns a bitmask of ESteamInputConfigurationEnableType values.
976
+ *
977
+ * @returns Configuration settings bitmask
978
+ */
979
+ getSessionInputConfigurationSettings() {
980
+ const iface = this.getSteamInputInterface();
981
+ if (!iface)
982
+ return 0;
983
+ try {
984
+ return this.libraryLoader.SteamAPI_ISteamInput_GetSessionInputConfigurationSettings(iface);
985
+ }
986
+ catch (error) {
987
+ console.error('[SteamInput] GetSessionInputConfigurationSettings error:', error);
988
+ return 0;
989
+ }
990
+ }
991
+ }
992
+ exports.SteamInputManager = SteamInputManager;
993
+ //# sourceMappingURL=SteamInputManager.js.map