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

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 (314) hide show
  1. package/CHANGELOG.md +123 -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 +96 -54
  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 +176 -11
  36. package/dist/RpgClientEngine.js +669 -68
  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 +606 -248
  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.js +2 -2
  90. package/dist/components/gui/mobile/index.js.map +1 -1
  91. package/dist/components/gui/mobile/mobile.ce.js +7 -5
  92. package/dist/components/gui/mobile/mobile.ce.js.map +1 -1
  93. package/dist/components/gui/notification/notification.ce.js +28 -26
  94. package/dist/components/gui/notification/notification.ce.js.map +1 -1
  95. package/dist/components/gui/save-load.ce.js +81 -256
  96. package/dist/components/gui/save-load.ce.js.map +1 -1
  97. package/dist/components/gui/shop/shop.ce.js +107 -142
  98. package/dist/components/gui/shop/shop.ce.js.map +1 -1
  99. package/dist/components/gui/title-screen.ce.js +50 -73
  100. package/dist/components/gui/title-screen.ce.js.map +1 -1
  101. package/dist/components/index.d.ts +2 -1
  102. package/dist/components/index.js +1 -0
  103. package/dist/components/interaction-components.ce.js +22 -0
  104. package/dist/components/interaction-components.ce.js.map +1 -0
  105. package/dist/components/player-components-utils.d.ts +67 -0
  106. package/dist/components/player-components-utils.js +162 -0
  107. package/dist/components/player-components-utils.js.map +1 -0
  108. package/dist/components/player-components-utils.spec.d.ts +1 -0
  109. package/dist/components/player-components.ce.js +191 -0
  110. package/dist/components/player-components.ce.js.map +1 -0
  111. package/dist/components/prebuilt/hp-bar.ce.js +45 -45
  112. package/dist/components/prebuilt/hp-bar.ce.js.map +1 -1
  113. package/dist/components/prebuilt/light-halo.ce.js +39 -60
  114. package/dist/components/prebuilt/light-halo.ce.js.map +1 -1
  115. package/dist/components/scenes/canvas.ce.js +205 -27
  116. package/dist/components/scenes/canvas.ce.js.map +1 -1
  117. package/dist/components/scenes/draw-map.ce.js +39 -39
  118. package/dist/components/scenes/draw-map.ce.js.map +1 -1
  119. package/dist/components/scenes/event-layer.ce.js +51 -10
  120. package/dist/components/scenes/event-layer.ce.js.map +1 -1
  121. package/dist/core/inject.js +1 -1
  122. package/dist/core/inject.js.map +1 -1
  123. package/dist/core/setup.js +1 -1
  124. package/dist/core/setup.js.map +1 -1
  125. package/dist/decorators/spritesheet.d.ts +1 -0
  126. package/dist/decorators/spritesheet.js +11 -0
  127. package/dist/decorators/spritesheet.js.map +1 -0
  128. package/dist/i18n.d.ts +55 -0
  129. package/dist/i18n.js +60 -0
  130. package/dist/i18n.js.map +1 -0
  131. package/dist/i18n.spec.d.ts +1 -0
  132. package/dist/index.d.ts +7 -0
  133. package/dist/index.js +29 -21
  134. package/dist/module.js +45 -4
  135. package/dist/module.js.map +1 -1
  136. package/dist/node_modules/.pnpm/{@signe_di@2.9.0 → @signe_di@3.1.0}/node_modules/@signe/di/dist/index.js +7 -117
  137. package/dist/node_modules/.pnpm/@signe_di@3.1.0/node_modules/@signe/di/dist/index.js.map +1 -0
  138. package/dist/node_modules/.pnpm/@signe_reactive@3.1.0/node_modules/@signe/reactive/dist/index.js +239 -0
  139. package/dist/node_modules/.pnpm/@signe_reactive@3.1.0/node_modules/@signe/reactive/dist/index.js.map +1 -0
  140. package/dist/node_modules/.pnpm/@signe_room@3.1.0_react@19.2.7/node_modules/@signe/room/dist/chunk-EUXUH3YW.js +13 -0
  141. 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
  142. package/dist/node_modules/.pnpm/@signe_room@3.1.0_react@19.2.7/node_modules/@signe/room/dist/index.js +698 -0
  143. package/dist/node_modules/.pnpm/@signe_room@3.1.0_react@19.2.7/node_modules/@signe/room/dist/index.js.map +1 -0
  144. package/dist/node_modules/.pnpm/@signe_sync@3.1.0_react@19.2.7/node_modules/@signe/sync/dist/client/index.js +43 -0
  145. 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
  146. 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
  147. package/dist/node_modules/.pnpm/@signe_sync@3.1.0_react@19.2.7/node_modules/@signe/sync/dist/index.js.map +1 -0
  148. 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
  149. package/dist/node_modules/.pnpm/partysocket@1.2.0_react@19.2.7/node_modules/partysocket/dist/index.js.map +1 -0
  150. 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
  151. package/dist/node_modules/.pnpm/partysocket@1.2.0_react@19.2.7/node_modules/partysocket/dist/ws.js.map +1 -0
  152. package/dist/node_modules/.pnpm/zod@3.25.76/node_modules/zod/index.js +13 -0
  153. package/dist/node_modules/.pnpm/zod@3.25.76/node_modules/zod/index.js.map +1 -0
  154. package/dist/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/ZodError.js +106 -0
  155. package/dist/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/ZodError.js.map +1 -0
  156. package/dist/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/errors.js +13 -0
  157. package/dist/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/errors.js.map +1 -0
  158. package/dist/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/external.js +121 -0
  159. package/dist/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/external.js.map +1 -0
  160. package/dist/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/errorUtil.js +10 -0
  161. package/dist/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/errorUtil.js.map +1 -0
  162. package/dist/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/parseUtil.js +110 -0
  163. package/dist/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/parseUtil.js.map +1 -0
  164. package/dist/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/util.js +99 -0
  165. package/dist/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/util.js.map +1 -0
  166. package/dist/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/locales/en.js +82 -0
  167. package/dist/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/locales/en.js.map +1 -0
  168. 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
  169. package/dist/node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/types.js.map +1 -0
  170. package/dist/presets/animation.js.map +1 -1
  171. package/dist/presets/faceset.js.map +1 -1
  172. package/dist/presets/icon.js.map +1 -1
  173. package/dist/presets/index.js.map +1 -1
  174. package/dist/presets/lpc.js.map +1 -1
  175. package/dist/presets/rmspritesheet.js.map +1 -1
  176. package/dist/services/AbstractSocket.d.ts +2 -0
  177. package/dist/services/AbstractSocket.js.map +1 -1
  178. package/dist/services/actionInput.d.ts +14 -0
  179. package/dist/services/actionInput.js +59 -0
  180. package/dist/services/actionInput.js.map +1 -0
  181. package/dist/services/actionInput.spec.d.ts +1 -0
  182. package/dist/services/interactions.d.ts +159 -0
  183. package/dist/services/interactions.js +460 -0
  184. package/dist/services/interactions.js.map +1 -0
  185. package/dist/services/interactions.spec.d.ts +1 -0
  186. package/dist/services/keyboardControls.d.ts +1 -0
  187. package/dist/services/keyboardControls.js +1 -0
  188. package/dist/services/keyboardControls.js.map +1 -1
  189. package/dist/services/loadMap.d.ts +9 -0
  190. package/dist/services/loadMap.js +1 -1
  191. package/dist/services/loadMap.js.map +1 -1
  192. package/dist/services/mmorpg-connection.d.ts +5 -0
  193. package/dist/services/mmorpg-connection.js +50 -0
  194. package/dist/services/mmorpg-connection.js.map +1 -0
  195. package/dist/services/mmorpg-connection.spec.d.ts +1 -0
  196. package/dist/services/mmorpg.d.ts +11 -4
  197. package/dist/services/mmorpg.js +57 -33
  198. package/dist/services/mmorpg.js.map +1 -1
  199. package/dist/services/pointerContext.d.ts +11 -0
  200. package/dist/services/pointerContext.js +48 -0
  201. package/dist/services/pointerContext.js.map +1 -0
  202. package/dist/services/pointerContext.spec.d.ts +1 -0
  203. package/dist/services/save.js.map +1 -1
  204. package/dist/services/save.spec.d.ts +1 -0
  205. package/dist/services/standalone-message.d.ts +1 -0
  206. package/dist/services/standalone-message.js +9 -0
  207. package/dist/services/standalone-message.js.map +1 -0
  208. package/dist/services/standalone.d.ts +4 -1
  209. package/dist/services/standalone.js +36 -16
  210. package/dist/services/standalone.js.map +1 -1
  211. package/dist/services/standalone.spec.d.ts +1 -0
  212. package/dist/utils/getEntityProp.js +4 -3
  213. package/dist/utils/getEntityProp.js.map +1 -1
  214. package/dist/utils/getEntityProp.spec.d.ts +1 -0
  215. package/dist/utils/mapId.d.ts +1 -0
  216. package/dist/utils/mapId.js +6 -0
  217. package/dist/utils/mapId.js.map +1 -0
  218. package/dist/utils/readPropValue.d.ts +2 -0
  219. package/dist/utils/readPropValue.js +13 -0
  220. package/dist/utils/readPropValue.js.map +1 -0
  221. package/package.json +13 -13
  222. package/src/Game/AnimationManager.spec.ts +30 -0
  223. package/src/Game/AnimationManager.ts +26 -10
  224. package/src/Game/ClientVisuals.spec.ts +56 -0
  225. package/src/Game/ClientVisuals.ts +184 -0
  226. package/src/Game/EventComponentResolver.spec.ts +84 -0
  227. package/src/Game/EventComponentResolver.ts +74 -0
  228. package/src/Game/Map.ts +134 -2
  229. package/src/Game/Object.spec.ts +59 -0
  230. package/src/Game/Object.ts +181 -77
  231. package/src/Game/ProjectileManager.spec.ts +449 -0
  232. package/src/Game/ProjectileManager.ts +346 -0
  233. package/src/Gui/Gui.spec.ts +340 -0
  234. package/src/Gui/Gui.ts +129 -57
  235. package/src/Resource.ts +1 -2
  236. package/src/RpgClient.ts +220 -17
  237. package/src/RpgClientEngine.ts +959 -116
  238. package/src/components/animations/fx.ce +101 -0
  239. package/src/components/animations/index.ts +4 -2
  240. package/src/components/character.ce +681 -45
  241. package/src/components/dynamics/bar.ce +88 -0
  242. package/src/components/dynamics/image.ce +21 -0
  243. package/src/components/dynamics/parse-value.spec.ts +83 -0
  244. package/src/components/dynamics/parse-value.ts +111 -37
  245. package/src/components/dynamics/shape-utils.spec.ts +46 -0
  246. package/src/components/dynamics/shape-utils.ts +61 -0
  247. package/src/components/dynamics/shape.ce +90 -0
  248. package/src/components/dynamics/text.ce +35 -149
  249. package/src/components/gui/dialogbox/index.ce +52 -21
  250. package/src/components/gui/gameover.ce +6 -4
  251. package/src/components/gui/menu/equip-menu.ce +11 -9
  252. package/src/components/gui/menu/exit-menu.ce +6 -4
  253. package/src/components/gui/menu/items-menu.ce +11 -9
  254. package/src/components/gui/menu/main-menu.ce +14 -12
  255. package/src/components/gui/menu/options-menu.ce +4 -3
  256. package/src/components/gui/menu/skills-menu.ce +2 -1
  257. package/src/components/gui/notification/notification.ce +7 -1
  258. package/src/components/gui/save-load.ce +13 -11
  259. package/src/components/gui/shop/shop.ce +20 -18
  260. package/src/components/gui/title-screen.ce +6 -4
  261. package/src/components/index.ts +2 -1
  262. package/src/components/interaction-components.ce +23 -0
  263. package/src/components/player-components-utils.spec.ts +109 -0
  264. package/src/components/player-components-utils.ts +205 -0
  265. package/src/components/player-components.ce +222 -0
  266. package/src/components/prebuilt/hp-bar.ce +4 -3
  267. package/src/components/prebuilt/light-halo.ce +2 -2
  268. package/src/components/scenes/canvas.ce +219 -15
  269. package/src/components/scenes/draw-map.ce +34 -22
  270. package/src/components/scenes/event-layer.ce +55 -4
  271. package/src/core/setup.ts +2 -2
  272. package/src/decorators/spritesheet.ts +8 -0
  273. package/src/i18n.spec.ts +39 -0
  274. package/src/i18n.ts +59 -0
  275. package/src/index.ts +7 -0
  276. package/src/module.ts +61 -11
  277. package/src/services/AbstractSocket.ts +3 -0
  278. package/src/services/actionInput.spec.ts +155 -0
  279. package/src/services/actionInput.ts +120 -0
  280. package/src/services/interactions.spec.ts +175 -0
  281. package/src/services/interactions.ts +722 -0
  282. package/src/services/keyboardControls.ts +2 -1
  283. package/src/services/loadMap.ts +5 -1
  284. package/src/services/mmorpg-connection.spec.ts +99 -0
  285. package/src/services/mmorpg-connection.ts +69 -0
  286. package/src/services/mmorpg.ts +70 -36
  287. package/src/services/pointerContext.spec.ts +36 -0
  288. package/src/services/pointerContext.ts +84 -0
  289. package/src/services/save.spec.ts +127 -0
  290. package/src/services/standalone-message.ts +7 -0
  291. package/src/services/standalone.spec.ts +54 -0
  292. package/src/services/standalone.ts +44 -12
  293. package/src/utils/getEntityProp.spec.ts +96 -0
  294. package/src/utils/getEntityProp.ts +4 -3
  295. package/src/utils/mapId.ts +2 -0
  296. package/src/utils/readPropValue.ts +16 -0
  297. package/dist/node_modules/.pnpm/@signe_di@2.9.0/node_modules/@signe/di/dist/index.js.map +0 -1
  298. package/dist/node_modules/.pnpm/@signe_reactive@2.8.3/node_modules/@signe/reactive/dist/index.js +0 -457
  299. package/dist/node_modules/.pnpm/@signe_reactive@2.8.3/node_modules/@signe/reactive/dist/index.js.map +0 -1
  300. package/dist/node_modules/.pnpm/@signe_reactive@2.9.0/node_modules/@signe/reactive/dist/index.js +0 -463
  301. package/dist/node_modules/.pnpm/@signe_reactive@2.9.0/node_modules/@signe/reactive/dist/index.js.map +0 -1
  302. package/dist/node_modules/.pnpm/@signe_room@2.9.0/node_modules/@signe/room/dist/index.js +0 -2191
  303. package/dist/node_modules/.pnpm/@signe_room@2.9.0/node_modules/@signe/room/dist/index.js.map +0 -1
  304. package/dist/node_modules/.pnpm/@signe_sync@2.9.0/node_modules/@signe/sync/dist/chunk-7QVYU63E.js +0 -10
  305. package/dist/node_modules/.pnpm/@signe_sync@2.9.0/node_modules/@signe/sync/dist/chunk-7QVYU63E.js.map +0 -1
  306. package/dist/node_modules/.pnpm/@signe_sync@2.9.0/node_modules/@signe/sync/dist/client/index.js +0 -91
  307. package/dist/node_modules/.pnpm/@signe_sync@2.9.0/node_modules/@signe/sync/dist/client/index.js.map +0 -1
  308. package/dist/node_modules/.pnpm/@signe_sync@2.9.0/node_modules/@signe/sync/dist/index.js.map +0 -1
  309. package/dist/node_modules/.pnpm/dset@3.1.4/node_modules/dset/dist/index.js +0 -14
  310. package/dist/node_modules/.pnpm/dset@3.1.4/node_modules/dset/dist/index.js.map +0 -1
  311. package/dist/node_modules/.pnpm/partysocket@1.1.3/node_modules/partysocket/dist/chunk-HAC622V3.js.map +0 -1
  312. package/dist/node_modules/.pnpm/partysocket@1.1.3/node_modules/partysocket/dist/chunk-S74YV6PU.js.map +0 -1
  313. package/dist/node_modules/.pnpm/partysocket@1.1.3/node_modules/partysocket/dist/index.js +0 -2
  314. package/dist/node_modules/.pnpm/zod@3.24.2/node_modules/zod/lib/index.js.map +0 -1
