@rpgjs/client 5.0.0-beta.1 → 5.0.0-beta.11

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 (245) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/LICENSE +19 -0
  3. package/dist/Game/AnimationManager.d.ts +1 -1
  4. package/dist/Game/AnimationManager.js +18 -9
  5. package/dist/Game/AnimationManager.js.map +1 -1
  6. package/dist/Game/AnimationManager.spec.d.ts +1 -0
  7. package/dist/Game/Event.js.map +1 -1
  8. package/dist/Game/Map.d.ts +9 -1
  9. package/dist/Game/Map.js +63 -5
  10. package/dist/Game/Map.js.map +1 -1
  11. package/dist/Game/Object.d.ts +47 -15
  12. package/dist/Game/Object.js +82 -38
  13. package/dist/Game/Object.js.map +1 -1
  14. package/dist/Game/Player.js.map +1 -1
  15. package/dist/Game/ProjectileManager.d.ts +89 -0
  16. package/dist/Game/ProjectileManager.js +179 -0
  17. package/dist/Game/ProjectileManager.js.map +1 -0
  18. package/dist/Game/ProjectileManager.spec.d.ts +1 -0
  19. package/dist/Gui/Gui.d.ts +17 -4
  20. package/dist/Gui/Gui.js +78 -48
  21. package/dist/Gui/Gui.js.map +1 -1
  22. package/dist/Gui/Gui.spec.d.ts +1 -0
  23. package/dist/Gui/NotificationManager.js.map +1 -1
  24. package/dist/Resource.js +1 -1
  25. package/dist/Resource.js.map +1 -1
  26. package/dist/RpgClient.d.ts +110 -15
  27. package/dist/RpgClientEngine.d.ts +86 -10
  28. package/dist/RpgClientEngine.js +306 -49
  29. package/dist/RpgClientEngine.js.map +1 -1
  30. package/dist/Sound.js.map +1 -1
  31. package/dist/_virtual/{_@oxc-project_runtime@0.122.0 → _@oxc-project_runtime@0.130.0}/helpers/decorate.js +1 -1
  32. package/dist/_virtual/{_@oxc-project_runtime@0.122.0 → _@oxc-project_runtime@0.130.0}/helpers/decorateMetadata.js +1 -1
  33. package/dist/components/animations/animation.ce.js +4 -5
  34. package/dist/components/animations/animation.ce.js.map +1 -1
  35. package/dist/components/animations/hit.ce.js +19 -25
  36. package/dist/components/animations/hit.ce.js.map +1 -1
  37. package/dist/components/animations/index.js +4 -4
  38. package/dist/components/animations/index.js.map +1 -1
  39. package/dist/components/character.ce.js +422 -240
  40. package/dist/components/character.ce.js.map +1 -1
  41. package/dist/components/dynamics/bar.ce.js +97 -0
  42. package/dist/components/dynamics/bar.ce.js.map +1 -0
  43. package/dist/components/dynamics/image.ce.js +24 -0
  44. package/dist/components/dynamics/image.ce.js.map +1 -0
  45. package/dist/components/dynamics/parse-value.d.ts +3 -0
  46. package/dist/components/dynamics/parse-value.js +54 -35
  47. package/dist/components/dynamics/parse-value.js.map +1 -1
  48. package/dist/components/dynamics/parse-value.spec.d.ts +1 -0
  49. package/dist/components/dynamics/shape-utils.d.ts +16 -0
  50. package/dist/components/dynamics/shape-utils.js +73 -0
  51. package/dist/components/dynamics/shape-utils.js.map +1 -0
  52. package/dist/components/dynamics/shape-utils.spec.d.ts +1 -0
  53. package/dist/components/dynamics/shape.ce.js +84 -0
  54. package/dist/components/dynamics/shape.ce.js.map +1 -0
  55. package/dist/components/dynamics/text.ce.js +34 -56
  56. package/dist/components/dynamics/text.ce.js.map +1 -1
  57. package/dist/components/gui/box.ce.js +6 -8
  58. package/dist/components/gui/box.ce.js.map +1 -1
  59. package/dist/components/gui/dialogbox/index.ce.js +56 -62
  60. package/dist/components/gui/dialogbox/index.ce.js.map +1 -1
  61. package/dist/components/gui/gameover.ce.js +42 -65
  62. package/dist/components/gui/gameover.ce.js.map +1 -1
  63. package/dist/components/gui/hud/hud.ce.js +21 -30
  64. package/dist/components/gui/hud/hud.ce.js.map +1 -1
  65. package/dist/components/gui/menu/equip-menu.ce.js +112 -165
  66. package/dist/components/gui/menu/equip-menu.ce.js.map +1 -1
  67. package/dist/components/gui/menu/exit-menu.ce.js +8 -6
  68. package/dist/components/gui/menu/exit-menu.ce.js.map +1 -1
  69. package/dist/components/gui/menu/items-menu.ce.js +52 -69
  70. package/dist/components/gui/menu/items-menu.ce.js.map +1 -1
  71. package/dist/components/gui/menu/main-menu.ce.js +75 -92
  72. package/dist/components/gui/menu/main-menu.ce.js.map +1 -1
  73. package/dist/components/gui/menu/options-menu.ce.js +5 -4
  74. package/dist/components/gui/menu/options-menu.ce.js.map +1 -1
  75. package/dist/components/gui/menu/skills-menu.ce.js +12 -17
  76. package/dist/components/gui/menu/skills-menu.ce.js.map +1 -1
  77. package/dist/components/gui/mobile/index.js +2 -2
  78. package/dist/components/gui/mobile/index.js.map +1 -1
  79. package/dist/components/gui/mobile/mobile.ce.js +5 -4
  80. package/dist/components/gui/mobile/mobile.ce.js.map +1 -1
  81. package/dist/components/gui/notification/notification.ce.js +22 -24
  82. package/dist/components/gui/notification/notification.ce.js.map +1 -1
  83. package/dist/components/gui/save-load.ce.js +72 -249
  84. package/dist/components/gui/save-load.ce.js.map +1 -1
  85. package/dist/components/gui/shop/shop.ce.js +90 -127
  86. package/dist/components/gui/shop/shop.ce.js.map +1 -1
  87. package/dist/components/gui/title-screen.ce.js +45 -70
  88. package/dist/components/gui/title-screen.ce.js.map +1 -1
  89. package/dist/components/index.d.ts +2 -1
  90. package/dist/components/index.js +1 -0
  91. package/dist/components/player-components-utils.d.ts +67 -0
  92. package/dist/components/player-components-utils.js +162 -0
  93. package/dist/components/player-components-utils.js.map +1 -0
  94. package/dist/components/player-components-utils.spec.d.ts +1 -0
  95. package/dist/components/player-components.ce.js +189 -0
  96. package/dist/components/player-components.ce.js.map +1 -0
  97. package/dist/components/prebuilt/hp-bar.ce.js +42 -44
  98. package/dist/components/prebuilt/hp-bar.ce.js.map +1 -1
  99. package/dist/components/prebuilt/light-halo.ce.js +36 -59
  100. package/dist/components/prebuilt/light-halo.ce.js.map +1 -1
  101. package/dist/components/scenes/canvas.ce.js +165 -21
  102. package/dist/components/scenes/canvas.ce.js.map +1 -1
  103. package/dist/components/scenes/draw-map.ce.js +25 -32
  104. package/dist/components/scenes/draw-map.ce.js.map +1 -1
  105. package/dist/components/scenes/event-layer.ce.js +9 -8
  106. package/dist/components/scenes/event-layer.ce.js.map +1 -1
  107. package/dist/core/inject.js +1 -1
  108. package/dist/core/inject.js.map +1 -1
  109. package/dist/core/setup.js +1 -1
  110. package/dist/core/setup.js.map +1 -1
  111. package/dist/decorators/spritesheet.d.ts +1 -0
  112. package/dist/decorators/spritesheet.js +11 -0
  113. package/dist/decorators/spritesheet.js.map +1 -0
  114. package/dist/index.d.ts +4 -0
  115. package/dist/index.js +26 -21
  116. package/dist/module.js +15 -1
  117. package/dist/module.js.map +1 -1
  118. package/dist/node_modules/.pnpm/{@signe_di@2.9.0 → @signe_di@3.0.1}/node_modules/@signe/di/dist/index.js +7 -117
  119. package/dist/node_modules/.pnpm/@signe_di@3.0.1/node_modules/@signe/di/dist/index.js.map +1 -0
  120. package/dist/node_modules/.pnpm/@signe_reactive@3.0.1/node_modules/@signe/reactive/dist/index.js +239 -0
  121. package/dist/node_modules/.pnpm/@signe_reactive@3.0.1/node_modules/@signe/reactive/dist/index.js.map +1 -0
  122. package/dist/node_modules/.pnpm/@signe_room@3.0.1/node_modules/@signe/room/dist/chunk-EUXUH3YW.js +13 -0
  123. package/dist/node_modules/.pnpm/@signe_room@3.0.1/node_modules/@signe/room/dist/chunk-EUXUH3YW.js.map +1 -0
  124. package/dist/node_modules/.pnpm/@signe_room@3.0.1/node_modules/@signe/room/dist/index.js +696 -0
  125. package/dist/node_modules/.pnpm/@signe_room@3.0.1/node_modules/@signe/room/dist/index.js.map +1 -0
  126. package/dist/node_modules/.pnpm/@signe_sync@3.0.1/node_modules/@signe/sync/dist/client/index.js +44 -0
  127. package/dist/node_modules/.pnpm/@signe_sync@3.0.1/node_modules/@signe/sync/dist/client/index.js.map +1 -0
  128. package/dist/node_modules/.pnpm/{@signe_sync@2.9.0 → @signe_sync@3.0.1}/node_modules/@signe/sync/dist/index.js +57 -141
  129. package/dist/node_modules/.pnpm/@signe_sync@3.0.1/node_modules/@signe/sync/dist/index.js.map +1 -0
  130. package/dist/node_modules/.pnpm/partysocket@1.1.3/node_modules/partysocket/dist/chunk-HAC622V3.js.map +1 -1
  131. package/dist/node_modules/.pnpm/partysocket@1.1.3/node_modules/partysocket/dist/chunk-S74YV6PU.js.map +1 -1
  132. package/dist/node_modules/.pnpm/zod@3.24.2/node_modules/zod/lib/index.js +27 -27
  133. package/dist/node_modules/.pnpm/zod@3.24.2/node_modules/zod/lib/index.js.map +1 -1
  134. package/dist/presets/animation.js.map +1 -1
  135. package/dist/presets/faceset.js.map +1 -1
  136. package/dist/presets/icon.js.map +1 -1
  137. package/dist/presets/index.js.map +1 -1
  138. package/dist/presets/lpc.js.map +1 -1
  139. package/dist/presets/rmspritesheet.js.map +1 -1
  140. package/dist/services/AbstractSocket.js.map +1 -1
  141. package/dist/services/actionInput.d.ts +12 -0
  142. package/dist/services/actionInput.js +27 -0
  143. package/dist/services/actionInput.js.map +1 -0
  144. package/dist/services/actionInput.spec.d.ts +1 -0
  145. package/dist/services/keyboardControls.js.map +1 -1
  146. package/dist/services/loadMap.d.ts +6 -0
  147. package/dist/services/loadMap.js +1 -1
  148. package/dist/services/loadMap.js.map +1 -1
  149. package/dist/services/mmorpg-connection.d.ts +5 -0
  150. package/dist/services/mmorpg-connection.js +50 -0
  151. package/dist/services/mmorpg-connection.js.map +1 -0
  152. package/dist/services/mmorpg-connection.spec.d.ts +1 -0
  153. package/dist/services/mmorpg.d.ts +10 -4
  154. package/dist/services/mmorpg.js +56 -33
  155. package/dist/services/mmorpg.js.map +1 -1
  156. package/dist/services/pointerContext.d.ts +11 -0
  157. package/dist/services/pointerContext.js +48 -0
  158. package/dist/services/pointerContext.js.map +1 -0
  159. package/dist/services/pointerContext.spec.d.ts +1 -0
  160. package/dist/services/save.js.map +1 -1
  161. package/dist/services/save.spec.d.ts +1 -0
  162. package/dist/services/standalone-message.d.ts +1 -0
  163. package/dist/services/standalone-message.js +9 -0
  164. package/dist/services/standalone-message.js.map +1 -0
  165. package/dist/services/standalone.js +4 -3
  166. package/dist/services/standalone.js.map +1 -1
  167. package/dist/services/standalone.spec.d.ts +1 -0
  168. package/dist/utils/getEntityProp.js +4 -3
  169. package/dist/utils/getEntityProp.js.map +1 -1
  170. package/dist/utils/getEntityProp.spec.d.ts +1 -0
  171. package/dist/utils/readPropValue.d.ts +2 -0
  172. package/dist/utils/readPropValue.js +13 -0
  173. package/dist/utils/readPropValue.js.map +1 -0
  174. package/package.json +13 -14
  175. package/src/Game/AnimationManager.spec.ts +30 -0
  176. package/src/Game/AnimationManager.ts +22 -10
  177. package/src/Game/Map.ts +91 -2
  178. package/src/Game/Object.ts +148 -69
  179. package/src/Game/ProjectileManager.spec.ts +338 -0
  180. package/src/Game/ProjectileManager.ts +324 -0
  181. package/src/Gui/Gui.spec.ts +273 -0
  182. package/src/Gui/Gui.ts +105 -50
  183. package/src/Resource.ts +1 -2
  184. package/src/RpgClient.ts +125 -17
  185. package/src/RpgClientEngine.ts +457 -87
  186. package/src/components/character.ce +441 -32
  187. package/src/components/dynamics/bar.ce +88 -0
  188. package/src/components/dynamics/image.ce +21 -0
  189. package/src/components/dynamics/parse-value.spec.ts +83 -0
  190. package/src/components/dynamics/parse-value.ts +111 -37
  191. package/src/components/dynamics/shape-utils.spec.ts +46 -0
  192. package/src/components/dynamics/shape-utils.ts +61 -0
  193. package/src/components/dynamics/shape.ce +90 -0
  194. package/src/components/dynamics/text.ce +35 -149
  195. package/src/components/gui/dialogbox/index.ce +18 -8
  196. package/src/components/gui/gameover.ce +2 -1
  197. package/src/components/gui/menu/equip-menu.ce +2 -1
  198. package/src/components/gui/menu/exit-menu.ce +2 -1
  199. package/src/components/gui/menu/items-menu.ce +3 -2
  200. package/src/components/gui/menu/main-menu.ce +2 -1
  201. package/src/components/gui/save-load.ce +2 -1
  202. package/src/components/gui/shop/shop.ce +3 -2
  203. package/src/components/gui/title-screen.ce +2 -1
  204. package/src/components/index.ts +2 -1
  205. package/src/components/player-components-utils.spec.ts +109 -0
  206. package/src/components/player-components-utils.ts +205 -0
  207. package/src/components/player-components.ce +222 -0
  208. package/src/components/prebuilt/hp-bar.ce +4 -3
  209. package/src/components/prebuilt/light-halo.ce +2 -2
  210. package/src/components/scenes/canvas.ce +175 -8
  211. package/src/components/scenes/draw-map.ce +18 -17
  212. package/src/components/scenes/event-layer.ce +1 -2
  213. package/src/core/setup.ts +2 -2
  214. package/src/decorators/spritesheet.ts +8 -0
  215. package/src/index.ts +4 -0
  216. package/src/module.ts +18 -1
  217. package/src/services/actionInput.spec.ts +101 -0
  218. package/src/services/actionInput.ts +53 -0
  219. package/src/services/loadMap.ts +2 -0
  220. package/src/services/mmorpg-connection.spec.ts +99 -0
  221. package/src/services/mmorpg-connection.ts +69 -0
  222. package/src/services/mmorpg.ts +68 -36
  223. package/src/services/pointerContext.spec.ts +36 -0
  224. package/src/services/pointerContext.ts +84 -0
  225. package/src/services/save.spec.ts +127 -0
  226. package/src/services/standalone-message.ts +7 -0
  227. package/src/services/standalone.spec.ts +34 -0
  228. package/src/services/standalone.ts +3 -2
  229. package/src/utils/getEntityProp.spec.ts +96 -0
  230. package/src/utils/getEntityProp.ts +4 -3
  231. package/src/utils/readPropValue.ts +16 -0
  232. package/dist/node_modules/.pnpm/@signe_di@2.9.0/node_modules/@signe/di/dist/index.js.map +0 -1
  233. package/dist/node_modules/.pnpm/@signe_reactive@2.8.3/node_modules/@signe/reactive/dist/index.js +0 -457
  234. package/dist/node_modules/.pnpm/@signe_reactive@2.8.3/node_modules/@signe/reactive/dist/index.js.map +0 -1
  235. package/dist/node_modules/.pnpm/@signe_reactive@2.9.0/node_modules/@signe/reactive/dist/index.js +0 -463
  236. package/dist/node_modules/.pnpm/@signe_reactive@2.9.0/node_modules/@signe/reactive/dist/index.js.map +0 -1
  237. package/dist/node_modules/.pnpm/@signe_room@2.9.0/node_modules/@signe/room/dist/index.js +0 -2191
  238. package/dist/node_modules/.pnpm/@signe_room@2.9.0/node_modules/@signe/room/dist/index.js.map +0 -1
  239. package/dist/node_modules/.pnpm/@signe_sync@2.9.0/node_modules/@signe/sync/dist/chunk-7QVYU63E.js +0 -10
  240. package/dist/node_modules/.pnpm/@signe_sync@2.9.0/node_modules/@signe/sync/dist/chunk-7QVYU63E.js.map +0 -1
  241. package/dist/node_modules/.pnpm/@signe_sync@2.9.0/node_modules/@signe/sync/dist/client/index.js +0 -91
  242. package/dist/node_modules/.pnpm/@signe_sync@2.9.0/node_modules/@signe/sync/dist/client/index.js.map +0 -1
  243. package/dist/node_modules/.pnpm/@signe_sync@2.9.0/node_modules/@signe/sync/dist/index.js.map +0 -1
  244. package/dist/node_modules/.pnpm/dset@3.1.4/node_modules/dset/dist/index.js +0 -14
  245. package/dist/node_modules/.pnpm/dset@3.1.4/node_modules/dset/dist/index.js.map +0 -1
