@rpgjs/client 5.0.0-beta.2 → 5.0.0-beta.22

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 (325) hide show
  1. package/CHANGELOG.md +130 -0
  2. package/dist/Game/AnimationManager.d.ts +2 -1
  3. package/dist/Game/AnimationManager.js +21 -9
  4. package/dist/Game/AnimationManager.js.map +1 -1
  5. package/dist/Game/AnimationManager.spec.d.ts +1 -0
  6. package/dist/Game/ClientVisuals.d.ts +61 -0
  7. package/dist/Game/ClientVisuals.js +96 -0
  8. package/dist/Game/ClientVisuals.js.map +1 -0
  9. package/dist/Game/ClientVisuals.spec.d.ts +1 -0
  10. package/dist/Game/Event.js.map +1 -1
  11. package/dist/Game/EventComponentResolver.d.ts +16 -0
  12. package/dist/Game/EventComponentResolver.js +52 -0
  13. package/dist/Game/EventComponentResolver.js.map +1 -0
  14. package/dist/Game/EventComponentResolver.spec.d.ts +1 -0
  15. package/dist/Game/Map.d.ts +9 -1
  16. package/dist/Game/Map.js +83 -5
  17. package/dist/Game/Map.js.map +1 -1
  18. package/dist/Game/Object.d.ts +49 -15
  19. package/dist/Game/Object.js +101 -42
  20. package/dist/Game/Object.js.map +1 -1
  21. package/dist/Game/Object.spec.d.ts +1 -0
  22. package/dist/Game/Player.js.map +1 -1
  23. package/dist/Game/ProjectileManager.d.ts +98 -0
  24. package/dist/Game/ProjectileManager.js +196 -0
  25. package/dist/Game/ProjectileManager.js.map +1 -0
  26. package/dist/Game/ProjectileManager.spec.d.ts +1 -0
  27. package/dist/Gui/Gui.d.ts +20 -6
  28. package/dist/Gui/Gui.js +132 -57
  29. package/dist/Gui/Gui.js.map +1 -1
  30. package/dist/Gui/Gui.spec.d.ts +1 -0
  31. package/dist/Gui/NotificationManager.js.map +1 -1
  32. package/dist/Resource.js +1 -1
  33. package/dist/Resource.js.map +1 -1
  34. package/dist/RpgClient.d.ts +194 -15
  35. package/dist/RpgClientEngine.d.ts +191 -19
  36. package/dist/RpgClientEngine.js +693 -74
  37. package/dist/RpgClientEngine.js.map +1 -1
  38. package/dist/Sound.js.map +1 -1
  39. package/dist/_virtual/{_@oxc-project_runtime@0.122.0/helpers → _@oxc-project_runtime@0.133.0/helpers/esm}/decorate.js +1 -1
  40. package/dist/_virtual/{_@oxc-project_runtime@0.122.0/helpers → _@oxc-project_runtime@0.133.0/helpers/esm}/decorateMetadata.js +1 -1
  41. package/dist/_virtual/_rolldown/runtime.js +13 -0
  42. package/dist/components/animations/animation.ce.js +6 -5
  43. package/dist/components/animations/animation.ce.js.map +1 -1
  44. package/dist/components/animations/fx.ce.js +60 -0
  45. package/dist/components/animations/fx.ce.js.map +1 -0
  46. package/dist/components/animations/hit.ce.js +24 -28
  47. package/dist/components/animations/hit.ce.js.map +1 -1
  48. package/dist/components/animations/index.d.ts +1 -0
  49. package/dist/components/animations/index.js +6 -4
  50. package/dist/components/animations/index.js.map +1 -1
  51. package/dist/components/character.ce.js +748 -249
  52. package/dist/components/character.ce.js.map +1 -1
  53. package/dist/components/dynamics/bar.ce.js +99 -0
  54. package/dist/components/dynamics/bar.ce.js.map +1 -0
  55. package/dist/components/dynamics/image.ce.js +26 -0
  56. package/dist/components/dynamics/image.ce.js.map +1 -0
  57. package/dist/components/dynamics/parse-value.d.ts +3 -0
  58. package/dist/components/dynamics/parse-value.js +54 -35
  59. package/dist/components/dynamics/parse-value.js.map +1 -1
  60. package/dist/components/dynamics/parse-value.spec.d.ts +1 -0
  61. package/dist/components/dynamics/shape-utils.d.ts +16 -0
  62. package/dist/components/dynamics/shape-utils.js +73 -0
  63. package/dist/components/dynamics/shape-utils.js.map +1 -0
  64. package/dist/components/dynamics/shape-utils.spec.d.ts +1 -0
  65. package/dist/components/dynamics/shape.ce.js +86 -0
  66. package/dist/components/dynamics/shape.ce.js.map +1 -0
  67. package/dist/components/dynamics/text.ce.js +36 -56
  68. package/dist/components/dynamics/text.ce.js.map +1 -1
  69. package/dist/components/gui/box.ce.js +9 -9
  70. package/dist/components/gui/box.ce.js.map +1 -1
  71. package/dist/components/gui/dialogbox/index.ce.js +75 -65
  72. package/dist/components/gui/dialogbox/index.ce.js.map +1 -1
  73. package/dist/components/gui/gameover.ce.js +47 -68
  74. package/dist/components/gui/gameover.ce.js.map +1 -1
  75. package/dist/components/gui/hud/hud.ce.js +23 -31
  76. package/dist/components/gui/hud/hud.ce.js.map +1 -1
  77. package/dist/components/gui/menu/equip-menu.ce.js +121 -172
  78. package/dist/components/gui/menu/equip-menu.ce.js.map +1 -1
  79. package/dist/components/gui/menu/exit-menu.ce.js +15 -10
  80. package/dist/components/gui/menu/exit-menu.ce.js.map +1 -1
  81. package/dist/components/gui/menu/items-menu.ce.js +62 -77
  82. package/dist/components/gui/menu/items-menu.ce.js.map +1 -1
  83. package/dist/components/gui/menu/main-menu.ce.js +89 -104
  84. package/dist/components/gui/menu/main-menu.ce.js.map +1 -1
  85. package/dist/components/gui/menu/options-menu.ce.js +12 -8
  86. package/dist/components/gui/menu/options-menu.ce.js.map +1 -1
  87. package/dist/components/gui/menu/skills-menu.ce.js +17 -19
  88. package/dist/components/gui/menu/skills-menu.ce.js.map +1 -1
  89. package/dist/components/gui/mobile/index.d.ts +51 -2
  90. package/dist/components/gui/mobile/index.js +14 -6
  91. package/dist/components/gui/mobile/index.js.map +1 -1
  92. package/dist/components/gui/mobile/index.spec.d.ts +1 -0
  93. package/dist/components/gui/mobile/mobile.ce.js +309 -59
  94. package/dist/components/gui/mobile/mobile.ce.js.map +1 -1
  95. package/dist/components/gui/notification/notification.ce.js +28 -26
  96. package/dist/components/gui/notification/notification.ce.js.map +1 -1
  97. package/dist/components/gui/save-load.ce.js +81 -256
  98. package/dist/components/gui/save-load.ce.js.map +1 -1
  99. package/dist/components/gui/shop/shop.ce.js +107 -142
  100. package/dist/components/gui/shop/shop.ce.js.map +1 -1
  101. package/dist/components/gui/title-screen.ce.js +50 -73
  102. package/dist/components/gui/title-screen.ce.js.map +1 -1
  103. package/dist/components/index.d.ts +2 -1
  104. package/dist/components/index.js +1 -0
  105. package/dist/components/interaction-components.ce.js +22 -0
  106. package/dist/components/interaction-components.ce.js.map +1 -0
  107. package/dist/components/player-components-utils.d.ts +67 -0
  108. package/dist/components/player-components-utils.js +162 -0
  109. package/dist/components/player-components-utils.js.map +1 -0
  110. package/dist/components/player-components-utils.spec.d.ts +1 -0
  111. package/dist/components/player-components.ce.js +191 -0
  112. package/dist/components/player-components.ce.js.map +1 -0
  113. package/dist/components/prebuilt/hp-bar.ce.js +45 -45
  114. package/dist/components/prebuilt/hp-bar.ce.js.map +1 -1
  115. package/dist/components/prebuilt/light-halo.ce.js +39 -60
  116. package/dist/components/prebuilt/light-halo.ce.js.map +1 -1
  117. package/dist/components/scenes/canvas.ce.js +205 -27
  118. package/dist/components/scenes/canvas.ce.js.map +1 -1
  119. package/dist/components/scenes/draw-map.ce.js +39 -39
  120. package/dist/components/scenes/draw-map.ce.js.map +1 -1
  121. package/dist/components/scenes/event-layer.ce.js +51 -10
  122. package/dist/components/scenes/event-layer.ce.js.map +1 -1
  123. package/dist/core/inject.js +1 -1
  124. package/dist/core/inject.js.map +1 -1
  125. package/dist/core/setup.js +1 -1
  126. package/dist/core/setup.js.map +1 -1
  127. package/dist/decorators/spritesheet.d.ts +1 -0
  128. package/dist/decorators/spritesheet.js +11 -0
  129. package/dist/decorators/spritesheet.js.map +1 -0
  130. package/dist/i18n.d.ts +55 -0
  131. package/dist/i18n.js +60 -0
  132. package/dist/i18n.js.map +1 -0
  133. package/dist/i18n.spec.d.ts +1 -0
  134. package/dist/index.d.ts +8 -0
  135. package/dist/index.js +29 -21
  136. package/dist/module.js +45 -4
  137. package/dist/module.js.map +1 -1
  138. package/dist/node_modules/.pnpm/{@signe_di@2.9.0 → @signe_di@3.1.0}/node_modules/@signe/di/dist/index.js +7 -117
  139. package/dist/node_modules/.pnpm/@signe_di@3.1.0/node_modules/@signe/di/dist/index.js.map +1 -0
  140. package/dist/node_modules/.pnpm/@signe_reactive@3.1.0/node_modules/@signe/reactive/dist/index.js +239 -0
  141. package/dist/node_modules/.pnpm/@signe_reactive@3.1.0/node_modules/@signe/reactive/dist/index.js.map +1 -0
  142. package/dist/node_modules/.pnpm/@signe_room@3.1.0_react@19.2.7/node_modules/@signe/room/dist/chunk-EUXUH3YW.js +13 -0
  143. package/dist/node_modules/.pnpm/@signe_room@3.1.0_react@19.2.7/node_modules/@signe/room/dist/chunk-EUXUH3YW.js.map +1 -0
  144. package/dist/node_modules/.pnpm/@signe_room@3.1.0_react@19.2.7/node_modules/@signe/room/dist/index.js +698 -0
  145. package/dist/node_modules/.pnpm/@signe_room@3.1.0_react@19.2.7/node_modules/@signe/room/dist/index.js.map +1 -0
  146. package/dist/node_modules/.pnpm/@signe_sync@3.1.0_react@19.2.7/node_modules/@signe/sync/dist/client/index.js +43 -0
  147. package/dist/node_modules/.pnpm/@signe_sync@3.1.0_react@19.2.7/node_modules/@signe/sync/dist/client/index.js.map +1 -0
  148. package/dist/node_modules/.pnpm/{@signe_sync@2.9.0 → @signe_sync@3.1.0_react@19.2.7}/node_modules/@signe/sync/dist/index.js +57 -141
  149. package/dist/node_modules/.pnpm/@signe_sync@3.1.0_react@19.2.7/node_modules/@signe/sync/dist/index.js.map +1 -0
  150. package/dist/node_modules/.pnpm/{partysocket@1.1.3/node_modules/partysocket/dist/chunk-HAC622V3.js → partysocket@1.2.0_react@19.2.7/node_modules/partysocket/dist/index.js} +30 -17
  151. package/dist/node_modules/.pnpm/partysocket@1.2.0_react@19.2.7/node_modules/partysocket/dist/index.js.map +1 -0
  152. package/dist/node_modules/.pnpm/{partysocket@1.1.3/node_modules/partysocket/dist/chunk-S74YV6PU.js → partysocket@1.2.0_react@19.2.7/node_modules/partysocket/dist/ws.js} +65 -34
  153. package/dist/node_modules/.pnpm/partysocket@1.2.0_react@19.2.7/node_modules/partysocket/dist/ws.js.map +1 -0
  154. package/dist/node_modules/.pnpm/zod@3.25.76/node_modules/zod/index.js +13 -0
  155. package/dist/node_modules/.pnpm/zod@3.25.76/node_modules/zod/index.js.map +1 -0
  156. package/dist/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/ZodError.js +106 -0
  157. package/dist/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/ZodError.js.map +1 -0
  158. package/dist/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/errors.js +13 -0
  159. package/dist/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/errors.js.map +1 -0
  160. package/dist/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/external.js +121 -0
  161. package/dist/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/external.js.map +1 -0
  162. package/dist/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/errorUtil.js +10 -0
  163. package/dist/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/errorUtil.js.map +1 -0
  164. package/dist/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/parseUtil.js +110 -0
  165. package/dist/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/parseUtil.js.map +1 -0
  166. package/dist/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/util.js +99 -0
  167. package/dist/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/util.js.map +1 -0
  168. package/dist/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/locales/en.js +82 -0
  169. package/dist/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/locales/en.js.map +1 -0
  170. package/dist/node_modules/.pnpm/{zod@3.24.2/node_modules/zod/lib/index.js → zod@3.25.76/node_modules/zod/v3/types.js} +74 -611
  171. package/dist/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/types.js.map +1 -0
  172. package/dist/presets/animation.js.map +1 -1
  173. package/dist/presets/faceset.js.map +1 -1
  174. package/dist/presets/icon.js.map +1 -1
  175. package/dist/presets/index.js.map +1 -1
  176. package/dist/presets/lpc.js.map +1 -1
  177. package/dist/presets/rmspritesheet.js.map +1 -1
  178. package/dist/services/AbstractSocket.d.ts +2 -0
  179. package/dist/services/AbstractSocket.js.map +1 -1
  180. package/dist/services/actionInput.d.ts +14 -0
  181. package/dist/services/actionInput.js +59 -0
  182. package/dist/services/actionInput.js.map +1 -0
  183. package/dist/services/actionInput.spec.d.ts +1 -0
  184. package/dist/services/cameraFollow.d.ts +51 -0
  185. package/dist/services/cameraFollow.js +134 -0
  186. package/dist/services/cameraFollow.js.map +1 -0
  187. package/dist/services/cameraFollow.spec.d.ts +1 -0
  188. package/dist/services/interactions.d.ts +159 -0
  189. package/dist/services/interactions.js +460 -0
  190. package/dist/services/interactions.js.map +1 -0
  191. package/dist/services/interactions.spec.d.ts +1 -0
  192. package/dist/services/keyboardControls.d.ts +1 -0
  193. package/dist/services/keyboardControls.js +1 -0
  194. package/dist/services/keyboardControls.js.map +1 -1
  195. package/dist/services/loadMap.d.ts +9 -0
  196. package/dist/services/loadMap.js +1 -1
  197. package/dist/services/loadMap.js.map +1 -1
  198. package/dist/services/mmorpg-connection.d.ts +5 -0
  199. package/dist/services/mmorpg-connection.js +50 -0
  200. package/dist/services/mmorpg-connection.js.map +1 -0
  201. package/dist/services/mmorpg-connection.spec.d.ts +1 -0
  202. package/dist/services/mmorpg.d.ts +11 -4
  203. package/dist/services/mmorpg.js +57 -33
  204. package/dist/services/mmorpg.js.map +1 -1
  205. package/dist/services/pointerContext.d.ts +11 -0
  206. package/dist/services/pointerContext.js +48 -0
  207. package/dist/services/pointerContext.js.map +1 -0
  208. package/dist/services/pointerContext.spec.d.ts +1 -0
  209. package/dist/services/save.js.map +1 -1
  210. package/dist/services/save.spec.d.ts +1 -0
  211. package/dist/services/standalone-message.d.ts +1 -0
  212. package/dist/services/standalone-message.js +9 -0
  213. package/dist/services/standalone-message.js.map +1 -0
  214. package/dist/services/standalone.d.ts +4 -1
  215. package/dist/services/standalone.js +36 -16
  216. package/dist/services/standalone.js.map +1 -1
  217. package/dist/services/standalone.spec.d.ts +1 -0
  218. package/dist/utils/getEntityProp.js +4 -3
  219. package/dist/utils/getEntityProp.js.map +1 -1
  220. package/dist/utils/getEntityProp.spec.d.ts +1 -0
  221. package/dist/utils/mapId.d.ts +1 -0
  222. package/dist/utils/mapId.js +6 -0
  223. package/dist/utils/mapId.js.map +1 -0
  224. package/dist/utils/readPropValue.d.ts +2 -0
  225. package/dist/utils/readPropValue.js +13 -0
  226. package/dist/utils/readPropValue.js.map +1 -0
  227. package/package.json +13 -13
  228. package/src/Game/AnimationManager.spec.ts +30 -0
  229. package/src/Game/AnimationManager.ts +26 -10
  230. package/src/Game/ClientVisuals.spec.ts +56 -0
  231. package/src/Game/ClientVisuals.ts +184 -0
  232. package/src/Game/EventComponentResolver.spec.ts +84 -0
  233. package/src/Game/EventComponentResolver.ts +74 -0
  234. package/src/Game/Map.ts +134 -2
  235. package/src/Game/Object.spec.ts +59 -0
  236. package/src/Game/Object.ts +181 -77
  237. package/src/Game/ProjectileManager.spec.ts +449 -0
  238. package/src/Game/ProjectileManager.ts +346 -0
  239. package/src/Gui/Gui.spec.ts +359 -0
  240. package/src/Gui/Gui.ts +178 -67
  241. package/src/Resource.ts +1 -2
  242. package/src/RpgClient.ts +220 -17
  243. package/src/RpgClientEngine.ts +995 -133
  244. package/src/components/animations/fx.ce +101 -0
  245. package/src/components/animations/index.ts +4 -2
  246. package/src/components/character.ce +839 -45
  247. package/src/components/dynamics/bar.ce +88 -0
  248. package/src/components/dynamics/image.ce +21 -0
  249. package/src/components/dynamics/parse-value.spec.ts +83 -0
  250. package/src/components/dynamics/parse-value.ts +111 -37
  251. package/src/components/dynamics/shape-utils.spec.ts +46 -0
  252. package/src/components/dynamics/shape-utils.ts +61 -0
  253. package/src/components/dynamics/shape.ce +90 -0
  254. package/src/components/dynamics/text.ce +35 -149
  255. package/src/components/gui/dialogbox/index.ce +52 -21
  256. package/src/components/gui/gameover.ce +6 -4
  257. package/src/components/gui/menu/equip-menu.ce +11 -9
  258. package/src/components/gui/menu/exit-menu.ce +6 -4
  259. package/src/components/gui/menu/items-menu.ce +11 -9
  260. package/src/components/gui/menu/main-menu.ce +14 -12
  261. package/src/components/gui/menu/options-menu.ce +4 -3
  262. package/src/components/gui/menu/skills-menu.ce +2 -1
  263. package/src/components/gui/mobile/index.spec.ts +94 -0
  264. package/src/components/gui/mobile/index.ts +74 -6
  265. package/src/components/gui/mobile/mobile.ce +347 -65
  266. package/src/components/gui/notification/notification.ce +7 -1
  267. package/src/components/gui/save-load.ce +13 -11
  268. package/src/components/gui/shop/shop.ce +20 -18
  269. package/src/components/gui/title-screen.ce +6 -4
  270. package/src/components/index.ts +2 -1
  271. package/src/components/interaction-components.ce +23 -0
  272. package/src/components/player-components-utils.spec.ts +109 -0
  273. package/src/components/player-components-utils.ts +205 -0
  274. package/src/components/player-components.ce +222 -0
  275. package/src/components/prebuilt/hp-bar.ce +4 -3
  276. package/src/components/prebuilt/light-halo.ce +2 -2
  277. package/src/components/scenes/canvas.ce +219 -15
  278. package/src/components/scenes/draw-map.ce +34 -22
  279. package/src/components/scenes/event-layer.ce +55 -4
  280. package/src/core/setup.ts +2 -2
  281. package/src/decorators/spritesheet.ts +8 -0
  282. package/src/i18n.spec.ts +39 -0
  283. package/src/i18n.ts +59 -0
  284. package/src/index.ts +19 -0
  285. package/src/module.ts +61 -11
  286. package/src/services/AbstractSocket.ts +3 -0
  287. package/src/services/actionInput.spec.ts +155 -0
  288. package/src/services/actionInput.ts +120 -0
  289. package/src/services/cameraFollow.spec.ts +220 -0
  290. package/src/services/cameraFollow.ts +222 -0
  291. package/src/services/interactions.spec.ts +175 -0
  292. package/src/services/interactions.ts +722 -0
  293. package/src/services/keyboardControls.ts +2 -1
  294. package/src/services/loadMap.ts +5 -1
  295. package/src/services/mmorpg-connection.spec.ts +99 -0
  296. package/src/services/mmorpg-connection.ts +69 -0
  297. package/src/services/mmorpg.ts +70 -36
  298. package/src/services/pointerContext.spec.ts +36 -0
  299. package/src/services/pointerContext.ts +84 -0
  300. package/src/services/save.spec.ts +127 -0
  301. package/src/services/standalone-message.ts +7 -0
  302. package/src/services/standalone.spec.ts +54 -0
  303. package/src/services/standalone.ts +44 -12
  304. package/src/utils/getEntityProp.spec.ts +96 -0
  305. package/src/utils/getEntityProp.ts +4 -3
  306. package/src/utils/mapId.ts +2 -0
  307. package/src/utils/readPropValue.ts +16 -0
  308. package/dist/node_modules/.pnpm/@signe_di@2.9.0/node_modules/@signe/di/dist/index.js.map +0 -1
  309. package/dist/node_modules/.pnpm/@signe_reactive@2.8.3/node_modules/@signe/reactive/dist/index.js +0 -457
  310. package/dist/node_modules/.pnpm/@signe_reactive@2.8.3/node_modules/@signe/reactive/dist/index.js.map +0 -1
  311. package/dist/node_modules/.pnpm/@signe_reactive@2.9.0/node_modules/@signe/reactive/dist/index.js +0 -463
  312. package/dist/node_modules/.pnpm/@signe_reactive@2.9.0/node_modules/@signe/reactive/dist/index.js.map +0 -1
  313. package/dist/node_modules/.pnpm/@signe_room@2.9.0/node_modules/@signe/room/dist/index.js +0 -2191
  314. package/dist/node_modules/.pnpm/@signe_room@2.9.0/node_modules/@signe/room/dist/index.js.map +0 -1
  315. package/dist/node_modules/.pnpm/@signe_sync@2.9.0/node_modules/@signe/sync/dist/chunk-7QVYU63E.js +0 -10
  316. package/dist/node_modules/.pnpm/@signe_sync@2.9.0/node_modules/@signe/sync/dist/chunk-7QVYU63E.js.map +0 -1
  317. package/dist/node_modules/.pnpm/@signe_sync@2.9.0/node_modules/@signe/sync/dist/client/index.js +0 -91
  318. package/dist/node_modules/.pnpm/@signe_sync@2.9.0/node_modules/@signe/sync/dist/client/index.js.map +0 -1
  319. package/dist/node_modules/.pnpm/@signe_sync@2.9.0/node_modules/@signe/sync/dist/index.js.map +0 -1
  320. package/dist/node_modules/.pnpm/dset@3.1.4/node_modules/dset/dist/index.js +0 -14
  321. package/dist/node_modules/.pnpm/dset@3.1.4/node_modules/dset/dist/index.js.map +0 -1
  322. package/dist/node_modules/.pnpm/partysocket@1.1.3/node_modules/partysocket/dist/chunk-HAC622V3.js.map +0 -1
  323. package/dist/node_modules/.pnpm/partysocket@1.1.3/node_modules/partysocket/dist/chunk-S74YV6PU.js.map +0 -1
  324. package/dist/node_modules/.pnpm/partysocket@1.1.3/node_modules/partysocket/dist/index.js +0 -2
  325. package/dist/node_modules/.pnpm/zod@3.24.2/node_modules/zod/lib/index.js.map +0 -1