@@ -0,0 +1,88 @@
1
+ <Container width={width} height={containerHeight} minWidth={width} minHeight={containerHeight}>
2
+ <Graphics width={width} height={containerHeight} draw={drawBar} />
3
+ @if (hasLabel) {
4
+ <Text text={labelText} x={labelPosition.x} y={labelPosition.y} size={labelSize} color={labelColor} />
5
+ }
6
+ </Container>
7
+
8
+ <script>
9
+ import { computed } from "canvasengine";
10
+ import { resolveDynamicValue } from "./parse-value";
11
+
12
+ const { object, current, max, style, text } = defineProps();
13
+ const sprite = object();
14
+
15
+ const read = (prop, fallback) => prop ? prop() : fallback;
16
+
17
+ const toNumber = (value, fallback = 0) => {
18
+ const resolved = resolveDynamicValue(value, sprite);
19
+ const num = typeof resolved === 'number' ? resolved : parseFloat(resolved);
20
+ return Number.isFinite(num) ? num : fallback;
21
+ };
22
+
23
+ const toColor = (value, fallback) => {
24
+ const resolved = resolveDynamicValue(value, sprite);
25
+ if (typeof resolved === 'number') return resolved;
26
+ if (typeof resolved === 'string' && resolved.startsWith('#')) {
27
+ return parseInt(resolved.slice(1), 16);
28
+ }
29
+ return resolved ?? fallback;
30
+ };
31
+
32
+ const config = computed(() => read(style, {}) ?? {});
33
+ const width = computed(() => toNumber(config().width, 50));
34
+ const height = computed(() => toNumber(config().height, 8));
35
+ const borderRadius = computed(() => toNumber(config().borderRadius, 3));
36
+ const borderWidth = computed(() => toNumber(config().borderWidth, 1));
37
+ const backgroundColor = computed(() => toColor(config().bgColor, 0x16213e));
38
+ const fillColor = computed(() => toColor(config().fillColor, 0x4ade80));
39
+ const borderColor = computed(() => toColor(config().borderColor, 0x4a5568));
40
+ const opacity = computed(() => Math.max(0, Math.min(1, toNumber(config().opacity, 1))));
41
+
42
+ const currentValue = computed(() => toNumber(read(current, 0), 0));
43
+ const maxValue = computed(() => Math.max(0, toNumber(read(max, 0), 0)));
44
+ const percent = computed(() => {
45
+ const max = maxValue();
46
+ if (max <= 0) return 0;
47
+ return Math.max(0, Math.min(1, currentValue() / max));
48
+ });
49
+
50
+ const fillWidth = computed(() => Math.max(0, width() * percent()));
51
+ const labelTemplate = computed(() => read(text, null));
52
+ const labelText = computed(() => {
53
+ const template = labelTemplate();
54
+ if (template == null || template === '') return '';
55
+
56
+ const value = String(template)
57
+ .replace(/\{\$current\}/g, String(currentValue()))
58
+ .replace(/\{\$max\}/g, String(maxValue()))
59
+ .replace(/\{\$percent\}/g, String(Math.round(percent() * 100)));
60
+
61
+ return String(resolveDynamicValue(value, sprite) ?? '');
62
+ });
63
+ const labelSize = computed(() => toNumber(config().fontSize, 10));
64
+ const hasLabel = computed(() => labelText().length > 0);
65
+ const labelOffset = computed(() => hasLabel() ? labelSize() + 2 : 0);
66
+ const containerHeight = computed(() => labelOffset() + height());
67
+ const labelColor = computed(() => toColor(config().textColor, 0xffffff));
68
+ const labelPosition = computed(() => ({
69
+ x: 0,
70
+ y: 0
71
+ }));
72
+
73
+ const drawBar = (g) => {
74
+ g.roundRect(0, labelOffset(), width(), height(), borderRadius());
75
+ g.fill({ color: backgroundColor(), alpha: opacity() });
76
+
77
+ const currentWidth = fillWidth();
78
+ if (currentWidth > 0) {
79
+ g.roundRect(0, labelOffset(), currentWidth, height(), borderRadius());
80
+ g.fill({ color: fillColor(), alpha: opacity() });
81
+ }
82
+
83
+ const strokeWidth = borderWidth();
84
+ if (strokeWidth <= 0) return;
85
+ g.roundRect(0, labelOffset(), width(), height(), borderRadius());
86
+ g.stroke({ color: borderColor(), width: strokeWidth, alpha: opacity() });
87
+ };
88
+ </script>
@@ -0,0 +1,21 @@
1
+ <Sprite sheet={sheet} />
2
+
3
+ <script>
4
+ import { computed } from "canvasengine";
5
+ import { RpgClientEngine } from "../../RpgClientEngine";
6
+ import { inject } from "../../core/inject";
7
+ import { resolveDynamicValue } from "./parse-value";
8
+
9
+ const { object, value } = defineProps();
10
+ const sprite = object();
11
+ const client = inject(RpgClientEngine);
12
+
13
+ const sheet = computed(() => {
14
+ const id = resolveDynamicValue(value?.(), sprite);
15
+ if (!id) return null;
16
+ return {
17
+ definition: client.getSpriteSheet(id),
18
+ playing: 'default'
19
+ };
20
+ });
21
+ </script>
@@ -0,0 +1,83 @@
1
+ import { describe, expect, test } from "vitest";
2
+ import { signal } from "canvasengine";
3
+ import { resolveDynamicProps, resolveDynamicValue } from "./parse-value";
4
+
5
+ describe("dynamic component values", () => {
6
+ test("resolves player properties and keeps bar placeholders for the bar renderer", () => {
7
+ const object = {
8
+ _name: signal("Alex"),
9
+ _speed: signal(4),
10
+ _canMove: signal(true),
11
+ hpSignal: signal(100),
12
+ _param: signal({ maxHp: 120 }),
13
+ get name() {
14
+ return this._name();
15
+ },
16
+ set name(value: string) {
17
+ this._name.set(value);
18
+ },
19
+ get speed() {
20
+ return this._speed();
21
+ },
22
+ set speed(value: number) {
23
+ this._speed.set(value);
24
+ },
25
+ get canMove() {
26
+ return this._canMove();
27
+ },
28
+ set canMove(value: boolean) {
29
+ this._canMove.set(value);
30
+ }
31
+ };
32
+
33
+ expect(resolveDynamicValue("HP: {hp}/{param.maxHp} {name} {speed} {canMove} {$current}", object)).toBe("HP: 100/120 Alex 4 true {$current}");
34
+ });
35
+
36
+ test("keeps resolved props reactive", () => {
37
+ const object = {
38
+ _name: signal("Alex"),
39
+ _speed: signal(4),
40
+ _canMove: signal(true),
41
+ hpSignal: signal(100),
42
+ _param: signal({ maxHp: 120 }),
43
+ get name() {
44
+ return this._name();
45
+ },
46
+ set name(value: string) {
47
+ this._name.set(value);
48
+ },
49
+ get speed() {
50
+ return this._speed();
51
+ },
52
+ set speed(value: number) {
53
+ this._speed.set(value);
54
+ },
55
+ get canMove() {
56
+ return this._canMove();
57
+ },
58
+ set canMove(value: boolean) {
59
+ this._canMove.set(value);
60
+ }
61
+ };
62
+ const props: any = resolveDynamicProps({
63
+ value: "HP: {hp} {name} {speed} {canMove}",
64
+ text: "{$current}/{$max} {name}",
65
+ style: {
66
+ width: "{hp}"
67
+ }
68
+ }, object);
69
+
70
+ expect(props.value()).toBe("HP: 100 Alex 4 true");
71
+ expect(props.text()).toBe("{$current}/{$max} Alex");
72
+ expect(props.style()).toEqual({ width: "100" });
73
+
74
+ object.hpSignal.set(10);
75
+ object.name = "Sam";
76
+ object.speed = 6;
77
+ object.canMove = false;
78
+
79
+ expect(props.value()).toBe("HP: 10 Sam 6 false");
80
+ expect(props.text()).toBe("{$current}/{$max} Sam");
81
+ expect(props.style()).toEqual({ width: "10" });
82
+ });
83
+ });
@@ -6,17 +6,123 @@ interface MatchResult {
6
6
  index: number;
7
7
  }
