@rpgjs/client 5.0.0-alpha.8 → 5.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (305) hide show
  1. package/dist/Game/AnimationManager.d.ts +8 -0
  2. package/dist/Game/AnimationManager.js +26 -0
  3. package/dist/Game/AnimationManager.js.map +1 -0
  4. package/dist/Game/Event.d.ts +1 -1
  5. package/dist/Game/Event.js +12 -0
  6. package/dist/Game/Event.js.map +1 -0
  7. package/dist/Game/Map.d.ts +23 -2
  8. package/dist/Game/Map.js +80 -0
  9. package/dist/Game/Map.js.map +1 -0
  10. package/dist/Game/Object.d.ts +157 -0
  11. package/dist/Game/Object.js +211 -0
  12. package/dist/Game/Object.js.map +1 -0
  13. package/dist/Game/Player.d.ts +1 -1
  14. package/dist/Game/Player.js +12 -0
  15. package/dist/Game/Player.js.map +1 -0
  16. package/dist/Gui/Gui.d.ts +177 -5
  17. package/dist/Gui/Gui.js +445 -0
  18. package/dist/Gui/Gui.js.map +1 -0
  19. package/dist/Gui/NotificationManager.d.ts +23 -0
  20. package/dist/Gui/NotificationManager.js +49 -0
  21. package/dist/Gui/NotificationManager.js.map +1 -0
  22. package/dist/Resource.d.ts +97 -0
  23. package/dist/Resource.js +133 -0
  24. package/dist/Resource.js.map +1 -0
  25. package/dist/RpgClient.d.ts +290 -58
  26. package/dist/RpgClientEngine.d.ts +649 -9
  27. package/dist/RpgClientEngine.js +1334 -0
  28. package/dist/RpgClientEngine.js.map +1 -0
  29. package/dist/Sound.d.ts +199 -0
  30. package/dist/Sound.js +167 -0
  31. package/dist/Sound.js.map +1 -0
  32. package/dist/_virtual/_@oxc-project_runtime@0.122.0/helpers/decorate.js +9 -0
  33. package/dist/_virtual/_@oxc-project_runtime@0.122.0/helpers/decorateMetadata.js +6 -0
  34. package/dist/components/animations/animation.ce.js +24 -0
  35. package/dist/components/animations/animation.ce.js.map +1 -0
  36. package/dist/components/animations/hit.ce.js +70 -0
  37. package/dist/components/animations/hit.ce.js.map +1 -0
  38. package/dist/components/animations/index.d.ts +4 -0
  39. package/dist/components/animations/index.js +11 -0
  40. package/dist/components/animations/index.js.map +1 -0
  41. package/dist/components/character.ce.js +392 -0
  42. package/dist/components/character.ce.js.map +1 -0
  43. package/dist/components/dynamics/parse-value.d.ts +1 -0
  44. package/dist/components/dynamics/parse-value.js +44 -0
  45. package/dist/components/dynamics/parse-value.js.map +1 -0
  46. package/dist/components/dynamics/text.ce.js +73 -0
  47. package/dist/components/dynamics/text.ce.js.map +1 -0
  48. package/dist/components/gui/box.ce.js +28 -0
  49. package/dist/components/gui/box.ce.js.map +1 -0
  50. package/dist/components/gui/dialogbox/index.ce.js +205 -0
  51. package/dist/components/gui/dialogbox/index.ce.js.map +1 -0
  52. package/dist/components/gui/gameover.ce.js +193 -0
  53. package/dist/components/gui/gameover.ce.js.map +1 -0
  54. package/dist/components/gui/hud/hud.ce.js +92 -0
  55. package/dist/components/gui/hud/hud.ce.js.map +1 -0
  56. package/dist/components/gui/index.d.ts +15 -3
  57. package/dist/components/gui/index.js +14 -0
  58. package/dist/components/gui/menu/equip-menu.ce.js +481 -0
  59. package/dist/components/gui/menu/equip-menu.ce.js.map +1 -0
  60. package/dist/components/gui/menu/exit-menu.ce.js +54 -0
  61. package/dist/components/gui/menu/exit-menu.ce.js.map +1 -0
  62. package/dist/components/gui/menu/items-menu.ce.js +344 -0
  63. package/dist/components/gui/menu/items-menu.ce.js.map +1 -0
  64. package/dist/components/gui/menu/main-menu.ce.js +417 -0
  65. package/dist/components/gui/menu/main-menu.ce.js.map +1 -0
  66. package/dist/components/gui/menu/options-menu.ce.js +48 -0
  67. package/dist/components/gui/menu/options-menu.ce.js.map +1 -0
  68. package/dist/components/gui/menu/skills-menu.ce.js +107 -0
  69. package/dist/components/gui/menu/skills-menu.ce.js.map +1 -0
  70. package/dist/components/gui/mobile/index.d.ts +8 -0
  71. package/dist/components/gui/mobile/index.js +21 -0
  72. package/dist/components/gui/mobile/index.js.map +1 -0
  73. package/dist/components/gui/mobile/mobile.ce.js +78 -0
  74. package/dist/components/gui/mobile/mobile.ce.js.map +1 -0
  75. package/dist/components/gui/notification/notification.ce.js +64 -0
  76. package/dist/components/gui/notification/notification.ce.js.map +1 -0
  77. package/dist/components/gui/save-load.ce.js +389 -0
  78. package/dist/components/gui/save-load.ce.js.map +1 -0
  79. package/dist/components/gui/shop/shop.ce.js +652 -0
  80. package/dist/components/gui/shop/shop.ce.js.map +1 -0
  81. package/dist/components/gui/title-screen.ce.js +190 -0
  82. package/dist/components/gui/title-screen.ce.js.map +1 -0
  83. package/dist/components/index.d.ts +1 -0
  84. package/dist/components/index.js +4 -0
  85. package/dist/components/prebuilt/hp-bar.ce.js +116 -0
  86. package/dist/components/prebuilt/hp-bar.ce.js.map +1 -0
  87. package/dist/components/prebuilt/index.d.ts +19 -0
  88. package/dist/components/prebuilt/index.js +2 -0
  89. package/dist/components/prebuilt/light-halo.ce.js +94 -0
  90. package/dist/components/prebuilt/light-halo.ce.js.map +1 -0
  91. package/dist/components/scenes/canvas.ce.js +60 -0
  92. package/dist/components/scenes/canvas.ce.js.map +1 -0
  93. package/dist/components/scenes/draw-map.ce.js +89 -0
  94. package/dist/components/scenes/draw-map.ce.js.map +1 -0
  95. package/dist/components/scenes/event-layer.ce.js +28 -0
  96. package/dist/components/scenes/event-layer.ce.js.map +1 -0
  97. package/dist/core/inject.js +18 -0
  98. package/dist/core/inject.js.map +1 -0
  99. package/dist/core/setup.js +16 -0
  100. package/dist/core/setup.js.map +1 -0
  101. package/dist/index.d.ts +15 -1
  102. package/dist/index.js +44 -14
  103. package/dist/module.d.ts +43 -4
  104. package/dist/module.js +176 -0
  105. package/dist/module.js.map +1 -0
  106. package/dist/node_modules/.pnpm/@signe_di@2.9.0/node_modules/@signe/di/dist/index.js +277 -0
  107. package/dist/node_modules/.pnpm/@signe_di@2.9.0/node_modules/@signe/di/dist/index.js.map +1 -0
  108. package/dist/node_modules/.pnpm/@signe_reactive@2.8.3/node_modules/@signe/reactive/dist/index.js +457 -0
  109. package/dist/node_modules/.pnpm/@signe_reactive@2.8.3/node_modules/@signe/reactive/dist/index.js.map +1 -0
  110. package/dist/node_modules/.pnpm/@signe_reactive@2.9.0/node_modules/@signe/reactive/dist/index.js +463 -0
  111. package/dist/node_modules/.pnpm/@signe_reactive@2.9.0/node_modules/@signe/reactive/dist/index.js.map +1 -0
  112. package/dist/node_modules/.pnpm/@signe_room@2.9.0/node_modules/@signe/room/dist/index.js +2191 -0
  113. package/dist/node_modules/.pnpm/@signe_room@2.9.0/node_modules/@signe/room/dist/index.js.map +1 -0
  114. package/dist/node_modules/.pnpm/@signe_sync@2.9.0/node_modules/@signe/sync/dist/chunk-7QVYU63E.js +10 -0
  115. package/dist/node_modules/.pnpm/@signe_sync@2.9.0/node_modules/@signe/sync/dist/chunk-7QVYU63E.js.map +1 -0
  116. package/dist/node_modules/.pnpm/@signe_sync@2.9.0/node_modules/@signe/sync/dist/client/index.js +91 -0
  117. package/dist/node_modules/.pnpm/@signe_sync@2.9.0/node_modules/@signe/sync/dist/client/index.js.map +1 -0
  118. package/dist/node_modules/.pnpm/@signe_sync@2.9.0/node_modules/@signe/sync/dist/index.js +325 -0
  119. package/dist/node_modules/.pnpm/@signe_sync@2.9.0/node_modules/@signe/sync/dist/index.js.map +1 -0
  120. package/dist/node_modules/.pnpm/dset@3.1.4/node_modules/dset/dist/index.js +14 -0
  121. package/dist/node_modules/.pnpm/dset@3.1.4/node_modules/dset/dist/index.js.map +1 -0
  122. package/dist/node_modules/.pnpm/partysocket@1.1.3/node_modules/partysocket/dist/chunk-HAC622V3.js +115 -0
  123. package/dist/node_modules/.pnpm/partysocket@1.1.3/node_modules/partysocket/dist/chunk-HAC622V3.js.map +1 -0
  124. package/dist/node_modules/.pnpm/partysocket@1.1.3/node_modules/partysocket/dist/chunk-S74YV6PU.js +401 -0
  125. package/dist/node_modules/.pnpm/partysocket@1.1.3/node_modules/partysocket/dist/chunk-S74YV6PU.js.map +1 -0
  126. package/dist/node_modules/.pnpm/partysocket@1.1.3/node_modules/partysocket/dist/index.js +2 -0
  127. package/dist/node_modules/.pnpm/zod@3.24.2/node_modules/zod/lib/index.js +3756 -0
  128. package/dist/node_modules/.pnpm/zod@3.24.2/node_modules/zod/lib/index.js.map +1 -0
  129. package/dist/presets/animation.d.ts +31 -0
  130. package/dist/presets/animation.js +39 -0
  131. package/dist/presets/animation.js.map +1 -0
  132. package/dist/presets/faceset.d.ts +30 -0
  133. package/dist/presets/faceset.js +51 -0
  134. package/dist/presets/faceset.js.map +1 -0
  135. package/dist/presets/icon.d.ts +20 -0
  136. package/dist/presets/icon.js +15 -0
  137. package/dist/presets/icon.js.map +1 -0
  138. package/dist/presets/index.d.ts +123 -0
  139. package/dist/presets/index.js +17 -0
  140. package/dist/presets/index.js.map +1 -0
  141. package/dist/presets/lpc.d.ts +89 -0
  142. package/dist/presets/lpc.js +98 -0
  143. package/dist/presets/lpc.js.map +1 -0
  144. package/dist/presets/rmspritesheet.js +42 -0
  145. package/dist/presets/rmspritesheet.js.map +1 -0
  146. package/dist/services/AbstractSocket.d.ts +9 -5
  147. package/dist/services/AbstractSocket.js +11 -0
  148. package/dist/services/AbstractSocket.js.map +1 -0
  149. package/dist/services/keyboardControls.d.ts +15 -0
  150. package/dist/services/keyboardControls.js +23 -0
  151. package/dist/services/keyboardControls.js.map +1 -0
  152. package/dist/services/loadMap.js +123 -0
  153. package/dist/services/loadMap.js.map +1 -0
  154. package/dist/services/mmorpg.d.ts +21 -9
  155. package/dist/services/mmorpg.js +131 -0
  156. package/dist/services/mmorpg.js.map +1 -0
  157. package/dist/services/save.d.ts +19 -0
  158. package/dist/services/save.js +77 -0
  159. package/dist/services/save.js.map +1 -0
  160. package/dist/services/standalone.d.ts +67 -7
  161. package/dist/services/standalone.js +168 -0
  162. package/dist/services/standalone.js.map +1 -0
  163. package/dist/utils/getEntityProp.d.ts +39 -0
  164. package/dist/utils/getEntityProp.js +52 -0
  165. package/dist/utils/getEntityProp.js.map +1 -0
  166. package/package.json +13 -9
  167. package/src/Game/{EffectManager.ts → AnimationManager.ts} +3 -2
  168. package/src/Game/Event.ts +1 -1
  169. package/src/Game/Map.ts +95 -3
  170. package/src/Game/Object.ts +330 -14
  171. package/src/Game/Player.ts +1 -1
  172. package/src/Gui/Gui.ts +506 -18
  173. package/src/Gui/NotificationManager.ts +69 -0
  174. package/src/Resource.ts +150 -0
  175. package/src/RpgClient.ts +300 -58
  176. package/src/RpgClientEngine.ts +1707 -48
  177. package/src/Sound.ts +253 -0
  178. package/src/components/{effects → animations}/animation.ce +3 -6
  179. package/src/components/{effects → animations}/index.ts +1 -1
  180. package/src/components/character.ce +406 -40
  181. package/src/components/dynamics/parse-value.ts +80 -0
  182. package/src/components/dynamics/text.ce +183 -0
  183. package/src/components/gui/box.ce +17 -0
  184. package/src/components/gui/dialogbox/index.ce +204 -187
  185. package/src/components/gui/gameover.ce +158 -0
  186. package/src/components/gui/hud/hud.ce +61 -0
  187. package/src/components/gui/index.ts +30 -4
  188. package/src/components/gui/menu/equip-menu.ce +410 -0
  189. package/src/components/gui/menu/exit-menu.ce +41 -0
  190. package/src/components/gui/menu/items-menu.ce +317 -0
  191. package/src/components/gui/menu/main-menu.ce +294 -0
  192. package/src/components/gui/menu/options-menu.ce +35 -0
  193. package/src/components/gui/menu/skills-menu.ce +83 -0
  194. package/src/components/gui/mobile/index.ts +24 -0
  195. package/src/components/gui/mobile/mobile.ce +80 -0
  196. package/src/components/gui/notification/notification.ce +51 -0
  197. package/src/components/gui/save-load.ce +208 -0
  198. package/src/components/gui/shop/shop.ce +493 -0
  199. package/src/components/gui/title-screen.ce +163 -0
  200. package/src/components/index.ts +3 -0
  201. package/src/components/prebuilt/hp-bar.ce +255 -0
  202. package/src/components/prebuilt/index.ts +24 -0
  203. package/src/components/prebuilt/light-halo.ce +148 -0
  204. package/src/components/scenes/canvas.ce +20 -15
  205. package/src/components/scenes/draw-map.ce +60 -13
  206. package/src/components/scenes/event-layer.ce +9 -2
  207. package/src/components/scenes/transition.ce +60 -0
  208. package/src/index.ts +16 -2
  209. package/src/module.ts +145 -9
  210. package/src/presets/animation.ts +46 -0
  211. package/src/presets/faceset.ts +60 -0
  212. package/src/presets/icon.ts +17 -0
  213. package/src/presets/index.ts +9 -1
  214. package/src/presets/lpc.ts +108 -0
  215. package/src/services/AbstractSocket.ts +10 -2
  216. package/src/services/keyboardControls.ts +20 -0
  217. package/src/services/loadMap.ts +1 -1
  218. package/src/services/mmorpg.ts +100 -12
  219. package/src/services/save.ts +103 -0
  220. package/src/services/standalone.ts +110 -18
  221. package/src/utils/getEntityProp.ts +87 -0
  222. package/tsconfig.json +1 -1
  223. package/vite.config.ts +4 -2
  224. package/dist/Game/EffectManager.d.ts +0 -5
  225. package/dist/components/effects/index.d.ts +0 -4
  226. package/dist/index.js.map +0 -1
  227. package/dist/index10.js +0 -8
  228. package/dist/index10.js.map +0 -1
  229. package/dist/index11.js +0 -10
  230. package/dist/index11.js.map +0 -1
  231. package/dist/index12.js +0 -8
  232. package/dist/index12.js.map +0 -1
  233. package/dist/index13.js +0 -17
  234. package/dist/index13.js.map +0 -1
  235. package/dist/index14.js +0 -91
  236. package/dist/index14.js.map +0 -1
  237. package/dist/index15.js +0 -50
  238. package/dist/index15.js.map +0 -1
  239. package/dist/index16.js +0 -191
  240. package/dist/index16.js.map +0 -1
  241. package/dist/index17.js +0 -9
  242. package/dist/index17.js.map +0 -1
  243. package/dist/index18.js +0 -387
  244. package/dist/index18.js.map +0 -1
  245. package/dist/index19.js +0 -31
  246. package/dist/index19.js.map +0 -1
  247. package/dist/index2.js +0 -112
  248. package/dist/index2.js.map +0 -1
  249. package/dist/index20.js +0 -24
  250. package/dist/index20.js.map +0 -1
  251. package/dist/index21.js +0 -2421
  252. package/dist/index21.js.map +0 -1
  253. package/dist/index22.js +0 -114
  254. package/dist/index22.js.map +0 -1
  255. package/dist/index23.js +0 -109
  256. package/dist/index23.js.map +0 -1
  257. package/dist/index24.js +0 -71
  258. package/dist/index24.js.map +0 -1
  259. package/dist/index25.js +0 -21
  260. package/dist/index25.js.map +0 -1
  261. package/dist/index26.js +0 -41
  262. package/dist/index26.js.map +0 -1
  263. package/dist/index27.js +0 -5
  264. package/dist/index27.js.map +0 -1
  265. package/dist/index28.js +0 -322
  266. package/dist/index28.js.map +0 -1
  267. package/dist/index29.js +0 -27
  268. package/dist/index29.js.map +0 -1
  269. package/dist/index3.js +0 -87
  270. package/dist/index3.js.map +0 -1
  271. package/dist/index30.js +0 -11
  272. package/dist/index30.js.map +0 -1
  273. package/dist/index31.js +0 -11
  274. package/dist/index31.js.map +0 -1
  275. package/dist/index32.js +0 -12
  276. package/dist/index32.js.map +0 -1
  277. package/dist/index33.js +0 -4403
  278. package/dist/index33.js.map +0 -1
  279. package/dist/index34.js +0 -316
  280. package/dist/index34.js.map +0 -1
  281. package/dist/index35.js +0 -174
  282. package/dist/index35.js.map +0 -1
  283. package/dist/index36.js +0 -501
  284. package/dist/index36.js.map +0 -1
  285. package/dist/index37.js +0 -61
  286. package/dist/index37.js.map +0 -1
  287. package/dist/index38.js +0 -20
  288. package/dist/index38.js.map +0 -1
  289. package/dist/index39.js +0 -20
  290. package/dist/index39.js.map +0 -1
  291. package/dist/index4.js +0 -67
  292. package/dist/index4.js.map +0 -1
  293. package/dist/index5.js +0 -16
  294. package/dist/index5.js.map +0 -1
  295. package/dist/index6.js +0 -17
  296. package/dist/index6.js.map +0 -1
  297. package/dist/index7.js +0 -39
  298. package/dist/index7.js.map +0 -1
  299. package/dist/index8.js +0 -90
  300. package/dist/index8.js.map +0 -1
  301. package/dist/index9.js +0 -76
  302. package/dist/index9.js.map +0 -1
  303. package/src/components/gui/dialogbox/itemMenu.ce +0 -23
  304. package/src/components/gui/dialogbox/selection.ce +0 -67
  305. /package/src/components/{effects → animations}/hit.ce +0 -0