@@ -0,0 +1,50 @@
1
+ //#region src/services/mmorpg-connection.ts
2
+ function parseSocketMessage(data) {
3
+ if (typeof data !== "string") return data;
4
+ try {
5
+ return JSON.parse(data);
6
+ } catch {
7
+ return;
8
+ }
9
+ }
10
+ function isNativeSocketEvent(event) {
11
+ return event === "open" || event === "close" || event === "error";
12
+ }
13
+ function waitForRpgjsConnected(conn, timeoutMs = 1e4, options = {}) {
14
+ return new Promise((resolve, reject) => {
15
+ let timeoutId;
16
+ const cleanup = () => {
17
+ conn.removeEventListener("message", onMessage);
18
+ conn.removeEventListener("close", onClose);
19
+ conn.removeEventListener("error", onError);
20
+ if (timeoutId !== void 0) window.clearTimeout(timeoutId);
21
+ };
22
+ const rejectWith = (error) => {
23
+ cleanup();
24
+ reject(error);
25
+ };
26
+ const onMessage = (event) => {
27
+ if (parseSocketMessage(event.data)?.type !== "connected") return;
28
+ cleanup();
29
+ resolve();
30
+ };
31
+ const onClose = (event) => {
32
+ const rawReason = event.reason;
33
+ if (options.ignoreCleanClose && (event.code === 1e3 || rawReason instanceof Event || typeof rawReason !== "string")) return;
34
+ rejectWith(new Error(typeof rawReason === "string" && rawReason ? rawReason : "WebSocket closed before RPGJS connection was accepted"));
35
+ };
36
+ const onError = (event) => {
37
+ rejectWith(new Error(event.message || "WebSocket connection failed"));
38
+ };
39
+ conn.addEventListener("message", onMessage);
40
+ conn.addEventListener("close", onClose);
41
+ conn.addEventListener("error", onError);
42
+ timeoutId = window.setTimeout(() => {
43
+ rejectWith(/* @__PURE__ */ new Error("RPGJS connection timeout"));
44
+ }, timeoutMs);
45
+ });
46
+ }
47
+ //#endregion
48
+ export { isNativeSocketEvent, waitForRpgjsConnected };
49
+
50
+ //# sourceMappingURL=mmorpg-connection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mmorpg-connection.js","names":[],"sources":["../../src/services/mmorpg-connection.ts"],"sourcesContent":["export function parseSocketMessage(data: any) {\n if (typeof data !== \"string\") {\n return data;\n }\n try {\n return JSON.parse(data);\n }\n catch {\n return undefined;\n }\n}\n\nexport function isNativeSocketEvent(event: string) {\n return event === \"open\" || event === \"close\" || event === \"error\";\n}\n\nexport function waitForRpgjsConnected(\n conn: any,\n timeoutMs = 10000,\n options: { ignoreCleanClose?: boolean } = {},\n): Promise<void> {\n return new Promise((resolve, reject) => {\n let timeoutId: number | undefined;\n\n const cleanup = () => {\n conn.removeEventListener(\"message\", onMessage);\n conn.removeEventListener(\"close\", onClose);\n conn.removeEventListener(\"error\", onError);\n if (timeoutId !== undefined) {\n window.clearTimeout(timeoutId);\n }\n };\n const rejectWith = (error: Error) => {\n cleanup();\n reject(error);\n };\n const onMessage = (event: MessageEvent) => {\n const data = parseSocketMessage(event.data);\n if (data?.type !== \"connected\") {\n return;\n }\n cleanup();\n resolve();\n };\n const onClose = (event: CloseEvent) => {\n const rawReason: unknown = (event as any).reason;\n if (\n options.ignoreCleanClose\n && (event.code === 1000 || rawReason instanceof Event || typeof rawReason !== \"string\")\n ) {\n return;\n }\n const reason = typeof rawReason === \"string\" && rawReason\n ? rawReason\n : \"WebSocket closed before RPGJS connection was accepted\";\n rejectWith(new Error(reason));\n };\n const onError = (event: ErrorEvent) => {\n rejectWith(new Error(event.message || \"WebSocket connection failed\"));\n };\n\n conn.addEventListener(\"message\", onMessage);\n conn.addEventListener(\"close\", onClose);\n conn.addEventListener(\"error\", onError);\n timeoutId = window.setTimeout(() => {\n rejectWith(new Error(\"RPGJS connection timeout\"));\n }, timeoutMs);\n });\n}\n"],"mappings":";AAAA,SAAgB,mBAAmB,MAAW;CAC5C,IAAI,OAAO,SAAS,UAClB,OAAO;CAET,IAAI;EACF,OAAO,KAAK,MAAM,IAAI;CACxB,QACM;EACJ;CACF;AACF;AAEA,SAAgB,oBAAoB,OAAe;CACjD,OAAO,UAAU,UAAU,UAAU,WAAW,UAAU;AAC5D;AAEA,SAAgB,sBACd,MACA,YAAY,KACZ,UAA0C,CAAC,GAC5B;CACf,OAAO,IAAI,SAAS,SAAS,WAAW;EACtC,IAAI;EAEJ,MAAM,gBAAgB;GACpB,KAAK,oBAAoB,WAAW,SAAS;GAC7C,KAAK,oBAAoB,SAAS,OAAO;GACzC,KAAK,oBAAoB,SAAS,OAAO;GACzC,IAAI,cAAc,KAAA,GAChB,OAAO,aAAa,SAAS;EAEjC;EACA,MAAM,cAAc,UAAiB;GACnC,QAAQ;GACR,OAAO,KAAK;EACd;EACA,MAAM,aAAa,UAAwB;GAEzC,IADa,mBAAmB,MAAM,IAClC,GAAM,SAAS,aACjB;GAEF,QAAQ;GACR,QAAQ;EACV;EACA,MAAM,WAAW,UAAsB;GACrC,MAAM,YAAsB,MAAc;GAC1C,IACE,QAAQ,qBACJ,MAAM,SAAS,OAAQ,qBAAqB,SAAS,OAAO,cAAc,WAE9E;GAKF,WAAW,IAAI,MAHA,OAAO,cAAc,YAAY,YAC5C,YACA,uDACuB,CAAC;EAC9B;EACA,MAAM,WAAW,UAAsB;GACrC,WAAW,IAAI,MAAM,MAAM,WAAW,6BAA6B,CAAC;EACtE;EAEA,KAAK,iBAAiB,WAAW,SAAS;EAC1C,KAAK,iBAAiB,SAAS,OAAO;EACtC,KAAK,iBAAiB,SAAS,OAAO;EACtC,YAAY,OAAO,iBAAiB;GAClC,2BAAW,IAAI,MAAM,0BAA0B,CAAC;EAClD,GAAG,SAAS;CACd,CAAC;AACH"}
@@ -0,0 +1 @@
1
+ export {};
@@ -1,28 +1,35 @@
1
1
  import { Context } from '@signe/di';
