@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,123 @@
1
+ import { inject } from "../node_modules/.pnpm/@signe_di@2.9.0/node_modules/@signe/di/dist/index.js";
2
+ import { UpdateMapToken } from "@rpgjs/common";
3
+ //#region src/services/loadMap.ts
4
+ var LoadMapToken = "LoadMapToken";
5
+ var LoadMapService = class {
6
+ constructor(context, options) {
7
+ this.context = context;
8
+ this.options = options;
9
+ if (context["side"] === "server") return;
10
+ this.updateMapService = inject(context, UpdateMapToken);
11
+ }
12
+ async load(mapId) {
13
+ const map = await this.options(mapId.replace("map-", ""));
14
+ await this.updateMapService.update(map);
15
+ return map;
16
+ }
17
+ };
18
+ /**
19
+ * Creates a dependency injection configuration for custom map loading on the client side.
20
+ *
21
+ * This function allows you to customize how maps are loaded and displayed by providing
22
+ * a callback that defines custom map data and rendering components. It's designed to work
23
+ * with the RPG-JS dependency injection system and enables integration of custom map formats
24
+ * like Tiled TMX files or any other map data structure.
25
+ *
26
+ * The function sets up the necessary service providers for map loading, including:
27
+ * - UpdateMapToken: Handles map updates in the client context
28
+ * - LoadMapToken: Provides the LoadMapService with your custom loading logic
29
+ *
30
+ * **Design Concept:**
31
+ * The function follows the provider pattern, creating a modular way to inject custom
32
+ * map loading behavior into the RPG-JS client engine. It separates the concern of
33
+ * map data fetching from map rendering, allowing developers to focus on their specific
34
+ * map format while leveraging the engine's rendering capabilities.
35
+ *
36
+ * @param {LoadMapOptions} options - Callback function that handles map loading logic
37
+ * @returns {Array<Object>} Array of dependency injection provider configurations
38
+ *
39
+ * @example
40
+ * ```typescript
41
+ * import { provideLoadMap } from '@rpgjs/client'
42
+ * import { createModule } from '@rpgjs/common'
43
+ * import MyTiledMapComponent from './MyTiledMapComponent.ce'
44
+ *
45
+ * // Basic usage with JSON map data
46
+ * export function provideCustomMap() {
47
+ * return createModule("CustomMap", [
48
+ * provideLoadMap(async (mapId) => {
49
+ * const response = await fetch(`/maps/${mapId}.json`)
50
+ * const mapData = await response.json()
51
+ *
52
+ * return {
53
+ * data: mapData,
54
+ * component: MyTiledMapComponent,
55
+ * width: mapData.width,
56
+ * height: mapData.height,
57
+ * events: mapData.events
58
+ * }
59
+ * })
60
+ * ])
61
+ * }
62
+ *
63
+ * // Advanced usage with Tiled TMX files
64
+ * export function provideTiledMap() {
65
+ * return createModule("TiledMap", [
66
+ * provideLoadMap(async (mapId) => {
67
+ * // Load TMX file
68
+ * const tmxResponse = await fetch(`/tiled/${mapId}.tmx`)
69
+ * const tmxData = await tmxResponse.text()
70
+ *
71
+ * // Parse TMX data (using a TMX parser)
72
+ * const parsedMap = parseTMX(tmxData)
73
+ *
74
+ * return {
75
+ * data: parsedMap,
76
+ * component: TiledMapRenderer,
77
+ * width: parsedMap.width * parsedMap.tilewidth,
78
+ * height: parsedMap.height * parsedMap.tileheight,
79
+ * events: parsedMap.objectGroups?.find(g => g.name === 'events')?.objects
80
+ * }
81
+ * })
82
+ * ])
83
+ * }
84
+ *
85
+ * // Synchronous usage for static maps
86
+ * export function provideStaticMap() {
87
+ * return createModule("StaticMap", [
88
+ * provideLoadMap((mapId) => {
89
+ * const staticMaps = {
90
+ * 'town': { tiles: [...], npcs: [...] },
91
+ * 'dungeon': { tiles: [...], monsters: [...] }
92
+ * }
93
+ *
94
+ * return {
95
+ * data: staticMaps[mapId],
96
+ * component: StaticMapComponent,
97
+ * width: 800,
98
+ * height: 600
99
+ * }
100
+ * })
101
+ * ])
102
+ * }
103
+ * ```
104
+ *
105
+ * @since 4.0.0
106
+ * @see {@link LoadMapOptions} for callback function signature
107
+ * @see {@link MapData} for return data structure
108
+ */
109
+ function provideLoadMap(options) {
110
+ return [{
111
+ provide: UpdateMapToken,
112
+ useFactory: (context) => {
113
+ if (context["side"] === "client") console.warn("UpdateMapToken is not overridden");
114
+ }
115
+ }, {
116
+ provide: LoadMapToken,
117
+ useFactory: (context) => new LoadMapService(context, options)
118
+ }];
119
+ }
120
+ //#endregion
121
+ export { LoadMapService, LoadMapToken, provideLoadMap };
122
+
123
+ //# sourceMappingURL=loadMap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loadMap.js","names":[],"sources":["../../src/services/loadMap.ts"],"sourcesContent":["import { Context, inject } from \"@signe/di\";\nimport { UpdateMapToken, UpdateMapService } from \"@rpgjs/common\";\n\nexport const LoadMapToken = 'LoadMapToken'\n\n/**\n * Represents the structure of map data that should be returned by the load map callback.\n * This interface defines all the properties that can be provided when loading a custom map.\n * \n * @interface MapData\n */\ntype MapData = {\n /** Raw map data that will be passed to the map component */\n data: any;\n /** CanvasEngine component that will render the map */\n component: any;\n /** Optional map width in pixels, used for viewport calculations */\n width?: number;\n /** Optional map height in pixels, used for viewport calculations */\n height?: number;\n /** Optional map events data (NPCs, interactive objects, etc.) */\n events?: any;\n /** Optional map identifier, defaults to the mapId parameter if not provided */\n id?: string;\n}\n\n/**\n * Callback function type for loading map data.\n * This function receives a map ID and should return either a MapData object directly\n * or a Promise that resolves to a MapData object.\n * \n * @callback LoadMapOptions\n * @param {string} mapId - The identifier of the map to load\n * @returns {Promise<MapData> | MapData} The map data object or a promise resolving to it\n */\nexport type LoadMapOptions = (mapId: string) => Promise<MapData> | MapData \n\nexport class LoadMapService {\n private updateMapService: UpdateMapService;\n\n constructor(private context: Context, private options: LoadMapOptions) {\n if (context['side'] === 'server') {\n return\n }\n this.updateMapService = inject(context, UpdateMapToken);\n }\n\n async load(mapId: string) {\n const map = await this.options(mapId.replace('map-', ''))\n await this.updateMapService.update(map);\n return map;\n }\n}\n\n/**\n * Creates a dependency injection configuration for custom map loading on the client side.\n * \n * This function allows you to customize how maps are loaded and displayed by providing\n * a callback that defines custom map data and rendering components. It's designed to work\n * with the RPG-JS dependency injection system and enables integration of custom map formats\n * like Tiled TMX files or any other map data structure.\n * \n * The function sets up the necessary service providers for map loading, including:\n * - UpdateMapToken: Handles map updates in the client context\n * - LoadMapToken: Provides the LoadMapService with your custom loading logic\n * \n * **Design Concept:**\n * The function follows the provider pattern, creating a modular way to inject custom\n * map loading behavior into the RPG-JS client engine. It separates the concern of\n * map data fetching from map rendering, allowing developers to focus on their specific\n * map format while leveraging the engine's rendering capabilities.\n * \n * @param {LoadMapOptions} options - Callback function that handles map loading logic\n * @returns {Array<Object>} Array of dependency injection provider configurations\n * \n * @example\n * ```typescript\n * import { provideLoadMap } from '@rpgjs/client'\n * import { createModule } from '@rpgjs/common'\n * import MyTiledMapComponent from './MyTiledMapComponent.ce'\n * \n * // Basic usage with JSON map data\n * export function provideCustomMap() {\n * return createModule(\"CustomMap\", [\n * provideLoadMap(async (mapId) => {\n * const response = await fetch(`/maps/${mapId}.json`)\n * const mapData = await response.json()\n * \n * return {\n * data: mapData,\n * component: MyTiledMapComponent,\n * width: mapData.width,\n * height: mapData.height,\n * events: mapData.events\n * }\n * })\n * ])\n * }\n * \n * // Advanced usage with Tiled TMX files\n * export function provideTiledMap() {\n * return createModule(\"TiledMap\", [\n * provideLoadMap(async (mapId) => {\n * // Load TMX file\n * const tmxResponse = await fetch(`/tiled/${mapId}.tmx`)\n * const tmxData = await tmxResponse.text()\n * \n * // Parse TMX data (using a TMX parser)\n * const parsedMap = parseTMX(tmxData)\n * \n * return {\n * data: parsedMap,\n * component: TiledMapRenderer,\n * width: parsedMap.width * parsedMap.tilewidth,\n * height: parsedMap.height * parsedMap.tileheight,\n * events: parsedMap.objectGroups?.find(g => g.name === 'events')?.objects\n * }\n * })\n * ])\n * }\n * \n * // Synchronous usage for static maps\n * export function provideStaticMap() {\n * return createModule(\"StaticMap\", [\n * provideLoadMap((mapId) => {\n * const staticMaps = {\n * 'town': { tiles: [...], npcs: [...] },\n * 'dungeon': { tiles: [...], monsters: [...] }\n * }\n * \n * return {\n * data: staticMaps[mapId],\n * component: StaticMapComponent,\n * width: 800,\n * height: 600\n * }\n * })\n * ])\n * }\n * ```\n * \n * @since 4.0.0\n * @see {@link LoadMapOptions} for callback function signature\n * @see {@link MapData} for return data structure\n */\nexport function provideLoadMap(options: LoadMapOptions) {\n return [\n {\n provide: UpdateMapToken,\n useFactory: (context: Context) => {\n if (context['side'] === 'client') {\n console.warn('UpdateMapToken is not overridden')\n }\n return\n },\n },\n {\n provide: LoadMapToken,\n useFactory: (context: Context) => new LoadMapService(context, options),\n },\n ];\n}\n"],"mappings":";;;AAGA,IAAa,eAAe;AAkC5B,IAAa,iBAAb,MAA4B;CAG1B,YAAY,SAA0B,SAAiC;AAAnD,OAAA,UAAA;AAA0B,OAAA,UAAA;AAC5C,MAAI,QAAQ,YAAY,SACtB;AAEF,OAAK,mBAAmB,OAAO,SAAS,eAAe;;CAGzD,MAAM,KAAK,OAAe;EACxB,MAAM,MAAM,MAAM,KAAK,QAAQ,MAAM,QAAQ,QAAQ,GAAG,CAAC;AACzD,QAAM,KAAK,iBAAiB,OAAO,IAAI;AACvC,SAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+FX,SAAgB,eAAe,SAAyB;AACtD,QAAO,CACL;EACE,SAAS;EACT,aAAa,YAAqB;AAChC,OAAI,QAAQ,YAAY,SACtB,SAAQ,KAAK,mCAAmC;;EAIrD,EACD;EACE,SAAS;EACT,aAAa,YAAqB,IAAI,eAAe,SAAS,QAAQ;EACvE,CACF"}
@@ -1,32 +1,44 @@
1
1
  import { Context } from '@signe/di';