@@ -0,0 +1,150 @@
1
+ import { RpgClientEngine } from './RpgClientEngine';
2
+
3
+ /**
4
+ * RpgResource class
5
+ *
6
+ * Provides a unified API to access resource file links (images and sounds) in the game.
7
+ * Resources are stored as Maps of resource IDs to file paths/URLs.
8
+ *
9
+ * ## Design
10
+ *
11
+ * RpgResource acts as a facade over the engine's resource storage, providing
12
+ * easy access to resource file links. It maintains Maps that are synchronized
13
+ * with the engine's internal storage, but only stores the file paths/URLs,
14
+ * not the full resource objects.
15
+ *
16
+ * @example
17
+ * ```ts
18
+ * import { RpgResource } from '@rpgjs/client'
19
+ *
20
+ * // Get spritesheet image link
21
+ * const imageLink = RpgResource.spritesheets.get('hero')
22
+ *
23
+ * // Get sound file link
24
+ * const soundLink = RpgResource.sounds.get('town-music')
25
+ *
26
+ * // Set a new resource link
27
+ * RpgResource.spritesheets.set('new-sprite', './assets/new-sprite.png')
28
+ * ```
29
+ */
30
+ export class RpgResource {
31
+ private static engine: RpgClientEngine | null = null;
32
+ private static _spritesheets: Map<string, string> = new Map();
33
+ private static _sounds: Map<string, string> = new Map();
34
+
35
+ /**
36
+ * Initialize RpgResource with the engine instance
37
+ *
38
+ * This is called automatically by the engine during initialization.
39
+ * It synchronizes the resource Maps with the engine's internal storage.
40
+ *
41
+ * @param engine - The RpgClientEngine instance
42
+ */
43
+ static init(engine: RpgClientEngine): void {
44
+ RpgResource.engine = engine;
45
+ RpgResource.syncResources();
46
+ }
47
+
48
+ /**
49
+ * Synchronize resource Maps with the engine's internal storage
50
+ *
51
+ * Extracts file links from spritesheets and sounds stored in the engine
52
+ * and updates the Maps accordingly.
53
+ *
54
+ * @private
55
+ */
56
+ private static syncResources(): void {
57
+ if (!RpgResource.engine) {
58
+ return;
59
+ }
60
+
61
+ // Sync spritesheets
62
+ RpgResource._spritesheets.clear();
63
+ RpgResource.engine.spritesheets.forEach((spritesheet, id) => {
64
+ // Extract image path from spritesheet
65
+ const imageLink = spritesheet?.image || spritesheet?.imageSource || undefined;
66
+ if (imageLink) {
67
+ RpgResource._spritesheets.set(id, imageLink);
68
+ }
69
+ });
70
+
71
+ // Sync sounds
72
+ RpgResource._sounds.clear();
73
+ RpgResource.engine.sounds.forEach((sound, id) => {
74
+ // Extract src path from sound
75
+ let soundLink: string | undefined;
76
+
77
+ // If it's a Howler instance, try to get src from _src or src property
78
+ if (sound && typeof sound === 'object') {
79
+ if (sound._src && Array.isArray(sound._src) && sound._src.length > 0) {
80
+ soundLink = sound._src[0];
81
+ } else if (sound.src && typeof sound.src === 'string') {
82
+ soundLink = sound.src;
83
+ } else if (sound.src && Array.isArray(sound.src) && sound.src.length > 0) {
84
+ soundLink = sound.src[0];
85
+ }
86
+ }
87
+
88
+ if (soundLink) {
89
+ RpgResource._sounds.set(id, soundLink);
90
+ }
91
+ });
92
+ }
93
+
94
+ /**
95
+ * Get/Set image links for spritesheets
96
+ *
97
+ * Map of spritesheet IDs to their image file paths/URLs.
98
+ * This Map is synchronized with the engine's spritesheet storage.
99
+ *
100
+ * @type {Map<string, string>}
101
+ *
102
+ * @example
103
+ * ```ts
104
+ * // Get an image link
105
+ * const imageLink = RpgResource.spritesheets.get('hero')
106
+ *
107
+ * // Set a new image link
108
+ * RpgResource.spritesheets.set('new-sprite', './assets/new-sprite.png')
109
+ *
110
+ * // Check if a spritesheet exists
111
+ * if (RpgResource.spritesheets.has('monster')) {
112
+ * const link = RpgResource.spritesheets.get('monster')
113
+ * }
114
+ * ```
115
+ */
116
+ static get spritesheets(): Map<string, string> {
117
+ // Sync before returning to ensure we have the latest data
118
+ RpgResource.syncResources();
119
+ return RpgResource._spritesheets;
120
+ }
121
+
122
+ /**
123
+ * Get/Set sound file links
124
+ *
125
+ * Map of sound IDs to their audio file paths/URLs.
126
+ * This Map is synchronized with the engine's sound storage.
127
+ *
128
+ * @type {Map<string, string>}
129
+ *
130
+ * @example
131
+ * ```ts
132
+ * // Get a sound link
133
+ * const soundLink = RpgResource.sounds.get('town-music')
134
+ *
135
+ * // Set a new sound link
136
+ * RpgResource.sounds.set('new-sound', './assets/new-sound.ogg')
137
+ *
138
+ * // Iterate over all sounds
139
+ * RpgResource.sounds.forEach((link, id) => {
140
+ * console.log(`Sound ${id}: ${link}`)
141
+ * })
142
+ * ```
143
+ */
144
+ static get sounds(): Map<string, string> {
145
+ // Sync before returning to ensure we have the latest data
146
+ RpgResource.syncResources();
147
+ return RpgResource._sounds;
148
+ }
149
+ }
150
+
package/src/RpgClient.ts CHANGED
@@ -1,9 +1,12 @@
1
+ import { ComponentFunction, Signal } from 'canvasengine'
1
2
  import { RpgClientEngine } from './RpgClientEngine'