8
8
 
9
+ const readSignal = (value: any) => typeof value === 'function' ? value() : value;
10
+ const DYNAMIC_VALUE_PATTERN = /\{([^}]+)\}/g;
11
+
12
+ const hasDynamicValue = (value: any) => {
13
+ value = readSignal(value);
14
+ if (typeof value !== 'string') return false;
15
+ DYNAMIC_VALUE_PATTERN.lastIndex = 0;
16
+ return DYNAMIC_VALUE_PATTERN.test(value);
17
+ };
18
+
19
+ const resolveDynamicSnapshot = (value: any, object?: any): any => {
20
+ value = readSignal(value);
21
+
22
+ if (Array.isArray(value)) {
23
+ return value.map((entry) => resolveDynamicSnapshot(entry, object));
24
+ }
25
+
26
+ if (value && typeof value === 'object') {
27
+ return Object.fromEntries(
28
+ Object.entries(value).map(([key, entry]) => [key, resolveDynamicSnapshot(entry, object)])
29
+ );
30
+ }
31
+
32
+ return resolveDynamicValue(value, object);
33
+ };
34
+
35
+ export const getDynamicValue = (property: string, object?: any) => {
36
+ try {
37
+ const propertyPath = property.split('.');
38
+ let currentValue = object;
39
+
40
+ for (let j = 0; j < propertyPath.length; j++) {
41
+ let prop = propertyPath[j];
42
+
43
+ currentValue = readSignal(currentValue);
44
+
45
+ if (j === 0) {
46
+ if (prop === 'hp') prop = 'hpSignal';
47
+ if (prop === 'sp') prop = 'spSignal';
48
+ if (prop === 'param') prop = '_param';
49
+ if (prop === 'name' && currentValue && typeof currentValue === 'object' && '_name' in currentValue) {
50
+ prop = '_name';
51
+ }
52
+ if (prop === 'speed' && currentValue && typeof currentValue === 'object' && '_speed' in currentValue) {
53
+ prop = '_speed';
54
+ }
55
+ if (prop === 'canMove' && currentValue && typeof currentValue === 'object' && '_canMove' in currentValue) {
56
+ prop = '_canMove';
57
+ }
58
+ }
59
+
60
+ if (currentValue && typeof currentValue === 'object' && prop in currentValue) {
61
+ currentValue = currentValue[prop];
62
+ } else {
63
+ return undefined;
64
+ }
65
+ }
66
+
67
+ return readSignal(currentValue);
68
+ } catch (error) {
69
+ return undefined;
70
+ }
71
+ };
72
+
73
+ export const resolveDynamicValue = (value: any, object?: any): any => {
74
+ value = readSignal(value);
75
+
76
+ if (typeof value !== 'string') {
77
+ return value;
78
+ }
79
+
80
+ return value.replace(DYNAMIC_VALUE_PATTERN, (fullMatch, property) => {
81
+ const propertyValue = getDynamicValue(property, object);
82
+ if (propertyValue == null && property.startsWith('$')) return fullMatch;
83
+ return propertyValue != null ? String(propertyValue) : '';
84
+ });
85
+ };
86
+
87
+ const resolveDynamicProp = (value: any, object?: any): any => {
88
+ if (Array.isArray(value) || (value && typeof value === 'object' && typeof value !== 'function')) {
89
+ return computed(() => resolveDynamicSnapshot(value, object));
90
+ }
91
+
92
+ if (typeof value === 'function' || hasDynamicValue(value)) {
93
+ return computed(() => resolveDynamicValue(value, object));
94
+ }
95
+
96
+ return value;
97
+ };
98
+
99
+ export const resolveDynamicProps = (props: any, object?: any): any => {
100
+ props = readSignal(props);
101
+
102
+ if (Array.isArray(props)) {
103
+ return computed(() => resolveDynamicSnapshot(props, object));
104
+ }
105
+
106
+ if (props && typeof props === 'object') {
107
+ return Object.fromEntries(
108
+ Object.entries(props).map(([key, value]) => [key, resolveDynamicProp(value, object)])
109
+ );
110
+ }
111
+
112
+ return resolveDynamicProp(props, object);
113
+ };
114
+
9
115
  export const parseDynamicValue = (value: any, object?: any) => {
10
116
  if (typeof value !== 'string') {
11
117
  return computed(() => String(value ?? ''));
12
118
  }
13
119
 
14
120
  // Find all dynamic references like {propertyName}
15
- const pattern = /\{([^}]+)\}/g;
16
121
  const matches: MatchResult[] = [];
