@rpgjs/client 5.0.0-alpha.2 → 5.0.0-alpha.21

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 (172) hide show
  1. package/dist/Game/AnimationManager.d.ts +8 -0
  2. package/dist/Game/Map.d.ts +7 -1
  3. package/dist/Gui/Gui.d.ts +170 -5
  4. package/dist/Resource.d.ts +97 -0
  5. package/dist/RpgClient.d.ts +259 -59
  6. package/dist/RpgClientEngine.d.ts +379 -6
  7. package/dist/Sound.d.ts +199 -0
  8. package/dist/components/animations/index.d.ts +4 -0
  9. package/dist/components/dynamics/parse-value.d.ts +1 -0
  10. package/dist/components/gui/index.d.ts +3 -3
  11. package/dist/components/index.d.ts +3 -1
  12. package/dist/components/prebuilt/index.d.ts +18 -0
  13. package/dist/index.d.ts +6 -1
  14. package/dist/index.js +11 -4
  15. package/dist/index.js.map +1 -1
  16. package/dist/index10.js +149 -4
  17. package/dist/index10.js.map +1 -1
  18. package/dist/index11.js +22 -7
  19. package/dist/index11.js.map +1 -1
  20. package/dist/index12.js +6 -4
  21. package/dist/index12.js.map +1 -1
  22. package/dist/index13.js +11 -14
  23. package/dist/index13.js.map +1 -1
  24. package/dist/index14.js +8 -40
  25. package/dist/index14.js.map +1 -1
  26. package/dist/index15.js +217 -180
  27. package/dist/index15.js.map +1 -1
  28. package/dist/index16.js +104 -7
  29. package/dist/index16.js.map +1 -1
  30. package/dist/index17.js +82 -372
  31. package/dist/index17.js.map +1 -1
  32. package/dist/index18.js +110 -27
  33. package/dist/index18.js.map +1 -1
  34. package/dist/index19.js +360 -18
  35. package/dist/index19.js.map +1 -1
  36. package/dist/index2.js +726 -32
  37. package/dist/index2.js.map +1 -1
  38. package/dist/index20.js +5 -2416
  39. package/dist/index20.js.map +1 -1
  40. package/dist/index21.js +47 -109
  41. package/dist/index21.js.map +1 -1
  42. package/dist/index22.js +7 -107
  43. package/dist/index22.js.map +1 -1
  44. package/dist/index23.js +394 -65
  45. package/dist/index23.js.map +1 -1
  46. package/dist/index24.js +40 -15
  47. package/dist/index24.js.map +1 -1
  48. package/dist/index25.js +20 -36
  49. package/dist/index25.js.map +1 -1
  50. package/dist/index26.js +2629 -1
  51. package/dist/index26.js.map +1 -1
  52. package/dist/index27.js +102 -310
  53. package/dist/index27.js.map +1 -1
  54. package/dist/index28.js +63 -17
  55. package/dist/index28.js.map +1 -1
  56. package/dist/index29.js +18 -8
  57. package/dist/index29.js.map +1 -1
  58. package/dist/index3.js +70 -8
  59. package/dist/index3.js.map +1 -1
  60. package/dist/index30.js +24 -8
  61. package/dist/index30.js.map +1 -1
  62. package/dist/index31.js +88 -167
  63. package/dist/index31.js.map +1 -1
  64. package/dist/index32.js +34 -494
  65. package/dist/index32.js.map +1 -1
  66. package/dist/index33.js +22 -10
  67. package/dist/index33.js.map +1 -1
  68. package/dist/index34.js +3 -4401
  69. package/dist/index34.js.map +1 -1
  70. package/dist/index35.js +20 -1
  71. package/dist/index35.js.map +1 -1
  72. package/dist/index36.js +18 -82
  73. package/dist/index36.js.map +1 -1
  74. package/dist/index37.js +8 -58
  75. package/dist/index37.js.map +1 -1
  76. package/dist/index38.js +4 -13
  77. package/dist/index38.js.map +1 -1
  78. package/dist/index39.js +10 -18
  79. package/dist/index39.js.map +1 -1
  80. package/dist/index4.js +25 -5
  81. package/dist/index4.js.map +1 -1
  82. package/dist/index40.js +7 -0
  83. package/dist/index40.js.map +1 -0
  84. package/dist/index41.js +3690 -0
  85. package/dist/index41.js.map +1 -0
  86. package/dist/index42.js +187 -0
  87. package/dist/index42.js.map +1 -0
  88. package/dist/index43.js +504 -0
  89. package/dist/index43.js.map +1 -0
  90. package/dist/index44.js +77 -0
  91. package/dist/index44.js.map +1 -0
  92. package/dist/index45.js +6 -0
  93. package/dist/index45.js.map +1 -0
  94. package/dist/index46.js +20 -0
  95. package/dist/index46.js.map +1 -0
  96. package/dist/index47.js +146 -0
  97. package/dist/index47.js.map +1 -0
  98. package/dist/index48.js +12 -0
  99. package/dist/index48.js.map +1 -0
  100. package/dist/index49.js +113 -0
  101. package/dist/index49.js.map +1 -0
  102. package/dist/index5.js +2 -1
  103. package/dist/index5.js.map +1 -1
  104. package/dist/index50.js +136 -0
  105. package/dist/index50.js.map +1 -0
  106. package/dist/index51.js +137 -0
  107. package/dist/index51.js.map +1 -0
  108. package/dist/index52.js +112 -0
  109. package/dist/index52.js.map +1 -0
  110. package/dist/index53.js +141 -0
  111. package/dist/index53.js.map +1 -0
  112. package/dist/index54.js +9 -0
  113. package/dist/index54.js.map +1 -0
  114. package/dist/index55.js +54 -0
  115. package/dist/index55.js.map +1 -0
  116. package/dist/index6.js +1 -1
  117. package/dist/index6.js.map +1 -1
  118. package/dist/index7.js +11 -3
  119. package/dist/index7.js.map +1 -1
  120. package/dist/index8.js +68 -7
  121. package/dist/index8.js.map +1 -1
  122. package/dist/index9.js +278 -15
  123. package/dist/index9.js.map +1 -1
  124. package/dist/presets/animation.d.ts +31 -0
  125. package/dist/presets/faceset.d.ts +30 -0
  126. package/dist/presets/index.d.ts +103 -0
  127. package/dist/presets/lpc.d.ts +89 -0
  128. package/dist/services/keyboardControls.d.ts +5 -0
  129. package/dist/services/loadMap.d.ts +123 -2
  130. package/dist/services/mmorpg.d.ts +12 -4
  131. package/dist/services/standalone.d.ts +54 -2
  132. package/package.json +22 -18
  133. package/src/Game/{EffectManager.ts → AnimationManager.ts} +3 -2
  134. package/src/Game/Map.ts +20 -2
  135. package/src/Game/Object.ts +163 -9
  136. package/src/Gui/Gui.ts +362 -17
  137. package/src/Resource.ts +150 -0
  138. package/src/RpgClient.ts +264 -58
  139. package/src/RpgClientEngine.ts +848 -36
  140. package/src/Sound.ts +253 -0
  141. package/src/components/{effects → animations}/animation.ce +3 -6
  142. package/src/components/{effects → animations}/index.ts +1 -1
  143. package/src/components/character.ce +193 -36
  144. package/src/components/dynamics/parse-value.ts +80 -0
  145. package/src/components/dynamics/text.ce +183 -0
  146. package/src/components/gui/box.ce +17 -0
  147. package/src/components/gui/dialogbox/index.ce +73 -35
  148. package/src/components/gui/dialogbox/selection.ce +16 -1
  149. package/src/components/gui/index.ts +3 -4
  150. package/src/components/index.ts +5 -1
  151. package/src/components/prebuilt/hp-bar.ce +255 -0
  152. package/src/components/prebuilt/index.ts +22 -0
  153. package/src/components/scenes/canvas.ce +12 -10
  154. package/src/components/scenes/draw-map.ce +6 -23
  155. package/src/components/scenes/event-layer.ce +9 -3
  156. package/src/core/setup.ts +2 -0
  157. package/src/index.ts +7 -2
  158. package/src/module.ts +72 -6
  159. package/src/presets/animation.ts +46 -0
  160. package/src/presets/faceset.ts +60 -0
  161. package/src/presets/index.ts +7 -1
  162. package/src/presets/lpc.ts +108 -0
  163. package/src/services/keyboardControls.ts +8 -0
  164. package/src/services/loadMap.ts +132 -3
  165. package/src/services/mmorpg.ts +29 -5
  166. package/src/services/standalone.ts +70 -6
  167. package/tsconfig.json +1 -1
  168. package/vite.config.ts +1 -1
  169. package/dist/Game/EffectManager.d.ts +0 -5
  170. package/dist/components/effects/index.d.ts +0 -4
  171. package/src/components/scenes/element-map.ce +0 -23
  172. /package/src/components/{effects → animations}/hit.ce +0 -0