2
2
  import { RpgGui } from '../Gui/Gui';
3
3
  import { RpgClientEngine } from '../RpgClientEngine';
4
- import { AbstractWebsocket, SocketUpdateProperties } from './AbstractSocket';
4
+ import { AbstractWebsocket, SocketQuery, SocketUpdateProperties } from './AbstractSocket';
5
5
  import { UpdateMapService } from '@rpgjs/common';
6
- interface MmorpgOptions {
6
+ export interface MmorpgOptions {
7
7
  host?: string;
8
8
  connectionId?: string;
9
9
  connectionIdScope?: "local" | "session" | "ephemeral";
10
+ query?: SocketQuery | (() => SocketQuery | undefined);
11
+ socketOptions?: Record<string, any>;
10
12
  }
11
- declare class BridgeWebsocket extends AbstractWebsocket {
13
+ export declare class BridgeWebsocket extends AbstractWebsocket {
12
14
  protected context: Context;
13
15
  private options;
16
+ readonly mode: "mmorpg";
14
17
  private socket;
15
18
  private privateId;
16
19
  private pendingOn;
20
+ private acceptedOpenListeners;
17
21
  private targetRoom;
18
22
  constructor(context: Context, options?: MmorpgOptions);
19
23
  private resolveConnectionId;
24
+ private resolveQuery;
20
25
  connection(listeners?: (data: any) => void): Promise<void>;
21
26
  on(key: string, callback: (data: any) => void): void;
22
27
  off(event: string, callback: (data: any) => void): void;
23
28
  emit(event: string, data: any): void;
29
+ private attachEvent;
30
+ private emitAcceptedOpen;
24
31
  updateProperties({ room, host, query }: SocketUpdateProperties): void;
25
- private waitForNextOpen;
32
+ private isNativeSocketEvent;
26
33
  reconnect(_listeners?: (data: any) => void): Promise<void>;
27
34
  getCurrentRoom(): string;
28
35
  }
@@ -3,7 +3,8 @@ import { provideSaveClient } from "./save.js";
3
3
  import { RpgGui } from "../Gui/Gui.js";
4
4
  import { RpgClientEngine } from "../RpgClientEngine.js";
5
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";
6
+ import { connectionRoom } from "../node_modules/.pnpm/@signe_sync@3.1.0_react@19.2.7/node_modules/@signe/sync/dist/client/index.js";
7
+ import { isNativeSocketEvent, waitForRpgjsConnected } from "./mmorpg-connection.js";
7
8
  import { UpdateMapService, UpdateMapToken } from "@rpgjs/common";
8
9
  //#region src/services/mmorpg.ts
9
10
  var BridgeWebsocket = class extends AbstractWebsocket {
@@ -11,7 +12,9 @@ var BridgeWebsocket = class extends AbstractWebsocket {
11
12
  super(context);
12
13
  this.context = context;
13
14
  this.options = options;
15
+ this.mode = "mmorpg";
14
16
  this.pendingOn = [];
17
+ this.acceptedOpenListeners = /* @__PURE__ */ new Set();
15
18
  this.targetRoom = "lobby-1";
16
19
  this.privateId = this.resolveConnectionId();
17
20
  }
@@ -27,17 +30,31 @@ var BridgeWebsocket = class extends AbstractWebsocket {
27
30
  storage.setItem(key, id);
28
31
  return id;
29
32
  }
33
+ resolveQuery() {
34
+ return (typeof this.options.query === "function" ? this.options.query() : this.options.query) ?? {};
35
+ }
30
36
  async connection(listeners) {
31
37
  class Room {}
32
38
  const instance = new Room();
39
+ const host = this.options.host || window.location.host;
33
40
  this.socket = await connectionRoom({
34
- host: this.options.host || window.location.host,
41
+ maxRetries: 0,
42
+ ...this.options.socketOptions,
43
+ host,
35
44
  room: this.targetRoom,
36
- id: this.privateId
45
+ id: this.privateId,
46
+ query: {
47
+ ...this.resolveQuery(),
48
+ id: this.privateId
49
+ }
37
50
  }, instance);
38
- listeners?.(this.socket);
39
- this.pendingOn.forEach(({ event, callback }) => this.socket.on(event, callback));
51
+ const pendingOn = this.pendingOn;
40
52
  this.pendingOn = [];
53
+ pendingOn.filter(({ event }) => !this.isNativeSocketEvent(event)).forEach(({ event, callback }) => this.attachEvent(event, callback));
54
+ await waitForRpgjsConnected(this.socket.conn);
55
+ pendingOn.filter(({ event }) => this.isNativeSocketEvent(event)).forEach(({ event, callback }) => this.attachEvent(event, callback));
56
+ this.emitAcceptedOpen();
57
+ listeners?.(this.socket);
41
58
  }
42
59
  on(key, callback) {
43
60
  if (!this.socket) {
@@ -47,15 +64,38 @@ var BridgeWebsocket = class extends AbstractWebsocket {
47
64
  });
48
65
  return;
49
66
  }
50
- this.socket.on(key, callback);
67
+ this.attachEvent(key, callback);
51
68
  }
52
69
  off(event, callback) {
53
70
  if (!this.socket) return;
71
+ if (event === "open") {
72
+ this.acceptedOpenListeners.delete(callback);
73
+ return;
74
+ }
75
+ if (this.isNativeSocketEvent(event)) {
76
+ this.socket.conn.removeEventListener(event, callback);
77
+ return;
78
+ }
54
79
  this.socket.off(event, callback);
55
80
  }
56
81
  emit(event, data) {
57
82
  this.socket.emit(event, data);
58
83
  }
84
+ attachEvent(event, callback) {
85
+ if (event === "open") {
86
+ this.acceptedOpenListeners.add(callback);
87
+ return;
88
+ }
89
+ if (this.isNativeSocketEvent(event)) {
90
+ this.socket.conn.addEventListener(event, callback);
91
+ return;
92
+ }
93
+ this.socket.on(event, callback);
94
+ }
95
+ emitAcceptedOpen() {
96
+ const event = new Event("open");
97
+ this.acceptedOpenListeners.forEach((callback) => callback(event));
98
+ }
59
99
  updateProperties({ room, host, query }) {
60
100
  if (!this.socket?.conn) return;
61
101
  this.targetRoom = room;
@@ -63,39 +103,23 @@ var BridgeWebsocket = class extends AbstractWebsocket {
63
103
  room,
64
104
  id: this.privateId,
65
105
  host: host || this.options.host || window.location.host,
66
- query
106
+ query: {
107
+ ...this.resolveQuery(),
108
+ ...query,
109
+ id: this.privateId
110
+ }
67
111
  });
68
112
  }
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
- });
113
+ isNativeSocketEvent(event) {
114
+ return isNativeSocketEvent(event);
92
115
  }