2
2
  import { RpgGui } from '../Gui/Gui';
3
3
  import { RpgClientEngine } from '../RpgClientEngine';
4
- import { AbstractWebsocket } from './AbstractSocket';
4
+ import { AbstractWebsocket, SocketUpdateProperties } from './AbstractSocket';
5
5
  import { UpdateMapService } from '@rpgjs/common';
6
6
  interface MmorpgOptions {
7
7
  host?: string;
8
+ connectionId?: string;
9
+ connectionIdScope?: "local" | "session" | "ephemeral";
8
10
  }
9
11
  declare class BridgeWebsocket extends AbstractWebsocket {
10
12
  protected context: Context;
11
13
  private options;
12
14
  private socket;
15
+ private privateId;
16
+ private pendingOn;
17
+ private targetRoom;
13
18
  constructor(context: Context, options?: MmorpgOptions);
19
+ private resolveConnectionId;
14
20
  connection(listeners?: (data: any) => void): Promise<void>;
15
21
  on(key: string, callback: (data: any) => void): void;
16
22
  off(event: string, callback: (data: any) => void): void;
17
23
  emit(event: string, data: any): void;
18
- updateProperties({ room }: {
19
- room: any;
20
- }): void;
21
- reconnect(listeners?: (data: any) => void): Promise<void>;
24
+ updateProperties({ room, host, query }: SocketUpdateProperties): void;
25
+ private waitForNextOpen;
26
+ reconnect(_listeners?: (data: any) => void): Promise<void>;
27
+ getCurrentRoom(): string;
22
28
  }