2
- import { Loader } from 'pixi.js'
3
+ import { Loader, Container } from 'pixi.js'
4
+ import { RpgClientObject } from './Game/Object'
5
+ import { type MapPhysicsEntityContext, type MapPhysicsInitContext } from '@rpgjs/common'
3
6
 
4
7
  type RpgClass<T = any> = new (...args: any[]) => T
5
- type RpgComponent = any
6
- type SceneMap = any
8
+ type RpgComponent = RpgClientObject
9
+ type SceneMap = Container
7
10
 
8
11
  export interface RpgClientEngineHooks {
9
12
  /**
@@ -65,6 +68,36 @@ export interface RpgClientEngineHooks {
65
68
  }
66
69
 
67
70
  export interface RpgSpriteHooks {
71
+ /**
72
+ * Array of components to render behind the sprite
73
+ * These components will be displayed with a lower z-index than the sprite itself
74
+ *
75
+ * @prop { ComponentFunction[] } [componentsBehind]
76
+ * @memberof RpgSpriteHooks
77
+ * @example
78
+ * ```ts
79
+ * const sprite: RpgSpriteHooks = {
80
+ * componentsBehind: [ShadowComponent, AuraComponent]
81
+ * }
82
+ * ```
83
+ */
84
+ componentsBehind?: ComponentFunction[]
85
+
86
+ /**
87
+ * Array of components to render in front of the sprite
88
+ * These components will be displayed with a higher z-index than the sprite itself
89
+ *
90
+ * @prop { ComponentFunction[] } [componentsInFront]
91
+ * @memberof RpgSpriteHooks
92
+ * @example
93
+ * ```ts
94
+ * const sprite: RpgSpriteHooks = {
95
+ * componentsInFront: [HealthBarComponent, StatusEffectComponent]
96
+ * }
97
+ * ```
98
+ */
99
+ componentsInFront?: ComponentFunction[]
100
+
68
101
  /**
69
102
  * As soon as the sprite is initialized
70
103
  *
@@ -165,6 +198,41 @@ export interface RpgSceneMapHooks extends RpgSceneHooks<SceneMap> {
165
198
  * @memberof RpgSceneHooks
166
199
  */
167
200
  onMapLoading?: (scene: SceneMap, loader: Loader) => any
201
+
202
+ /**
203
+ * Called when client physics has been initialized for the current map.
204
+ *
205
+ * Use this hook to initialize shared physics extensions based on map data
206
+ * (for example, tile-based collision rules used by client prediction).
207
+ *
208
+ * @prop { (scene: SceneMap, context: MapPhysicsInitContext) => any } [onPhysicsInit]
209
+ * @memberof RpgSceneMapHooks
210
+ */
211
+ onPhysicsInit?: (scene: SceneMap, context: MapPhysicsInitContext) => any
212
+
213
+ /**
214
+ * Called when a character physics body is added to the map.
215
+ *
216
+ * @prop { (scene: SceneMap, context: MapPhysicsEntityContext) => any } [onPhysicsEntityAdd]
217
+ * @memberof RpgSceneMapHooks
218
+ */
219
+ onPhysicsEntityAdd?: (scene: SceneMap, context: MapPhysicsEntityContext) => any
220
+
221
+ /**
222
+ * Called when a character physics body is removed from the map.
223
+ *
224
+ * @prop { (scene: SceneMap, context: MapPhysicsEntityContext) => any } [onPhysicsEntityRemove]
225
+ * @memberof RpgSceneMapHooks
226
+ */
227
+ onPhysicsEntityRemove?: (scene: SceneMap, context: MapPhysicsEntityContext) => any
228
+
229
+ /**
230
+ * Called when the physics world is reset (e.g. before a map physics reload).
231
+ *
232
+ * @prop { (scene: SceneMap) => any } [onPhysicsReset]
233
+ * @memberof RpgSceneMapHooks
234
+ */
235
+ onPhysicsReset?: (scene: SceneMap) => any
168
236
  }