93
116
  async reconnect(_listeners) {
94
117
  if (!this.socket?.conn) return;
95
118
  const conn = this.socket.conn;
96
- const opened = this.waitForNextOpen(conn);
119
+ const connected = waitForRpgjsConnected(conn, 1e4, { ignoreCleanClose: true });
97
120
  conn.reconnect();
98
- await opened;
121
+ await connected;
122
+ this.emitAcceptedOpen();
99
123
  }
100
124
  getCurrentRoom() {
101
125
  return this.targetRoom || this.socket?.conn?.room || "lobby-1";
@@ -126,6 +150,6 @@ function provideMmorpg(options) {
126
150
  ];
127
151
  }
128
152
  //#endregion
129
- export { provideMmorpg };
153
+ export { BridgeWebsocket, provideMmorpg };
130
154
 
131
155
  //# sourceMappingURL=mmorpg.js.map
@@ -1 +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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"}
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, SocketQuery, SocketUpdateProperties, WebSocketToken } from \"./AbstractSocket\";\nimport { UpdateMapService, UpdateMapToken } from \"@rpgjs/common\";\nimport { provideKeyboardControls } from \"./keyboardControls\";\nimport { provideSaveClient } from \"./save\";\nimport { isNativeSocketEvent, waitForRpgjsConnected } from \"./mmorpg-connection\";\n\nexport interface MmorpgOptions {\n host?: string;\n connectionId?: string;\n connectionIdScope?: \"local\" | \"session\" | \"ephemeral\";\n query?: SocketQuery | (() => SocketQuery | undefined);\n socketOptions?: Record<string, any>;\n}\n\nexport class BridgeWebsocket extends AbstractWebsocket {\n readonly mode = \"mmorpg\" as const;\n\n private socket: any;\n private privateId: string;\n private pendingOn: Array<{ event: string; callback: (data: any) => void }> = [];\n private acceptedOpenListeners = new Set<(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 private resolveQuery(): SocketQuery {\n const query = typeof this.options.query === \"function\"\n ? this.options.query()\n : this.options.query;\n\n return query ?? {};\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 maxRetries: 0,\n ...this.options.socketOptions,\n host,\n room: this.targetRoom,\n id: this.privateId,\n query: {\n ...this.resolveQuery(),\n id: this.privateId,\n },\n }, instance)\n\n const pendingOn = this.pendingOn;\n this.pendingOn = [];\n pendingOn\n .filter(({ event }) => !this.isNativeSocketEvent(event))\n .forEach(({ event, callback }) => this.attachEvent(event, callback));\n await waitForRpgjsConnected(this.socket.conn);\n pendingOn\n .filter(({ event }) => this.isNativeSocketEvent(event))\n .forEach(({ event, callback }) => this.attachEvent(event, callback));\n this.emitAcceptedOpen();\n listeners?.(this.socket)\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.attachEvent(key, callback);\n }\n\n off(event: string, callback: (data: any) => void) {\n if (!this.socket) return;\n if (event === \"open\") {\n this.acceptedOpenListeners.delete(callback);\n return;\n }\n if (this.isNativeSocketEvent(event)) {\n this.socket.conn.removeEventListener(event, callback);\n return;\n }\n this.socket.off(event, callback);\n }\n\n emit(event: string, data: any) {\n this.socket.emit(event, data);\n }\n\n private attachEvent(event: string, callback: (data: any) => void) {\n if (event === \"open\") {\n this.acceptedOpenListeners.add(callback);\n return;\n }\n if (this.isNativeSocketEvent(event)) {\n this.socket.conn.addEventListener(event, callback);\n return;\n }\n this.socket.on(event, callback);\n }\n\n private emitAcceptedOpen() {\n const event = new Event(\"open\");\n this.acceptedOpenListeners.forEach((callback) => callback(event));\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 ...this.resolveQuery(),\n ...query,\n id: this.privateId,\n },\n })\n }\n\n private isNativeSocketEvent(event: string) {\n return isNativeSocketEvent(event);\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 connected = waitForRpgjsConnected(conn, 10000, { ignoreCleanClose: true });\n conn.reconnect();\n await connected;\n this.emitAcceptedOpen();\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,11 @@
1
+ export interface ClientPointerPosition {
2
+ x: number;
3
+ y: number;
4
+ }
5
+ export interface ClientPointerContext {
6
+ screen(): ClientPointerPosition | null;
7
+ world(): ClientPointerPosition | null;
8
+ update(screen: ClientPointerPosition | null, world?: ClientPointerPosition | null): ClientPointerPosition | null;
9
+ updateFromEvent(event: any): ClientPointerPosition | null;
10
+ }
11
+ export declare function createClientPointerContext(): ClientPointerContext;
@@ -0,0 +1,48 @@
1
+ //#region src/services/pointerContext.ts
2
+ function toPosition(point) {
3
+ const x = Number(point?.x);
4
+ const y = Number(point?.y);
5
+ if (!Number.isFinite(x) || !Number.isFinite(y)) return null;
6
+ return {
7
+ x,
8
+ y
9
+ };
10
+ }
11
+ function extractGlobalPoint(event) {
12
+ return toPosition(event?.global) ?? toPosition(event?.data?.global) ?? toPosition(event);
13
+ }
14
+ function extractWorldPoint(event, global) {
15
+ const target = event?.currentTarget ?? event?.target;
16
+ if (target && global && typeof target.toLocal === "function") return toPosition(target.toLocal(global));
17
+ if (typeof event?.getLocalPosition === "function") return toPosition(event.getLocalPosition(target));
18
+ if (typeof event?.data?.getLocalPosition === "function") return toPosition(event.data.getLocalPosition(target));
19
+ return global;
20
+ }
21
+ function createClientPointerContext() {
22
+ let lastScreen = null;
23
+ let lastWorld = null;
24
+ const update = (screen, world) => {
25
+ const nextScreen = toPosition(screen);
26
+ const nextWorld = toPosition(world) ?? nextScreen;
27
+ if (nextScreen) lastScreen = nextScreen;
28
+ if (nextWorld) lastWorld = nextWorld;
29
+ return lastWorld ? { ...lastWorld } : null;
30
+ };
31
+ return {
32
+ screen() {
33
+ return lastScreen ? { ...lastScreen } : null;
34
+ },
35
+ world() {
36
+ return lastWorld ? { ...lastWorld } : null;
37
+ },
38
+ update,
39
+ updateFromEvent(event) {
40
+ const global = extractGlobalPoint(event);
41
+ return update(global, extractWorldPoint(event, global));
42
+ }
43
+ };
44
+ }
45
+ //#endregion
46
+ export { createClientPointerContext };
47
+
48
+ //# sourceMappingURL=pointerContext.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pointerContext.js","names":[],"sources":["../../src/services/pointerContext.ts"],"sourcesContent":["export interface ClientPointerPosition {\n x: number;\n y: number;\n}\n\nexport interface ClientPointerContext {\n screen(): ClientPointerPosition | null;\n world(): ClientPointerPosition | null;\n update(screen: ClientPointerPosition | null, world?: ClientPointerPosition | null): ClientPointerPosition | null;\n updateFromEvent(event: any): ClientPointerPosition | null;\n}\n\nfunction toPosition(point: any): ClientPointerPosition | null {\n const x = Number(point?.x);\n const y = Number(point?.y);\n\n if (!Number.isFinite(x) || !Number.isFinite(y)) {\n return null;\n }\n\n return { x, y };\n}\n\nfunction extractGlobalPoint(event: any): ClientPointerPosition | null {\n return toPosition(event?.global)\n ?? toPosition(event?.data?.global)\n ?? toPosition(event);\n}\n\nfunction extractWorldPoint(event: any, global: ClientPointerPosition | null): ClientPointerPosition | null {\n const target = event?.currentTarget ?? event?.target;\n\n if (target && global && typeof target.toLocal === \"function\") {\n return toPosition(target.toLocal(global));\n }\n\n if (typeof event?.getLocalPosition === \"function\") {\n return toPosition(event.getLocalPosition(target));\n }\n\n if (typeof event?.data?.getLocalPosition === \"function\") {\n return toPosition(event.data.getLocalPosition(target));\n }\n\n return global;\n}\n\nexport function createClientPointerContext(): ClientPointerContext {\n let lastScreen: ClientPointerPosition | null = null;\n let lastWorld: ClientPointerPosition | null = null;\n\n const update = (screen: ClientPointerPosition | null, world?: ClientPointerPosition | null) => {\n const nextScreen = toPosition(screen);\n const nextWorld = toPosition(world) ?? nextScreen;\n\n if (nextScreen) {\n lastScreen = nextScreen;\n }\n\n if (nextWorld) {\n lastWorld = nextWorld;\n }\n\n return lastWorld ? { ...lastWorld } : null;\n };\n\n return {\n screen() {\n return lastScreen ? { ...lastScreen } : null;\n },\n\n world() {\n return lastWorld ? { ...lastWorld } : null;\n },\n\n update,\n\n updateFromEvent(event: any) {\n const global = extractGlobalPoint(event);\n const world = extractWorldPoint(event, global);\n return update(global, world);\n },\n };\n}\n"],"mappings":";AAYA,SAAS,WAAW,OAA0C;CAC5D,MAAM,IAAI,OAAO,OAAO,CAAC;CACzB,MAAM,IAAI,OAAO,OAAO,CAAC;CAEzB,IAAI,CAAC,OAAO,SAAS,CAAC,KAAK,CAAC,OAAO,SAAS,CAAC,GAC3C,OAAO;CAGT,OAAO;EAAE;EAAG;CAAE;AAChB;AAEA,SAAS,mBAAmB,OAA0C;CACpE,OAAO,WAAW,OAAO,MAAM,KAC1B,WAAW,OAAO,MAAM,MAAM,KAC9B,WAAW,KAAK;AACvB;AAEA,SAAS,kBAAkB,OAAY,QAAoE;CACzG,MAAM,SAAS,OAAO,iBAAiB,OAAO;CAE9C,IAAI,UAAU,UAAU,OAAO,OAAO,YAAY,YAChD,OAAO,WAAW,OAAO,QAAQ,MAAM,CAAC;CAG1C,IAAI,OAAO,OAAO,qBAAqB,YACrC,OAAO,WAAW,MAAM,iBAAiB,MAAM,CAAC;CAGlD,IAAI,OAAO,OAAO,MAAM,qBAAqB,YAC3C,OAAO,WAAW,MAAM,KAAK,iBAAiB,MAAM,CAAC;CAGvD,OAAO;AACT;AAEA,SAAgB,6BAAmD;CACjE,IAAI,aAA2C;CAC/C,IAAI,YAA0C;CAE9C,MAAM,UAAU,QAAsC,UAAyC;EAC7F,MAAM,aAAa,WAAW,MAAM;EACpC,MAAM,YAAY,WAAW,KAAK,KAAK;EAEvC,IAAI,YACF,aAAa;EAGf,IAAI,WACF,YAAY;EAGd,OAAO,YAAY,EAAE,GAAG,UAAU,IAAI;CACxC;CAEA,OAAO;EACL,SAAS;GACP,OAAO,aAAa,EAAE,GAAG,WAAW,IAAI;EAC1C;EAEA,QAAQ;GACN,OAAO,YAAY,EAAE,GAAG,UAAU,IAAI;EACxC;EAEA;EAEA,gBAAgB,OAAY;GAC1B,MAAM,SAAS,mBAAmB,KAAK;GAEvC,OAAO,OAAO,QADA,kBAAkB,OAAO,MACjB,CAAK;EAC7B;CACF;AACF"}
@@ -0,0 +1 @@
1
+ export {};
@@ -1 +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
+ {"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,cAAc;iCACb,IAAI,IAAI;wBAC9B;;CAEzB,aAAa;EACX,MAAM,kBAAkB,SAAyB,KAAK,eAAe,KAAK,WAAW,IAAI;EACzF,MAAM,kBAAkB,SAAyB,KAAK,eAAe,KAAK,WAAW,IAAI;EACzF,MAAM,kBAAkB,SAAyB,KAAK,eAAe,KAAK,WAAW,IAAI;EACzF,MAAM,mBAAmB,SAA0B,KAAK,cAAc,KAAK,WAAW,KAAK,OAAO;EAClG,KAAK,UAAU,IAAI,oBAAoB,cAAc;EACrD,KAAK,UAAU,IAAI,oBAAoB,cAAc;EACrD,KAAK,UAAU,IAAI,oBAAoB,cAAc;EACrD,KAAK,UAAU,IAAI,cAAc,eAAe;EAChD,KAAK,UAAU,GAAG,oBAAoB,cAAc;EACpD,KAAK,UAAU,GAAG,oBAAoB,cAAc;EACpD,KAAK,UAAU,GAAG,oBAAoB,cAAc;EACpD,KAAK,UAAU,GAAG,cAAc,eAAe;CACjD;CAEA,YAAmC;EACjC,OAAO,KAAK,QAAwB,aAAa,CAAC,CAAC,EAAE,MAAM,WAAW,OAAO,KAAK;CACpF;CAEA,SAAS,OAAe,OAAqB,CAAC,GAA0B;EACtE,OAAO,KAAK,QAAwB,aAAa;GAAE;GAAO;EAAK,CAAC,EAAE,MAAM,WAAW,OAAO,KAAK;CACjG;CAEA,SAAS,OAAiC;EACxC,OAAO,KAAK,QAAwB,aAAa,EAAE,MAAM,CAAC,EAAE,MAAM,WAAW,OAAO,EAAE;CACxF;CAEA,QAAmB,OAAe,SAA0C;EAC1E,OAAO,IAAI,SAAS,SAAS,WAAW;GACtC,IAAI,CAAC,KAAK,WACR,KAAK,WAAW;GAElB,MAAM,YAAY,KAAK,cAAc;GACrC,KAAK,QAAQ,IAAI,WAAW;IAAE;IAAS;GAAO,CAAC;GAC/C,KAAK,WAAW,KAAK,OAAO;IAAE;IAAW,GAAG;GAAQ,CAAC;EACvD,CAAC;CACH;CAEA,eAAuB,WAAmB,QAAa;EACrD,MAAM,UAAU,KAAK,QAAQ,IAAI,SAAS;EAC1C,IAAI,CAAC,SAAS;EACd,KAAK,QAAQ,OAAO,SAAS;EAC7B,QAAQ,QAAQ,MAAM;CACxB;CAEA,cAAsB,WAAmB,SAAiB;EACxD,MAAM,UAAU,KAAK,QAAQ,IAAI,SAAS;EAC1C,IAAI,CAAC,SAAS;EACd,KAAK,QAAQ,OAAO,SAAS;EAC7B,QAAQ,OAAO,IAAI,MAAM,OAAO,CAAC;CACnC;CAEA,gBAAgC;EAC9B,KAAK,kBAAkB;EACvB,OAAO,GAAG,KAAK,IAAI,EAAE,GAAG,KAAK;CAC/B;AACF;AAEA,SAAgB,oBAAoB;CAClC,OAAO;EACL,SAAS;EACT,UAAU;CACZ;AACF"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export declare function normalizeStandaloneMessage(event: unknown): any;
@@ -0,0 +1,9 @@
1
+ //#region src/services/standalone-message.ts
2
+ function normalizeStandaloneMessage(event) {
3
+ const raw = event && typeof event === "object" && "data" in event ? event.data : event;
4
+ return typeof raw === "string" ? JSON.parse(raw) : raw;
5
+ }
6
+ //#endregion
7
+ export { normalizeStandaloneMessage };
8
+
9
+ //# sourceMappingURL=standalone-message.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"standalone-message.js","names":[],"sources":["../../src/services/standalone-message.ts"],"sourcesContent":["export function normalizeStandaloneMessage(event: unknown): any {\n const raw = event && typeof event === \"object\" && \"data\" in event\n ? (event as MessageEvent).data\n : event;\n\n return typeof raw === \"string\" ? JSON.parse(raw) : raw;\n}\n"],"mappings":";AAAA,SAAgB,2BAA2B,OAAqB;CAC9D,MAAM,MAAM,SAAS,OAAO,UAAU,YAAY,UAAU,QACvD,MAAuB,OACxB;CAEJ,OAAO,OAAO,QAAQ,WAAW,KAAK,MAAM,GAAG,IAAI;AACrD"}
@@ -9,9 +9,11 @@ interface StandaloneOptions {
9
9
  declare class BridgeWebsocket extends AbstractWebsocket {
10
10
  protected context: Context;
11
11
  private server;
12
+ readonly mode: "standalone";
12
13
  private room;
13
14
  private socket;
14
- private pendingOn;
15
+ private socketRoom?;
16
+ private listeners;
15
17
  private rooms;
16
18
  private serverInstance;
17
19
  constructor(context: Context, server: any, options?: StandaloneOptions);
@@ -55,6 +57,7 @@ declare class BridgeWebsocket extends AbstractWebsocket {
55
57
  * ```
56
58
  */
57
59
  reconnect(listeners?: (data: any) => void): Promise<void>;
60
+ private detachCurrentSocket;
58
61
  getServer(): any;
59
62
  getSocket(): any;
60
63
  }
@@ -2,8 +2,9 @@ import { AbstractWebsocket, WebSocketToken } from "./AbstractSocket.js";
2
2
  import { provideSaveClient } from "./save.js";
3
3
  import { RpgGui } from "../Gui/Gui.js";
4
4
  import { RpgClientEngine } from "../RpgClientEngine.js";
5
- import { ClientIo, ServerIo } from "../node_modules/.pnpm/@signe_room@2.9.0/node_modules/@signe/room/dist/index.js";
5
+ import { ClientIo, ServerIo } from "../node_modules/.pnpm/@signe_room@3.1.0_react@19.2.7/node_modules/@signe/room/dist/index.js";
6
6
  import { provideKeyboardControls } from "./keyboardControls.js";
7
+ import { normalizeStandaloneMessage } from "./standalone-message.js";
7
8
  import { UpdateMapService, UpdateMapToken } from "@rpgjs/common";
8
9
  //#region src/services/standalone.ts
9
10
  var BridgeWebsocket = class extends AbstractWebsocket {
@@ -11,7 +12,8 @@ var BridgeWebsocket = class extends AbstractWebsocket {
11
12
  super(context);
12
13
  this.context = context;
13
14
  this.server = server;
14
- this.pendingOn = [];
15
+ this.mode = "standalone";
16
+ this.listeners = [];
15
17
  this.rooms = {
16
18
  partyFn: async (roomId) => {
17
19
  this.room = new ServerIo(roomId, this.rooms);
@@ -34,6 +36,7 @@ var BridgeWebsocket = class extends AbstractWebsocket {
34
36
  return this._connection(listeners);
35
37
  }
36
38
  async _connection(listeners) {
39
+ this.detachCurrentSocket();
37
40
  this.serverInstance = this.context.get("server");
38
41
  this.socket = new ClientIo(this.serverInstance, "player-client-id");
39
42
  const url = new URL("http://localhost");
@@ -42,29 +45,37 @@ var BridgeWebsocket = class extends AbstractWebsocket {
42
45
  headers: { "Content-Type": "application/json" }
43
46
  });
44
47
  listeners?.(this.socket);
45
- await this.serverInstance.onConnect(this.socket.conn, { request });
46
48
  this.room.clients.set(this.socket.id, this.socket);
47
- this.pendingOn.forEach(({ event, callback }) => this.socket.addEventListener(event, callback));
48
- this.pendingOn = [];
49
+ this.socketRoom = this.room;
50
+ this.listeners.forEach(({ handler }) => {
51
+ this.socket.addEventListener("message", handler);
52
+ });
53
+ await this.serverInstance.onConnect(this.socket.conn, { request });
49
54
  return this.socket;
50
55
  }
51
56
  on(key, callback) {
57
+ if (this.listeners.some((listener) => listener.event === key && listener.callback === callback)) return;
52
58
  const handler = (event) => {
53
- const object = JSON.parse(event);
59
+ const object = normalizeStandaloneMessage(event);
54
60
  if (object.type === key) callback(object.value);
55
61
  };
56
- if (!this.socket) {
57
- this.pendingOn.push({
58
- event: "message",
59
- callback: handler
60
- });
61
- return;
62
- }
63
- this.socket.addEventListener("message", handler);
62
+ this.listeners.push({
63
+ event: key,
64
+ callback,
65
+ handler
66
+ });
67
+ this.socket?.addEventListener("message", handler);
64
68
  }
65
69
  off(event, callback) {
66
- if (!this.socket) return;
67
- this.socket.removeEventListener(event, callback);
70
+ const remaining = [];
71
+ for (const listener of this.listeners) {
72
+ if (listener.event === event && listener.callback === callback) {
73
+ this.socket?.removeEventListener("message", listener.handler);
74
+ continue;
75
+ }
76
+ remaining.push(listener);
77
+ }
78
+ this.listeners = remaining;
68
79
  }
69
80
  emit(event, data) {
70
81
  this.socket.send({
@@ -111,6 +122,15 @@ var BridgeWebsocket = class extends AbstractWebsocket {
111
122
  listeners?.(socket);
112
123
  });
113
124
  }
125
+ detachCurrentSocket() {
126
+ if (!this.socket) return;
127
+ this.listeners.forEach(({ handler }) => {
128
+ this.socket.removeEventListener("message", handler);
129
+ });
130
+ this.socketRoom?.clients?.delete?.(this.socket.id);
131
+ this.socket = void 0;
132
+ this.socketRoom = void 0;
133
+ }
114
134
  getServer() {
115
135
  return this.serverInstance;
116
136
  }
@@ -1 +1 @@
1
- {"version":3,"file":"standalone.js","names":[],"sources":["../../src/services/standalone.ts"],"sourcesContent":["import { AbstractWebsocket, SocketUpdateProperties, WebSocketToken } from \"./AbstractSocket\";\nimport { ClientIo, ServerIo } from \"@signe/room\";\nimport { Context } from \"@signe/di\";\nimport { RpgClientEngine } from \"../RpgClientEngine\";\nimport { UpdateMapService, UpdateMapToken } from \"@rpgjs/common\";\nimport { LoadMapToken } from \"./loadMap\";\nimport { RpgGui } from \"../Gui/Gui\";\nimport { provideKeyboardControls } from \"./keyboardControls\";\nimport { provideSaveClient } from \"./save\";\n\ntype ServerIo = any;\ntype ClientIo = any;\n\ninterface StandaloneOptions {\n env?: Record<string, any>;\n}\n\nclass BridgeWebsocket extends AbstractWebsocket {\n private room: ServerIo;\n private socket: ClientIo;\n private pendingOn: Array<{ event: string; callback: (data: any) => void }> = [];\n private rooms = {\n partyFn: async (roomId: string) => {\n this.room = new ServerIo(roomId, this.rooms);\n const server = new this.server(this.room)\n await server.onStart();\n await server.subRoom.onStart()\n this.context.set('server', server)\n return server\n },\n env: {}\n }\n private serverInstance: any;\n\n constructor(protected context: Context, private server: any, options: StandaloneOptions = {}) {\n super(context);\n // fake room\n this.rooms.env = options.env || {};\n this.room = new ServerIo(\"lobby-1\", this.rooms);\n }\n\n async connection(listeners?: (data: any) => void) {\n this.serverInstance = new this.server(this.room);\n await this.serverInstance.onStart();\n await this.serverInstance.subRoom.onStart()\n this.context.set('server', this.serverInstance)\n return this._connection(listeners)\n }\n\n private async _connection(listeners?: (data: any) => void) {\n this.serverInstance = this.context.get('server')\n this.socket = new ClientIo(this.serverInstance, 'player-client-id');\n const url = new URL('http://localhost')\n const request = new Request(url.toString(), {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/json'\n }\n })\n listeners?.(this.socket)\n await this.serverInstance.onConnect(this.socket.conn as any, { request } as any);\n this.room.clients.set(this.socket.id, this.socket);\n this.pendingOn.forEach(({ event, callback }) => this.socket.addEventListener(event, callback));\n this.pendingOn = [];\n return this.socket\n }\n\n on(key: string, callback: (data: any) => void) {\n const handler = (event) => {\n const object = JSON.parse(event);\n if (object.type === key) {\n callback(object.value);\n }\n };\n if (!this.socket) {\n this.pendingOn.push({ event: \"message\", callback: handler });\n return;\n }\n this.socket.addEventListener(\"message\", handler);\n }\n\n off(event: string, callback: (data: any) => void) {\n if (!this.socket) return;\n this.socket.removeEventListener(event, callback);\n }\n\n emit(event: string, data: any) {\n this.socket.send({\n action: event,\n value: data,\n });\n }\n\n /**\n * Update underlying connection properties before a reconnect\n *\n * Design\n * - Dynamically register a factory for the requested room to ensure a fresh server instance\n * - Swap the internal ServerIo to target the new room\n *\n * @param params - Properties to update\n * @param params.room - The target room id (e.g. `map-simplemap2`)\n *\n * @example\n * ```ts\n * websocket.updateProperties({ room: 'map-simplemap2' })\n * await websocket.reconnect()\n * ```\n */\n updateProperties(_params: SocketUpdateProperties) {\n // empty\n }\n\n /**\n * Reconnect the client to the current Party room\n *\n * Design\n * - Must be called after `updateProperties()` when switching rooms\n * - Rebuilds the client <-> server bridge and re-triggers connection listeners\n *\n * @param listeners - Optional callback to re-bind event handlers on the new socket\n *\n * @example\n * ```ts\n * websocket.updateProperties({ room: 'map-dungeon' })\n * await websocket.reconnect((socket) => {\n * // re-bind events here\n * })\n * ```\n */\n async reconnect(listeners?: (data: any) => void): Promise<void> {\n await this._connection((socket) => {\n listeners?.(socket)\n })\n }\n\n getServer() {\n return this.serverInstance\n }\n\n getSocket() {\n return this.socket\n }\n}\n\nclass UpdateMapStandaloneService extends UpdateMapService {\n private server: any;\n\n /**\n * Update the current room map data on the server side\n *\n * Design\n * - Uses the in-memory server instance stored in context (standalone mode)\n * - Builds a local HTTP-like request to the current Party room endpoint\n *\n * @param map - The map payload to apply on the server\n *\n * @example\n * ```ts\n * await updateMapService.update({ width: 1024, height: 768, events: [] })\n * ```\n */\n async update(map: any) {\n this.server = this.context.get('server')\n const roomId = this.server?.room?.id ?? 'lobby-1'\n const req = {\n url: `http://localhost/parties/main/${roomId}/map/update`,\n method: 'POST',\n headers: new Headers({}),\n json: async () => {\n return map;\n }\n };\n await this.server.onRequest(req)\n }\n}\n\nexport function provideRpg(server: any, options: StandaloneOptions = {}) {\n return [\n {\n provide: WebSocketToken,\n useFactory: (context: Context) => new BridgeWebsocket(context, server, options),\n },\n {\n provide: UpdateMapToken,\n useClass: UpdateMapStandaloneService,\n },\n provideKeyboardControls(),\n provideSaveClient(),\n RpgGui,\n RpgClientEngine,\n ];\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"standalone.js","names":[],"sources":["../../src/services/standalone.ts"],"sourcesContent":["import { AbstractWebsocket, SocketUpdateProperties, WebSocketToken } from \"./AbstractSocket\";\nimport { ClientIo, ServerIo } from \"@signe/room\";\nimport { Context } from \"@signe/di\";\nimport { RpgClientEngine } from \"../RpgClientEngine\";\nimport { UpdateMapService, UpdateMapToken } from \"@rpgjs/common\";\nimport { LoadMapToken } from \"./loadMap\";\nimport { RpgGui } from \"../Gui/Gui\";\nimport { provideKeyboardControls } from \"./keyboardControls\";\nimport { provideSaveClient } from \"./save\";\nimport { normalizeStandaloneMessage } from \"./standalone-message\";\n\ntype ServerIo = any;\ntype ClientIo = any;\n\ninterface StandaloneOptions {\n env?: Record<string, any>;\n}\n\nclass BridgeWebsocket extends AbstractWebsocket {\n readonly mode = \"standalone\" as const;\n\n private room: ServerIo;\n private socket: ClientIo;\n private socketRoom?: ServerIo;\n private listeners: Array<{\n event: string;\n callback: (data: any) => void;\n handler: (event: any) => void;\n }> = [];\n private rooms = {\n partyFn: async (roomId: string) => {\n this.room = new ServerIo(roomId, this.rooms);\n const server = new this.server(this.room)\n await server.onStart();\n await server.subRoom.onStart()\n this.context.set('server', server)\n return server\n },\n env: {}\n }\n private serverInstance: any;\n\n constructor(protected context: Context, private server: any, options: StandaloneOptions = {}) {\n super(context);\n // fake room\n this.rooms.env = options.env || {};\n this.room = new ServerIo(\"lobby-1\", this.rooms);\n }\n\n async connection(listeners?: (data: any) => void) {\n this.serverInstance = new this.server(this.room);\n await this.serverInstance.onStart();\n await this.serverInstance.subRoom.onStart()\n this.context.set('server', this.serverInstance)\n return this._connection(listeners)\n }\n\n private async _connection(listeners?: (data: any) => void) {\n this.detachCurrentSocket();\n this.serverInstance = this.context.get('server')\n this.socket = new ClientIo(this.serverInstance, 'player-client-id');\n const url = new URL('http://localhost')\n const request = new Request(url.toString(), {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/json'\n }\n })\n listeners?.(this.socket)\n this.room.clients.set(this.socket.id, this.socket);\n this.socketRoom = this.room;\n this.listeners.forEach(({ handler }) => {\n this.socket.addEventListener(\"message\", handler);\n });\n await this.serverInstance.onConnect(this.socket.conn as any, { request } as any);\n return this.socket\n }\n\n on(key: string, callback: (data: any) => void) {\n if (\n this.listeners.some(\n (listener) => listener.event === key && listener.callback === callback\n )\n ) {\n return;\n }\n const handler = (event) => {\n const object = normalizeStandaloneMessage(event);\n if (object.type === key) {\n callback(object.value);\n }\n };\n this.listeners.push({ event: key, callback, handler });\n this.socket?.addEventListener(\"message\", handler);\n }\n\n off(event: string, callback: (data: any) => void) {\n const remaining: typeof this.listeners = [];\n for (const listener of this.listeners) {\n if (listener.event === event && listener.callback === callback) {\n this.socket?.removeEventListener(\"message\", listener.handler);\n continue;\n }\n remaining.push(listener);\n }\n this.listeners = remaining;\n }\n\n emit(event: string, data: any) {\n this.socket.send({\n action: event,\n value: data,\n });\n }\n\n /**\n * Update underlying connection properties before a reconnect\n *\n * Design\n * - Dynamically register a factory for the requested room to ensure a fresh server instance\n * - Swap the internal ServerIo to target the new room\n *\n * @param params - Properties to update\n * @param params.room - The target room id (e.g. `map-simplemap2`)\n *\n * @example\n * ```ts\n * websocket.updateProperties({ room: 'map-simplemap2' })\n * await websocket.reconnect()\n * ```\n */\n updateProperties(_params: SocketUpdateProperties) {\n // empty\n }\n\n /**\n * Reconnect the client to the current Party room\n *\n * Design\n * - Must be called after `updateProperties()` when switching rooms\n * - Rebuilds the client <-> server bridge and re-triggers connection listeners\n *\n * @param listeners - Optional callback to re-bind event handlers on the new socket\n *\n * @example\n * ```ts\n * websocket.updateProperties({ room: 'map-dungeon' })\n * await websocket.reconnect((socket) => {\n * // re-bind events here\n * })\n * ```\n */\n async reconnect(listeners?: (data: any) => void): Promise<void> {\n await this._connection((socket) => {\n listeners?.(socket)\n })\n }\n\n private detachCurrentSocket() {\n if (!this.socket) return;\n this.listeners.forEach(({ handler }) => {\n this.socket.removeEventListener(\"message\", handler);\n });\n this.socketRoom?.clients?.delete?.(this.socket.id);\n this.socket = undefined as any;\n this.socketRoom = undefined;\n }\n\n getServer() {\n return this.serverInstance\n }\n\n getSocket() {\n return this.socket\n }\n}\n\nclass UpdateMapStandaloneService extends UpdateMapService {\n private server: any;\n\n /**\n * Update the current room map data on the server side\n *\n * Design\n * - Uses the in-memory server instance stored in context (standalone mode)\n * - Builds a local HTTP-like request to the current Party room endpoint\n *\n * @param map - The map payload to apply on the server\n *\n * @example\n * ```ts\n * await updateMapService.update({ width: 1024, height: 768, events: [] })\n * ```\n */\n async update(map: any) {\n this.server = this.context.get('server')\n const roomId = this.server?.room?.id ?? 'lobby-1'\n const req = {\n url: `http://localhost/parties/main/${roomId}/map/update`,\n method: 'POST',\n headers: new Headers({}),\n json: async () => {\n return map;\n }\n };\n await this.server.onRequest(req)\n }\n}\n\nexport function provideRpg(server: any, options: StandaloneOptions = {}) {\n return [\n {\n provide: WebSocketToken,\n useFactory: (context: Context) => new BridgeWebsocket(context, server, options),\n },\n {\n provide: UpdateMapToken,\n useClass: UpdateMapStandaloneService,\n },\n provideKeyboardControls(),\n provideSaveClient(),\n RpgGui,\n RpgClientEngine,\n ];\n}\n"],"mappings":";;;;;;;;;AAkBA,IAAM,kBAAN,cAA8B,kBAAkB;CAwB9C,YAAY,SAA4B,QAAqB,UAA6B,CAAC,GAAG;EAC5F,MAAM,OAAO;EADO,KAAA,UAAA;EAA0B,KAAA,SAAA;cAvBhC;mBASX,CAAC;eACU;GACd,SAAS,OAAO,WAAmB;IACjC,KAAK,OAAO,IAAI,SAAS,QAAQ,KAAK,KAAK;IAC3C,MAAM,SAAS,IAAI,KAAK,OAAO,KAAK,IAAI;IACxC,MAAM,OAAO,QAAQ;IACrB,MAAM,OAAO,QAAQ,QAAQ;IAC7B,KAAK,QAAQ,IAAI,UAAU,MAAM;IACjC,OAAO;GACT;GACA,KAAK,CAAC;EACR;EAME,KAAK,MAAM,MAAM,QAAQ,OAAO,CAAC;EACjC,KAAK,OAAO,IAAI,SAAS,WAAW,KAAK,KAAK;CAChD;CAEA,MAAM,WAAW,WAAiC;EAChD,KAAK,iBAAiB,IAAI,KAAK,OAAO,KAAK,IAAI;EAC/C,MAAM,KAAK,eAAe,QAAQ;EAClC,MAAM,KAAK,eAAe,QAAQ,QAAQ;EAC1C,KAAK,QAAQ,IAAI,UAAU,KAAK,cAAc;EAC9C,OAAO,KAAK,YAAY,SAAS;CACnC;CAEA,MAAc,YAAY,WAAiC;EACzD,KAAK,oBAAoB;EACzB,KAAK,iBAAiB,KAAK,QAAQ,IAAI,QAAQ;EAC/C,KAAK,SAAS,IAAI,SAAS,KAAK,gBAAgB,kBAAkB;EAClE,MAAM,MAAM,IAAI,IAAI,kBAAkB;EACtC,MAAM,UAAU,IAAI,QAAQ,IAAI,SAAS,GAAG;GAC1C,QAAQ;GACR,SAAS,EACP,gBAAgB,mBAClB;EACF,CAAC;EACD,YAAY,KAAK,MAAM;EACvB,KAAK,KAAK,QAAQ,IAAI,KAAK,OAAO,IAAI,KAAK,MAAM;EACjD,KAAK,aAAa,KAAK;EACvB,KAAK,UAAU,SAAS,EAAE,cAAc;GACtC,KAAK,OAAO,iBAAiB,WAAW,OAAO;EACjD,CAAC;EACD,MAAM,KAAK,eAAe,UAAU,KAAK,OAAO,MAAa,EAAE,QAAQ,CAAQ;EAC/E,OAAO,KAAK;CACd;CAEA,GAAG,KAAa,UAA+B;EAC7C,IACE,KAAK,UAAU,MACZ,aAAa,SAAS,UAAU,OAAO,SAAS,aAAa,QAChE,GAEA;EAEF,MAAM,WAAW,UAAU;GACzB,MAAM,SAAS,2BAA2B,KAAK;GAC/C,IAAI,OAAO,SAAS,KAClB,SAAS,OAAO,KAAK;EAEzB;EACA,KAAK,UAAU,KAAK;GAAE,OAAO;GAAK;GAAU;EAAQ,CAAC;EACrD,KAAK,QAAQ,iBAAiB,WAAW,OAAO;CAClD;CAEA,IAAI,OAAe,UAA+B;EAChD,MAAM,YAAmC,CAAC;EAC1C,KAAK,MAAM,YAAY,KAAK,WAAW;GACrC,IAAI,SAAS,UAAU,SAAS,SAAS,aAAa,UAAU;IAC9D,KAAK,QAAQ,oBAAoB,WAAW,SAAS,OAAO;IAC5D;GACF;GACA,UAAU,KAAK,QAAQ;EACzB;EACA,KAAK,YAAY;CACnB;CAEA,KAAK,OAAe,MAAW;EAC7B,KAAK,OAAO,KAAK;GACf,QAAQ;GACR,OAAO;EACT,CAAC;CACH;;;;;;;;;;;;;;;;;CAkBA,iBAAiB,SAAiC,CAElD;;;;;;;;;;;;;;;;;;CAmBA,MAAM,UAAU,WAAgD;EAC9D,MAAM,KAAK,aAAa,WAAW;GACjC,YAAY,MAAM;EACpB,CAAC;CACH;CAEA,sBAA8B;EAC5B,IAAI,CAAC,KAAK,QAAQ;EAClB,KAAK,UAAU,SAAS,EAAE,cAAc;GACtC,KAAK,OAAO,oBAAoB,WAAW,OAAO;EACpD,CAAC;EACD,KAAK,YAAY,SAAS,SAAS,KAAK,OAAO,EAAE;EACjD,KAAK,SAAS,KAAA;EACd,KAAK,aAAa,KAAA;CACpB;CAEA,YAAY;EACV,OAAO,KAAK;CACd;CAEA,YAAY;EACV,OAAO,KAAK;CACd;AACF;AAEA,IAAM,6BAAN,cAAyC,iBAAiB;;;;;;;;;;;;;;;CAiBxD,MAAM,OAAO,KAAU;EACrB,KAAK,SAAS,KAAK,QAAQ,IAAI,QAAQ;EAEvC,MAAM,MAAM;GACV,KAAK,iCAFQ,KAAK,QAAQ,MAAM,MAAM,UAEO;GAC7C,QAAQ;GACR,SAAS,IAAI,QAAQ,CAAC,CAAC;GACvB,MAAM,YAAY;IAChB,OAAO;GACT;EACF;EACA,MAAM,KAAK,OAAO,UAAU,GAAG;CACjC;AACF;AAEA,SAAgB,WAAW,QAAa,UAA6B,CAAC,GAAG;CACvE,OAAO;EACL;GACE,SAAS;GACT,aAAa,YAAqB,IAAI,gBAAgB,SAAS,QAAQ,OAAO;EAChF;EACA;GACE,SAAS;GACT,UAAU;EACZ;EACA,wBAAwB;EACxB,kBAAkB;EAClB;EACA;CACF;AACF"}
@@ -0,0 +1 @@
1
+ export {};
@@ -1,3 +1,4 @@
1
+ import { readPropValue } from "./readPropValue.js";
1
2
  import { computed } from "canvasengine";
2
3
  //#region src/utils/getEntityProp.ts
3
4
  var entityPropMap = {
@@ -6,17 +7,17 @@ var entityPropMap = {
6
7
  gold: (entity) => entity._gold(),
7
8
  hp: (entity) => entity.hpSignal(),
8
9
  sp: (entity) => entity.spSignal(),
9
- name: (entity) => entity.name(),
10
+ name: (entity) => entity.name,
10
11
  type: (entity) => entity.type(),
11
12
  x: (entity) => entity.x(),
12
13
  y: (entity) => entity.y(),
13
14
  z: (entity) => entity.z(),
14
15
  tint: (entity) => entity.tint(),
15
16
  direction: (entity) => entity.direction(),
16
- speed: (entity) => entity.speed(),
17
+ speed: (entity) => entity.speed,
17
18
  hitbox: (entity) => entity.hitbox(),
18
19
  animation: (entity) => entity.animationName(),
19
- canMove: (entity) => entity.canMove(),
20
+ canMove: (entity) => readPropValue(entity._canMove ?? entity.canMove),
20
21
  graphics: (entity) => entity.graphics(),
21
22
  items: (entity) => entity.items(),
22
23
  equipments: (entity) => entity.equipments(),