@rpgjs/client 5.0.0-alpha.3 → 5.0.0-alpha.30

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 (275) hide show
  1. package/dist/Game/AnimationManager.d.ts +8 -0
  2. package/dist/{index19.js → Game/AnimationManager.js} +4 -3
  3. package/dist/Game/AnimationManager.js.map +1 -0
  4. package/dist/{index30.js → Game/Event.js} +2 -2
  5. package/dist/Game/Event.js.map +1 -0
  6. package/dist/Game/Map.d.ts +8 -1
  7. package/dist/Game/Map.js +54 -0
  8. package/dist/Game/Map.js.map +1 -0
  9. package/dist/Game/Object.d.ts +129 -0
  10. package/dist/Game/Object.js +218 -0
  11. package/dist/Game/Object.js.map +1 -0
  12. package/dist/{index29.js → Game/Player.js} +2 -2
  13. package/dist/Game/Player.js.map +1 -0
  14. package/dist/Gui/Gui.d.ts +177 -5
  15. package/dist/Gui/Gui.js +478 -0
  16. package/dist/Gui/Gui.js.map +1 -0
  17. package/dist/Gui/NotificationManager.d.ts +23 -0
  18. package/dist/Gui/NotificationManager.js +51 -0
  19. package/dist/Gui/NotificationManager.js.map +1 -0
  20. package/dist/Resource.d.ts +97 -0
  21. package/dist/Resource.js +114 -0
  22. package/dist/Resource.js.map +1 -0
  23. package/dist/RpgClient.d.ts +259 -59
  24. package/dist/RpgClientEngine.d.ts +632 -9
  25. package/dist/RpgClientEngine.js +1262 -0
  26. package/dist/RpgClientEngine.js.map +1 -0
  27. package/dist/Sound.d.ts +199 -0
  28. package/dist/Sound.js +97 -0
  29. package/dist/Sound.js.map +1 -0
  30. package/dist/components/animations/animation.ce.js +21 -0
  31. package/dist/components/animations/animation.ce.js.map +1 -0
  32. package/dist/{index23.js → components/animations/hit.ce.js} +3 -3
  33. package/dist/components/animations/hit.ce.js.map +1 -0
  34. package/dist/components/animations/index.d.ts +4 -0
  35. package/dist/components/animations/index.js +10 -0
  36. package/dist/components/animations/index.js.map +1 -0
  37. package/dist/components/character.ce.js +316 -0
  38. package/dist/components/character.ce.js.map +1 -0
  39. package/dist/components/dynamics/parse-value.d.ts +1 -0
  40. package/dist/components/dynamics/parse-value.js +54 -0
  41. package/dist/components/dynamics/parse-value.js.map +1 -0
  42. package/dist/components/dynamics/text.ce.js +141 -0
  43. package/dist/components/dynamics/text.ce.js.map +1 -0
  44. package/dist/components/gui/box.ce.js +27 -0
  45. package/dist/components/gui/box.ce.js.map +1 -0
  46. package/dist/components/gui/dialogbox/index.ce.js +152 -0
  47. package/dist/components/gui/dialogbox/index.ce.js.map +1 -0
  48. package/dist/components/gui/gameover.ce.js +141 -0
  49. package/dist/components/gui/gameover.ce.js.map +1 -0
  50. package/dist/components/gui/hud/hud.ce.js +35 -0
  51. package/dist/components/gui/hud/hud.ce.js.map +1 -0
  52. package/dist/components/gui/index.d.ts +15 -3
  53. package/dist/components/gui/menu/equip-menu.ce.js +349 -0
  54. package/dist/components/gui/menu/equip-menu.ce.js.map +1 -0
  55. package/dist/components/gui/menu/exit-menu.ce.js +35 -0
  56. package/dist/components/gui/menu/exit-menu.ce.js.map +1 -0
  57. package/dist/components/gui/menu/items-menu.ce.js +229 -0
  58. package/dist/components/gui/menu/items-menu.ce.js.map +1 -0
  59. package/dist/components/gui/menu/main-menu.ce.js +205 -0
  60. package/dist/components/gui/menu/main-menu.ce.js.map +1 -0
  61. package/dist/components/gui/menu/options-menu.ce.js +28 -0
  62. package/dist/components/gui/menu/options-menu.ce.js.map +1 -0
  63. package/dist/components/gui/menu/skills-menu.ce.js +53 -0
  64. package/dist/components/gui/menu/skills-menu.ce.js.map +1 -0
  65. package/dist/components/gui/mobile/index.d.ts +8 -0
  66. package/dist/components/gui/mobile/index.js +24 -0
  67. package/dist/components/gui/mobile/index.js.map +1 -0
  68. package/dist/components/gui/mobile/mobile.ce.js +17 -0
  69. package/dist/components/gui/mobile/mobile.ce.js.map +1 -0
  70. package/dist/components/gui/notification/notification.ce.js +38 -0
  71. package/dist/components/gui/notification/notification.ce.js.map +1 -0
  72. package/dist/components/gui/save-load.ce.js +242 -0
  73. package/dist/components/gui/save-load.ce.js.map +1 -0
  74. package/dist/components/gui/shop/shop.ce.js +322 -0
  75. package/dist/components/gui/shop/shop.ce.js.map +1 -0
  76. package/dist/components/gui/title-screen.ce.js +148 -0
  77. package/dist/components/gui/title-screen.ce.js.map +1 -0
  78. package/dist/components/index.d.ts +3 -1
  79. package/dist/components/prebuilt/hp-bar.ce.js +106 -0
  80. package/dist/components/prebuilt/hp-bar.ce.js.map +1 -0
  81. package/dist/components/prebuilt/index.d.ts +19 -0
  82. package/dist/components/prebuilt/light-halo.ce.js +76 -0
  83. package/dist/components/prebuilt/light-halo.ce.js.map +1 -0
  84. package/dist/components/scenes/canvas.ce.js +44 -0
  85. package/dist/components/scenes/canvas.ce.js.map +1 -0
  86. package/dist/components/scenes/draw-map.ce.js +34 -0
  87. package/dist/components/scenes/draw-map.ce.js.map +1 -0
  88. package/dist/{index13.js → components/scenes/event-layer.ce.js} +7 -6
  89. package/dist/components/scenes/event-layer.ce.js.map +1 -0
  90. package/dist/{index6.js → core/inject.js} +2 -2
  91. package/dist/core/inject.js.map +1 -0
  92. package/dist/core/setup.js +16 -0
  93. package/dist/core/setup.js.map +1 -0
  94. package/dist/index.d.ts +15 -1
  95. package/dist/index.js +40 -12
  96. package/dist/index.js.map +1 -1
  97. package/dist/module.d.ts +43 -4
  98. package/dist/module.js +175 -0
  99. package/dist/module.js.map +1 -0
  100. package/dist/node_modules/.pnpm/@signe_di@2.8.2/node_modules/@signe/di/dist/index.js +366 -0
  101. package/dist/node_modules/.pnpm/@signe_di@2.8.2/node_modules/@signe/di/dist/index.js.map +1 -0
  102. package/dist/{index27.js → node_modules/.pnpm/@signe_reactive@2.8.2/node_modules/@signe/reactive/dist/index.js} +229 -11
  103. package/dist/node_modules/.pnpm/@signe_reactive@2.8.2/node_modules/@signe/reactive/dist/index.js.map +1 -0
  104. package/dist/{index20.js → node_modules/.pnpm/@signe_room@2.8.2/node_modules/@signe/room/dist/index.js} +308 -40
  105. package/dist/node_modules/.pnpm/@signe_room@2.8.2/node_modules/@signe/room/dist/index.js.map +1 -0
  106. package/dist/{index26.js → node_modules/.pnpm/@signe_sync@2.8.2/node_modules/@signe/sync/dist/chunk-7QVYU63E.js} +1 -1
  107. package/dist/node_modules/.pnpm/@signe_sync@2.8.2/node_modules/@signe/sync/dist/chunk-7QVYU63E.js.map +1 -0
  108. package/dist/{index21.js → node_modules/.pnpm/@signe_sync@2.8.2/node_modules/@signe/sync/dist/client/index.js} +5 -5
  109. package/dist/node_modules/.pnpm/@signe_sync@2.8.2/node_modules/@signe/sync/dist/client/index.js.map +1 -0
  110. package/dist/{index17.js → node_modules/.pnpm/@signe_sync@2.8.2/node_modules/@signe/sync/dist/index.js} +89 -12
  111. package/dist/node_modules/.pnpm/@signe_sync@2.8.2/node_modules/@signe/sync/dist/index.js.map +1 -0
  112. package/dist/{index33.js → node_modules/.pnpm/dset@3.1.4/node_modules/dset/dist/index.js} +1 -1
  113. package/dist/node_modules/.pnpm/dset@3.1.4/node_modules/dset/dist/index.js.map +1 -0
  114. package/dist/{index31.js → node_modules/.pnpm/partysocket@1.1.3/node_modules/partysocket/dist/chunk-HAC622V3.js} +2 -2
  115. package/dist/node_modules/.pnpm/partysocket@1.1.3/node_modules/partysocket/dist/chunk-HAC622V3.js.map +1 -0
  116. package/dist/{index32.js → node_modules/.pnpm/partysocket@1.1.3/node_modules/partysocket/dist/chunk-S74YV6PU.js} +1 -1
  117. package/dist/node_modules/.pnpm/partysocket@1.1.3/node_modules/partysocket/dist/chunk-S74YV6PU.js.map +1 -0
  118. package/dist/{index34.js → node_modules/.pnpm/zod@3.24.2/node_modules/zod/lib/index.js} +1 -1
  119. package/dist/node_modules/.pnpm/zod@3.24.2/node_modules/zod/lib/index.js.map +1 -0
  120. package/dist/presets/animation.d.ts +31 -0
  121. package/dist/presets/animation.js +27 -0
  122. package/dist/presets/animation.js.map +1 -0
  123. package/dist/presets/faceset.d.ts +30 -0
  124. package/dist/presets/faceset.js +24 -0
  125. package/dist/presets/faceset.js.map +1 -0
  126. package/dist/presets/icon.d.ts +20 -0
  127. package/dist/presets/icon.js +15 -0
  128. package/dist/presets/icon.js.map +1 -0
  129. package/dist/presets/index.d.ts +123 -0
  130. package/dist/presets/index.js +16 -0
  131. package/dist/presets/index.js.map +1 -0
  132. package/dist/presets/lpc.d.ts +89 -0
  133. package/dist/presets/lpc.js +95 -0
  134. package/dist/presets/lpc.js.map +1 -0
  135. package/dist/{index25.js → presets/rmspritesheet.js} +1 -1
  136. package/dist/presets/rmspritesheet.js.map +1 -0
  137. package/dist/{index16.js → services/AbstractSocket.js} +1 -1
  138. package/dist/services/AbstractSocket.js.map +1 -0
  139. package/dist/services/keyboardControls.d.ts +15 -0
  140. package/dist/services/keyboardControls.js +21 -0
  141. package/dist/services/keyboardControls.js.map +1 -0
  142. package/dist/services/loadMap.d.ts +123 -2
  143. package/dist/{index7.js → services/loadMap.js} +12 -4
  144. package/dist/services/loadMap.js.map +1 -0
  145. package/dist/services/mmorpg.d.ts +16 -4
  146. package/dist/services/mmorpg.js +84 -0
  147. package/dist/services/mmorpg.js.map +1 -0
  148. package/dist/services/save.d.ts +19 -0
  149. package/dist/services/save.js +69 -0
  150. package/dist/services/save.js.map +1 -0
  151. package/dist/services/standalone.d.ts +65 -3
  152. package/dist/services/standalone.js +170 -0
  153. package/dist/services/standalone.js.map +1 -0
  154. package/dist/utils/getEntityProp.d.ts +39 -0
  155. package/dist/utils/getEntityProp.js +54 -0
  156. package/dist/utils/getEntityProp.js.map +1 -0
  157. package/package.json +24 -18
  158. package/src/Game/{EffectManager.ts → AnimationManager.ts} +3 -2
  159. package/src/Game/Map.ts +37 -2
  160. package/src/Game/Object.ts +296 -11
  161. package/src/Gui/Gui.ts +506 -18
  162. package/src/Gui/NotificationManager.ts +69 -0
  163. package/src/Resource.ts +150 -0
  164. package/src/RpgClient.ts +264 -58
  165. package/src/RpgClientEngine.ts +1421 -44
  166. package/src/Sound.ts +253 -0
  167. package/src/components/{effects → animations}/animation.ce +3 -6
  168. package/src/components/{effects → animations}/index.ts +1 -1
  169. package/src/components/character.ce +406 -40
  170. package/src/components/dynamics/parse-value.ts +80 -0
  171. package/src/components/dynamics/text.ce +183 -0
  172. package/src/components/gui/box.ce +17 -0
  173. package/src/components/gui/dialogbox/index.ce +204 -187
  174. package/src/components/gui/gameover.ce +158 -0
  175. package/src/components/gui/hud/hud.ce +56 -0
  176. package/src/components/gui/index.ts +30 -4
  177. package/src/components/gui/menu/equip-menu.ce +410 -0
  178. package/src/components/gui/menu/exit-menu.ce +41 -0
  179. package/src/components/gui/menu/items-menu.ce +317 -0
  180. package/src/components/gui/menu/main-menu.ce +291 -0
  181. package/src/components/gui/menu/options-menu.ce +35 -0
  182. package/src/components/gui/menu/skills-menu.ce +83 -0
  183. package/src/components/gui/mobile/index.ts +24 -0
  184. package/src/components/gui/mobile/mobile.ce +80 -0
  185. package/src/components/gui/notification/notification.ce +51 -0
  186. package/src/components/gui/save-load.ce +208 -0
  187. package/src/components/gui/shop/shop.ce +493 -0
  188. package/src/components/gui/title-screen.ce +163 -0
  189. package/src/components/index.ts +5 -1
  190. package/src/components/prebuilt/hp-bar.ce +255 -0
  191. package/src/components/prebuilt/index.ts +24 -0
  192. package/src/components/prebuilt/light-halo.ce +148 -0
  193. package/src/components/scenes/canvas.ce +19 -14
  194. package/src/components/scenes/draw-map.ce +21 -29
  195. package/src/components/scenes/event-layer.ce +10 -3
  196. package/src/components/scenes/transition.ce +60 -0
  197. package/src/core/setup.ts +2 -0
  198. package/src/index.ts +16 -2
  199. package/src/module.ts +145 -9
  200. package/src/presets/animation.ts +46 -0
  201. package/src/presets/faceset.ts +60 -0
  202. package/src/presets/icon.ts +17 -0
  203. package/src/presets/index.ts +9 -1
  204. package/src/presets/lpc.ts +108 -0
  205. package/src/services/keyboardControls.ts +20 -0
  206. package/src/services/loadMap.ts +132 -3
  207. package/src/services/mmorpg.ts +39 -5
  208. package/src/services/save.ts +103 -0
  209. package/src/services/standalone.ts +107 -15
  210. package/src/utils/getEntityProp.ts +87 -0
  211. package/tsconfig.json +1 -1
  212. package/vite.config.ts +5 -3
  213. package/CHANGELOG.md +0 -9
  214. package/dist/Game/EffectManager.d.ts +0 -5
  215. package/dist/components/effects/index.d.ts +0 -4
  216. package/dist/index10.js +0 -8
  217. package/dist/index10.js.map +0 -1
  218. package/dist/index11.js +0 -10
  219. package/dist/index11.js.map +0 -1
  220. package/dist/index12.js +0 -8
  221. package/dist/index12.js.map +0 -1
  222. package/dist/index13.js.map +0 -1
  223. package/dist/index14.js +0 -50
  224. package/dist/index14.js.map +0 -1
  225. package/dist/index15.js +0 -191
  226. package/dist/index15.js.map +0 -1
  227. package/dist/index16.js.map +0 -1
  228. package/dist/index17.js.map +0 -1
  229. package/dist/index18.js +0 -31
  230. package/dist/index18.js.map +0 -1
  231. package/dist/index19.js.map +0 -1
  232. package/dist/index2.js +0 -112
  233. package/dist/index2.js.map +0 -1
  234. package/dist/index20.js.map +0 -1
  235. package/dist/index21.js.map +0 -1
  236. package/dist/index22.js +0 -109
  237. package/dist/index22.js.map +0 -1
  238. package/dist/index23.js.map +0 -1
  239. package/dist/index24.js +0 -21
  240. package/dist/index24.js.map +0 -1
  241. package/dist/index25.js.map +0 -1
  242. package/dist/index26.js.map +0 -1
  243. package/dist/index27.js.map +0 -1
  244. package/dist/index28.js +0 -25
  245. package/dist/index28.js.map +0 -1
  246. package/dist/index29.js.map +0 -1
  247. package/dist/index3.js +0 -87
  248. package/dist/index3.js.map +0 -1
  249. package/dist/index30.js.map +0 -1
  250. package/dist/index31.js.map +0 -1
  251. package/dist/index32.js.map +0 -1
  252. package/dist/index33.js.map +0 -1
  253. package/dist/index34.js.map +0 -1
  254. package/dist/index35.js +0 -91
  255. package/dist/index35.js.map +0 -1
  256. package/dist/index36.js +0 -61
  257. package/dist/index36.js.map +0 -1
  258. package/dist/index37.js +0 -20
  259. package/dist/index37.js.map +0 -1
  260. package/dist/index38.js +0 -20
  261. package/dist/index38.js.map +0 -1
  262. package/dist/index4.js +0 -54
  263. package/dist/index4.js.map +0 -1
  264. package/dist/index5.js +0 -15
  265. package/dist/index5.js.map +0 -1
  266. package/dist/index6.js.map +0 -1
  267. package/dist/index7.js.map +0 -1
  268. package/dist/index8.js +0 -90
  269. package/dist/index8.js.map +0 -1
  270. package/dist/index9.js +0 -76
  271. package/dist/index9.js.map +0 -1
  272. package/src/components/gui/dialogbox/itemMenu.ce +0 -23
  273. package/src/components/gui/dialogbox/selection.ce +0 -67
  274. package/src/components/scenes/element-map.ce +0 -23
  275. /package/src/components/{effects → animations}/hit.ce +0 -0