169
237
 
170
238
  export interface RpgClient {
@@ -178,14 +246,13 @@ export interface RpgClient {
178
246
  * @example
179
247
  *
180
248
  * ```ts
181
- * import { RpgClient, RpgModule } from '@rpgjs/client'
249
+ * import { RpgClient, defineModule } from '@rpgjs/client'
182
250
  *
183
- * @RpgModule<RpgClient>({
251
+ * defineModule<RpgClient>({
184
252
  * hooks: {
185
253
  * player: ['onAuth']
186
254
  * }
187
255
  * })
188
- * class RpgClientEngine { }
189
256
  * ```
190
257
  *
191
258
  * Emit the hook:
@@ -224,7 +291,7 @@ export interface RpgClient {
224
291
  * Object containing the hooks concerning the engine
225
292
  *
226
293
  * ```ts
227
- * import { RpgClientEngine, RpgClientEngineHooks, RpgModule, RpgClient } from '@rpgjs/client'
294
+ * import { RpgClientEngine, RpgClientEngineHooks, defineModule, RpgClient } from '@rpgjs/client'
228
295
  *
229
296
  * const engine: RpgClientEngineHooks = {
230
297
  * onConnected(engine: RpgClientEngine) {
@@ -232,10 +299,9 @@ export interface RpgClient {
232
299
  * }
233
300
  * }
234
301
  *
235
- * @RpgModule<RpgClient>({
302
+ * defineModule<RpgClient>({
236
303
  * engine
237
304
  * })
238
- * class RpgClientModule {}
239
305
  * ```
240
306
  *
241
307
  * @prop {RpgClientEngineHooks} [engine]
@@ -245,102 +311,251 @@ export interface RpgClient {
245
311
 
246
312
  /**
247
313
  * Array containing the list of spritesheets
248
- * An element contains a class with the `@Spritesheet` decorator
314
+ * Each element is a simple object containing spritesheet definitions
249
315
  *
250
316
  * ```ts
251
- * import { Spritesheet, Animation, Direction, RpgClient, RpgModule } from '@rpgjs/client'
317
+ * import { defineModule, RpgClient } from '@rpgjs/client'
252
318
  *
253
- * @Spritesheet({
254
- * id: 'chest',
255
- * image: require('./assets/chest.png'),
256
- * // other options
257
- * })
258
- * class Chest { }
259
- *
260
- * @RpgModule<RpgClient>({
319
+ * defineModule<RpgClient>({
261
320
  * spritesheets: [
262
- * Chest
321
+ * {
322
+ * id: 'chest',
323
+ * image: require('./assets/chest.png'),
324
+ * framesWidth: 32,
325
+ * framesHeight: 32,
326
+ * animations: {
327
+ * default: {
328
+ * frames: [0, 1, 2],
329
+ * duration: 1000
330
+ * }
331
+ * }
332
+ * }
263
333
  * ]
264
334
  * })
265
- * class RpgClientEngine {}
266
335
  * ```
267
336
  *
268
337
  * [Guide: Create Sprite](/guide/create-sprite.html)
269
338
  *
270
- * @prop {Array<Class>} [spritesheets]
339
+ * @prop {Array<Object>} [spritesheets]
271
340
  * @memberof RpgClient
272
341
  * */
273
342
  spritesheets?: any[],
274
343
 
275
344
  /**
276
- * Array containing the list of VueJS components
345
+ * Resolver function for dynamically creating spritesheets
346
+ *
347
+ * This function is called when a spritesheet is requested but not found in the cache.
348
+ * It can be synchronous (returns directly) or asynchronous (returns a Promise).
349
+ * The resolved spritesheet is automatically cached for future use.
277
350
  *
278
351
  * ```ts
279
- * import { RpgClient, RpgModule } from '@rpgjs/client'
280
- *
281
- * const component = {
282
- * name: 'my-gui',
283
- * template: `
284
- * <div>
285
- * Component
286
- * </div>
287
- * `
288
- * }
352
+ * import { defineModule, RpgClient } from '@rpgjs/client'
353
+ *
354
+ * defineModule<RpgClient>({
355
+ * spritesheetResolver: (id: string) => {
356
+ * // Synchronous resolver
357
+ * if (id === 'dynamic-sprite') {
358
+ * return {
359
+ * id: 'dynamic-sprite',
360
+ * image: 'path/to/image.png',
361
+ * framesWidth: 32,
362
+ * framesHeight: 32
363
+ * };
364
+ * }
365
+ * return undefined;
366
+ * }
367
+ * })
289
368
  *
290
- * @RpgModule<RpgClient>({
369
+ * // Or asynchronous resolver
370
+ * defineModule<RpgClient>({
371
+ * spritesheetResolver: async (id: string) => {
372
+ * const response = await fetch(`/api/spritesheets/${id}`);
373
+ * const data = await response.json();
374
+ * return data;
375
+ * }
376
+ * })
377
+ * ```
378
+ *
379
+ * @prop {(id: string) => any | Promise<any>} [spritesheetResolver]
380
+ * @memberof RpgClient
381
+ * */
382
+ spritesheetResolver?: (id: string) => any | Promise<any>,
383
+
384
+ /**
385
+ * Resolver function for dynamically loading sounds
386
+ *
387
+ * The resolver is called when a sound is requested but not found in the cache.
388
+ * It can be synchronous (returns directly) or asynchronous (returns a Promise).
389
+ * The resolved sound is automatically cached for future use.
390
+ *
391
+ * ```ts
392
+ * import { defineModule, RpgClient } from '@rpgjs/client'
393
+ *
394
+ * defineModule<RpgClient>({
395
+ * soundResolver: (id: string) => {
396
+ * if (id === 'dynamic-sound') {
397
+ * return { id: 'dynamic-sound', src: 'path/to/sound.mp3' };
398
+ * }
399
+ * return undefined;
400
+ * }
401
+ * })
402
+ * ```
403
+ *
404
+ * @prop {(id: string) => any | Promise<any>} [soundResolver]
405
+ * @memberof RpgClient
406
+ * */
407
+ soundResolver?: (id: string) => any | Promise<any>,
408
+
409
+ /**
410
+ * Array containing the list of GUI components
411
+ *
412
+ * ```ts
413
+ * import { defineModule, RpgClient } from '@rpgjs/client'
414
+ * import InventoryComponent from './inventory.ce'
415
+ *
416
+ * defineModule<RpgClient>({
291
417
  * gui: [
292
- * component
418
+ * {
419
+ * id: 'inventory',
420
+ * component: InventoryComponent,
421
+ * autoDisplay: true,
422
+ * dependencies: () => [playerSignal, inventorySignal]
423
+ * }
293
424
  * ]
294
425
  * })
295
- * class RpgClientEngine {}
296
426
  * ```
297
427
  *
298
428
  * [Guide: Create GUI](/guide/create-gui.html)
299
429
  *
300
- * @prop {Array<Component of VueJS>} [gui]
430
+ * @prop {Array<GuiOptions>} [gui]
301
431
  * @memberof RpgClient
302
432
  * */
303
- gui?: any[],
433
+ gui?: ({
434
+ id: string,
435
+ component: ComponentFunction,
436
+ /**
437
+ * Auto display the GUI when added to the system
438
+ * @default false
439
+ */
440
+ autoDisplay?: boolean,
441
+ /**
442
+ * Function that returns an array of Signal dependencies
443
+ * The GUI will only display when all dependencies are resolved (!= undefined)
444
+ */
445
+ dependencies?: () => Signal[]
446
+ /**
447
+ * Attach the GUI to sprites instead of displaying globally
448
+ *
449
+ * When set to `true`, the GUI component will be rendered directly on each sprite
450
+ * in the game world, rather than being displayed as a fixed overlay on the screen.
451
+ * This is useful for tooltips, health bars, name tags, or any UI element that
452
+ * should follow a specific sprite.
453
+ *
454
+ * The GUI will be rendered in the `character.ce` component for each sprite.
455
+ * You can control the display state of attached GUIs from the server side using
456
+ * `player.showAttachedGui()` and `player.hideAttachedGui()` methods.
457
+ *
458
+ * @default false
459
+ * @example
460
+ * ```ts
461
+ * import { defineModule, RpgClient } from '@rpgjs/client'
462
+ * import TooltipComponent from './tooltip.ce'
463
+ *
464
+ * defineModule<RpgClient>({
465
+ * gui: [
466
+ * {
467
+ * id: "my-tooltip",
468
+ * component: TooltipComponent,
469
+ * attachToSprite: true
470
+ * }
471
+ * ]
472
+ * })
473
+ * ```
474
+ *
475
+ * On the server side, control the display:
476
+ * ```ts
477
+ * // Show the tooltip for this player
478
+ * player.showAttachedGui()
479
+ *
480
+ * // Hide the tooltip for this player
481
+ * player.hideAttachedGui()
482
+ *
483
+ * // Show tooltip for other players
484
+ * player.showAttachedGui([otherPlayer1, otherPlayer2])
485
+ * ```
486
+ */
487
+ attachToSprite?: boolean
488
+ } | any)[],
304
489
 
305
490
  /**
306
491
  * Array containing the list of sounds
307
- * An element contains a class with the `@Sound` decorator
492
+ * Each element can be:
493
+ * - A simple object containing sound definitions
494
+ * - A class decorated with @Sound
308
495
  *
309
496
  * ```ts
310
- * import { Sound, RpgModule, RpgClient } from '@rpgjs/client'
497
+ * import { defineModule, RpgClient, Sound } from '@rpgjs/client'
498
+ *
499
+ * // Using simple objects
500
+ * defineModule<RpgClient>({
501
+ * sounds: [
502
+ * {
503
+ * id: 'typewriter',
504
+ * src: 'typewriter.wav'
505
+ * },
506
+ * {
507
+ * id: 'cursor',
508
+ * src: 'cursor.wav'
509
+ * }
510
+ * ]
511
+ * })
311
512
  *
513
+ * // Using @Sound decorator
312
514
  * @Sound({
313
- * sounds: {
314
- * town: require('./assets/Town_Theme.ogg')
315
- * }
515
+ * id: 'town-music',
516
+ * sound: require('./sound/town.ogg'),
517
+ * loop: true,
518
+ * volume: 0.5
519
+ * })
520
+ * export class TownMusic {}
521
+ *
522
+ * defineModule<RpgClient>({
523
+ * sounds: [TownMusic]
316
524
  * })
317
- * class Sounds {}
318
525
  *
319
- * @RpgModule<RpgClient>({
320
- * sounds: [ Sounds ]
526
+ * // Multiple sounds in one class
527
+ * @Sound({
528
+ * sounds: {
529
+ * hero: require('./assets/hero.ogg'),
530
+ * monster: require('./assets/monster.ogg')
531
+ * },
532
+ * loop: true
533
+ * })
534
+ * export class CharacterSounds {}
535
+ *
536
+ * defineModule<RpgClient>({
537
+ * sounds: [CharacterSounds]
321
538
  * })
322
- * class RpgClientEngine {}
323
539
  * ```
324
540
  *
325
- * @prop {Array<Class>} [sounds]
541
+ * @prop {Array<Object | Class>} [sounds]
326
542
  * @memberof RpgClient
327
543
  * */
328
- sounds?: RpgClass[],
544
+ sounds?: any[],
329
545
 
330
546
  /**
331
547
  * Give the `RpgSprite` class. A Sprite represents a player or an event
332
548
  *
333
549
  * ```ts
334
- * import { RpgSprite, RpgSpriteHooks, RpgClient, RpgModule } from '@rpgjs/client'
550
+ * import { RpgSprite, RpgSpriteHooks, RpgClient, defineModule } from '@rpgjs/client'
335
551
  *
336
552
  * export const sprite: RpgSpriteHooks = {
337
553
  * onInit(sprite: RpgSprite) {}
338
554
  * }
339
555
  *
340
- * @RpgModule<RpgClient>({
556
+ * defineModule<RpgClient>({
341
557
  * sprite
342
558
  * })
343
- * class RpgClientEngine {}
344
559
  * ```
345
560
  *
346
561
  * @prop {RpgSpriteHooks} [sprite]
@@ -352,19 +567,18 @@ export interface RpgClient {
352
567
  * Reference the scenes of the game. Here you can put your own class that inherits RpgSceneMap
353
568
  *
354
569
  * ```ts
355
- * import { RpgSceneMapHooks, RpgClient, RpgModule } from '@rpgjs/client'
570
+ * import { RpgSceneMapHooks, RpgClient, defineModule } from '@rpgjs/client'
356
571
  *
357
572
  * export const sceneMap: RpgSceneMapHooks = {
358
573
  *
359
574
  * }
360
575
  *
361
- * @RpgModule<RpgClient>({
576
+ * defineModule<RpgClient>({
362
577
  * scenes: {
363
578
  * // If you put the RpgSceneMap scene, Thhe key is called mandatory `map`
364
579
  * map: sceneMap
365
580
  * }
366
581
  * })
367
- * class RpgClientEngine {}
368
582
  * ```
369
583
  *
370
584
  * @prop { [sceneName: string]: RpgSceneMapHooks } [scenes]
@@ -374,8 +588,36 @@ export interface RpgClient {
374
588
  map: RpgSceneMapHooks
375
589
  }
376
590
 
377
- effects?: {
591
+ sceneMap?: RpgSceneMapHooks
592
+
593
+ /**
594
+ * Array containing the list of component animations
595
+ * Each element defines a temporary component to display for animations like hits, effects, etc.
596
+ *
597
+ * ```ts
598
+ * import { defineModule, RpgClient } from '@rpgjs/client'
599
+ * import HitComponent from './hit.ce'
600
+ * import ExplosionComponent from './explosion.ce'
601
+ *
602
+ * defineModule<RpgClient>({
603
+ * componentAnimations: [
604
+ * {
605
+ * id: 'hit',
606
+ * component: HitComponent
607
+ * },
608
+ * {
609
+ * id: 'explosion',
610
+ * component: ExplosionComponent
611
+ * }
612
+ * ]
613
+ * })
614
+ * ```
615
+ *
616
+ * @prop {Array<{id: string, component: ComponentFunction}>} [componentAnimations]
617
+ * @memberof RpgClient
618
+ * */
619
+ componentAnimations?: {
378
620
  id: string,
379
- component: any
621
+ component: ComponentFunction
380
622
  }[]
381
- }
623
+ }