package/CHANGELOG.md ADDED
@@ -0,0 +1,49 @@
1
+ # @rpgjs/client
2
+
3
+ ## 5.0.0-beta.11
4
+
5
+ ### Patch Changes
6
+
7
+ - Add projectile runtime support with client-side prediction, action input payload handling, pointer context helpers, standalone message handling, and MMORPG connection authentication.
8
+
9
+ Add composable CanvasEngine scene map components and update built-in GUI/dynamic components for the current CanvasEngine release.
10
+
11
+ - @rpgjs/common@5.0.0-beta.11
12
+ - @rpgjs/server@5.0.0-beta.11
13
+ - @rpgjs/ui-css@5.0.0-beta.11
14
+
15
+ ## 5.0.0-beta.10
16
+
17
+ ### Patch Changes
18
+
19
+ - Fix current-player control binding and canMove reads when values are provided by synced or reactive state.
20
+
21
+ Fix Vue GUI rendering for hidden fixed GUIs while keeping attached GUI targets updated.
22
+
23
+ - @rpgjs/server@5.0.0-beta.10
24
+
25
+ ## 5.0.0-beta.9
26
+
27
+ ### Major Changes
28
+
29
+ - c456d25: beta.9
30
+
31
+ ### Patch Changes
32
+
33
+ - Updated dependencies [c456d25]
34
+ - @rpgjs/common@5.0.0-beta.9
35
+ - @rpgjs/server@5.0.0-beta.9
36
+ - @rpgjs/ui-css@5.0.0-beta.9
37
+
38
+ ## 5.0.0-beta.8
39
+
40
+ ### Major Changes
41
+
42
+ - 35e7fa4: beta.8
43
+
44
+ ### Patch Changes
45
+
46
+ - Updated dependencies [35e7fa4]
47
+ - @rpgjs/common@5.0.0-beta.8
48
+ - @rpgjs/server@5.0.0-beta.8
49
+ - @rpgjs/ui-css@5.0.0-beta.8
package/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (C) 2026 by Samuel Ronce
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
@@ -4,5 +4,5 @@ export declare class AnimationManager {
4
4
  displayEffect(params: any, player: RpgCommonPlayer | {
5
5
  x: number;
6
6
  y: number;
7
- }): void;
7
+ }): Promise<void>;
8
8
  }