23
29
  declare class UpdateMapStandaloneService extends UpdateMapService {
24
30
  protected context: Context;
25
- private options;
26
- constructor(context: Context, options: MmorpgOptions);
27
- update(map: any): Promise<void>;
31
+ private _options;
32
+ constructor(context: Context, _options: MmorpgOptions);
33
+ update(_map: any): Promise<void>;
28
34
  }
29
- export declare function provideMmorpg(options: MmorpgOptions): (typeof RpgGui | typeof RpgClientEngine | {
35
+ export declare function provideMmorpg(options: MmorpgOptions): (typeof RpgClientEngine | typeof RpgGui | {
36
+ provide: typeof import('./save').SaveClientService;
37
+ useClass: typeof import('./save').SaveClientService;
38
+ } | {
39
+ provide: string;
40
+ useValue: null;
41
+ } | {
30
42
  provide: string;
31
43
  useFactory: (context: Context) => BridgeWebsocket;
32
44
  } | {
@@ -0,0 +1,131 @@
1
+ import { AbstractWebsocket, WebSocketToken } from "./AbstractSocket.js";
2
+ import { provideSaveClient } from "./save.js";
3
+ import { RpgGui } from "../Gui/Gui.js";
4
+ import { RpgClientEngine } from "../RpgClientEngine.js";
5
+ import { provideKeyboardControls } from "./keyboardControls.js";
6
+ import { connectionRoom } from "../node_modules/.pnpm/@signe_sync@2.9.0/node_modules/@signe/sync/dist/client/index.js";
7
+ import { UpdateMapService, UpdateMapToken } from "@rpgjs/common";
8
+ //#region src/services/mmorpg.ts
9
+ var BridgeWebsocket = class extends AbstractWebsocket {
10
+ constructor(context, options = {}) {
11
+ super(context);
12
+ this.context = context;
13
+ this.options = options;
14
+ this.pendingOn = [];
15
+ this.targetRoom = "lobby-1";
16
+ this.privateId = this.resolveConnectionId();
17
+ }
18
+ resolveConnectionId() {
19
+ if (this.options.connectionId) return this.options.connectionId;
20
+ const scope = this.options.connectionIdScope ?? "local";
21
+ const key = "rpgjs-user-id";
22
+ if (scope === "ephemeral") return crypto.randomUUID();
23
+ const storage = scope === "session" ? window.sessionStorage : window.localStorage;
24
+ const existing = storage.getItem(key);
25
+ if (existing) return existing;
26
+ const id = crypto.randomUUID();
27
+ storage.setItem(key, id);
28
+ return id;
29
+ }
30
+ async connection(listeners) {
31
+ class Room {}
32
+ const instance = new Room();
33
+ this.socket = await connectionRoom({
34
+ host: this.options.host || window.location.host,
35
+ room: this.targetRoom,
36
+ id: this.privateId
37
+ }, instance);
38
+ listeners?.(this.socket);
39
+ this.pendingOn.forEach(({ event, callback }) => this.socket.on(event, callback));
40
+ this.pendingOn = [];
41
+ }
42
+ on(key, callback) {
43
+ if (!this.socket) {
44
+ this.pendingOn.push({
45
+ event: key,
46
+ callback
47
+ });
48
+ return;
49
+ }
50
+ this.socket.on(key, callback);
51
+ }
52
+ off(event, callback) {
53
+ if (!this.socket) return;
54
+ this.socket.off(event, callback);
55
+ }
56
+ emit(event, data) {
57
+ this.socket.emit(event, data);
58
+ }
59
+ updateProperties({ room, host, query }) {
60
+ if (!this.socket?.conn) return;
61
+ this.targetRoom = room;
62
+ this.socket.conn.updateProperties({
63
+ room,
64
+ id: this.privateId,
65
+ host: host || this.options.host || window.location.host,
66
+ query
67
+ });
68
+ }
69
+ waitForNextOpen(conn, timeoutMs = 1e4) {
70
+ return new Promise((resolve, reject) => {
71
+ let timeoutId;
72
+ const onOpen = () => {
73
+ cleanup();
74
+ resolve();
75
+ };
76
+ const onError = () => {
77
+ cleanup();
78
+ reject(/* @__PURE__ */ new Error("WebSocket reconnect failed"));
79
+ };
80
+ const cleanup = () => {
81
+ conn.removeEventListener("open", onOpen);
82
+ conn.removeEventListener("error", onError);
83
+ if (timeoutId !== void 0) window.clearTimeout(timeoutId);
84
+ };
85
+ conn.addEventListener("open", onOpen);
86
+ conn.addEventListener("error", onError);
87
+ timeoutId = window.setTimeout(() => {
88
+ cleanup();
89
+ reject(/* @__PURE__ */ new Error("WebSocket reconnect timeout"));
90
+ }, timeoutMs);
91
+ });
92
+ }
93
+ async reconnect(_listeners) {
94
+ if (!this.socket?.conn) return;
95
+ const conn = this.socket.conn;
96
+ const opened = this.waitForNextOpen(conn);
97
+ conn.reconnect();
98
+ await opened;
99
+ }
100
+ getCurrentRoom() {
101
+ return this.targetRoom || this.socket?.conn?.room || "lobby-1";
102
+ }
103
+ };
104
+ var UpdateMapStandaloneService = class extends UpdateMapService {
105
+ constructor(context, _options) {
106
+ super(context);
107
+ this.context = context;
108
+ this._options = _options;
109
+ }
110
+ async update(_map) {}
111
+ };
112
+ function provideMmorpg(options) {
113
+ return [
114
+ {
115
+ provide: WebSocketToken,
116
+ useFactory: (context) => new BridgeWebsocket(context, options)
117
+ },
118
+ {
119
+ provide: UpdateMapToken,
120
+ useFactory: (context) => new UpdateMapStandaloneService(context, options)
121
+ },
122
+ provideKeyboardControls(),
123
+ provideSaveClient(),
124
+ RpgGui,
125
+ RpgClientEngine
126
+ ];
127
+ }
128
+ //#endregion
129
+ export { provideMmorpg };
130
+
131
+ //# sourceMappingURL=mmorpg.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mmorpg.js","names":[],"sources":["../../src/services/mmorpg.ts"],"sourcesContent":["import { Context } from \"@signe/di\";\nimport { connectionRoom } from \"@signe/sync/client\";\nimport { RpgGui } from \"../Gui/Gui\";\nimport { RpgClientEngine } from \"../RpgClientEngine\";\nimport { AbstractWebsocket, SocketUpdateProperties, WebSocketToken } from \"./AbstractSocket\";\nimport { UpdateMapService, UpdateMapToken } from \"@rpgjs/common\";\nimport { provideKeyboardControls } from \"./keyboardControls\";\nimport { provideSaveClient } from \"./save\";\n\ninterface MmorpgOptions {\n host?: string;\n connectionId?: string;\n connectionIdScope?: \"local\" | \"session\" | \"ephemeral\";\n}\n\nclass BridgeWebsocket extends AbstractWebsocket {\n private socket: any;\n private privateId: string;\n private pendingOn: Array<{ event: string; callback: (data: any) => void }> = [];\n private targetRoom = \"lobby-1\";\n\n constructor(protected context: Context, private options: MmorpgOptions = {}) {\n super(context);\n this.privateId = this.resolveConnectionId();\n }\n\n private resolveConnectionId(): string {\n if (this.options.connectionId) {\n return this.options.connectionId;\n }\n\n const scope = this.options.connectionIdScope ?? \"local\";\n const key = \"rpgjs-user-id\";\n\n if (scope === \"ephemeral\") {\n return crypto.randomUUID();\n }\n\n const storage =\n scope === \"session\"\n ? window.sessionStorage\n : window.localStorage;\n\n const existing = storage.getItem(key);\n if (existing) {\n return existing;\n }\n\n const id = crypto.randomUUID();\n storage.setItem(key, id);\n return id;\n }\n\n async connection(listeners?: (data: any) => void) {\n // tmp\n class Room {\n \n }\n const instance = new Room()\n const host = this.options.host || window.location.host;\n this.socket = await connectionRoom({\n host,\n room: this.targetRoom,\n id: this.privateId\n }, instance)\n\n listeners?.(this.socket)\n this.pendingOn.forEach(({ event, callback }) => this.socket.on(event, callback));\n this.pendingOn = [];\n }\n\n on(key: string, callback: (data: any) => void) {\n if (!this.socket) {\n this.pendingOn.push({ event: key, callback });\n return;\n }\n this.socket.on(key, callback);\n }\n\n off(event: string, callback: (data: any) => void) {\n if (!this.socket) return;\n this.socket.off(event, callback);\n }\n\n emit(event: string, data: any) {\n this.socket.emit(event, data);\n }\n\n updateProperties({ room, host, query }: SocketUpdateProperties) {\n if (!this.socket?.conn) return;\n this.targetRoom = room;\n this.socket.conn.updateProperties({\n room,\n id: this.privateId,\n host: host || this.options.host || window.location.host,\n query,\n })\n }\n\n private waitForNextOpen(conn: any, timeoutMs = 10000): Promise<void> {\n return new Promise((resolve, reject) => {\n let timeoutId: number | undefined;\n const onOpen = () => {\n cleanup();\n resolve();\n };\n const onError = () => {\n cleanup();\n reject(new Error(\"WebSocket reconnect failed\"));\n };\n const cleanup = () => {\n conn.removeEventListener(\"open\", onOpen);\n conn.removeEventListener(\"error\", onError);\n if (timeoutId !== undefined) {\n window.clearTimeout(timeoutId);\n }\n };\n\n conn.addEventListener(\"open\", onOpen);\n conn.addEventListener(\"error\", onError);\n timeoutId = window.setTimeout(() => {\n cleanup();\n reject(new Error(\"WebSocket reconnect timeout\"));\n }, timeoutMs);\n });\n }\n\n async reconnect(_listeners?: (data: any) => void): Promise<void> {\n if (!this.socket?.conn) return;\n const conn = this.socket.conn;\n const opened = this.waitForNextOpen(conn);\n conn.reconnect();\n await opened;\n }\n\n getCurrentRoom(): string {\n return this.targetRoom || this.socket?.conn?.room || \"lobby-1\";\n }\n}\n\nclass UpdateMapStandaloneService extends UpdateMapService {\n constructor(protected context: Context, private _options: MmorpgOptions) {\n super(context);\n }\n\n async update(_map: any) {\n // In MMORPG mode, clients are untrusted and must not push map definitions.\n // Map bootstrap/update is handled server-side by @rpgjs/vite.\n return;\n }\n}\n\nexport function provideMmorpg(options: MmorpgOptions) {\n return [\n {\n provide: WebSocketToken,\n useFactory: (context: Context) => new BridgeWebsocket(context, options),\n },\n {\n provide: UpdateMapToken,\n useFactory: (context: Context) => new UpdateMapStandaloneService(context, options),\n },\n provideKeyboardControls(),\n provideSaveClient(),\n RpgGui,\n RpgClientEngine,\n ];\n}\n"],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import { SaveSlotList, SaveSlotMeta } from '@rpgjs/common';
2
+ export declare const SaveClientToken = "SaveClientToken";
3
+ export declare class SaveClientService {
4
+ private webSocket;
5
+ private pending;
6
+ private requestCounter;
7
+ initialize(): void;
8
+ listSlots(): Promise<SaveSlotList>;
9
+ saveSlot(index: number, meta?: SaveSlotMeta): Promise<SaveSlotList>;
10
+ loadSlot(index: number): Promise<boolean>;
11
+ private request;
12
+ private resolveRequest;
13
+ private rejectRequest;
14
+ private nextRequestId;
15
+ }
16
+ export declare function provideSaveClient(): {
17
+ provide: typeof SaveClientService;
18
+ useClass: typeof SaveClientService;
19
+ };
@@ -0,0 +1,77 @@
1
+ import { inject } from "../core/inject.js";
2
+ import { WebSocketToken } from "./AbstractSocket.js";
3
+ //#region src/services/save.ts
4
+ var SaveClientToken = "SaveClientToken";
5
+ var SaveClientService = class {
6
+ constructor() {
7
+ this.webSocket = inject(WebSocketToken);
8
+ this.pending = /* @__PURE__ */ new Map();
9
+ this.requestCounter = 0;
10
+ }
11
+ initialize() {
12
+ const saveListResult = (data) => this.resolveRequest(data.requestId, data);
13
+ const saveSaveResult = (data) => this.resolveRequest(data.requestId, data);
14
+ const saveLoadResult = (data) => this.resolveRequest(data.requestId, data);
15
+ const saveErrorResult = (data) => this.rejectRequest(data.requestId, data.message);
16
+ this.webSocket.off("save.list.result", saveListResult);
17
+ this.webSocket.off("save.save.result", saveSaveResult);
18
+ this.webSocket.off("save.load.result", saveLoadResult);
19
+ this.webSocket.off("save.error", saveErrorResult);
20
+ this.webSocket.on("save.list.result", saveListResult);
21
+ this.webSocket.on("save.save.result", saveSaveResult);
22
+ this.webSocket.on("save.load.result", saveLoadResult);
23
+ this.webSocket.on("save.error", saveErrorResult);
24
+ }
25
+ listSlots() {
26
+ return this.request("save.list", {}).then((result) => result.slots);
27
+ }
28
+ saveSlot(index, meta = {}) {
29
+ return this.request("save.save", {
30
+ index,
31
+ meta
32
+ }).then((result) => result.slots);
33
+ }
34
+ loadSlot(index) {
35
+ return this.request("save.load", { index }).then((result) => result.ok);
36
+ }
37
+ request(event, payload) {
38
+ return new Promise((resolve, reject) => {
39
+ if (!this.webSocket) this.initialize();
40
+ const requestId = this.nextRequestId();
41
+ this.pending.set(requestId, {
42
+ resolve,
43
+ reject
44
+ });
45
+ this.webSocket?.emit(event, {
46
+ requestId,
47
+ ...payload
48
+ });
49
+ });
50
+ }
51
+ resolveRequest(requestId, result) {
52
+ const pending = this.pending.get(requestId);
53
+ if (!pending) return;
54
+ this.pending.delete(requestId);
55
+ pending.resolve(result);
56
+ }
57
+ rejectRequest(requestId, message) {
58
+ const pending = this.pending.get(requestId);
59
+ if (!pending) return;
60
+ this.pending.delete(requestId);
61
+ pending.reject(new Error(message));
62
+ }
63
+ nextRequestId() {
64
+ this.requestCounter += 1;
65
+ return `${Date.now()}-${this.requestCounter}`;
66
+ }
67
+ };
68
+ function provideSaveClient() {
69
+ return {
70
+ provide: SaveClientService,
71
+ useClass: SaveClientService
72
+ };
73
+ }
74
+ //#endregion
75
+ export { SaveClientService, SaveClientToken, provideSaveClient };
76
+
77
+ //# sourceMappingURL=save.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"save.js","names":[],"sources":["../../src/services/save.ts"],"sourcesContent":["import type { SaveSlotList, SaveSlotMeta } from \"@rpgjs/common\";\nimport { inject } from \"../core/inject\";\nimport { AbstractWebsocket, WebSocketToken } from \"./AbstractSocket\";\n\nexport const SaveClientToken = \"SaveClientToken\";\n\ntype SaveListResult = {\n requestId: string;\n slots: SaveSlotList;\n};\n\ntype SaveSaveResult = {\n requestId: string;\n index: number;\n slots: SaveSlotList;\n};\n\ntype SaveLoadResult = {\n requestId: string;\n index: number;\n ok: boolean;\n slot?: SaveSlotMeta;\n};\n\ntype SaveErrorResult = {\n requestId: string;\n message: string;\n};\n\ntype PendingRequest = {\n resolve: (value: any) => void;\n reject: (error: Error) => void;\n};\n\nexport class SaveClientService {\n private webSocket: AbstractWebsocket = inject(WebSocketToken);\n private pending: Map<string, PendingRequest> = new Map();\n private requestCounter = 0;\n\n initialize() {\n const saveListResult = (data: SaveListResult) => this.resolveRequest(data.requestId, data);\n const saveSaveResult = (data: SaveSaveResult) => this.resolveRequest(data.requestId, data);\n const saveLoadResult = (data: SaveLoadResult) => this.resolveRequest(data.requestId, data);\n const saveErrorResult = (data: SaveErrorResult) => this.rejectRequest(data.requestId, data.message);\n this.webSocket.off(\"save.list.result\", saveListResult);\n this.webSocket.off(\"save.save.result\", saveSaveResult);\n this.webSocket.off(\"save.load.result\", saveLoadResult);\n this.webSocket.off(\"save.error\", saveErrorResult);\n this.webSocket.on(\"save.list.result\", saveListResult);\n this.webSocket.on(\"save.save.result\", saveSaveResult);\n this.webSocket.on(\"save.load.result\", saveLoadResult);\n this.webSocket.on(\"save.error\", saveErrorResult);\n }\n\n listSlots(): Promise<SaveSlotList> {\n return this.request<SaveListResult>(\"save.list\", {}).then((result) => result.slots);\n }\n\n saveSlot(index: number, meta: SaveSlotMeta = {}): Promise<SaveSlotList> {\n return this.request<SaveSaveResult>(\"save.save\", { index, meta }).then((result) => result.slots);\n }\n\n loadSlot(index: number): Promise<boolean> {\n return this.request<SaveLoadResult>(\"save.load\", { index }).then((result) => result.ok);\n }\n\n private request<T>(event: string, payload: Record<string, any>): Promise<T> {\n return new Promise((resolve, reject) => {\n if (!this.webSocket) {\n this.initialize();\n }\n const requestId = this.nextRequestId();\n this.pending.set(requestId, { resolve, reject });\n this.webSocket?.emit(event, { requestId, ...payload });\n });\n }\n\n private resolveRequest(requestId: string, result: any) {\n const pending = this.pending.get(requestId);\n if (!pending) return;\n this.pending.delete(requestId);\n pending.resolve(result);\n }\n\n private rejectRequest(requestId: string, message: string) {\n const pending = this.pending.get(requestId);\n if (!pending) return;\n this.pending.delete(requestId);\n pending.reject(new Error(message));\n }\n\n private nextRequestId(): string {\n this.requestCounter += 1;\n return `${Date.now()}-${this.requestCounter}`;\n }\n}\n\nexport function provideSaveClient() {\n return {\n provide: SaveClientService,\n useClass: SaveClientService,\n };\n}\n"],"mappings":";;;AAIA,IAAa,kBAAkB;AA8B/B,IAAa,oBAAb,MAA+B;;mBACU,OAAO,eAAe;iCACd,IAAI,KAAK;wBAC/B;;CAEzB,aAAa;EACX,MAAM,kBAAkB,SAAyB,KAAK,eAAe,KAAK,WAAW,KAAK;EAC1F,MAAM,kBAAkB,SAAyB,KAAK,eAAe,KAAK,WAAW,KAAK;EAC1F,MAAM,kBAAkB,SAAyB,KAAK,eAAe,KAAK,WAAW,KAAK;EAC1F,MAAM,mBAAmB,SAA0B,KAAK,cAAc,KAAK,WAAW,KAAK,QAAQ;AACnG,OAAK,UAAU,IAAI,oBAAoB,eAAe;AACtD,OAAK,UAAU,IAAI,oBAAoB,eAAe;AACtD,OAAK,UAAU,IAAI,oBAAoB,eAAe;AACtD,OAAK,UAAU,IAAI,cAAc,gBAAgB;AACjD,OAAK,UAAU,GAAG,oBAAoB,eAAe;AACrD,OAAK,UAAU,GAAG,oBAAoB,eAAe;AACrD,OAAK,UAAU,GAAG,oBAAoB,eAAe;AACrD,OAAK,UAAU,GAAG,cAAc,gBAAgB;;CAGlD,YAAmC;AACjC,SAAO,KAAK,QAAwB,aAAa,EAAE,CAAC,CAAC,MAAM,WAAW,OAAO,MAAM;;CAGrF,SAAS,OAAe,OAAqB,EAAE,EAAyB;AACtE,SAAO,KAAK,QAAwB,aAAa;GAAE;GAAO;GAAM,CAAC,CAAC,MAAM,WAAW,OAAO,MAAM;;CAGlG,SAAS,OAAiC;AACxC,SAAO,KAAK,QAAwB,aAAa,EAAE,OAAO,CAAC,CAAC,MAAM,WAAW,OAAO,GAAG;;CAGzF,QAAmB,OAAe,SAA0C;AAC1E,SAAO,IAAI,SAAS,SAAS,WAAW;AACtC,OAAI,CAAC,KAAK,UACR,MAAK,YAAY;GAEnB,MAAM,YAAY,KAAK,eAAe;AACtC,QAAK,QAAQ,IAAI,WAAW;IAAE;IAAS;IAAQ,CAAC;AAChD,QAAK,WAAW,KAAK,OAAO;IAAE;IAAW,GAAG;IAAS,CAAC;IACtD;;CAGJ,eAAuB,WAAmB,QAAa;EACrD,MAAM,UAAU,KAAK,QAAQ,IAAI,UAAU;AAC3C,MAAI,CAAC,QAAS;AACd,OAAK,QAAQ,OAAO,UAAU;AAC9B,UAAQ,QAAQ,OAAO;;CAGzB,cAAsB,WAAmB,SAAiB;EACxD,MAAM,UAAU,KAAK,QAAQ,IAAI,UAAU;AAC3C,MAAI,CAAC,QAAS;AACd,OAAK,QAAQ,OAAO,UAAU;AAC9B,UAAQ,OAAO,IAAI,MAAM,QAAQ,CAAC;;CAGpC,gBAAgC;AAC9B,OAAK,kBAAkB;AACvB,SAAO,GAAG,KAAK,KAAK,CAAC,GAAG,KAAK;;;AAIjC,SAAgB,oBAAoB;AAClC,QAAO;EACL,SAAS;EACT,UAAU;EACX"}
@@ -1,28 +1,88 @@
1
- import { AbstractWebsocket } from './AbstractSocket';
1
+ import { AbstractWebsocket, SocketUpdateProperties } from './AbstractSocket';
2
2
  import { Context } from '@signe/di';
3
3
  import { RpgClientEngine } from '../RpgClientEngine';
4
4
  import { UpdateMapService } from '@rpgjs/common';
5
5
  import { RpgGui } from '../Gui/Gui';
6
+ interface StandaloneOptions {
7
+ env?: Record<string, any>;
8
+ }
6
9
  declare class BridgeWebsocket extends AbstractWebsocket {
7
10
  protected context: Context;
8
11
  private server;
9
12
  private room;
10
13
  private socket;
11
- constructor(context: Context, server: any);
14
+ private pendingOn;
15
+ private rooms;
16
+ private serverInstance;
17
+ constructor(context: Context, server: any, options?: StandaloneOptions);
12
18
  connection(listeners?: (data: any) => void): Promise<any>;
19
+ private _connection;
13
20
  on(key: string, callback: (data: any) => void): void;
14
21
  off(event: string, callback: (data: any) => void): void;
15
22
  emit(event: string, data: any): void;
16
- updateProperties({ room }: {
17
- room: any;
18
- }): void;
23
+ /**
24
+ * Update underlying connection properties before a reconnect
25
+ *
26
+ * Design
27
+ * - Dynamically register a factory for the requested room to ensure a fresh server instance
28
+ * - Swap the internal ServerIo to target the new room
29
+ *
30
+ * @param params - Properties to update
31
+ * @param params.room - The target room id (e.g. `map-simplemap2`)
32
+ *
33
+ * @example
34
+ * ```ts
35
+ * websocket.updateProperties({ room: 'map-simplemap2' })
36
+ * await websocket.reconnect()
37
+ * ```
38
+ */
39
+ updateProperties(_params: SocketUpdateProperties): void;
40
+ /**
41
+ * Reconnect the client to the current Party room
42
+ *
43
+ * Design
44
+ * - Must be called after `updateProperties()` when switching rooms
45
+ * - Rebuilds the client <-> server bridge and re-triggers connection listeners
46
+ *
47
+ * @param listeners - Optional callback to re-bind event handlers on the new socket
48
+ *
49
+ * @example
50
+ * ```ts
51
+ * websocket.updateProperties({ room: 'map-dungeon' })
52
+ * await websocket.reconnect((socket) => {
53
+ * // re-bind events here
54
+ * })
55
+ * ```
56
+ */
19
57
  reconnect(listeners?: (data: any) => void): Promise<void>;
58
+ getServer(): any;
59
+ getSocket(): any;
20
60
  }
21
61
  declare class UpdateMapStandaloneService extends UpdateMapService {
22
62
  private server;
23
- update(mapId: string, map: any): Promise<void>;
63
+ /**
64
+ * Update the current room map data on the server side
65
+ *
66
+ * Design
67
+ * - Uses the in-memory server instance stored in context (standalone mode)
68
+ * - Builds a local HTTP-like request to the current Party room endpoint
69
+ *
70
+ * @param map - The map payload to apply on the server
71
+ *
72
+ * @example
73
+ * ```ts
74
+ * await updateMapService.update({ width: 1024, height: 768, events: [] })
75
+ * ```
76
+ */
77
+ update(map: any): Promise<void>;
24
78
  }
25
- export declare function provideRpg(server: any): (typeof RpgGui | typeof RpgClientEngine | {
79
+ export declare function provideRpg(server: any, options?: StandaloneOptions): (typeof RpgClientEngine | typeof RpgGui | {
80
+ provide: typeof import('./save').SaveClientService;
81
+ useClass: typeof import('./save').SaveClientService;
82
+ } | {
83
+ provide: string;
84
+ useValue: null;
85
+ } | {
26
86
  provide: string;
27
87
  useFactory: (context: Context) => BridgeWebsocket;
28
88
  useClass?: undefined;