17
122
  let match;
18
-
19
- while ((match = pattern.exec(value)) !== null) {
123
+
124
+ DYNAMIC_VALUE_PATTERN.lastIndex = 0;
125
+ while ((match = DYNAMIC_VALUE_PATTERN.exec(value)) !== null) {
20
126
  matches.push({
21
127
  property: match[1],
22
128
  fullMatch: match[0],
@@ -37,40 +143,8 @@ export const parseDynamicValue = (value: any, object?: any) => {
37
143
  for (let i = matches.length - 1; i >= 0; i--) {
38
144
  const { property, fullMatch } = matches[i];
39
145
 
40
- // Try to access the property from the object
41
- // Support nested properties like {param.maxHp}
42
- let propertyValue = '';
43
- try {
44
- const propertyPath = property.split('.');
45
- let currentValue = object;
46
-
47
- for (let j = 0; j < propertyPath.length; j++) {
48
- const prop = propertyPath[j];
49
-
50
- // Check if currentValue is a signal (function) and call it
51
- if (typeof currentValue === 'function') {
52
- currentValue = currentValue();
53
- }
54
-
55
- // Access the property
56
- if (currentValue && typeof currentValue === 'object' && prop in currentValue) {
57
- currentValue = currentValue[prop];
58
- } else {
59
- currentValue = undefined;
60
- break;
61
- }
62
- }
63
-
64
- // If the final value is a signal, call it
65
- if (typeof currentValue === 'function') {
66
- currentValue = currentValue();
67
- }
68
-
69
- propertyValue = currentValue != null ? String(currentValue) : '';
70
- } catch (error) {
71
- // If property doesn't exist or can't be accessed, use empty string
72
- propertyValue = '';
73
- }
146
+ const currentValue = getDynamicValue(property, object);
147
+ const propertyValue = currentValue != null ? String(currentValue) : property.startsWith('$') ? fullMatch : '';
74
148
 
75
149
  result = result.replace(fullMatch, propertyValue);
76
150
  }
@@ -0,0 +1,46 @@
1
+ import { describe, expect, test } from "vitest";
2
+ import { getShapeBox, getShapePointBounds, translatePolygonPoints } from "./shape-utils";
3
+
4
+ describe("shape utilities", () => {
5
+ test("normalizes rectangles and circles around their rendered bounds", () => {
6
+ expect(getShapeBox({ type: "rect", width: 32, height: 32 })).toEqual({
7
+ width: 32,
8
+ height: 32,
9
+ offsetX: 0,
10
+ offsetY: 0
11
+ });
12
+ expect(getShapeBox({ type: "circle", radius: 8 })).toEqual({
13
+ width: 16,
14
+ height: 16,
15
+ offsetX: 0,
16
+ offsetY: 0
17
+ });
18
+ });
19
+
20
+ test("normalizes line bounds with negative coordinates", () => {
21
+ expect(getShapeBox({ type: "line", x1: -4, y1: 6, x2: 12, y2: -2 })).toEqual({
22
+ width: 16,
23
+ height: 8,
24
+ offsetX: 4,
25
+ offsetY: 2
26
+ });
27
+ });
28
+
29
+ test("normalizes polygon bounds and translated points", () => {
30
+ const box = getShapeBox({ type: "polygon", points: [-5, 2, 15, 2, 5, 12] });
31
+
32
+ expect(getShapePointBounds([-5, 2, 15, 2, 5, 12])).toEqual({
33
+ minX: -5,
34
+ minY: 2,
35
+ maxX: 15,
36
+ maxY: 12
37
+ });
38
+ expect(box).toEqual({
39
+ width: 20,
40
+ height: 10,
41
+ offsetX: 5,
42
+ offsetY: -2
43
+ });
44
+ expect(translatePolygonPoints([-5, 2, 15, 2, 5, 12], box)).toEqual([0, 0, 20, 0, 10, 10]);
45
+ });
46
+ });
@@ -0,0 +1,61 @@
1
+ const defaultToNumber = (value: any, fallback = 0) => {
2
+ const num = typeof value === 'number' ? value : parseFloat(value);
3
+ return Number.isFinite(num) ? num : fallback;
4
+ };
5
+
6
+ export function getShapePointBounds(points: any[] = [], toNumber = defaultToNumber) {
7
+ if (!Array.isArray(points) || points.length < 2) {
8
+ return { minX: 0, minY: 0, maxX: 1, maxY: 1 };
9
+ }
10
+
11
+ let minX = Infinity;
12
+ let minY = Infinity;
13
+ let maxX = -Infinity;
14
+ let maxY = -Infinity;
15
+
16
+ for (let i = 0; i < points.length; i += 2) {
17
+ const x = toNumber(points[i], 0);
18
+ const y = toNumber(points[i + 1], 0);
19
+ minX = Math.min(minX, x);
20
+ minY = Math.min(minY, y);
21
+ maxX = Math.max(maxX, x);
22
+ maxY = Math.max(maxY, y);
23
+ }
24
+
25
+ return { minX, minY, maxX, maxY };
26
+ }
27
+
28
+ export function getShapeBox(cfg: any, toNumber = defaultToNumber) {
29
+ if (cfg.type === 'circle') {
30
+ return { width: cfg.radius * 2, height: cfg.radius * 2, offsetX: 0, offsetY: 0 };
31
+ }
32
+
33
+ if (cfg.type === 'line') {
34
+ const minX = Math.min(cfg.x1, cfg.x2);
35
+ const minY = Math.min(cfg.y1, cfg.y2);
36
+ const maxX = Math.max(cfg.x1, cfg.x2);
37
+ const maxY = Math.max(cfg.y1, cfg.y2);
38
+ return {
39
+ width: Math.max(1, maxX - minX),
40
+ height: Math.max(1, maxY - minY),
41
+ offsetX: -minX,
42
+ offsetY: -minY
43
+ };
44
+ }
45
+
46
+ if (cfg.type === 'polygon') {
47
+ const bounds = getShapePointBounds(cfg.points, toNumber);
48
+ return {
49
+ width: Math.max(1, bounds.maxX - bounds.minX),
50
+ height: Math.max(1, bounds.maxY - bounds.minY),
51
+ offsetX: -bounds.minX,
52
+ offsetY: -bounds.minY
53
+ };
54
+ }
55
+
56
+ return { width: cfg.width, height: cfg.height, offsetX: 0, offsetY: 0 };
57
+ }
58
+
59
+ export function translatePolygonPoints(points: any[] = [], box: { offsetX: number; offsetY: number }, toNumber = defaultToNumber) {
60
+ return points.map((point, index) => toNumber(point, 0) + (index % 2 === 0 ? box.offsetX : box.offsetY));
61
+ }
@@ -0,0 +1,90 @@
1
+ <Container width={shapeWidth} height={shapeHeight} minWidth={shapeWidth} minHeight={shapeHeight}>
2
+ <Graphics width={shapeWidth} height={shapeHeight} draw={drawShape} />
3
+ </Container>
4
+
5
+ <script>
6
+ import { computed } from "canvasengine";
7
+ import { resolveDynamicValue } from "./parse-value";
8
+ import { getShapeBox, translatePolygonPoints } from "./shape-utils";
9
+
10
+ const props = defineProps();
11
+ const { object } = props;
12
+ const sprite = object();
13
+
14
+ const read = (prop, fallback) => prop ? prop() : fallback;
15
+
16
+ const toNumber = (value, fallback = 0) => {
17
+ const resolved = resolveDynamicValue(value, sprite);
18
+ const num = typeof resolved === 'number' ? resolved : parseFloat(resolved);
19
+ return Number.isFinite(num) ? num : fallback;
20
+ };
21
+
22
+ const toColor = (value, fallback) => {
23
+ const resolved = resolveDynamicValue(value, sprite);
24
+ if (typeof resolved === 'number') return resolved;
25
+ if (typeof resolved === 'string' && resolved.startsWith('#')) {
26
+ return parseInt(resolved.slice(1), 16);
27
+ }
28
+ return resolved ?? fallback;
29
+ };
30
+
31
+ const config = computed(() => ({
32
+ type: read(props.type, 'rectangle'),
33
+ fill: toColor(read(props.fill, '#ffffff'), 0xffffff),
34
+ radius: toNumber(read(props.radius, 8), 8),
35
+ width: toNumber(read(props.width, 16), 16),
36
+ height: toNumber(read(props.height, 16), 16),
37
+ x1: toNumber(read(props.x1, 0), 0),
38
+ y1: toNumber(read(props.y1, 0), 0),
39
+ x2: toNumber(read(props.x2, 16), 16),
40
+ y2: toNumber(read(props.y2, 0), 0),
41
+ opacity: Math.max(0, Math.min(1, toNumber(read(props.opacity, 1), 1))),
42
+ points: read(props.points, []),
43
+ line: read(props.line, null)
44
+ }));
45
+
46
+ const shapeBox = computed(() => getShapeBox(config(), toNumber));
47
+
48
+ const shapeWidth = computed(() => shapeBox().width);
49
+ const shapeHeight = computed(() => shapeBox().height);
50
+
51
+ const drawShape = (g) => {
52
+ const cfg = config();
53
+ const box = shapeBox();
54
+
55
+ if (cfg.type === 'circle') {
56
+ g.circle(cfg.radius, cfg.radius, cfg.radius);
57
+ } else if (cfg.type === 'ellipse') {
58
+ g.ellipse(box.width / 2, box.height / 2, box.width / 2, box.height / 2);
59
+ } else if (cfg.type === 'line') {
60
+ g.moveTo(cfg.x1 + box.offsetX, cfg.y1 + box.offsetY);
61
+ g.lineTo(cfg.x2 + box.offsetX, cfg.y2 + box.offsetY);
62
+ } else if (cfg.type === 'polygon' && Array.isArray(cfg.points)) {
63
+ g.poly(translatePolygonPoints(cfg.points, box, toNumber));
64
+ } else if (cfg.type === 'rounded-rectangle') {
65
+ g.roundRect(0, 0, box.width, box.height, toNumber(read(props.radius, 4), 4));
66
+ } else {
67
+ g.rect(0, 0, box.width, box.height);
68
+ }
69
+
70
+ if (cfg.type === 'line') {
71
+ const line = cfg.line ?? {};
72
+ g.stroke({
73
+ color: toColor(line.color, cfg.fill),
74
+ width: toNumber(line.width, 1),
75
+ alpha: toNumber(line.alpha, cfg.opacity)
76
+ });
77
+ return;
78
+ }
79
+
80
+ g.fill({ color: cfg.fill, alpha: cfg.opacity });
81
+
82
+ if (cfg.line) {
83
+ g.stroke({
84
+ color: toColor(cfg.line.color, cfg.fill),
85
+ width: toNumber(cfg.line.width, 1),
86
+ alpha: toNumber(cfg.line.alpha, cfg.opacity)
87
+ });
88
+ }
89
+ };
90
+ </script>