@@ -1,7 +1,11 @@
1
- import { Context } from '@signe/di';
2
- import { EffectManager } from './Game/EffectManager';
1
+ import { AbstractWebsocket } from './services/AbstractSocket';
2
+ import { Direction } from '@rpgjs/common';
3
+ import { RpgClientMap } from './Game/Map';
4
+ import { AnimationManager } from './Game/AnimationManager';
5
+ import { Observable } from 'rxjs';
6
+ import * as PIXI from "pixi.js";
3
7
  export declare class RpgClientEngine<T = any> {
4
- context: Context;
8
+ context: any;
5
9
  private guiService;
6
10
  private webSocket;
7
11
  private loadMapService;
@@ -15,29 +19,648 @@ export declare class RpgClientEngine<T = any> {
15
19
  height: import('canvasengine').WritableSignal<string>;
16
20
  spritesheets: Map<string, any>;
17
21
  sounds: Map<string, any>;
18
- effects: any[];
22
+ componentAnimations: any[];
23
+ private spritesheetResolver?;
24
+ private soundResolver?;
19
25
  particleSettings: {
20
26
  emitters: any[];
21
27
  };
22
- constructor(context: Context);
28
+ renderer: PIXI.Renderer;
29
+ tick: Observable<number>;
30
+ private canvasApp?;
31
+ private canvasElement?;
32
+ playerIdSignal: import('canvasengine').WritableSignal<string | null>;
33
+ spriteComponentsBehind: import('canvasengine').WritableArraySignal<any[]>;
34
+ spriteComponentsInFront: import('canvasengine').WritableArraySignal<any[]>;
35
+ /** ID of the sprite that the camera should follow. null means follow the current player */
36
+ cameraFollowTargetId: import('canvasengine').WritableSignal<string | null>;
37
+ /** Trigger for map shake animation */
38
+ mapShakeTrigger: import('canvasengine').Trigger<any>;
39
+ controlsReady: import('canvasengine').WritableSignal<undefined>;
40
+ private predictionEnabled;
41
+ private prediction?;
42
+ private readonly SERVER_CORRECTION_THRESHOLD;
43
+ private inputFrameCounter;
44
+ private frameOffset;
45
+ private rtt;
46
+ private pingInterval;
47
+ private readonly PING_INTERVAL_MS;
48
+ private lastInputTime;
49
+ private mapLoadCompleted$;
50
+ private playerIdReceived$;
51
+ private playersReceived$;
52
+ private eventsReceived$;
53
+ private onAfterLoadingSubscription?;
54
+ private sceneResetQueued;
55
+ private tickSubscriptions;
56
+ private resizeHandler?;
57
+ private notificationManager;
58
+ constructor(context: any);
59
+ /**
60
+ * Assigns a CanvasEngine KeyboardControls instance to the dependency injection context
61
+ *
62
+ * This method registers a KeyboardControls instance from CanvasEngine into the DI container,
63
+ * making it available for injection throughout the application. The particularity is that
64
+ * this method is automatically called when a sprite is displayed on the map, allowing the
65
+ * controls to be automatically associated with the active sprite.
66
+ *
67
+ * ## Design
68
+ *
69
+ * - The instance is stored in the DI context under the `KeyboardControls` token
70
+ * - It's automatically assigned when a sprite component mounts (in `character.ce`)
71
+ * - The controls instance comes from the CanvasEngine component's directives
72
+ * - Once registered, it can be retrieved using `inject(KeyboardControls)` from anywhere
73
+ *
74
+ * @param controlInstance - The CanvasEngine KeyboardControls instance to register
75
+ *
76
+ * @example
77
+ * ```ts
78
+ * // The method is automatically called when a sprite is displayed:
79
+ * // client.setKeyboardControls(element.directives.controls)
80
+ *
81
+ * // Later, retrieve and use the controls instance:
82
+ * import { Input, inject, KeyboardControls } from '@rpgjs/client'
83
+ *
84
+ * const controls = inject(KeyboardControls)
85
+ * const control = controls.getControl(Input.Enter)
86
+ *
87
+ * if (control) {
88
+ * console.log(control.actionName) // 'action'
89
+ * }
90
+ * ```
91
+ */
92
+ setKeyboardControls(controlInstance: any): void;
23
93
  start(): Promise<void>;
24
94
  private initListeners;
95
+ /**
96
+ * Start periodic ping/pong for client-server synchronization
97
+ *
98
+ * Sends ping requests to the server to measure round-trip time (RTT) and
99
+ * calculate the frame offset between client and server ticks.
100
+ *
101
+ * ## Design
102
+ *
103
+ * - Sends ping every 5 seconds
104
+ * - Measures RTT for latency compensation
105
+ * - Calculates frame offset to map client frames to server ticks
106
+ * - Used for accurate server reconciliation
107
+ *
108
+ * @example
109
+ * ```ts
110
+ * // Called automatically when connection opens
111
+ * this.startPingPong();
112
+ * ```
113
+ */
114
+ private startPingPong;
115
+ /**
116
+ * Stop periodic ping/pong
117
+ *
118
+ * Stops the ping interval when disconnecting or changing maps.
119
+ *
120
+ * @example
121
+ * ```ts
122
+ * // Called automatically when connection closes
123
+ * this.stopPingPong();
124
+ * ```
125
+ */
126
+ private stopPingPong;
127
+ /**
128
+ * Send a ping request to the server
129
+ *
130
+ * Sends current client time and frame counter to the server,
131
+ * which will respond with its server tick for synchronization.
132
+ *
133
+ * @example
134
+ * ```ts
135
+ * // Send a ping to measure RTT
136
+ * this.sendPing();
137
+ * ```
138
+ */
139
+ private sendPing;
25
140
  private loadScene;
26
141
  addSpriteSheet<T = any>(spritesheetClass: any, id?: string): any;
142
+ /**
143
+ * Set a resolver function for spritesheets
144
+ *
145
+ * The resolver is called when a spritesheet is requested but not found in the cache.
146
+ * It can be synchronous (returns directly) or asynchronous (returns a Promise).
147
+ * The resolved spritesheet is automatically cached for future use.
148
+ *
149
+ * @param resolver - Function that takes a spritesheet ID and returns a spritesheet or Promise of spritesheet
150
+ *
151
+ * @example
152
+ * ```ts
153
+ * // Synchronous resolver
154
+ * engine.setSpritesheetResolver((id) => {
155
+ * if (id === 'dynamic-sprite') {
156
+ * return { id: 'dynamic-sprite', image: 'path/to/image.png', framesWidth: 32, framesHeight: 32 };
157
+ * }
158
+ * return undefined;
159
+ * });
160
+ *
161
+ * // Asynchronous resolver (loading from API)
162
+ * engine.setSpritesheetResolver(async (id) => {
163
+ * const response = await fetch(`/api/spritesheets/${id}`);
164
+ * const data = await response.json();
165
+ * return data;
166
+ * });
167
+ * ```
168
+ */
169
+ setSpritesheetResolver(resolver: (id: string) => any | Promise<any>): void;
170
+ /**
171
+ * Get a spritesheet by ID, using resolver if not found in cache
172
+ *
173
+ * This method first checks if the spritesheet exists in the cache.
174
+ * If not found and a resolver is set, it calls the resolver to create the spritesheet.
175
+ * The resolved spritesheet is automatically cached for future use.
176
+ *
177
+ * @param id - The spritesheet ID to retrieve
178
+ * @returns The spritesheet if found or created, or undefined if not found and no resolver
179
+ * @returns Promise<any> if the resolver is asynchronous
180
+ *
181
+ * @example
182
+ * ```ts
183
+ * // Synchronous usage
184
+ * const spritesheet = engine.getSpriteSheet('my-sprite');
185
+ *
186
+ * // Asynchronous usage (when resolver returns Promise)
187
+ * const spritesheet = await engine.getSpriteSheet('dynamic-sprite');
188
+ * ```
189
+ */
190
+ getSpriteSheet(id: string): any | Promise<any>;
191
+ /**
192
+ * Add a sound to the engine
193
+ *
194
+ * Adds a sound to the engine's sound cache. The sound can be:
195
+ * - A simple object with `id` and `src` properties
196
+ * - A Howler instance
197
+ * - An object with a `play()` method
198
+ *
199
+ * If the sound has a `src` property, a Howler instance will be created automatically.
200
+ *
201
+ * @param sound - The sound object or Howler instance
202
+ * @param id - Optional sound ID (if not provided, uses sound.id)
203
+ * @returns The added sound
204
+ *
205
+ * @example
206
+ * ```ts
207
+ * // Simple sound object
208
+ * engine.addSound({ id: 'click', src: 'click.mp3' });
209
+ *
210
+ * // With explicit ID
211
+ * engine.addSound({ src: 'music.mp3' }, 'background-music');
212
+ * ```
213
+ */
27
214
  addSound(sound: any, id?: string): any;
215
+ /**
216
+ * Set a resolver function for sounds
217
+ *
218
+ * The resolver is called when a sound is requested but not found in the cache.
219
+ * It can be synchronous (returns directly) or asynchronous (returns a Promise).
220
+ * The resolved sound is automatically cached for future use.
221
+ *
222
+ * @param resolver - Function that takes a sound ID and returns a sound or Promise of sound
223
+ *
224
+ * @example
225
+ * ```ts
226
+ * // Synchronous resolver
227
+ * engine.setSoundResolver((id) => {
228
+ * if (id === 'dynamic-sound') {
229
+ * return { id: 'dynamic-sound', src: 'path/to/sound.mp3' };
230
+ * }
231
+ * return undefined;
232
+ * });
233
+ *
234
+ * // Asynchronous resolver (loading from API)
235
+ * engine.setSoundResolver(async (id) => {
236
+ * const response = await fetch(`/api/sounds/${id}`);
237
+ * const data = await response.json();
238
+ * return data;
239
+ * });
240
+ * ```
241
+ */
242
+ setSoundResolver(resolver: (id: string) => any | Promise<any>): void;
243
+ /**
244
+ * Get a sound by ID, using resolver if not found in cache
245
+ *
246
+ * This method first checks if the sound exists in the cache.
247
+ * If not found and a resolver is set, it calls the resolver to create the sound.
248
+ * The resolved sound is automatically cached for future use.
249
+ *
250
+ * @param id - The sound ID to retrieve
251
+ * @returns The sound if found or created, or undefined if not found and no resolver
252
+ * @returns Promise<any> if the resolver is asynchronous
253
+ *
254
+ * @example
255
+ * ```ts
256
+ * // Synchronous usage
257
+ * const sound = engine.getSound('my-sound');
258
+ *
259
+ * // Asynchronous usage (when resolver returns Promise)
260
+ * const sound = await engine.getSound('dynamic-sound');
261
+ * ```
262
+ */
263
+ getSound(id: string): any | Promise<any>;
264
+ /**
265
+ * Play a sound by its ID
266
+ *
267
+ * This method retrieves a sound from the cache or resolver and plays it.
268
+ * If the sound is not found, it will attempt to resolve it using the soundResolver.
269
+ * Uses Howler.js for audio playback instead of native Audio elements.
270
+ *
271
+ * @param soundId - The sound ID to play
272
+ * @param options - Optional sound configuration
273
+ * @param options.volume - Volume level (0.0 to 1.0, overrides sound default)
274
+ * @param options.loop - Whether the sound should loop (overrides sound default)
275
+ *
276
+ * @example
277
+ * ```ts
278
+ * // Play a sound synchronously
279
+ * engine.playSound('item-pickup');
280
+ *
281
+ * // Play a sound with volume and loop
282
+ * engine.playSound('background-music', { volume: 0.5, loop: true });
283
+ *
284
+ * // Play a sound asynchronously (when resolver returns Promise)
285
+ * await engine.playSound('dynamic-sound', { volume: 0.8 });
286
+ * ```
287
+ */
288
+ playSound(soundId: string, options?: {
289
+ volume?: number;
290
+ loop?: boolean;
291
+ }): Promise<void>;
292
+ /**
293
+ * Stop a sound that is currently playing
294
+ *
295
+ * This method stops a sound that was previously started with `playSound()`.
296
+ *
297
+ * @param soundId - The sound ID to stop
298
+ *
299
+ * @example
300
+ * ```ts
301
+ * // Start a looping sound
302
+ * engine.playSound('background-music', { loop: true });
303
+ *
304
+ * // Later, stop it
305
+ * engine.stopSound('background-music');
306
+ * ```
307
+ */
308
+ stopSound(soundId: string): void;
309
+ /**
310
+ * Stop all currently playing sounds
311
+ *
312
+ * This method stops all sounds that are currently playing.
313
+ * Useful when changing maps to prevent sound overlap.
314
+ *
315
+ * @example
316
+ * ```ts
317
+ * // Stop all sounds
318
+ * engine.stopAllSounds();
319
+ * ```
320
+ */
321
+ stopAllSounds(): void;
322
+ /**
323
+ * Set the camera to follow a specific sprite
324
+ *
325
+ * This method changes which sprite the camera viewport should follow.
326
+ * The camera will smoothly animate to the target sprite if smoothMove options are provided.
327
+ *
328
+ * ## Design
329
+ *
330
+ * The camera follow target is stored in a signal that is read by sprite components.
331
+ * Each sprite checks if it should be followed by comparing its ID with the target ID.
332
+ * When smoothMove options are provided, the viewport animation is handled by CanvasEngine's
333
+ * viewport system.
334
+ *
335
+ * @param targetId - The ID of the sprite to follow. Set to null to follow the current player
336
+ * @param smoothMove - Animation options. Can be a boolean (default: true) or an object with time and ease
337
+ * @param smoothMove.time - Duration of the animation in milliseconds (optional)
338
+ * @param smoothMove.ease - Easing function name from https://easings.net (optional)
339
+ *
340
+ * @example
341
+ * ```ts
342
+ * // Follow another player with default smooth animation
343
+ * engine.setCameraFollow(otherPlayerId, true);
344
+ *
345
+ * // Follow an event with custom smooth animation
346
+ * engine.setCameraFollow(eventId, {
347
+ * time: 1000,
348
+ * ease: "easeInOutQuad"
349
+ * });
350
+ *
351
+ * // Follow without animation (instant)
352
+ * engine.setCameraFollow(targetId, false);
353
+ *
354
+ * // Return to following current player
355
+ * engine.setCameraFollow(null);
356
+ * ```
357
+ */
358
+ setCameraFollow(targetId: string | null, smoothMove?: boolean | {
359
+ time?: number;
360
+ ease?: string;
361
+ }): void;
28
362
  addParticle(particle: any): any;
29
- addEffect(effect: {
363
+ /**
364
+ * Add a component to render behind sprites
365
+ * Components added with this method will be displayed with a lower z-index than the sprite
366
+ *
367
+ * Supports multiple formats:
368
+ * 1. Direct component: `ShadowComponent`
369
+ * 2. Configuration object: `{ component: LightHalo, props: {...} }`
370
+ * 3. With dynamic props: `{ component: LightHalo, props: (object) => {...} }`
371
+ * 4. With dependencies: `{ component: HealthBar, dependencies: (object) => [object.hp, object.param.maxHp] }`
372
+ *
373
+ * Components with dependencies will only be displayed when all dependencies are resolved (!= undefined).
374
+ * The object (sprite) is passed to the dependencies function to allow sprite-specific dependency resolution.
375
+ *
376
+ * @param component - The component to add behind sprites, or a configuration object
377
+ * @param component.component - The component function to render
378
+ * @param component.props - Static props object or function that receives the sprite object and returns props
379
+ * @param component.dependencies - Function that receives the sprite object and returns an array of Signals
380
+ * @returns The added component or configuration
381
+ *
382
+ * @example
383
+ * ```ts
384
+ * // Add a shadow component behind all sprites
385
+ * engine.addSpriteComponentBehind(ShadowComponent);
386
+ *
387
+ * // Add a component with static props
388
+ * engine.addSpriteComponentBehind({
389
+ * component: LightHalo,
390
+ * props: { radius: 30 }
391
+ * });
392
+ *
393
+ * // Add a component with dynamic props and dependencies
394
+ * engine.addSpriteComponentBehind({
395
+ * component: HealthBar,
396
+ * props: (object) => ({ hp: object.hp(), maxHp: object.param.maxHp() }),
397
+ * dependencies: (object) => [object.hp, object.param.maxHp]
398
+ * });
399
+ * ```
400
+ */
401
+ addSpriteComponentBehind(component: any): any;
402
+ /**
403
+ * Add a component to render in front of sprites
404
+ * Components added with this method will be displayed with a higher z-index than the sprite
405
+ *
406
+ * Supports multiple formats:
407
+ * 1. Direct component: `HealthBarComponent`
408
+ * 2. Configuration object: `{ component: StatusIndicator, props: {...} }`
409
+ * 3. With dynamic props: `{ component: HealthBar, props: (object) => {...} }`
410
+ * 4. With dependencies: `{ component: HealthBar, dependencies: (object) => [object.hp, object.param.maxHp] }`
411
+ *
412
+ * Components with dependencies will only be displayed when all dependencies are resolved (!= undefined).
413
+ * The object (sprite) is passed to the dependencies function to allow sprite-specific dependency resolution.
414
+ *
415
+ * @param component - The component to add in front of sprites, or a configuration object
416
+ * @param component.component - The component function to render
417
+ * @param component.props - Static props object or function that receives the sprite object and returns props
418
+ * @param component.dependencies - Function that receives the sprite object and returns an array of Signals
419
+ * @returns The added component or configuration
420
+ *
421
+ * @example
422
+ * ```ts
423
+ * // Add a health bar component in front of all sprites
424
+ * engine.addSpriteComponentInFront(HealthBarComponent);
425
+ *
426
+ * // Add a component with static props
427
+ * engine.addSpriteComponentInFront({
428
+ * component: StatusIndicator,
429
+ * props: { type: 'poison' }
430
+ * });
431
+ *
432
+ * // Add a component with dynamic props and dependencies
433
+ * engine.addSpriteComponentInFront({
434
+ * component: HealthBar,
435
+ * props: (object) => ({ hp: object.hp(), maxHp: object.param.maxHp() }),
436
+ * dependencies: (object) => [object.hp, object.param.maxHp]
437
+ * });
438
+ * ```
439
+ */
440
+ addSpriteComponentInFront(component: any | {
441
+ component: any;
442
+ props: (object: any) => any;
443
+ dependencies?: (object: any) => any[];
444
+ }): any;
445
+ /**
446
+ * Add a component animation to the engine
447
+ *
448
+ * Component animations are temporary visual effects that can be displayed
449
+ * on sprites or objects, such as hit indicators, spell effects, or status animations.
450
+ *
451
+ * @param componentAnimation - The component animation configuration
452
+ * @param componentAnimation.id - Unique identifier for the animation
453
+ * @param componentAnimation.component - The component function to render
454
+ * @returns The added component animation configuration
455
+ *
456
+ * @example
457
+ * ```ts
458
+ * // Add a hit animation component
459
+ * engine.addComponentAnimation({
460
+ * id: 'hit',
461
+ * component: HitComponent
462
+ * });
463
+ *
464
+ * // Add an explosion effect component
465
+ * engine.addComponentAnimation({
466
+ * id: 'explosion',
467
+ * component: ExplosionComponent
468
+ * });
469
+ * ```
470
+ */
471
+ addComponentAnimation(componentAnimation: {
30
472
  component: any;
31
473
  id: string;
32
474
  }): {
33
475
  component: any;
34
476
  id: string;
35
477
  };
36
- getEffect(id: string): EffectManager;
478
+ /**
479
+ * Get a component animation by its ID
480
+ *
481
+ * Retrieves the EffectManager instance for a specific component animation,
482
+ * which can be used to display the animation on sprites or objects.
483
+ *
484
+ * @param id - The unique identifier of the component animation
485
+ * @returns The EffectManager instance for the animation
486
+ * @throws Error if the component animation is not found
487
+ *
488
+ * @example
489
+ * ```ts
490
+ * // Get the hit animation and display it
491
+ * const hitAnimation = engine.getComponentAnimation('hit');
492
+ * hitAnimation.displayEffect({ text: "Critical!" }, player);
493
+ * ```
494
+ */
495
+ getComponentAnimation(id: string): AnimationManager;
496
+ /**
497
+ * Start a transition
498
+ *
499
+ * Convenience method to display a transition by its ID using the GUI system.
500
+ *
501
+ * @param id - The unique identifier of the transition to start
502
+ * @param props - Props to pass to the transition component
503
+ *
504
+ * @example
505
+ * ```ts
506
+ * // Start a fade transition
507
+ * engine.startTransition('fade', { duration: 1000, color: 'black' });
508
+ *
509
+ * // Start with onFinish callback
510
+ * engine.startTransition('fade', {
511
+ * duration: 1000,
512
+ * onFinish: () => console.log('Fade complete')
513
+ * });
514
+ * ```
515
+ */
516
+ startTransition(id: string, props?: any): void;
37
517
  processInput({ input }: {
38
- input: number;
39
- }): void;
518
+ input: Direction;
519
+ }): Promise<void>;
40
520
  processAction({ action }: {
41
521
  action: number;
42
522
  }): void;
523
+ get PIXI(): typeof PIXI;
524
+ get socket(): AbstractWebsocket;
525
+ get playerId(): string | null;
526
+ get scene(): RpgClientMap;
527
+ private getPhysicsTick;
528
+ private getLocalPlayerState;
529
+ private applyAuthoritativeState;
530
+ private initializePredictionController;
531
+ getCurrentPlayer(): import('.').RpgClientPlayer;
532
+ /**
533
+ * Setup RxJS observer to wait for all conditions before calling onAfterLoading hook
534
+ *
535
+ * This method uses RxJS `combineLatest` to wait for all conditions to be met,
536
+ * regardless of the order in which they arrive:
537
+ * 1. The map loading is completed (loadMapService.load is finished)
538
+ * 2. We received a player ID (pId)
539
+ * 3. Players array has at least one element
540
+ * 4. Events property is present in the sync data
541
+ *
542
+ * Once all conditions are met, it uses `switchMap` to call the onAfterLoading hook once.
543
+ *
544
+ * ## Design
545
+ *
546
+ * Uses BehaviorSubjects to track each condition state, allowing events to arrive
547
+ * in any order. The `combineLatest` operator waits until all observables emit `true`,
548
+ * then `take(1)` ensures the hook is called only once, and `switchMap` handles
549
+ * the hook execution.
550
+ *
551
+ * @example
552
+ * ```ts
553
+ * // Called automatically in loadScene to setup the observer
554
+ * this.setupOnAfterLoadingObserver();
555
+ * ```
556
+ */
557
+ private setupOnAfterLoadingObserver;
558
+ /**
559
+ * Clear client prediction states for cleanup
560
+ *
561
+ * Removes old prediction states and input history to prevent memory leaks.
562
+ * Should be called when changing maps or disconnecting.
563
+ *
564
+ * @example
565
+ * ```ts
566
+ * // Clear prediction states when changing maps
567
+ * engine.clearClientPredictionStates();
568
+ * ```
569
+ */
570
+ clearClientPredictionStates(): void;
571
+ /**
572
+ * Trigger a flash animation on a sprite
573
+ *
574
+ * This method allows you to trigger a flash effect on any sprite from client-side code.
575
+ * The flash can be configured with various options including type (alpha, tint, or both),
576
+ * duration, cycles, and color.
577
+ *
578
+ * ## Design
579
+ *
580
+ * The flash is applied directly to the sprite object using its flash trigger.
581
+ * This is useful for client-side visual feedback, UI interactions, or local effects
582
+ * that don't need to be synchronized with the server.
583
+ *
584
+ * @param spriteId - The ID of the sprite to flash. If not provided, flashes the current player
585
+ * @param options - Flash configuration options
586
+ * @param options.type - Type of flash effect: 'alpha' (opacity), 'tint' (color), or 'both' (default: 'alpha')
587
+ * @param options.duration - Duration of the flash animation in milliseconds (default: 300)
588
+ * @param options.cycles - Number of flash cycles (flash on/off) (default: 1)
589
+ * @param options.alpha - Alpha value when flashing, from 0 to 1 (default: 0.3)
590
+ * @param options.tint - Tint color when flashing as hex value or color name (default: 0xffffff - white)
591
+ *
592
+ * @example
593
+ * ```ts
594
+ * // Flash the current player with default settings
595
+ * engine.flash();
596
+ *
597
+ * // Flash a specific sprite with red tint
598
+ * engine.flash('sprite-id', { type: 'tint', tint: 0xff0000 });
599
+ *
600
+ * // Flash with both alpha and tint for dramatic effect
601
+ * engine.flash(undefined, {
602
+ * type: 'both',
603
+ * alpha: 0.5,
604
+ * tint: 0xff0000,
605
+ * duration: 200,
606
+ * cycles: 2
607
+ * });
608
+ *
609
+ * // Quick damage flash on current player
610
+ * engine.flash(undefined, {
611
+ * type: 'tint',
612
+ * tint: 'red',
613
+ * duration: 150,
614
+ * cycles: 1
615
+ * });
616
+ * ```
617
+ */
618
+ flash(spriteId?: string, options?: {
619
+ type?: 'alpha' | 'tint' | 'both';
620
+ duration?: number;
621
+ cycles?: number;
622
+ alpha?: number;
623
+ tint?: number | string;
624
+ }): void;
625
+ private applyServerAck;
626
+ /**
627
+ * Replay unacknowledged inputs from a given frame to resimulate client prediction
628
+ * after applying server authority at a certain frame.
629
+ *
630
+ * @param startFrame - The last server-acknowledged frame
631
+ *
632
+ * @example
633
+ * ```ts
634
+ * // After applying a server correction at frame N
635
+ * this.replayUnackedInputsFromFrame(N);
636
+ * ```
637
+ */
638
+ private replayUnackedInputsFromFrame;
639
+ /**
640
+ * Clear all client resources and reset state
641
+ *
642
+ * This method should be called to clean up all client-side resources when
643
+ * shutting down or resetting the client engine. It:
644
+ * - Destroys the PIXI renderer
645
+ * - Stops all sounds
646
+ * - Cleans up subscriptions and event listeners
647
+ * - Resets scene map
648
+ * - Stops ping/pong interval
649
+ * - Clears prediction states
650
+ *
651
+ * ## Design
652
+ *
653
+ * This method is used primarily in testing environments to ensure clean
654
+ * state between tests. In production, the client engine typically persists
655
+ * for the lifetime of the application.
656
+ *
657
+ * @example
658
+ * ```ts
659
+ * // In test cleanup
660
+ * afterEach(() => {
661
+ * clientEngine.clear();
662
+ * });
663
+ * ```
664
+ */
665
+ clear(): void;
43
666
  }