@@ -1,5 +1,10 @@
1
1
  import { Context } from '@signe/di';
2
- import { EffectManager } from './Game/EffectManager';
2
+ import { AbstractWebsocket } from './services/AbstractSocket';
3
+ import { Direction } from '@rpgjs/common';
4
+ import { RpgClientMap } from './Game/Map';
5
+ import { AnimationManager } from './Game/AnimationManager';
6
+ import { Observable } from 'rxjs';
7
+ import * as PIXI from "pixi.js";
3
8
  export declare class RpgClientEngine<T = any> {
4
9
  context: Context;
5
10
  private guiService;
@@ -15,29 +20,397 @@ export declare class RpgClientEngine<T = any> {
15
20
  height: import('canvasengine').WritableSignal<string>;
16
21
  spritesheets: Map<string, any>;
17
22
  sounds: Map<string, any>;
18
- effects: any[];
23
+ componentAnimations: any[];
24
+ private spritesheetResolver?;
25
+ private soundResolver?;
19
26
  particleSettings: {
20
27
  emitters: any[];
21
28
  };
29
+ renderer: PIXI.Renderer;
30
+ tick: Observable<number>;
31
+ playerIdSignal: import('canvasengine').WritableSignal<string | null>;
32
+ spriteComponentsBehind: import('canvasengine').WritableArraySignal<any[]>;
33
+ spriteComponentsInFront: import('canvasengine').WritableArraySignal<any[]>;
34
+ private predictionEnabled;
35
+ private prediction?;
36
+ private readonly SERVER_CORRECTION_THRESHOLD;
37
+ private inputFrameCounter;
38
+ private frameOffset;
39
+ private rtt;
40
+ private pingInterval;
41
+ private readonly PING_INTERVAL_MS;
42
+ private lastInputTime;
22
43
  constructor(context: Context);
44
+ /**
45
+ * Assigns a CanvasEngine KeyboardControls instance to the dependency injection context
46
+ *
47
+ * This method registers a KeyboardControls instance from CanvasEngine into the DI container,
48
+ * making it available for injection throughout the application. The particularity is that
49
+ * this method is automatically called when a sprite is displayed on the map, allowing the
50
+ * controls to be automatically associated with the active sprite.
51
+ *
52
+ * ## Design
53
+ *
54
+ * - The instance is stored in the DI context under the `KeyboardControls` token
55
+ * - It's automatically assigned when a sprite component mounts (in `character.ce`)
56
+ * - The controls instance comes from the CanvasEngine component's directives
57
+ * - Once registered, it can be retrieved using `inject(KeyboardControls)` from anywhere
58
+ *
59
+ * @param controlInstance - The CanvasEngine KeyboardControls instance to register
60
+ *
61
+ * @example
62
+ * ```ts
63
+ * // The method is automatically called when a sprite is displayed:
64
+ * // client.setKeyboardControls(element.directives.controls)
65
+ *
66
+ * // Later, retrieve and use the controls instance:
67
+ * import { Input, inject, KeyboardControls } from '@rpgjs/client'
68
+ *
69
+ * const controls = inject(KeyboardControls)
70
+ * const control = controls.getControl(Input.Enter)
71
+ *
72
+ * if (control) {
73
+ * console.log(control.actionName) // 'action'
74
+ * }
75
+ * ```
76
+ */
77
+ setKeyboardControls(controlInstance: any): void;
23
78
  start(): Promise<void>;
24
79
  private initListeners;
80
+ /**
81
+ * Start periodic ping/pong for client-server synchronization
82
+ *
83
+ * Sends ping requests to the server to measure round-trip time (RTT) and
84
+ * calculate the frame offset between client and server ticks.
85
+ *
86
+ * ## Design
87
+ *
88
+ * - Sends ping every 5 seconds
89
+ * - Measures RTT for latency compensation
90
+ * - Calculates frame offset to map client frames to server ticks
91
+ * - Used for accurate server reconciliation
92
+ *
93
+ * @example
94
+ * ```ts
95
+ * // Called automatically when connection opens
96
+ * this.startPingPong();
97
+ * ```
98
+ */
99
+ private startPingPong;
100
+ /**
101
+ * Stop periodic ping/pong
102
+ *
103
+ * Stops the ping interval when disconnecting or changing maps.
104
+ *
105
+ * @example
106
+ * ```ts
107
+ * // Called automatically when connection closes
108
+ * this.stopPingPong();
109
+ * ```
110
+ */
111
+ private stopPingPong;
112
+ /**
113
+ * Send a ping request to the server
114
+ *
115
+ * Sends current client time and frame counter to the server,
116
+ * which will respond with its server tick for synchronization.
117
+ *
118
+ * @example
119
+ * ```ts
120
+ * // Send a ping to measure RTT
121
+ * this.sendPing();
122
+ * ```
123
+ */
124
+ private sendPing;
25
125
  private loadScene;
26
126
  addSpriteSheet<T = any>(spritesheetClass: any, id?: string): any;
127
+ /**
128
+ * Set a resolver function for spritesheets
129
+ *
130
+ * The resolver is called when a spritesheet is requested but not found in the cache.
131
+ * It can be synchronous (returns directly) or asynchronous (returns a Promise).
132
+ * The resolved spritesheet is automatically cached for future use.
133
+ *
134
+ * @param resolver - Function that takes a spritesheet ID and returns a spritesheet or Promise of spritesheet
135
+ *
136
+ * @example
137
+ * ```ts
138
+ * // Synchronous resolver
139
+ * engine.setSpritesheetResolver((id) => {
140
+ * if (id === 'dynamic-sprite') {
141
+ * return { id: 'dynamic-sprite', image: 'path/to/image.png', framesWidth: 32, framesHeight: 32 };
142
+ * }
143
+ * return undefined;
144
+ * });
145
+ *
146
+ * // Asynchronous resolver (loading from API)
147
+ * engine.setSpritesheetResolver(async (id) => {
148
+ * const response = await fetch(`/api/spritesheets/${id}`);
149
+ * const data = await response.json();
150
+ * return data;
151
+ * });
152
+ * ```
153
+ */
154
+ setSpritesheetResolver(resolver: (id: string) => any | Promise<any>): void;
155
+ /**
156
+ * Get a spritesheet by ID, using resolver if not found in cache
157
+ *
158
+ * This method first checks if the spritesheet exists in the cache.
159
+ * If not found and a resolver is set, it calls the resolver to create the spritesheet.
160
+ * The resolved spritesheet is automatically cached for future use.
161
+ *
162
+ * @param id - The spritesheet ID to retrieve
163
+ * @returns The spritesheet if found or created, or undefined if not found and no resolver
164
+ * @returns Promise<any> if the resolver is asynchronous
165
+ *
166
+ * @example
167
+ * ```ts
168
+ * // Synchronous usage
169
+ * const spritesheet = engine.getSpriteSheet('my-sprite');
170
+ *
171
+ * // Asynchronous usage (when resolver returns Promise)
172
+ * const spritesheet = await engine.getSpriteSheet('dynamic-sprite');
173
+ * ```
174
+ */
175
+ getSpriteSheet(id: string): any | Promise<any>;
176
+ /**
177
+ * Add a sound to the engine
178
+ *
179
+ * Adds a sound to the engine's sound cache. The sound can be:
180
+ * - A simple object with `id` and `src` properties
181
+ * - A Howler instance
182
+ * - An object with a `play()` method
183
+ *
184
+ * If the sound has a `src` property, a Howler instance will be created automatically.
185
+ *
186
+ * @param sound - The sound object or Howler instance
187
+ * @param id - Optional sound ID (if not provided, uses sound.id)
188
+ * @returns The added sound
189
+ *
190
+ * @example
191
+ * ```ts
192
+ * // Simple sound object
193
+ * engine.addSound({ id: 'click', src: 'click.mp3' });
194
+ *
195
+ * // With explicit ID
196
+ * engine.addSound({ src: 'music.mp3' }, 'background-music');
197
+ * ```
198
+ */
27
199
  addSound(sound: any, id?: string): any;
200
+ /**
201
+ * Set a resolver function for sounds
202
+ *
203
+ * The resolver is called when a sound is requested but not found in the cache.
204
+ * It can be synchronous (returns directly) or asynchronous (returns a Promise).
205
+ * The resolved sound is automatically cached for future use.
206
+ *
207
+ * @param resolver - Function that takes a sound ID and returns a sound or Promise of sound
208
+ *
209
+ * @example
210
+ * ```ts
211
+ * // Synchronous resolver
212
+ * engine.setSoundResolver((id) => {
213
+ * if (id === 'dynamic-sound') {
214
+ * return { id: 'dynamic-sound', src: 'path/to/sound.mp3' };
215
+ * }
216
+ * return undefined;
217
+ * });
218
+ *
219
+ * // Asynchronous resolver (loading from API)
220
+ * engine.setSoundResolver(async (id) => {
221
+ * const response = await fetch(`/api/sounds/${id}`);
222
+ * const data = await response.json();
223
+ * return data;
224
+ * });
225
+ * ```
226
+ */
227
+ setSoundResolver(resolver: (id: string) => any | Promise<any>): void;
228
+ /**
229
+ * Get a sound by ID, using resolver if not found in cache
230
+ *
231
+ * This method first checks if the sound exists in the cache.
232
+ * If not found and a resolver is set, it calls the resolver to create the sound.
233
+ * The resolved sound is automatically cached for future use.
234
+ *
235
+ * @param id - The sound ID to retrieve
236
+ * @returns The sound if found or created, or undefined if not found and no resolver
237
+ * @returns Promise<any> if the resolver is asynchronous
238
+ *
239
+ * @example
240
+ * ```ts
241
+ * // Synchronous usage
242
+ * const sound = engine.getSound('my-sound');
243
+ *
244
+ * // Asynchronous usage (when resolver returns Promise)
245
+ * const sound = await engine.getSound('dynamic-sound');
246
+ * ```
247
+ */
248
+ getSound(id: string): any | Promise<any>;
249
+ /**
250
+ * Play a sound by its ID
251
+ *
252
+ * This method retrieves a sound from the cache or resolver and plays it.
253
+ * If the sound is not found, it will attempt to resolve it using the soundResolver.
254
+ * Uses Howler.js for audio playback instead of native Audio elements.
255
+ *
256
+ * @param soundId - The sound ID to play
257
+ * @param options - Optional sound configuration
258
+ * @param options.volume - Volume level (0.0 to 1.0, overrides sound default)
259
+ * @param options.loop - Whether the sound should loop (overrides sound default)
260
+ *
261
+ * @example
262
+ * ```ts
263
+ * // Play a sound synchronously
264
+ * engine.playSound('item-pickup');
265
+ *
266
+ * // Play a sound with volume and loop
267
+ * engine.playSound('background-music', { volume: 0.5, loop: true });
268
+ *
269
+ * // Play a sound asynchronously (when resolver returns Promise)
270
+ * await engine.playSound('dynamic-sound', { volume: 0.8 });
271
+ * ```
272
+ */
273
+ playSound(soundId: string, options?: {
274
+ volume?: number;
275
+ loop?: boolean;
276
+ }): Promise<void>;
277
+ /**
278
+ * Stop a sound that is currently playing
279
+ *
280
+ * This method stops a sound that was previously started with `playSound()`.
281
+ *
282
+ * @param soundId - The sound ID to stop
283
+ *
284
+ * @example
285
+ * ```ts
286
+ * // Start a looping sound
287
+ * engine.playSound('background-music', { loop: true });
288
+ *
289
+ * // Later, stop it
290
+ * engine.stopSound('background-music');
291
+ * ```
292
+ */
293
+ stopSound(soundId: string): void;
28
294
  addParticle(particle: any): any;
29
- addEffect(effect: {
295
+ /**
296
+ * Add a component to render behind sprites
297
+ * Components added with this method will be displayed with a lower z-index than the sprite
298
+ *
299
+ * @param component - The component to add behind sprites
300
+ * @returns The added component
301
+ *
302
+ * @example
303
+ * ```ts
304
+ * // Add a shadow component behind all sprites
305
+ * engine.addSpriteComponentBehind(ShadowComponent);
306
+ * ```
307
+ */
308
+ addSpriteComponentBehind(component: any): any;
309
+ /**
310
+ * Add a component to render in front of sprites
311
+ * Components added with this method will be displayed with a higher z-index than the sprite
312
+ *
313
+ * @param component - The component to add in front of sprites
314
+ * @returns The added component
315
+ *
316
+ * @example
317
+ * ```ts
318
+ * // Add a health bar component in front of all sprites
319
+ * engine.addSpriteComponentInFront(HealthBarComponent);
320
+ * ```
321
+ */
322
+ addSpriteComponentInFront(component: any): any;
323
+ /**
324
+ * Add a component animation to the engine
325
+ *
326
+ * Component animations are temporary visual effects that can be displayed
327
+ * on sprites or objects, such as hit indicators, spell effects, or status animations.
328
+ *
329
+ * @param componentAnimation - The component animation configuration
330
+ * @param componentAnimation.id - Unique identifier for the animation
331
+ * @param componentAnimation.component - The component function to render
332
+ * @returns The added component animation configuration
333
+ *
334
+ * @example
335
+ * ```ts
336
+ * // Add a hit animation component
337
+ * engine.addComponentAnimation({
338
+ * id: 'hit',
339
+ * component: HitComponent
340
+ * });
341
+ *
342
+ * // Add an explosion effect component
343
+ * engine.addComponentAnimation({
344
+ * id: 'explosion',
345
+ * component: ExplosionComponent
346
+ * });
347
+ * ```
348
+ */
349
+ addComponentAnimation(componentAnimation: {
30
350
  component: any;
31
351
  id: string;
32
352
  }): {
33
353
  component: any;
34
354
  id: string;
35
355
  };
36
- getEffect(id: string): EffectManager;
356
+ /**
357
+ * Get a component animation by its ID
358
+ *
359
+ * Retrieves the EffectManager instance for a specific component animation,
360
+ * which can be used to display the animation on sprites or objects.
361
+ *
362
+ * @param id - The unique identifier of the component animation
363
+ * @returns The EffectManager instance for the animation
364
+ * @throws Error if the component animation is not found
365
+ *
366
+ * @example
367
+ * ```ts
368
+ * // Get the hit animation and display it
369
+ * const hitAnimation = engine.getComponentAnimation('hit');
370
+ * hitAnimation.displayEffect({ text: "Critical!" }, player);
371
+ * ```
372
+ */
373
+ getComponentAnimation(id: string): AnimationManager;
37
374
  processInput({ input }: {
38
- input: number;
39
- }): void;
375
+ input: Direction;
376
+ }): Promise<void>;
40
377
  processAction({ action }: {
41
378
  action: number;
42
379
  }): void;
380
+ get PIXI(): typeof PIXI;
381
+ get socket(): AbstractWebsocket;
382
+ get playerId(): string | null;
383
+ get scene(): RpgClientMap;
384
+ private getPhysicsTick;
385
+ private getLocalPlayerState;
386
+ private applyAuthoritativeState;
387
+ private initializePredictionController;
388
+ getCurrentPlayer(): import('./Game/Player').RpgClientPlayer;
389
+ /**
390
+ * Clear client prediction states for cleanup
391
+ *
392
+ * Removes old prediction states and input history to prevent memory leaks.
393
+ * Should be called when changing maps or disconnecting.
394
+ *
395
+ * @example
396
+ * ```ts
397
+ * // Clear prediction states when changing maps
398
+ * engine.clearClientPredictionStates();
399
+ * ```
400
+ */
401
+ clearClientPredictionStates(): void;
402
+ private applyServerAck;
403
+ /**
404
+ * Replay unacknowledged inputs from a given frame to resimulate client prediction
405
+ * after applying server authority at a certain frame.
406
+ *
407
+ * @param startFrame - The last server-acknowledged frame
408
+ *
409
+ * @example
410
+ * ```ts
411
+ * // After applying a server correction at frame N
412
+ * this.replayUnackedInputsFromFrame(N);
413
+ * ```
414
+ */
415
+ private replayUnackedInputsFromFrame;
43
416
  }
@@ -0,0 +1,199 @@
1
+ import { Howler } from 'canvasengine';
2
+ import { RpgClientEngine } from './RpgClientEngine';
3
+ /**
4
+ * Sound decorator options
5
+ *
6
+ * Defines the configuration for a sound that can be played in the game.
7
+ * The sound can be a single file or multiple files (for different formats).
8
+ *
9
+ * @interface SoundOptions
10
+ */
11
+ export interface SoundOptions {
12
+ /**
13
+ * Sound identifier. Used to retrieve the sound later with RpgSound.get()
14
+ *
15
+ * @type {string}
16
+ */
17
+ id?: string;
18
+ /**
19
+ * Single sound file path. Use require() to wrap the path.
20
+ *
21
+ * @type {string}
22
+ * @example
23
+ * sound: require('./assets/sound.ogg')
24
+ */
25
+ sound?: string;
26
+ /**
27
+ * Multiple sounds with different IDs. The key is the sound ID and the value is the file path.
28
+ * Use require() to wrap each path.
29
+ *
30
+ * @type {{ [id: string]: string }}
31
+ * @example
32
+ * sounds: {
33
+ * hero: require('./assets/hero.ogg'),
34
+ * monster: require('./assets/monster.ogg')
35
+ * }
36
+ */
37
+ sounds?: {
38
+ [id: string]: string;
39
+ };
40
+ /**
41
+ * Whether the sound should loop when it finishes playing.
42
+ *
43
+ * @type {boolean}
44
+ * @default false
45
+ */
46
+ loop?: boolean;
47
+ /**
48
+ * Volume level (0.0 to 1.0).
49
+ *
50
+ * @type {number}
51
+ * @default 1.0
52
+ */
53
+ volume?: number;
54
+ }
55
+ /**
56
+ * Metadata stored on the class decorated with @Sound
57
+ *
58
+ * @interface SoundMetadata
59
+ */
60
+ interface SoundMetadata {
61
+ id?: string;
62
+ sound?: string;
63
+ sounds?: {
64
+ [id: string]: string;
65
+ };
66
+ loop?: boolean;
67
+ volume?: number;
68
+ }
69
+ /**
70
+ * Sound decorator
71
+ *
72
+ * Decorates a class to define a sound configuration. The decorated class can be
73
+ * added to the RpgClient module configuration, and the sound will be automatically
74
+ * registered and available through RpgSound.get().
75
+ *
76
+ * ## Design
77
+ *
78
+ * The decorator stores metadata on the class that is later used by the module loader
79
+ * to register sounds with the engine. The sound is created using Howler.js for
80
+ * advanced audio features like looping, volume control, and cross-browser compatibility.
81
+ *
82
+ * @param options - Sound configuration options
83
+ *
84
+ * @example
85
+ * ```ts
86
+ * import { Sound } from '@rpgjs/client'
87
+ *
88
+ * @Sound({
89
+ * id: 'town-music',
90
+ * sound: require('./sound/town.ogg'),
91
+ * loop: true,
92
+ * volume: 0.5
93
+ * })
94
+ * export class TownMusic {}
95
+ *
96
+ * // Multiple sounds in one class
97
+ * @Sound({
98
+ * sounds: {
99
+ * hero: require('./assets/hero.ogg'),
100
+ * monster: require('./assets/monster.ogg')
101
+ * },
102
+ * loop: true
103
+ * })
104
+ * export class CharacterSounds {}
105
+ * ```
106
+ */
107
+ export declare function Sound(options: SoundOptions): <T extends {
108
+ new (...args: any[]): {};
109
+ }>(constructor: T) => T;
110
+ /**
111
+ * Get sound metadata from a decorated class
112
+ *
113
+ * @param soundClass - The class decorated with @Sound
114
+ * @returns The sound metadata or undefined
115
+ */
116
+ export declare function getSoundMetadata(soundClass: any): SoundMetadata | undefined;
117
+ /**
118
+ * RpgSound class
119
+ *
120
+ * Provides a unified API to manage sounds in the game. Uses Howler.js internally
121
+ * for advanced audio features. Sounds can be retrieved by ID and controlled
122
+ * using Howler.js methods.
123
+ *
124
+ * ## Design
125
+ *
126
+ * RpgSound acts as a facade over Howler.js, providing easy access to sounds
127
+ * registered in the engine. It supports both individual sound control and
128
+ * global sound management (volume, mute, etc.).
129
+ *
130
+ * @example
131
+ * ```ts
132
+ * import { RpgSound } from '@rpgjs/client'
133
+ *
134
+ * // Play a sound
135
+ * RpgSound.get('town-music').play()
136
+ *
137
+ * // Control volume
138
+ * RpgSound.get('town-music').volume(0.5)
139
+ *
140
+ * // Stop a sound
141
+ * RpgSound.get('town-music').stop()
142
+ *
143
+ * // Global volume control
144
+ * RpgSound.global.volume(0.2)
145
+ * ```
146
+ */
147
+ export declare class RpgSound {
148
+ private static engine;
149
+ /**
150
+ * Initialize RpgSound with the engine instance
151
+ *
152
+ * This is called automatically by the engine during initialization.
153
+ *
154
+ * @param engine - The RpgClientEngine instance
155
+ */
156
+ static init(engine: RpgClientEngine): void;
157
+ /**
158
+ * Get a sound by its ID
159
+ *
160
+ * Retrieves a Howler sound instance from the engine's sound cache.
161
+ * The sound must be registered beforehand (via @Sound decorator or manually).
162
+ *
163
+ * @param id - The sound identifier
164
+ * @returns The Howler sound instance, or undefined if not found
165
+ *
166
+ * @example
167
+ * ```ts
168
+ * // Get and play a sound
169
+ * const sound = RpgSound.get('town-music');
170
+ * if (sound) {
171
+ * sound.play();
172
+ * }
173
+ *
174
+ * // Chain methods
175
+ * RpgSound.get('battle-theme')?.volume(0.8).play();
176
+ * ```
177
+ */
178
+ static get(id: string): any;
179
+ /**
180
+ * Global Howler instance for managing all sounds
181
+ *
182
+ * Provides access to Howler.js global methods for controlling all sounds
183
+ * at once (volume, mute, etc.).
184
+ *
185
+ * @example
186
+ * ```ts
187
+ * // Set global volume to 20%
188
+ * RpgSound.global.volume(0.2)
189
+ *
190
+ * // Mute all sounds
191
+ * RpgSound.global.mute(true)
192
+ *
193
+ * // Unmute all sounds
194
+ * RpgSound.global.mute(false)
195
+ * ```
196
+ */
197
+ static get global(): typeof Howler;
198
+ }
199
+ export {};
@@ -0,0 +1,4 @@
1
+ export declare const PrebuiltComponentAnimations: {
2
+ Hit: any;
3
+ Animation: any;
4
+ };
@@ -0,0 +1 @@
1
+ export declare const parseDynamicValue: (value: any, object?: any) => import('canvasengine').ComputedSignal<string>;
@@ -1,3 +1,3 @@
1
- export declare const PrebuiltGui: {
2
- Dialogbox: any;
3
- };
1
+ import { default as DialogboxComponent } from './dialogbox/index.ce';
2
+ import { default as BoxComponent } from './box.ce';
3
+ export { DialogboxComponent, BoxComponent };
@@ -1,2 +1,4 @@
1
1
  import { default as EventLayerComponent } from './scenes/event-layer.ce';
2
- export { EventLayerComponent };
2
+ import { default as CharacterComponent } from './character.ce';
3
+ export { HpBar } from './prebuilt';
4
+ export { EventLayerComponent, CharacterComponent };
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Prebuilt sprite components for common UI elements
3
+ *
4
+ * This module exports ready-to-use components that can be attached
5
+ * to sprites using componentsInFront or componentsBehind configuration.
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * import { HpBar } from '@rpgjs/client/components/prebuilt';
10
+ *
11
+ * export default defineModule<RpgClient>({
12
+ * sprite: {
13
+ * componentsInFront: [HpBar]
14
+ * }
15
+ * })
16
+ * ```
17
+ */
18
+ export { default as HpBar } from './hp-bar.ce';
package/dist/index.d.ts CHANGED
@@ -8,6 +8,11 @@ export * from './services/loadMap';
8
8
  export * from './module';
9
9
  export * from './Gui/Gui';
10
10
  export * from './components/gui';
11
- export * from './components/effects';
11
+ export * from './components/animations';
12
12
  export * from './presets';
13
13
  export * from './components';
14
+ export * from './components/gui';
15
+ export * from './Sound';
16
+ export * from './Resource';
17
+ export { Context } from '@signe/di';
18
+ export * from './services/keyboardControls';
package/dist/index.js CHANGED
@@ -6,8 +6,15 @@ export { clearInject, context, inject, setInject } from './index6.js';
6
6
  export { LoadMapService, LoadMapToken, provideLoadMap } from './index7.js';
7
7
  export { GlobalConfigToken, provideClientGlobalConfig, provideClientModules, provideGlobalConfig } from './index8.js';
8
8
  export { RpgGui } from './index9.js';
9
- export { PrebuiltGui } from './index10.js';
10
- export { PrebuiltEffects } from './index11.js';
11
- export { Presets } from './index12.js';
12
- export { default as EventLayerComponent } from './index13.js';
9
+ export { default as DialogboxComponent } from './index10.js';
10
+ export { default as BoxComponent } from './index11.js';
11
+ export { PrebuiltComponentAnimations } from './index12.js';
12
+ export { Presets } from './index13.js';
13
+ export { default as EventLayerComponent } from './index14.js';
14
+ export { default as CharacterComponent } from './index15.js';
15
+ export { default as HpBar } from './index16.js';
16
+ export { RpgSound, Sound, getSoundMetadata } from './index17.js';
17
+ export { RpgResource } from './index18.js';
18
+ export { Context } from './index19.js';
19
+ export { KeyboardControls, provideKeyboardControls } from './index20.js';
13
20
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;"}