@@ -7,16 +7,25 @@ var AnimationManager = class {
7
7
  }
8
8
  displayEffect(params, player) {
9
9
  const id = generateUID();
10
- this.current().push({
11
- ...params,
12
- id,
13
- x: player.x,
14
- y: player.y,
15
- object: player,
16
- onFinish: () => {
10
+ const effectParams = params ?? {};
11
+ return new Promise((resolve) => {
12
+ let finished = false;
13
+ const finish = (data) => {
14
+ if (finished) return;
15
+ finished = true;
17
16
  const index = this.current().findIndex((value) => value.id === id);
18
- this.current().splice(index, 1);
19
- }
17
+ if (index !== -1) this.current().splice(index, 1);
18
+ effectParams.onFinish?.(data);
19
+ resolve();
20
+ };
21
+ this.current().push({
22
+ ...effectParams,
23
+ id,
24
+ x: player.x,
25
+ y: player.y,
26
+ object: player,
27
+ onFinish: finish
28
+ });
20
29
  });
21
30
  }
22
31
  };
@@ -1 +1 @@
1
- {"version":3,"file":"AnimationManager.js","names":[],"sources":["../../src/Game/AnimationManager.ts"],"sourcesContent":["import { generateUID, RpgCommonPlayer } from \"@rpgjs/common\";\nimport { signal } from \"canvasengine\";\n\nexport class AnimationManager {\n current = signal<any[]>([]);\n\n displayEffect(params: any, player: RpgCommonPlayer | { x: number, y: number }) {\n const id = generateUID();\n this.current().push({\n ...params,\n id,\n x: player.x,\n y: player.y,\n object: player,\n onFinish: () => {\n const index = this.current().findIndex((value) => value.id === id);\n this.current().splice(index, 1);\n },\n });\n }\n}\n"],"mappings":";;;AAGA,IAAa,mBAAb,MAA8B;;iBAClB,OAAc,EAAE,CAAC;;CAE3B,cAAc,QAAa,QAAoD;EAC7E,MAAM,KAAK,aAAa;AACxB,OAAK,SAAS,CAAC,KAAK;GAClB,GAAG;GACH;GACA,GAAG,OAAO;GACV,GAAG,OAAO;GACV,QAAQ;GACR,gBAAgB;IACd,MAAM,QAAQ,KAAK,SAAS,CAAC,WAAW,UAAU,MAAM,OAAO,GAAG;AAClE,SAAK,SAAS,CAAC,OAAO,OAAO,EAAE;;GAElC,CAAC"}
1
+ {"version":3,"file":"AnimationManager.js","names":[],"sources":["../../src/Game/AnimationManager.ts"],"sourcesContent":["import { generateUID, RpgCommonPlayer } from \"@rpgjs/common\";\nimport { signal } from \"canvasengine\";\n\nexport class AnimationManager {\n current = signal<any[]>([]);\n\n displayEffect(params: any, player: RpgCommonPlayer | { x: number, y: number }): Promise<void> {\n const id = generateUID();\n const effectParams = params ?? {};\n return new Promise<void>((resolve) => {\n let finished = false;\n const finish = (data?: any) => {\n if (finished) return;\n finished = true;\n const index = this.current().findIndex((value) => value.id === id);\n if (index !== -1) {\n this.current().splice(index, 1);\n }\n effectParams.onFinish?.(data);\n resolve();\n };\n\n this.current().push({\n ...effectParams,\n id,\n x: player.x,\n y: player.y,\n object: player,\n onFinish: finish,\n });\n });\n }\n}\n"],"mappings":";;;AAGA,IAAa,mBAAb,MAA8B;;iBAClB,OAAc,CAAC,CAAC;;CAE1B,cAAc,QAAa,QAAmE;EAC5F,MAAM,KAAK,YAAY;EACvB,MAAM,eAAe,UAAU,CAAC;EAChC,OAAO,IAAI,SAAe,YAAY;GACpC,IAAI,WAAW;GACf,MAAM,UAAU,SAAe;IAC7B,IAAI,UAAU;IACd,WAAW;IACX,MAAM,QAAQ,KAAK,QAAQ,EAAE,WAAW,UAAU,MAAM,OAAO,EAAE;IACjE,IAAI,UAAU,IACZ,KAAK,QAAQ,EAAE,OAAO,OAAO,CAAC;IAEhC,aAAa,WAAW,IAAI;IAC5B,QAAQ;GACV;GAEA,KAAK,QAAQ,EAAE,KAAK;IAClB,GAAG;IACH;IACA,GAAG,OAAO;IACV,GAAG,OAAO;IACV,QAAQ;IACR,UAAU;GACZ,CAAC;EACH,CAAC;CACH;AACF"}
@@ -0,0 +1 @@
1
+ export {};
@@ -1 +1 @@
1
- {"version":3,"file":"Event.js","names":[],"sources":["../../src/Game/Event.ts"],"sourcesContent":["import { RpgClientObject } from \"./Object\"; \n\nexport class RpgClientEvent extends RpgClientObject {\n _type = 'event'\n} "],"mappings":";;AAEA,IAAa,iBAAb,cAAoC,gBAAgB;;;eACxC"}
1
+ {"version":3,"file":"Event.js","names":[],"sources":["../../src/Game/Event.ts"],"sourcesContent":["import { RpgClientObject } from \"./Object\"; \n\nexport class RpgClientEvent extends RpgClientObject {\n _type = 'event'\n} "],"mappings":";;AAEA,IAAa,iBAAb,cAAoC,gBAAgB;;;eACxC;;AACZ"}
@@ -1,4 +1,4 @@
1
- import { RpgCommonMap, WeatherState, MapPhysicsInitContext, MapPhysicsEntityContext } from '@rpgjs/common';
1
+ import { RpgCommonMap, LightSpot, LightingState, WeatherState, MapPhysicsInitContext, MapPhysicsEntityContext } from '@rpgjs/common';
2
2
  import { RpgClientPlayer } from './Player';
3
3
  import { RpgClientEvent } from './Event';
4
4
  import { RpgClientEngine } from '../RpgClientEngine';
@@ -9,7 +9,10 @@ export declare class RpgClientMap extends RpgCommonMap<any> {
9
9
  currentPlayer: import('canvasengine').ComputedSignal<RpgClientPlayer>;
10
10
  weatherState: import('canvasengine').WritableSignal<WeatherState | null>;
11
11
  localWeatherOverride: import('canvasengine').WritableSignal<WeatherState | null>;
12
+ lightingState: import('canvasengine').WritableSignal<LightingState | null>;
13
+ localLightSpots: import('canvasengine').WritableObjectSignal<Record<string, LightSpot>>;
12
14
  weather: import('canvasengine').ComputedSignal<WeatherState | null>;
15
+ lighting: import('canvasengine').ComputedSignal<LightingState | null>;
13
16
  private manualClientPhysicsTick;
14
17
  private readonly isTestEnvironment;
15
18
  constructor();
@@ -19,6 +22,11 @@ export declare class RpgClientMap extends RpgCommonMap<any> {
19
22
  getWeather(): WeatherState | null;
20
23
  setLocalWeather(next: WeatherState | null): void;
21
24
  clearLocalWeather(): void;
25
+ getLighting(): LightingState | null;
26
+ addLightSpot(id: string, spot: LightSpot): void;
27
+ patchLightSpot(id: string, patch: Partial<LightSpot>): void;
28
+ removeLightSpot(id: string): void;
29
+ clearLightSpots(): void;
22
30
  stepClientPhysics(deltaMs: number): number;
23
31
  stepPredictionTick(): void;
24
32
  protected emitPhysicsInit(context: MapPhysicsInitContext): void;
package/dist/Game/Map.js CHANGED
@@ -1,12 +1,12 @@
1
1
  import { inject } from "../core/inject.js";
2
- import { sync, users } from "../node_modules/.pnpm/@signe_sync@2.9.0/node_modules/@signe/sync/dist/index.js";
2
+ import { sync, users } from "../node_modules/.pnpm/@signe_sync@3.0.1/node_modules/@signe/sync/dist/index.js";
3
3
  import { RpgClientPlayer } from "./Player.js";
4
4
  import { RpgClientEvent } from "./Event.js";
5
- import { __decorateMetadata } from "../_virtual/_@oxc-project_runtime@0.122.0/helpers/decorateMetadata.js";
6
- import { __decorate } from "../_virtual/_@oxc-project_runtime@0.122.0/helpers/decorate.js";
5
+ import { __decorateMetadata } from "../_virtual/_@oxc-project_runtime@0.130.0/helpers/decorateMetadata.js";
6
+ import { __decorate } from "../_virtual/_@oxc-project_runtime@0.130.0/helpers/decorate.js";
7
7
  import { RpgClientEngine } from "../RpgClientEngine.js";
8
8
  import { computed, signal } from "canvasengine";
9
- import { RpgCommonMap } from "@rpgjs/common";
9
+ import { RpgCommonMap, cloneLightingState, normalizeLightingState } from "@rpgjs/common";
10
10
  //#region src/Game/Map.ts
11
11
  var RpgClientMap = class extends RpgCommonMap {
12
12
  constructor() {
@@ -17,13 +17,28 @@ var RpgClientMap = class extends RpgCommonMap {
17
17
  this.currentPlayer = computed(() => this.players()[this.engine.playerIdSignal()]);
18
18
  this.weatherState = signal(null);
19
19
  this.localWeatherOverride = signal(null);
20
+ this.lightingState = signal(null);
21
+ this.localLightSpots = signal({});
20
22
  this.weather = computed(() => {
21
23
  const local = this.localWeatherOverride();
22
24
  const state = this.weatherState();
23
25
  return local ?? state;
24
26
  });
27
+ this.lighting = computed(() => {
28
+ const state = cloneLightingState(this.lightingState());
29
+ const localSpots = Object.entries(this.localLightSpots()).map(([id, spot]) => ({
30
+ ...spot,
31
+ id: spot.id ?? id
32
+ }));
33
+ if (!state && localSpots.length === 0) return null;
34
+ const next = { ...state ?? {} };
35
+ if (!state?.ambient) delete next.ambient;
36
+ next.spots = [...state?.spots ?? [], ...localSpots];
37
+ return next;
38
+ });
25
39
  this.manualClientPhysicsTick = false;
26
- const isTest = typeof process !== "undefined" && process.env?.TEST === "true" || typeof window !== "undefined" && window.__RPGJS_TEST__ === true;
40
+ const testGlobal = globalThis;
41
+ const isTest = testGlobal.process?.env?.TEST === "true" || testGlobal.__RPGJS_TEST__ === true;
27
42
  this.isTestEnvironment = isTest;
28
43
  if (isTest) this.autoTickEnabled = false;
29
44
  }
@@ -41,6 +56,8 @@ var RpgClientMap = class extends RpgCommonMap {
41
56
  this.events.set({});
42
57
  this.weatherState.set(null);
43
58
  this.localWeatherOverride.set(null);
59
+ this.lightingState.set(null);
60
+ this.localLightSpots.set({});
44
61
  this.clearPhysic();
45
62
  }
46
63
  getWeather() {
@@ -52,6 +69,47 @@ var RpgClientMap = class extends RpgCommonMap {
52
69
  clearLocalWeather() {
53
70
  this.localWeatherOverride.set(null);
54
71
  }
72
+ getLighting() {
73
+ return this.lighting();
74
+ }
75
+ addLightSpot(id, spot) {
76
+ const nextSpot = normalizeLightingState({ spots: [{
77
+ ...spot,
78
+ id
79
+ }] })?.spots?.[0];
80
+ if (!nextSpot) return;
81
+ this.localLightSpots.update((spots) => ({
82
+ ...spots,
83
+ [id]: nextSpot
84
+ }));
85
+ }
86
+ patchLightSpot(id, patch) {
87
+ this.localLightSpots.update((spots) => {
88
+ const current = spots[id];
89
+ if (!current) return spots;
90
+ return {
91
+ ...spots,
92
+ [id]: {
93
+ ...current,
94
+ ...patch,
95
+ id,
96
+ x: patch.x ?? current.x,
97
+ y: patch.y ?? current.y
98
+ }
99
+ };
100
+ });
101
+ }
102
+ removeLightSpot(id) {
103
+ this.localLightSpots.update((spots) => {
104
+ if (!(id in spots)) return spots;
105
+ const next = { ...spots };
106
+ delete next[id];
107
+ return next;
108
+ });
109
+ }
110
+ clearLightSpots() {
111
+ this.localLightSpots.set({});
112
+ }
55
113
  stepClientPhysics(deltaMs) {
56
114
  if (!this.manualClientPhysicsTick) return 0;
57
115
  return this.nextTick(deltaMs);
@@ -1 +1 @@
1
- {"version":3,"file":"Map.js","names":[],"sources":["../../src/Game/Map.ts"],"sourcesContent":["import {\n RpgCommonMap,\n type WeatherState,\n type MapPhysicsInitContext,\n type MapPhysicsEntityContext,\n} from \"@rpgjs/common\";\nimport { sync, users } from \"@signe/sync\";\nimport { RpgClientPlayer } from \"./Player\";\nimport { Signal, signal, computed, effect } from \"canvasengine\";\nimport { RpgClientEvent } from \"./Event\";\nimport { RpgClientEngine } from \"../RpgClientEngine\";\nimport { inject } from \"../core/inject\";\n\nexport class RpgClientMap extends RpgCommonMap<any> {\n engine: RpgClientEngine = inject(RpgClientEngine)\n @users(RpgClientPlayer) players = signal<Record<string, RpgClientPlayer>>({});\n @sync(RpgClientEvent) events = signal<Record<string, RpgClientEvent>>({});\n currentPlayer = computed(() => this.players()[this.engine.playerIdSignal()!])\n weatherState = signal<WeatherState | null>(null);\n localWeatherOverride = signal<WeatherState | null>(null);\n weather = computed<WeatherState | null>(() => {\n const local = this.localWeatherOverride() \n const state = this.weatherState()\n return local ?? state\n });\n private manualClientPhysicsTick = false;\n private readonly isTestEnvironment: boolean;\n\n constructor() {\n super();\n // Détecter l'environnement de test\n const isTest = (typeof process !== 'undefined' && process.env?.TEST === 'true')\n || (typeof window !== 'undefined' && (window as any).__RPGJS_TEST__ === true);\n this.isTestEnvironment = isTest;\n if (isTest) {\n this.autoTickEnabled = false;\n }\n }\n\n configureClientPrediction(enabled: boolean): void {\n this.manualClientPhysicsTick = enabled;\n this.autoTickEnabled = enabled ? false : !this.isTestEnvironment;\n }\n\n getCurrentPlayer() {\n return this.currentPlayer()\n }\n\n reset(force = false) {\n const currentPlayerId = this.engine.playerIdSignal();\n const currentPlayer = !force && currentPlayerId\n ? this.players()[currentPlayerId]\n : undefined;\n\n this.players.set(\n currentPlayerId && currentPlayer ? { [currentPlayerId]: currentPlayer } : {}\n );\n this.events.set({})\n this.weatherState.set(null);\n this.localWeatherOverride.set(null);\n this.clearPhysic()\n }\n\n getWeather(): WeatherState | null {\n return this.weather();\n }\n\n setLocalWeather(next: WeatherState | null): void {\n this.localWeatherOverride.set(next);\n }\n\n clearLocalWeather(): void {\n this.localWeatherOverride.set(null);\n }\n\n stepClientPhysics(deltaMs: number): number {\n if (!this.manualClientPhysicsTick) {\n return 0;\n }\n return this.nextTick(deltaMs);\n }\n\n stepPredictionTick(): void {\n this.forceSingleTick();\n }\n\n protected emitPhysicsInit(context: MapPhysicsInitContext): void {\n this.engine?.emitSceneMapHook?.(\"onPhysicsInit\", this, context);\n }\n\n protected emitPhysicsEntityAdd(context: MapPhysicsEntityContext): void {\n this.engine?.emitSceneMapHook?.(\"onPhysicsEntityAdd\", this, context);\n }\n\n protected emitPhysicsEntityRemove(context: MapPhysicsEntityContext): void {\n this.engine?.emitSceneMapHook?.(\"onPhysicsEntityRemove\", this, context);\n }\n\n protected emitPhysicsReset(): void {\n this.engine?.emitSceneMapHook?.(\"onPhysicsReset\", this);\n }\n}\n"],"mappings":";;;;;;;;;;AAaA,IAAa,eAAb,cAAkC,aAAkB;CAelD,cAAc;AACZ,SAAO;gBAfiB,OAAO,gBAAgB;iBACf,OAAwC,EAAE,CAAC;gBAC9C,OAAuC,EAAE,CAAC;uBACzD,eAAe,KAAK,SAAS,CAAC,KAAK,OAAO,gBAAgB,EAAG;sBAC9D,OAA4B,KAAK;8BACzB,OAA4B,KAAK;iBAC9C,eAAoC;GAC5C,MAAM,QAAQ,KAAK,sBAAsB;GACzC,MAAM,QAAQ,KAAK,cAAc;AACjC,UAAO,SAAS;IAChB;iCACgC;EAMhC,MAAM,SAAU,OAAO,YAAY,eAAe,QAAQ,KAAK,SAAS,UAClE,OAAO,WAAW,eAAgB,OAAe,mBAAmB;AAC1E,OAAK,oBAAoB;AACzB,MAAI,OACF,MAAK,kBAAkB;;CAI3B,0BAA0B,SAAwB;AAChD,OAAK,0BAA0B;AAC/B,OAAK,kBAAkB,UAAU,QAAQ,CAAC,KAAK;;CAGjD,mBAAmB;AACjB,SAAO,KAAK,eAAe;;CAG7B,MAAM,QAAQ,OAAO;EACnB,MAAM,kBAAkB,KAAK,OAAO,gBAAgB;EACpD,MAAM,gBAAgB,CAAC,SAAS,kBAC5B,KAAK,SAAS,CAAC,mBACf,KAAA;AAEJ,OAAK,QAAQ,IACX,mBAAmB,gBAAgB,GAAG,kBAAkB,eAAe,GAAG,EAAE,CAC7E;AACD,OAAK,OAAO,IAAI,EAAE,CAAC;AACnB,OAAK,aAAa,IAAI,KAAK;AAC3B,OAAK,qBAAqB,IAAI,KAAK;AACnC,OAAK,aAAa;;CAGpB,aAAkC;AAChC,SAAO,KAAK,SAAS;;CAGvB,gBAAgB,MAAiC;AAC/C,OAAK,qBAAqB,IAAI,KAAK;;CAGrC,oBAA0B;AACxB,OAAK,qBAAqB,IAAI,KAAK;;CAGrC,kBAAkB,SAAyB;AACzC,MAAI,CAAC,KAAK,wBACR,QAAO;AAET,SAAO,KAAK,SAAS,QAAQ;;CAG/B,qBAA2B;AACzB,OAAK,iBAAiB;;CAGxB,gBAA0B,SAAsC;AAC9D,OAAK,QAAQ,mBAAmB,iBAAiB,MAAM,QAAQ;;CAGjE,qBAA+B,SAAwC;AACrE,OAAK,QAAQ,mBAAmB,sBAAsB,MAAM,QAAQ;;CAGtE,wBAAkC,SAAwC;AACxE,OAAK,QAAQ,mBAAmB,yBAAyB,MAAM,QAAQ;;CAGzE,mBAAmC;AACjC,OAAK,QAAQ,mBAAmB,kBAAkB,KAAK;;;YApFxD,MAAM,gBAAgB,EAAA,mBAAA,eAAA,OAAA,CAAA,EAAA,aAAA,WAAA,WAAA,KAAA,EAAA;YACtB,KAAK,eAAe,EAAA,mBAAA,eAAA,OAAA,CAAA,EAAA,aAAA,WAAA,UAAA,KAAA,EAAA"}
1
+ {"version":3,"file":"Map.js","names":[],"sources":["../../src/Game/Map.ts"],"sourcesContent":["import {\n RpgCommonMap,\n cloneLightingState,\n normalizeLightingState,\n type LightSpot,\n type LightingState,\n type WeatherState,\n type MapPhysicsInitContext,\n type MapPhysicsEntityContext,\n} from \"@rpgjs/common\";\nimport { sync, users } from \"@signe/sync\";\nimport { RpgClientPlayer } from \"./Player\";\nimport { Signal, signal, computed, effect } from \"canvasengine\";\nimport { RpgClientEvent } from \"./Event\";\nimport { RpgClientEngine } from \"../RpgClientEngine\";\nimport { inject } from \"../core/inject\";\n\ntype TestGlobalScope = typeof globalThis & {\n process?: {\n env?: {\n TEST?: string;\n };\n };\n __RPGJS_TEST__?: boolean;\n};\n\nexport class RpgClientMap extends RpgCommonMap<any> {\n engine: RpgClientEngine = inject(RpgClientEngine)\n @users(RpgClientPlayer) players = signal<Record<string, RpgClientPlayer>>({});\n @sync(RpgClientEvent) events = signal<Record<string, RpgClientEvent>>({});\n currentPlayer = computed(() => this.players()[this.engine.playerIdSignal()!])\n weatherState = signal<WeatherState | null>(null);\n localWeatherOverride = signal<WeatherState | null>(null);\n lightingState = signal<LightingState | null>(null);\n localLightSpots = signal<Record<string, LightSpot>>({});\n weather = computed<WeatherState | null>(() => {\n const local = this.localWeatherOverride() \n const state = this.weatherState()\n return local ?? state\n });\n lighting = computed<LightingState | null>(() => {\n const state = cloneLightingState(this.lightingState());\n const localSpots = Object.entries(this.localLightSpots()).map(([id, spot]) => ({\n ...spot,\n id: spot.id ?? id,\n }));\n\n if (!state && localSpots.length === 0) {\n return null;\n }\n\n const next: LightingState = { ...(state ?? {}) };\n if (!state?.ambient) {\n delete next.ambient;\n }\n next.spots = [\n ...(state?.spots ?? []),\n ...localSpots,\n ];\n return next;\n });\n private manualClientPhysicsTick = false;\n private readonly isTestEnvironment: boolean;\n\n constructor() {\n super();\n // Détecter l'environnement de test\n const testGlobal = globalThis as TestGlobalScope;\n const isTest = testGlobal.process?.env?.TEST === 'true'\n || testGlobal.__RPGJS_TEST__ === true;\n this.isTestEnvironment = isTest;\n if (isTest) {\n this.autoTickEnabled = false;\n }\n }\n\n configureClientPrediction(enabled: boolean): void {\n this.manualClientPhysicsTick = enabled;\n this.autoTickEnabled = enabled ? false : !this.isTestEnvironment;\n }\n\n getCurrentPlayer() {\n return this.currentPlayer()\n }\n\n reset(force = false) {\n const currentPlayerId = this.engine.playerIdSignal();\n const currentPlayer = !force && currentPlayerId\n ? this.players()[currentPlayerId]\n : undefined;\n\n this.players.set(\n currentPlayerId && currentPlayer ? { [currentPlayerId]: currentPlayer } : {}\n );\n this.events.set({})\n this.weatherState.set(null);\n this.localWeatherOverride.set(null);\n this.lightingState.set(null);\n this.localLightSpots.set({});\n this.clearPhysic()\n }\n\n getWeather(): WeatherState | null {\n return this.weather();\n }\n\n setLocalWeather(next: WeatherState | null): void {\n this.localWeatherOverride.set(next);\n }\n\n clearLocalWeather(): void {\n this.localWeatherOverride.set(null);\n }\n\n getLighting(): LightingState | null {\n return this.lighting();\n }\n\n addLightSpot(id: string, spot: LightSpot): void {\n const normalized = normalizeLightingState({ spots: [{ ...spot, id }] });\n const nextSpot = normalized?.spots?.[0];\n if (!nextSpot) {\n return;\n }\n this.localLightSpots.update((spots) => ({\n ...spots,\n [id]: nextSpot,\n }));\n }\n\n patchLightSpot(id: string, patch: Partial<LightSpot>): void {\n this.localLightSpots.update((spots) => {\n const current = spots[id];\n if (!current) {\n return spots;\n }\n return {\n ...spots,\n [id]: {\n ...current,\n ...patch,\n id,\n x: patch.x ?? current.x,\n y: patch.y ?? current.y,\n },\n };\n });\n }\n\n removeLightSpot(id: string): void {\n this.localLightSpots.update((spots) => {\n if (!(id in spots)) {\n return spots;\n }\n const next = { ...spots };\n delete next[id];\n return next;\n });\n }\n\n clearLightSpots(): void {\n this.localLightSpots.set({});\n }\n\n stepClientPhysics(deltaMs: number): number {\n if (!this.manualClientPhysicsTick) {\n return 0;\n }\n return this.nextTick(deltaMs);\n }\n\n stepPredictionTick(): void {\n this.forceSingleTick();\n }\n\n protected emitPhysicsInit(context: MapPhysicsInitContext): void {\n this.engine?.emitSceneMapHook?.(\"onPhysicsInit\", this, context);\n }\n\n protected emitPhysicsEntityAdd(context: MapPhysicsEntityContext): void {\n this.engine?.emitSceneMapHook?.(\"onPhysicsEntityAdd\", this, context);\n }\n\n protected emitPhysicsEntityRemove(context: MapPhysicsEntityContext): void {\n this.engine?.emitSceneMapHook?.(\"onPhysicsEntityRemove\", this, context);\n }\n\n protected emitPhysicsReset(): void {\n this.engine?.emitSceneMapHook?.(\"onPhysicsReset\", this);\n }\n}\n"],"mappings":"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"}
@@ -1,21 +1,41 @@
1
1
  import { Hooks, RpgCommonPlayer } from '@rpgjs/common';
2
+ import { Trigger } from 'canvasengine';
2
3
  import { RpgClientEngine } from '../RpgClientEngine';
3
4
  type Frame = {
4
5
  x: number;
5
6
  y: number;
6
7
  ts: number;
7
8
  };
9
+ type AnimationRestoreOptions = {
10
+ restoreAnimationName?: string;
11
+ restoreGraphics?: any[];
12
+ timeoutMs?: number;
13
+ };
14
+ type FlashType = 'alpha' | 'tint' | 'both';
15
+ type FlashOptions = {
16
+ type?: FlashType;
17
+ duration?: number;
18
+ cycles?: number;
19
+ alpha?: number;
20
+ tint?: number | string;
21
+ };
22
+ type FlashTriggerOptions = Omit<FlashOptions, "tint"> & {
23
+ tint: number;
24
+ };
25
+ type ConfigurableTrigger<T> = Omit<Trigger<T>, "start"> & {
26
+ start(config?: T): Promise<void>;
27
+ };
8
28
  export declare abstract class RpgClientObject extends RpgCommonPlayer {
9
29
  abstract _type: string;
10
- emitParticleTrigger: import('canvasengine').Trigger<any>;
30
+ emitParticleTrigger: Trigger<any>;
11
31
  particleName: import('canvasengine').WritableSignal<string>;
12
32
  animationCurrentIndex: import('canvasengine').WritableSignal<number>;
13
33
  animationIsPlaying: import('canvasengine').WritableSignal<boolean>;
14
34
  _param: import('canvasengine').WritableObjectSignal<{}>;
15
35
  frames: Frame[];
16
36
  graphicsSignals: import('canvasengine').WritableArraySignal<any[]>;
17
- _component: {};
18
- flashTrigger: import('canvasengine').Trigger<any>;
37
+ flashTrigger: ConfigurableTrigger<FlashTriggerOptions>;
38
+ private animationRestoreState?;
19
39
  constructor();
20
40
  /**
21
41
  * Access the shared client hook registry.
@@ -30,6 +50,11 @@ export declare abstract class RpgClientObject extends RpgCommonPlayer {
30
50
  */
31
51
  get engine(): RpgClientEngine<unknown>;
32
52
  private animationSubscription?;
53
+ private animationResetTimeout?;
54
+ private animationWaitResolve?;
55
+ private clearAnimationControls;
56
+ private resolveAnimationWait;
57
+ private finishTemporaryAnimation;
33
58
  /**
34
59
  * Trigger a flash animation on this sprite
35
60
  *
@@ -76,13 +101,7 @@ export declare abstract class RpgClientObject extends RpgCommonPlayer {
76
101
  * });
77
102
  * ```
78
103
  */
79
- flash(options?: {
80
- type?: 'alpha' | 'tint' | 'both';
81
- duration?: number;
82
- cycles?: number;
83
- alpha?: number;
84
- tint?: number | string;
85
- }): void;
104
+ flash(options?: FlashOptions): void;
86
105
  /**
87
106
  * Reset animation state when animation changes externally
88
107
  *
@@ -105,17 +124,19 @@ export declare abstract class RpgClientObject extends RpgCommonPlayer {
105
124
  *
106
125
  * @param animationName - Name of the animation to play
107
126
  * @param nbTimes - Number of times to repeat the animation (default: Infinity for continuous)
127
+ * @param options - Restore and timeout options
128
+ * @returns A promise resolved when a finite animation finishes, is interrupted, or times out
108
129
  *
109
130
  * @example
110
131
  * ```ts
111
132
  * // Play attack animation 3 times
112
- * player.setAnimation('attack', 3);
133
+ * await player.setAnimation('attack', 3);
113
134
  *
114
135
  * // Play continuous spell animation
115
136
  * player.setAnimation('spell');
116
137
  * ```
117
138
  */
118
- setAnimation(animationName: string, nbTimes?: number): void;
139
+ setAnimation(animationName: string, nbTimes?: number, options?: AnimationRestoreOptions): Promise<void>;
119
140
  /**
120
141
  * Set a custom animation with temporary graphic change
121
142
  *
@@ -126,21 +147,32 @@ export declare abstract class RpgClientObject extends RpgCommonPlayer {
126
147
  * @param animationName - Name of the animation to play
127
148
  * @param graphic - The graphic(s) to temporarily use during the animation
128
149
  * @param nbTimes - Number of times to repeat the animation (default: Infinity for continuous)
150
+ * @param options - Restore and timeout options
151
+ * @returns A promise resolved when a finite animation finishes, is interrupted, or times out
129
152
  *
130
153
  * @example
131
154
  * ```ts
132
155
  * // Play attack animation with temporary graphic change
133
- * player.setAnimation('attack', 'hero_attack', 3);
156
+ * await player.setAnimation('attack', 'hero_attack', 3);
134
157
  * ```
135
158
  */
136
- setAnimation(animationName: string, graphic?: string | string[], nbTimes?: number): void;
159
+ setAnimation(animationName: string, graphic?: string | string[], nbTimes?: number, options?: AnimationRestoreOptions): Promise<void>;
137
160
  /**
138
161
  * Display a registered component animation effect on this object.
139
162
  *
140
163
  * @param id - Identifier of the component animation to play.
141
164
  * @param params - Parameters forwarded to the animation effect.
165
+ * @returns A promise resolved when the animation component calls `onFinish`.
166
+ */
167
+ showComponentAnimation(id: string, params: any): Promise<void>;
168
+ /**
169
+ * Display a registered spritesheet animation effect on this object.
170
+ *
171
+ * @param graphic - Identifier of the spritesheet to use.
172
+ * @param animationName - Name of the animation inside the spritesheet.
173
+ * @returns A promise resolved when the animation component calls `onFinish`.
142
174
  */
143
- showComponentAnimation(id: string, params: any): void;
175
+ showAnimation(graphic: string, animationName?: string): Promise<void>;
144
176
  /**
145
177
  * Check whether this client object represents an event.
146
178
  *
@@ -1,11 +1,9 @@
1
1
  import { inject } from "../core/inject.js";
2
- import component from "../components/dynamics/text.ce.js";
3
2
  import { RpgClientEngine } from "../RpgClientEngine.js";
4
3
  import { signal, trigger } from "canvasengine";
5
4
  import { ModulesToken, RpgCommonPlayer } from "@rpgjs/common";
6
- import { filter, from, map, switchMap } from "rxjs";
5
+ import { from, map, of, switchMap } from "rxjs";
7
6
  //#region src/Game/Object.ts
8
- var DYNAMIC_COMPONENTS = { text: component };
9
7
  var RpgClientObject = class extends RpgCommonPlayer {
10
8
  constructor() {
11
9
  super();
@@ -16,7 +14,6 @@ var RpgClientObject = class extends RpgCommonPlayer {
16
14
  this._param = signal({});
17
15
  this.frames = [];
18
16
  this.graphicsSignals = signal([]);
19
- this._component = {};
20
17
  this.flashTrigger = trigger();
21
18
  this.hooks.callHooks("client-sprite-onInit", this).subscribe();
22
19
  this._frames.observable.subscribe(({ items }) => {
@@ -24,17 +21,12 @@ var RpgClientObject = class extends RpgCommonPlayer {
24
21
  const nextFrames = items.flatMap((item) => Array.isArray(item) ? item : [item]);
25
22
  this.frames = [...this.frames, ...nextFrames];
26
23
  });
27
- this.graphics.observable.pipe(map(({ items }) => items), filter((graphics) => graphics.length > 0), switchMap((graphics) => from(Promise.all(graphics.map((graphic) => this.engine.getSpriteSheet(graphic)))))).subscribe((sheets) => {
24
+ this.graphics.observable.pipe(map(({ items }) => items), switchMap((graphics) => {
25
+ if (graphics.length === 0) return of([]);
26
+ return from(Promise.all(graphics.map((graphic) => this.engine.getSpriteSheet(graphic))));
27
+ })).subscribe((sheets) => {
28
28
  this.graphicsSignals.set(sheets);
29
29
  });
30
- this.componentsTop.observable.pipe(filter((value) => value !== null && value !== void 0), map((value) => typeof value === "string" ? JSON.parse(value) : value)).subscribe(({ components }) => {
31
- for (const component of components) for (const [key, value] of Object.entries(component)) {
32
- this._component = value;
33
- console.log(value);
34
- const type = value.type;
35
- if (DYNAMIC_COMPONENTS[type]) this.engine.addSpriteComponentInFront(DYNAMIC_COMPONENTS[type]);
36
- }
37
- });
38
30
  this.engine.tick.pipe().subscribe(() => {
39
31
  const frame = this.frames.shift();
40
32
  if (frame) {
@@ -59,6 +51,33 @@ var RpgClientObject = class extends RpgCommonPlayer {
59
51
  get engine() {
60
52
  return inject(RpgClientEngine);
61
53
  }
54
+ clearAnimationControls() {
55
+ if (this.animationSubscription) {
56
+ this.animationSubscription.unsubscribe();
57
+ this.animationSubscription = void 0;
58
+ }
59
+ if (this.animationResetTimeout) {
60
+ clearTimeout(this.animationResetTimeout);
61
+ this.animationResetTimeout = void 0;
62
+ }
63
+ }
64
+ resolveAnimationWait() {
65
+ const resolve = this.animationWaitResolve;
66
+ this.animationWaitResolve = void 0;
67
+ resolve?.();
68
+ }
69
+ finishTemporaryAnimation() {
70
+ const restoreState = this.animationRestoreState;
71
+ this.clearAnimationControls();
72
+ this.animationCurrentIndex.set(0);
73
+ if (restoreState) {
74
+ this.animationName.set(restoreState.animationName);
75
+ this.graphics.set([...restoreState.graphics]);
76
+ }
77
+ this.animationRestoreState = void 0;
78
+ this.animationIsPlaying.set(false);
79
+ this.resolveAnimationWait();
80
+ }
62
81
  /**
63
82
  * Trigger a flash animation on this sprite
64
83
  *
@@ -142,51 +161,76 @@ var RpgClientObject = class extends RpgCommonPlayer {
142
161
  * ```
143
162
  */
144
163
  resetAnimationState() {
164
+ if (this.animationRestoreState) {
165
+ this.finishTemporaryAnimation();
166
+ return;
167
+ }
145
168
  this.animationIsPlaying.set(false);
146
169
  this.animationCurrentIndex.set(0);
147
- if (this.animationSubscription) {
148
- this.animationSubscription.unsubscribe();
149
- this.animationSubscription = void 0;
150
- }
170
+ this.clearAnimationControls();
171
+ this.resolveAnimationWait();
151
172
  }
152
- setAnimation(animationName, graphicOrNbTimes, nbTimes) {
153
- if (this.animationIsPlaying()) return;
154
- this.animationIsPlaying.set(true);
155
- const previousAnimationName = this.animationName();
156
- const previousGraphics = this.graphics();
157
- this.animationCurrentIndex.set(0);
173
+ setAnimation(animationName, graphicOrNbTimes, nbTimesOrOptions, options) {
158
174
  let graphic;
159
175
  let finalNbTimes = Infinity;
160
- if (typeof graphicOrNbTimes === "number") finalNbTimes = graphicOrNbTimes;
161
- else if (graphicOrNbTimes !== void 0) {
176
+ let restoreOptions = options;
177
+ if (typeof graphicOrNbTimes === "number") {
178
+ finalNbTimes = graphicOrNbTimes;
179
+ restoreOptions = typeof nbTimesOrOptions === "object" ? nbTimesOrOptions : options;
180
+ } else if (graphicOrNbTimes !== void 0) {
162
181
  graphic = graphicOrNbTimes;
163
- finalNbTimes = nbTimes ?? Infinity;
182
+ if (typeof nbTimesOrOptions === "number") finalNbTimes = nbTimesOrOptions;
183
+ else {
184
+ finalNbTimes = Infinity;
185
+ restoreOptions = nbTimesOrOptions ?? options;
186
+ }
164
187
  } else finalNbTimes = Infinity;
188
+ if (this.animationIsPlaying()) this.finishTemporaryAnimation();
189
+ const waitPromise = finalNbTimes === Infinity ? Promise.resolve() : new Promise((resolve) => {
190
+ this.animationWaitResolve = resolve;
191
+ });
192
+ this.animationIsPlaying.set(true);
193
+ const previousAnimationName = restoreOptions?.restoreAnimationName ?? this.animationName();
194
+ const previousGraphics = restoreOptions?.restoreGraphics ? [...restoreOptions.restoreGraphics] : [...this.graphics()];
195
+ this.animationRestoreState = {
196
+ animationName: previousAnimationName,
197
+ graphics: previousGraphics
198
+ };
199
+ this.animationCurrentIndex.set(0);
165
200
  if (graphic !== void 0) if (Array.isArray(graphic)) this.graphics.set(graphic);
166
201
  else this.graphics.set([graphic]);
167
- if (this.animationSubscription) this.animationSubscription.unsubscribe();
202
+ this.clearAnimationControls();
168
203
  this.animationSubscription = this.animationCurrentIndex.observable.subscribe((index) => {
169
- if (index >= finalNbTimes) {
170
- this.animationCurrentIndex.set(0);
171
- this.animationName.set(previousAnimationName);
172
- if (graphic !== void 0) this.graphics.set(previousGraphics);
173
- this.animationIsPlaying.set(false);
174
- if (this.animationSubscription) {
175
- this.animationSubscription.unsubscribe();
176
- this.animationSubscription = void 0;
177
- }
178
- }
204
+ if (index >= finalNbTimes) this.finishTemporaryAnimation();
179
205
  });
206
+ if (finalNbTimes !== Infinity) this.animationResetTimeout = setTimeout(() => {
207
+ if (this.animationIsPlaying()) this.finishTemporaryAnimation();
208
+ }, restoreOptions?.timeoutMs ?? Math.max(1e3, finalNbTimes * 1e3));
180
209
  this.animationName.set(animationName);
210
+ return waitPromise;
181
211
  }
182
212
  /**
183
213
  * Display a registered component animation effect on this object.
184
214
  *
185
215
  * @param id - Identifier of the component animation to play.
186
216
  * @param params - Parameters forwarded to the animation effect.
217
+ * @returns A promise resolved when the animation component calls `onFinish`.
187
218
  */
188
219
  showComponentAnimation(id, params) {
189
- inject(RpgClientEngine).getComponentAnimation(id).displayEffect(params, this);
220
+ return inject(RpgClientEngine).getComponentAnimation(id).displayEffect(params, this);
221
+ }
222
+ /**
223
+ * Display a registered spritesheet animation effect on this object.
224
+ *
225
+ * @param graphic - Identifier of the spritesheet to use.
226
+ * @param animationName - Name of the animation inside the spritesheet.
227
+ * @returns A promise resolved when the animation component calls `onFinish`.
228
+ */
229
+ showAnimation(graphic, animationName = "default") {
230
+ return this.showComponentAnimation("animation", {
231
+ graphic,
232
+ animationName
233
+ });
190
234
  }
191
235
  /**
192
236
  * Check whether this client object represents an event.