@rpgjs/client 5.0.0-alpha.24 → 5.0.0-alpha.26

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 (175) hide show
  1. package/dist/{index30.js → Game/AnimationManager.js} +1 -1
  2. package/dist/Game/AnimationManager.js.map +1 -0
  3. package/dist/{index24.js → Game/Event.js} +2 -2
  4. package/dist/Game/Event.js.map +1 -0
  5. package/dist/{index29.js → Game/Map.js} +6 -6
  6. package/dist/Game/Map.js.map +1 -0
  7. package/dist/{index22.js → Game/Object.js} +4 -4
  8. package/dist/Game/Object.js.map +1 -0
  9. package/dist/{index23.js → Game/Player.js} +2 -2
  10. package/dist/Game/Player.js.map +1 -0
  11. package/dist/{index9.js → Gui/Gui.js} +10 -10
  12. package/dist/{index9.js.map → Gui/Gui.js.map} +1 -1
  13. package/dist/{index19.js → Resource.js} +1 -1
  14. package/dist/Resource.js.map +1 -0
  15. package/dist/RpgClientEngine.d.ts +31 -0
  16. package/dist/{index2.js → RpgClientEngine.js} +150 -18
  17. package/dist/RpgClientEngine.js.map +1 -0
  18. package/dist/{index18.js → Sound.js} +1 -1
  19. package/dist/Sound.js.map +1 -0
  20. package/dist/{index34.js → components/animations/animation.ce.js} +3 -3
  21. package/dist/components/animations/animation.ce.js.map +1 -0
  22. package/dist/{index33.js → components/animations/hit.ce.js} +1 -1
  23. package/dist/components/animations/hit.ce.js.map +1 -0
  24. package/dist/{index12.js → components/animations/index.js} +3 -3
  25. package/dist/components/animations/index.js.map +1 -0
  26. package/dist/{index17.js → components/character.ce.js} +4 -4
  27. package/dist/components/character.ce.js.map +1 -0
  28. package/dist/{index51.js → components/dynamics/parse-value.js} +1 -1
  29. package/dist/components/dynamics/parse-value.js.map +1 -0
  30. package/dist/{index39.js → components/dynamics/text.ce.js} +2 -2
  31. package/dist/components/dynamics/text.ce.js.map +1 -0
  32. package/dist/{index11.js → components/gui/box.ce.js} +8 -8
  33. package/dist/components/gui/box.ce.js.map +1 -0
  34. package/dist/{index10.js → components/gui/dialogbox/index.ce.js} +4 -4
  35. package/dist/components/gui/dialogbox/index.ce.js.map +1 -0
  36. package/dist/{index52.js → components/gui/dialogbox/itemMenu.ce.js} +1 -1
  37. package/dist/components/gui/dialogbox/itemMenu.ce.js.map +1 -0
  38. package/dist/{index48.js → components/gui/dialogbox/selection.ce.js} +4 -4
  39. package/dist/components/gui/dialogbox/selection.ce.js.map +1 -0
  40. package/dist/{index25.js → components/gui/mobile/index.js} +4 -4
  41. package/dist/components/gui/mobile/index.js.map +1 -0
  42. package/dist/{index40.js → components/gui/mobile/mobile.ce.js} +2 -2
  43. package/dist/components/gui/mobile/mobile.ce.js.map +1 -0
  44. package/dist/{index13.js → components/prebuilt/hp-bar.ce.js} +1 -1
  45. package/dist/components/prebuilt/hp-bar.ce.js.map +1 -0
  46. package/dist/{index14.js → components/prebuilt/light-halo.ce.js} +1 -1
  47. package/dist/components/prebuilt/light-halo.ce.js.map +1 -0
  48. package/dist/{index26.js → components/scenes/canvas.ce.js} +5 -5
  49. package/dist/components/scenes/canvas.ce.js.map +1 -0
  50. package/dist/{index43.js → components/scenes/draw-map.ce.js} +8 -8
  51. package/dist/components/scenes/draw-map.ce.js.map +1 -0
  52. package/dist/{index16.js → components/scenes/event-layer.ce.js} +4 -4
  53. package/dist/components/scenes/event-layer.ce.js.map +1 -0
  54. package/dist/{index6.js → core/inject.js} +2 -2
  55. package/dist/core/inject.js.map +1 -0
  56. package/dist/{index5.js → core/setup.js} +4 -4
  57. package/dist/core/setup.js.map +1 -0
  58. package/dist/index.d.ts +1 -0
  59. package/dist/index.js +25 -24
  60. package/dist/index.js.map +1 -1
  61. package/dist/{index8.js → module.js} +4 -4
  62. package/dist/{index8.js.map → module.js.map} +1 -1
  63. package/dist/{index20.js → node_modules/.pnpm/@signe_di@2.7.2/node_modules/@signe/di/dist/index.js} +1 -1
  64. package/dist/node_modules/.pnpm/@signe_di@2.7.2/node_modules/@signe/di/dist/index.js.map +1 -0
  65. package/dist/{index42.js → node_modules/.pnpm/@signe_reactive@2.7.2/node_modules/@signe/reactive/dist/index.js} +1 -1
  66. package/dist/node_modules/.pnpm/@signe_reactive@2.7.2/node_modules/@signe/reactive/dist/index.js.map +1 -0
  67. package/dist/{index31.js → node_modules/.pnpm/@signe_room@2.7.2/node_modules/@signe/room/dist/index.js} +66 -39
  68. package/dist/node_modules/.pnpm/@signe_room@2.7.2/node_modules/@signe/room/dist/index.js.map +1 -0
  69. package/dist/{index41.js → node_modules/.pnpm/@signe_sync@2.7.2/node_modules/@signe/sync/dist/chunk-7QVYU63E.js} +1 -1
  70. package/dist/node_modules/.pnpm/@signe_sync@2.7.2/node_modules/@signe/sync/dist/chunk-7QVYU63E.js.map +1 -0
  71. package/dist/{index32.js → node_modules/.pnpm/@signe_sync@2.7.2/node_modules/@signe/sync/dist/client/index.js} +5 -5
  72. package/dist/node_modules/.pnpm/@signe_sync@2.7.2/node_modules/@signe/sync/dist/client/index.js.map +1 -0
  73. package/dist/{index28.js → node_modules/.pnpm/@signe_sync@2.7.2/node_modules/@signe/sync/dist/index.js} +3 -3
  74. package/dist/node_modules/.pnpm/@signe_sync@2.7.2/node_modules/@signe/sync/dist/index.js.map +1 -0
  75. package/dist/{index44.js → node_modules/.pnpm/dset@3.1.4/node_modules/dset/dist/index.js} +1 -1
  76. package/dist/node_modules/.pnpm/dset@3.1.4/node_modules/dset/dist/index.js.map +1 -0
  77. package/dist/{index49.js → node_modules/.pnpm/partysocket@1.1.3/node_modules/partysocket/dist/chunk-HAC622V3.js} +2 -15
  78. package/dist/node_modules/.pnpm/partysocket@1.1.3/node_modules/partysocket/dist/chunk-HAC622V3.js.map +1 -0
  79. package/dist/{index50.js → node_modules/.pnpm/partysocket@1.1.3/node_modules/partysocket/dist/chunk-S74YV6PU.js} +2 -5
  80. package/dist/node_modules/.pnpm/partysocket@1.1.3/node_modules/partysocket/dist/chunk-S74YV6PU.js.map +1 -0
  81. package/dist/{index47.js → node_modules/.pnpm/zod@3.24.2/node_modules/zod/lib/index.js} +813 -100
  82. package/dist/node_modules/.pnpm/zod@3.24.2/node_modules/zod/lib/index.js.map +1 -0
  83. package/dist/{index35.js → presets/animation.js} +1 -1
  84. package/dist/presets/animation.js.map +1 -0
  85. package/dist/{index38.js → presets/faceset.js} +1 -1
  86. package/dist/presets/faceset.js.map +1 -0
  87. package/dist/presets/index.js +14 -0
  88. package/dist/presets/index.js.map +1 -0
  89. package/dist/{index36.js → presets/lpc.js} +1 -1
  90. package/dist/presets/lpc.js.map +1 -0
  91. package/dist/{index37.js → presets/rmspritesheet.js} +1 -1
  92. package/dist/presets/rmspritesheet.js.map +1 -0
  93. package/dist/{index27.js → services/AbstractSocket.js} +1 -1
  94. package/dist/services/AbstractSocket.js.map +1 -0
  95. package/dist/{index21.js → services/keyboardControls.js} +1 -1
  96. package/dist/services/keyboardControls.js.map +1 -0
  97. package/dist/{index7.js → services/loadMap.js} +2 -2
  98. package/dist/services/loadMap.js.map +1 -0
  99. package/dist/{index4.js → services/mmorpg.js} +6 -6
  100. package/dist/services/mmorpg.js.map +1 -0
  101. package/dist/services/standalone.d.ts +8 -2
  102. package/dist/{index3.js → services/standalone.js} +24 -16
  103. package/dist/services/standalone.js.map +1 -0
  104. package/package.json +8 -8
  105. package/src/RpgClientEngine.ts +193 -7
  106. package/src/components/scenes/draw-map.ce +3 -3
  107. package/src/index.ts +2 -1
  108. package/src/services/standalone.ts +26 -11
  109. package/vite.config.ts +4 -2
  110. package/dist/index10.js.map +0 -1
  111. package/dist/index11.js.map +0 -1
  112. package/dist/index12.js.map +0 -1
  113. package/dist/index13.js.map +0 -1
  114. package/dist/index14.js.map +0 -1
  115. package/dist/index15.js +0 -14
  116. package/dist/index15.js.map +0 -1
  117. package/dist/index16.js.map +0 -1
  118. package/dist/index17.js.map +0 -1
  119. package/dist/index18.js.map +0 -1
  120. package/dist/index19.js.map +0 -1
  121. package/dist/index2.js.map +0 -1
  122. package/dist/index20.js.map +0 -1
  123. package/dist/index21.js.map +0 -1
  124. package/dist/index22.js.map +0 -1
  125. package/dist/index23.js.map +0 -1
  126. package/dist/index24.js.map +0 -1
  127. package/dist/index25.js.map +0 -1
  128. package/dist/index26.js.map +0 -1
  129. package/dist/index27.js.map +0 -1
  130. package/dist/index28.js.map +0 -1
  131. package/dist/index29.js.map +0 -1
  132. package/dist/index3.js.map +0 -1
  133. package/dist/index30.js.map +0 -1
  134. package/dist/index31.js.map +0 -1
  135. package/dist/index32.js.map +0 -1
  136. package/dist/index33.js.map +0 -1
  137. package/dist/index34.js.map +0 -1
  138. package/dist/index35.js.map +0 -1
  139. package/dist/index36.js.map +0 -1
  140. package/dist/index37.js.map +0 -1
  141. package/dist/index38.js.map +0 -1
  142. package/dist/index39.js.map +0 -1
  143. package/dist/index4.js.map +0 -1
  144. package/dist/index40.js.map +0 -1
  145. package/dist/index41.js.map +0 -1
  146. package/dist/index42.js.map +0 -1
  147. package/dist/index43.js.map +0 -1
  148. package/dist/index44.js.map +0 -1
  149. package/dist/index45.js +0 -7
  150. package/dist/index45.js.map +0 -1
  151. package/dist/index46.js +0 -329
  152. package/dist/index46.js.map +0 -1
  153. package/dist/index47.js.map +0 -1
  154. package/dist/index48.js.map +0 -1
  155. package/dist/index49.js.map +0 -1
  156. package/dist/index5.js.map +0 -1
  157. package/dist/index50.js.map +0 -1
  158. package/dist/index51.js.map +0 -1
  159. package/dist/index52.js.map +0 -1
  160. package/dist/index53.js +0 -6
  161. package/dist/index53.js.map +0 -1
  162. package/dist/index54.js +0 -12
  163. package/dist/index54.js.map +0 -1
  164. package/dist/index55.js +0 -113
  165. package/dist/index55.js.map +0 -1
  166. package/dist/index56.js +0 -136
  167. package/dist/index56.js.map +0 -1
  168. package/dist/index57.js +0 -137
  169. package/dist/index57.js.map +0 -1
  170. package/dist/index58.js +0 -112
  171. package/dist/index58.js.map +0 -1
  172. package/dist/index59.js +0 -9
  173. package/dist/index59.js.map +0 -1
  174. package/dist/index6.js.map +0 -1
  175. package/dist/index7.js.map +0 -1
@@ -24,4 +24,4 @@ const AnimationSpritesheetPreset = (framesWidth, framesHeight) => {
24
24
  };
25
25
 
26
26
  export { AnimationSpritesheetPreset };
27
- //# sourceMappingURL=index35.js.map
27
+ //# sourceMappingURL=animation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"animation.js","sources":["../../src/presets/animation.ts"],"sourcesContent":["/**\n * Creates an animation spritesheet preset with automatic frame generation\n * \n * This function generates animation frames based on the provided width and height dimensions.\n * It creates a sequence of frames that progresses through the spritesheet from left to right,\n * top to bottom, with each frame having a 10ms time increment.\n * \n * @param {number} framesWidth - The number of frames horizontally in the spritesheet\n * @param {number} framesHeight - The number of frames vertically in the spritesheet\n * @returns {Object} Animation preset configuration object\n * \n * @example\n * ```javascript\n * // For a 4x4 spritesheet\n * const preset = AnimationSpritesheetPreset(4, 4);\n * // This will generate 16 frames with coordinates from (0,0) to (3,3)\n * ```\n */\nexport const AnimationSpritesheetPreset = (framesWidth: number, framesHeight: number) => {\n \n const animations: Array<{ time: number; frameX: number; frameY: number }> = [];\n\n for (let y = 0; y < framesHeight; y++) {\n for (let x = 0; x < framesWidth; x++) {\n const frameIndex = y * framesWidth + x;\n animations.push({ \n time: frameIndex * 10, \n frameX: x, \n frameY: y \n });\n }\n }\n \n return {\n framesWidth,\n framesHeight,\n textures: {\n default: {\n animations: () => [\n animations\n ],\n }\n }\n };\n};\n "],"names":[],"mappings":"AAkBO,MAAM,0BAAA,GAA6B,CAAC,WAAA,EAAqB,YAAA,KAAyB;AAErF,EAAA,MAAM,aAAsE,EAAC;AAE7E,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,YAAA,EAAc,CAAA,EAAA,EAAK;AACnC,IAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,WAAA,EAAa,CAAA,EAAA,EAAK;AAClC,MAAA,MAAM,UAAA,GAAa,IAAI,WAAA,GAAc,CAAA;AACrC,MAAA,UAAA,CAAW,IAAA,CAAK;AAAA,QACZ,MAAM,UAAA,GAAa,EAAA;AAAA,QACnB,MAAA,EAAQ,CAAA;AAAA,QACR,MAAA,EAAQ;AAAA,OACX,CAAA;AAAA,IACL;AAAA,EACJ;AAEA,EAAA,OAAO;AAAA,IACH,WAAA;AAAA,IACA,YAAA;AAAA,IACA,QAAA,EAAU;AAAA,MACN,OAAA,EAAS;AAAA,QACL,YAAY,MAAM;AAAA,UACd;AAAA;AACJ;AACJ;AACJ,GACJ;AACJ;;;;"}
@@ -21,4 +21,4 @@ const FacesetPreset = (options, framesWidth, framesHeight, expressions) => {
21
21
  };
22
22
 
23
23
  export { FacesetPreset };
24
- //# sourceMappingURL=index38.js.map
24
+ //# sourceMappingURL=faceset.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"faceset.js","sources":["../../src/presets/faceset.ts"],"sourcesContent":["/**\n * Creates a faceset preset for character expressions\n * \n * This preset allows you to define multiple facial expressions for a character,\n * where each expression corresponds to a specific frame position (frameX, frameY)\n * within a single faceset texture. Each expression is defined by its position\n * in the faceset grid.\n * \n * @param options - Object containing the faceset configuration\n * @param framesWidth - Number of frames horizontally in the faceset texture\n * @param framesHeight - Number of frames vertically in the faceset texture\n * @param expressions - Object mapping expression names to their frame positions as tuples [frameX, frameY]\n * @returns Faceset configuration with animations for each expression\n * \n * @example\n * ```typescript\n * const faceset = FacesetPreset({\n * id: \"facesetId\",\n * image: \"faceset.png\",\n * width: 1024,\n * height: 1024,\n * }, 4, 2, {\n * happy: [0, 0],\n * sad: [1, 0],\n * angry: [2, 0],\n * surprised: [3, 0]\n * });\n * ```\n */\nexport const FacesetPreset = (\n options: any,\n framesWidth: number, \n framesHeight: number,\n expressions: Record<string, [number, number]>,\n) => {\n \n const textures: Record<string, any> = {};\n \n // Create texture configuration for each expression\n Object.keys(expressions).forEach((expressionName) => {\n const [frameX, frameY] = expressions[expressionName];\n textures[expressionName] = {\n animations: () => [\n [{ \n time: 0, \n frameX: frameX, \n frameY: frameY \n }]\n ],\n };\n });\n \n return {\n ...options,\n framesWidth,\n framesHeight,\n textures\n };\n};\n "],"names":[],"mappings":"AA6BO,MAAM,aAAA,GAAgB,CACzB,OAAA,EACA,WAAA,EACA,cACA,WAAA,KACC;AAED,EAAA,MAAM,WAAgC,EAAC;AAGvC,EAAA,MAAA,CAAO,IAAA,CAAK,WAAW,CAAA,CAAE,OAAA,CAAQ,CAAC,cAAA,KAAmB;AACjD,IAAA,MAAM,CAAC,MAAA,EAAQ,MAAM,CAAA,GAAI,YAAY,cAAc,CAAA;AACnD,IAAA,QAAA,CAAS,cAAc,CAAA,GAAI;AAAA,MACvB,YAAY,MAAM;AAAA,QACd,CAAC;AAAA,UACG,IAAA,EAAM,CAAA;AAAA,UACN,MAAA;AAAA,UACA;AAAA,SACH;AAAA;AACL,KACJ;AAAA,EACJ,CAAC,CAAA;AAED,EAAA,OAAO;AAAA,IACH,GAAG,OAAA;AAAA,IACH,WAAA;AAAA,IACA,YAAA;AAAA,IACA;AAAA,GACJ;AACJ;;;;"}
@@ -0,0 +1,14 @@
1
+ import { AnimationSpritesheetPreset } from './animation.js';
2
+ import { LPCSpritesheetPreset } from './lpc.js';
3
+ import { RMSpritesheet } from './rmspritesheet.js';
4
+ import { FacesetPreset } from './faceset.js';
5
+
6
+ const Presets = {
7
+ RMSpritesheet,
8
+ LPCSpritesheetPreset,
9
+ AnimationSpritesheetPreset,
10
+ FacesetPreset
11
+ };
12
+
13
+ export { Presets };
14
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../../src/presets/index.ts"],"sourcesContent":["import { AnimationSpritesheetPreset } from \"./animation\";\nimport { LPCSpritesheetPreset } from \"./lpc\";\nimport { RMSpritesheet } from \"./rmspritesheet\";\nimport { FacesetPreset } from \"./faceset\";\n\nexport const Presets = {\n RMSpritesheet,\n LPCSpritesheetPreset,\n AnimationSpritesheetPreset,\n FacesetPreset\n}"],"names":[],"mappings":";;;;;AAKO,MAAM,OAAA,GAAU;AAAA,EACnB,aAAA;AAAA,EACA,oBAAA;AAAA,EACA,0BAAA;AAAA,EACA;AACJ;;;;"}
@@ -92,4 +92,4 @@ const LPCSpritesheetPreset = (options) => {
92
92
  };
93
93
 
94
94
  export { LPCSpritesheetPreset };
95
- //# sourceMappingURL=index36.js.map
95
+ //# sourceMappingURL=lpc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lpc.js","sources":["../../src/presets/lpc.ts"],"sourcesContent":["import { Animation, Direction } from \"@rpgjs/common\";\n\nexport const LPCSpritesheetPreset = (options: {\n id: string;\n imageSource: string;\n width: number;\n height: number;\n ratio?: number;\n }) => {\n const ratio = options.ratio ?? 1;\n\n const frameY = (direction: Direction) => {\n return {\n [Direction.Down]: 2,\n [Direction.Left]: 1,\n [Direction.Right]: 3,\n [Direction.Up]: 0,\n }[direction];\n };\n \n const stand = (direction: Direction) => [\n { time: 0, frameX: 0, frameY: frameY(direction) },\n ];\n const anim = (\n direction: Direction,\n framesWidth: number,\n speed: number = 5\n ) => {\n const array: any = [];\n for (let i = 0; i < framesWidth; i++) {\n array.push({ time: i * speed, frameX: i, frameY: frameY(direction) });\n }\n return array;\n };\n \n return {\n id: options.id,\n image: options.imageSource,\n width: options.width,\n height: options.height,\n opacity: 1,\n rectWidth: 64 * ratio,\n rectHeight: 64 * ratio,\n framesWidth: 6,\n framesHeight: 4,\n spriteRealSize: {\n width: 48 * ratio,\n height: 52 * ratio,\n },\n textures: {\n [Animation.Stand]: {\n offset: {\n x: 0,\n y: 512 * ratio,\n },\n animations: ({ direction }) => [stand(direction)],\n },\n [Animation.Walk]: {\n offset: {\n x: 0,\n y: 512 * ratio,\n },\n framesWidth: 9,\n framesHeight: 4,\n animations: ({ direction }) => [anim(direction, 9)],\n },\n [Animation.Attack]: {\n offset: {\n x: 0,\n y: 768 * ratio,\n },\n framesWidth: 6,\n framesHeight: 4,\n animations: ({ direction }) => [anim(direction, 6, 3)],\n },\n [Animation.Skill]: {\n framesWidth: 7,\n framesHeight: 4,\n animations: ({ direction }) => [anim(direction, 7, 3)],\n },\n attack2: {\n offset: {\n x: 0,\n y: 256 * ratio,\n },\n framesWidth: 7,\n framesHeight: 8,\n animations: ({ direction }) => [anim(direction, 7, 3)],\n },\n ...(options.height > 3000\n ? {\n attack3: {\n offset: {\n x: 0,\n y: 5568 - 288 * 4,\n },\n rectWidth: 288,\n rectHeight: 288,\n framesWidth: 6,\n framesHeight: 4,\n animations: ({ direction }) => [anim(direction, 6, 3)],\n },\n }\n : {}),\n },\n };\n };\n "],"names":[],"mappings":"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"}
@@ -38,4 +38,4 @@ const RMSpritesheet = (framesWidth, framesHeight, frameStand = 1) => {
38
38
  };
39
39
 
40
40
  export { RMSpritesheet };
41
- //# sourceMappingURL=index37.js.map
41
+ //# sourceMappingURL=rmspritesheet.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rmspritesheet.js","sources":["../../src/presets/rmspritesheet.ts"],"sourcesContent":["import { Direction, Animation } from '@rpgjs/common'\n\nexport const RMSpritesheet = (framesWidth: number, framesHeight: number, frameStand: number = 1) => {\n\n if (framesWidth <= frameStand) {\n frameStand = framesWidth - 1\n }\n\n const frameY = direction => {\n const gap = Math.max(4 - framesHeight, 0)\n return {\n [Direction.Down]: 0,\n [Direction.Left]: Math.max(0, 1 - gap),\n [Direction.Right]: Math.max(0, 2 - gap),\n [Direction.Up]: Math.max(0, 3 - gap)\n }[direction]\n }\n\n const stand = (direction: number) => [{ time: 0, frameX: frameStand, frameY: frameY(direction) }]\n const walk = direction => {\n const array: any = []\n const durationFrame = 10\n for (let i = 0; i < framesWidth; i++) {\n array.push({ time: i * durationFrame, frameX: i, frameY: frameY(direction) })\n }\n array.push({ time: array[array.length - 1].time + durationFrame })\n return array\n }\n\n return {\n textures: {\n [Animation.Stand]: {\n animations: ({direction}) => [stand(direction)]\n },\n [Animation.Walk]: {\n animations: ({direction}) => [walk(direction)]\n }\n },\n framesHeight,\n framesWidth\n }\n}"],"names":[],"mappings":";;AAEO,MAAM,aAAA,GAAgB,CAAC,WAAA,EAAqB,YAAA,EAAsB,aAAqB,CAAA,KAAM;AAEhG,EAAA,IAAI,eAAe,UAAA,EAAY;AAC3B,IAAA,UAAA,GAAa,WAAA,GAAc,CAAA;AAAA,EAC/B;AAEA,EAAA,MAAM,SAAS,CAAA,SAAA,KAAa;AACxB,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,GAAA,CAAI,CAAA,GAAI,cAAc,CAAC,CAAA;AACxC,IAAA,OAAO;AAAA,MACH,CAAC,SAAA,CAAU,IAAI,GAAG,CAAA;AAAA,MAClB,CAAC,UAAU,IAAI,GAAG,KAAK,GAAA,CAAI,CAAA,EAAG,IAAI,GAAG,CAAA;AAAA,MACrC,CAAC,UAAU,KAAK,GAAG,KAAK,GAAA,CAAI,CAAA,EAAG,IAAI,GAAG,CAAA;AAAA,MACtC,CAAC,UAAU,EAAE,GAAG,KAAK,GAAA,CAAI,CAAA,EAAG,IAAI,GAAG;AAAA,MACrC,SAAS,CAAA;AAAA,EACf,CAAA;AAEA,EAAA,MAAM,KAAA,GAAQ,CAAC,SAAA,KAAsB,CAAC,EAAE,IAAA,EAAM,CAAA,EAAG,MAAA,EAAQ,UAAA,EAAY,MAAA,EAAQ,MAAA,CAAO,SAAS,GAAG,CAAA;AAChG,EAAA,MAAM,OAAO,CAAA,SAAA,KAAa;AACtB,IAAA,MAAM,QAAa,EAAC;AACpB,IAAA,MAAM,aAAA,GAAgB,EAAA;AACtB,IAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,WAAA,EAAa,CAAA,EAAA,EAAK;AAClC,MAAA,KAAA,CAAM,IAAA,CAAK,EAAE,IAAA,EAAM,CAAA,GAAI,aAAA,EAAe,MAAA,EAAQ,CAAA,EAAG,MAAA,EAAQ,MAAA,CAAO,SAAS,CAAA,EAAG,CAAA;AAAA,IAChF;AACA,IAAA,KAAA,CAAM,IAAA,CAAK,EAAE,IAAA,EAAM,KAAA,CAAM,KAAA,CAAM,SAAS,CAAC,CAAA,CAAE,IAAA,GAAO,aAAA,EAAe,CAAA;AACjE,IAAA,OAAO,KAAA;AAAA,EACX,CAAA;AAEA,EAAA,OAAO;AAAA,IACH,QAAA,EAAU;AAAA,MACN,CAAC,SAAA,CAAU,KAAK,GAAG;AAAA,QACf,UAAA,EAAY,CAAC,EAAC,SAAA,OAAe,CAAC,KAAA,CAAM,SAAS,CAAC;AAAA,OAClD;AAAA,MACA,CAAC,SAAA,CAAU,IAAI,GAAG;AAAA,QACd,UAAA,EAAY,CAAC,EAAC,SAAA,OAAe,CAAC,IAAA,CAAK,SAAS,CAAC;AAAA;AACjD,KACJ;AAAA,IACA,YAAA;AAAA,IACA;AAAA,GACJ;AACJ;;;;"}
@@ -6,4 +6,4 @@ class AbstractWebsocket {
6
6
  }
7
7
 
8
8
  export { AbstractWebsocket, WebSocketToken };
9
- //# sourceMappingURL=index27.js.map
9
+ //# sourceMappingURL=AbstractSocket.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AbstractSocket.js","sources":["../../src/services/AbstractSocket.ts"],"sourcesContent":["import { Context } from \"@signe/di\";\n\nexport const WebSocketToken = \"websocket\";\n\nexport abstract class AbstractWebsocket {\n constructor(protected context: Context) {}\n\n abstract connection(listeners?: (data: any) => void): Promise<void>;\n abstract emit(event: string, data: any): void;\n abstract on(event: string, callback: (data: any) => void): void;\n abstract off(event: string, callback: (data: any) => void): void;\n abstract updateProperties(params: { room: string, host?: string }): void;\n abstract reconnect(listeners?: (data: any) => void): void;\n}\n"],"names":[],"mappings":"AAEO,MAAM,cAAA,GAAiB;AAEvB,MAAe,iBAAA,CAAkB;AAAA,EACtC,YAAsB,OAAA,EAAkB;AAAlB,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AAAA,EAAmB;AAQ3C;;;;"}
@@ -18,4 +18,4 @@ function provideKeyboardControls() {
18
18
  }
19
19
 
20
20
  export { Control, provideKeyboardControls };
21
- //# sourceMappingURL=index21.js.map
21
+ //# sourceMappingURL=keyboardControls.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keyboardControls.js","sources":["../../src/services/keyboardControls.ts"],"sourcesContent":["import { KeyboardControls } from \"canvasengine\";\n\nexport enum Control {\n Action = 'action',\n Attack = 'attack',\n Defense = 'defense',\n Skill = 'skill',\n Back = 'back',\n Up = 1,\n Down = 3,\n Right = 2,\n Left = 4\n}\n\nexport function provideKeyboardControls() {\n return {\n provide: 'KeyboardControls',\n useValue: null,\n };\n}"],"names":["Control"],"mappings":"AAEO,IAAK,OAAA,qBAAAA,QAAAA,KAAL;AACL,EAAAA,SAAA,QAAA,CAAA,GAAS,QAAA;AACT,EAAAA,SAAA,QAAA,CAAA,GAAS,QAAA;AACT,EAAAA,SAAA,SAAA,CAAA,GAAU,SAAA;AACV,EAAAA,SAAA,OAAA,CAAA,GAAQ,OAAA;AACR,EAAAA,SAAA,MAAA,CAAA,GAAO,MAAA;AACP,EAAAA,QAAAA,CAAAA,QAAAA,CAAA,QAAK,CAAA,CAAA,GAAL,IAAA;AACA,EAAAA,QAAAA,CAAAA,QAAAA,CAAA,UAAO,CAAA,CAAA,GAAP,MAAA;AACA,EAAAA,QAAAA,CAAAA,QAAAA,CAAA,WAAQ,CAAA,CAAA,GAAR,OAAA;AACA,EAAAA,QAAAA,CAAAA,QAAAA,CAAA,UAAO,CAAA,CAAA,GAAP,MAAA;AATU,EAAA,OAAAA,QAAAA;AAAA,CAAA,EAAA,OAAA,IAAA,EAAA;AAYL,SAAS,uBAAA,GAA0B;AACxC,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,kBAAA;AAAA,IACT,QAAA,EAAU;AAAA,GACZ;AACF;;;;"}
@@ -1,4 +1,4 @@
1
- import { inject } from './index20.js';
1
+ import { inject } from '../node_modules/.pnpm/@signe_di@2.7.2/node_modules/@signe/di/dist/index.js';
2
2
  import { UpdateMapToken } from '@rpgjs/common';
3
3
 
4
4
  const LoadMapToken = "LoadMapToken";
@@ -36,4 +36,4 @@ function provideLoadMap(options) {
36
36
  }
37
37
 
38
38
  export { LoadMapService, LoadMapToken, provideLoadMap };
39
- //# sourceMappingURL=index7.js.map
39
+ //# sourceMappingURL=loadMap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loadMap.js","sources":["../../src/services/loadMap.ts"],"sourcesContent":["import { Context, inject } from \"@signe/di\";\nimport { UpdateMapToken, UpdateMapService } from \"@rpgjs/common\";\n\nexport const LoadMapToken = 'LoadMapToken'\n\n/**\n * Represents the structure of map data that should be returned by the load map callback.\n * This interface defines all the properties that can be provided when loading a custom map.\n * \n * @interface MapData\n */\ntype MapData = {\n /** Raw map data that will be passed to the map component */\n data: any;\n /** CanvasEngine component that will render the map */\n component: any;\n /** Optional map width in pixels, used for viewport calculations */\n width?: number;\n /** Optional map height in pixels, used for viewport calculations */\n height?: number;\n /** Optional map events data (NPCs, interactive objects, etc.) */\n events?: any;\n /** Optional map identifier, defaults to the mapId parameter if not provided */\n id?: string;\n}\n\n/**\n * Callback function type for loading map data.\n * This function receives a map ID and should return either a MapData object directly\n * or a Promise that resolves to a MapData object.\n * \n * @callback LoadMapOptions\n * @param {string} mapId - The identifier of the map to load\n * @returns {Promise<MapData> | MapData} The map data object or a promise resolving to it\n */\nexport type LoadMapOptions = (mapId: string) => Promise<MapData> | MapData \n\nexport class LoadMapService {\n private updateMapService: UpdateMapService;\n\n constructor(private context: Context, private options: LoadMapOptions) {\n if (context['side'] === 'server') {\n return\n }\n this.updateMapService = inject(context, UpdateMapToken);\n }\n\n async load(mapId: string) {\n const map = await this.options(mapId.replace('map-', ''))\n await this.updateMapService.update(map);\n return map;\n }\n}\n\n/**\n * Creates a dependency injection configuration for custom map loading on the client side.\n * \n * This function allows you to customize how maps are loaded and displayed by providing\n * a callback that defines custom map data and rendering components. It's designed to work\n * with the RPG-JS dependency injection system and enables integration of custom map formats\n * like Tiled TMX files or any other map data structure.\n * \n * The function sets up the necessary service providers for map loading, including:\n * - UpdateMapToken: Handles map updates in the client context\n * - LoadMapToken: Provides the LoadMapService with your custom loading logic\n * \n * **Design Concept:**\n * The function follows the provider pattern, creating a modular way to inject custom\n * map loading behavior into the RPG-JS client engine. It separates the concern of\n * map data fetching from map rendering, allowing developers to focus on their specific\n * map format while leveraging the engine's rendering capabilities.\n * \n * @param {LoadMapOptions} options - Callback function that handles map loading logic\n * @returns {Array<Object>} Array of dependency injection provider configurations\n * \n * @example\n * ```typescript\n * import { provideLoadMap } from '@rpgjs/client'\n * import { createModule } from '@rpgjs/common'\n * import MyTiledMapComponent from './MyTiledMapComponent.ce'\n * \n * // Basic usage with JSON map data\n * export function provideCustomMap() {\n * return createModule(\"CustomMap\", [\n * provideLoadMap(async (mapId) => {\n * const response = await fetch(`/maps/${mapId}.json`)\n * const mapData = await response.json()\n * \n * return {\n * data: mapData,\n * component: MyTiledMapComponent,\n * width: mapData.width,\n * height: mapData.height,\n * events: mapData.events\n * }\n * })\n * ])\n * }\n * \n * // Advanced usage with Tiled TMX files\n * export function provideTiledMap() {\n * return createModule(\"TiledMap\", [\n * provideLoadMap(async (mapId) => {\n * // Load TMX file\n * const tmxResponse = await fetch(`/tiled/${mapId}.tmx`)\n * const tmxData = await tmxResponse.text()\n * \n * // Parse TMX data (using a TMX parser)\n * const parsedMap = parseTMX(tmxData)\n * \n * return {\n * data: parsedMap,\n * component: TiledMapRenderer,\n * width: parsedMap.width * parsedMap.tilewidth,\n * height: parsedMap.height * parsedMap.tileheight,\n * events: parsedMap.objectGroups?.find(g => g.name === 'events')?.objects\n * }\n * })\n * ])\n * }\n * \n * // Synchronous usage for static maps\n * export function provideStaticMap() {\n * return createModule(\"StaticMap\", [\n * provideLoadMap((mapId) => {\n * const staticMaps = {\n * 'town': { tiles: [...], npcs: [...] },\n * 'dungeon': { tiles: [...], monsters: [...] }\n * }\n * \n * return {\n * data: staticMaps[mapId],\n * component: StaticMapComponent,\n * width: 800,\n * height: 600\n * }\n * })\n * ])\n * }\n * ```\n * \n * @since 4.0.0\n * @see {@link LoadMapOptions} for callback function signature\n * @see {@link MapData} for return data structure\n */\nexport function provideLoadMap(options: LoadMapOptions) {\n return [\n {\n provide: UpdateMapToken,\n useFactory: (context: Context) => {\n if (context['side'] === 'client') {\n console.warn('UpdateMapToken is not overridden')\n }\n return\n },\n },\n {\n provide: LoadMapToken,\n useFactory: (context: Context) => new LoadMapService(context, options),\n },\n ];\n}\n"],"names":[],"mappings":";;;AAGO,MAAM,YAAA,GAAe;AAkCrB,MAAM,cAAA,CAAe;AAAA,EAG1B,WAAA,CAAoB,SAA0B,OAAA,EAAyB;AAAnD,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AAA0B,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AAC5C,IAAA,IAAI,OAAA,CAAQ,MAAM,CAAA,KAAM,QAAA,EAAU;AAChC,MAAA;AAAA,IACF;AACA,IAAA,IAAA,CAAK,gBAAA,GAAmB,MAAA,CAAO,OAAA,EAAS,cAAc,CAAA;AAAA,EACxD;AAAA,EAEA,MAAM,KAAK,KAAA,EAAe;AACxB,IAAA,MAAM,GAAA,GAAM,MAAM,IAAA,CAAK,OAAA,CAAQ,MAAM,OAAA,CAAQ,MAAA,EAAQ,EAAE,CAAC,CAAA;AACxD,IAAA,MAAM,IAAA,CAAK,gBAAA,CAAiB,MAAA,CAAO,GAAG,CAAA;AACtC,IAAA,OAAO,GAAA;AAAA,EACT;AACF;AA6FO,SAAS,eAAe,OAAA,EAAyB;AACtD,EAAA,OAAO;AAAA,IACL;AAAA,MACE,OAAA,EAAS,cAAA;AAAA,MACT,UAAA,EAAY,CAAC,OAAA,KAAqB;AAChC,QAAA,IAAI,OAAA,CAAQ,MAAM,CAAA,KAAM,QAAA,EAAU;AAChC,UAAA,OAAA,CAAQ,KAAK,kCAAkC,CAAA;AAAA,QACjD;AACA,QAAA;AAAA,MACF;AAAA,KACF;AAAA,IACA;AAAA,MACE,OAAA,EAAS,YAAA;AAAA,MACT,YAAY,CAAC,OAAA,KAAqB,IAAI,cAAA,CAAe,SAAS,OAAO;AAAA;AACvE,GACF;AACF;;;;"}
@@ -1,9 +1,9 @@
1
- import { connectionRoom } from './index32.js';
2
- import { RpgGui } from './index9.js';
3
- import { RpgClientEngine } from './index2.js';
4
- import { WebSocketToken, AbstractWebsocket } from './index27.js';
1
+ import { connectionRoom } from '../node_modules/.pnpm/@signe_sync@2.7.2/node_modules/@signe/sync/dist/client/index.js';
2
+ import { RpgGui } from '../Gui/Gui.js';
3
+ import { RpgClientEngine } from '../RpgClientEngine.js';
4
+ import { WebSocketToken, AbstractWebsocket } from './AbstractSocket.js';
5
5
  import { UpdateMapToken, UpdateMapService } from '@rpgjs/common';
6
- import { provideKeyboardControls } from './index21.js';
6
+ import { provideKeyboardControls } from './keyboardControls.js';
7
7
 
8
8
  class BridgeWebsocket extends AbstractWebsocket {
9
9
  constructor(context, options = {}) {
@@ -71,4 +71,4 @@ function provideMmorpg(options) {
71
71
  }
72
72
 
73
73
  export { provideMmorpg };
74
- //# sourceMappingURL=index4.js.map
74
+ //# sourceMappingURL=mmorpg.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mmorpg.js","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, WebSocketToken } from \"./AbstractSocket\";\nimport { UpdateMapService, UpdateMapToken } from \"@rpgjs/common\";\nimport { provideKeyboardControls } from \"./keyboardControls\";\n\ninterface MmorpgOptions {\n host?: string;\n}\n\nclass BridgeWebsocket extends AbstractWebsocket {\n private socket: any;\n private privateId: string;\n\n constructor(protected context: Context, private options: MmorpgOptions = {}) {\n super(context);\n const id = localStorage.getItem(\"rpgjs-user-id\") || crypto.randomUUID()\n localStorage.setItem(\"rpgjs-user-id\", id)\n this.privateId = id\n }\n\n async connection(listeners?: (data: any) => void) {\n // tmp\n class Room {\n \n }\n const instance = new Room()\n this.socket = await connectionRoom({\n host: this.options.host || window.location.host,\n room: \"lobby-1\",\n id: this.privateId\n }, instance)\n\n listeners?.(this.socket)\n }\n\n on(key: string, callback: (data: any) => void) {\n this.socket.on(key, callback);\n }\n\n off(event: string, callback: (data: any) => void) {\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 }: { room: any }) {\n this.socket.conn.updateProperties({\n room: room,\n id: this.privateId,\n host: this.options.host\n })\n }\n\n async reconnect(listeners?: (data: any) => void) {\n this.socket.conn.reconnect()\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 // nothing\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 RpgGui,\n RpgClientEngine,\n ];\n}\n"],"names":[],"mappings":";;;;;;;AAYA,MAAM,wBAAwB,iBAAA,CAAkB;AAAA,EAI9C,WAAA,CAAsB,OAAA,EAA0B,OAAA,GAAyB,EAAC,EAAG;AAC3E,IAAA,KAAA,CAAM,OAAO,CAAA;AADO,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AAA0B,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AAE9C,IAAA,MAAM,KAAK,YAAA,CAAa,OAAA,CAAQ,eAAe,CAAA,IAAK,OAAO,UAAA,EAAW;AACtE,IAAA,YAAA,CAAa,OAAA,CAAQ,iBAAiB,EAAE,CAAA;AACxC,IAAA,IAAA,CAAK,SAAA,GAAY,EAAA;AAAA,EACnB;AAAA,EAEA,MAAM,WAAW,SAAA,EAAiC;AAAA,IAEhD,MAAM,IAAA,CAAK;AAAA;AAGX,IAAA,MAAM,QAAA,GAAW,IAAI,IAAA,EAAK;AAC1B,IAAA,IAAA,CAAK,MAAA,GAAS,MAAM,cAAA,CAAe;AAAA,MAC/B,IAAA,EAAM,IAAA,CAAK,OAAA,CAAQ,IAAA,IAAQ,OAAO,QAAA,CAAS,IAAA;AAAA,MAC3C,IAAA,EAAM,SAAA;AAAA,MACN,IAAI,IAAA,CAAK;AAAA,OACV,QAAQ,CAAA;AAEX,IAAA,SAAA,GAAY,KAAK,MAAM,CAAA;AAAA,EACzB;AAAA,EAEA,EAAA,CAAG,KAAa,QAAA,EAA+B;AAC7C,IAAA,IAAA,CAAK,MAAA,CAAO,EAAA,CAAG,GAAA,EAAK,QAAQ,CAAA;AAAA,EAC9B;AAAA,EAEA,GAAA,CAAI,OAAe,QAAA,EAA+B;AAChD,IAAA,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,KAAA,EAAO,QAAQ,CAAA;AAAA,EACjC;AAAA,EAEA,IAAA,CAAK,OAAe,IAAA,EAAW;AAC7B,IAAA,IAAA,CAAK,MAAA,CAAO,IAAA,CAAK,KAAA,EAAO,IAAI,CAAA;AAAA,EAC9B;AAAA,EAEA,gBAAA,CAAiB,EAAE,IAAA,EAAK,EAAkB;AACxC,IAAA,IAAA,CAAK,MAAA,CAAO,KAAK,gBAAA,CAAiB;AAAA,MAChC,IAAA;AAAA,MACA,IAAI,IAAA,CAAK,SAAA;AAAA,MACT,IAAA,EAAM,KAAK,OAAA,CAAQ;AAAA,KACpB,CAAA;AAAA,EACH;AAAA,EAEA,MAAM,UAAU,SAAA,EAAiC;AAChD,IAAA,IAAA,CAAK,MAAA,CAAO,KAAK,SAAA,EAAU;AAAA,EAC5B;AACF;AAEA,MAAM,mCAAmC,gBAAA,CAAiB;AAAA,EACxD,WAAA,CAAsB,SAA0B,OAAA,EAAwB;AACtE,IAAA,KAAA,CAAM,OAAO,CAAA;AADO,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AAA0B,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AAAA,EAEhD;AAAA,EAEA,MAAM,OAAO,GAAA,EAAU;AAAA,EAEvB;AACF;AAEO,SAAS,cAAc,OAAA,EAAwB;AACpD,EAAA,OAAO;AAAA,IACL;AAAA,MACE,OAAA,EAAS,cAAA;AAAA,MACT,YAAY,CAAC,OAAA,KAAqB,IAAI,eAAA,CAAgB,SAAS,OAAO;AAAA,KACxE;AAAA,IACA;AAAA,MACE,OAAA,EAAS,cAAA;AAAA,MACT,YAAY,CAAC,OAAA,KAAqB,IAAI,0BAAA,CAA2B,SAAS,OAAO;AAAA,KACnF;AAAA,IACA,uBAAA,EAAwB;AAAA,IACxB,MAAA;AAAA,IACA;AAAA,GACF;AACF;;;;"}
@@ -3,13 +3,17 @@ import { Context } from '@signe/di';
3
3
  import { RpgClientEngine } from '../RpgClientEngine';
4
4
  import { UpdateMapService } from '@rpgjs/common';
5
5
  import { RpgGui } from '../Gui/Gui';
6
+ interface StandaloneOptions {
7
+ env?: Record<string, any>;
8
+ }
6
9
  declare class BridgeWebsocket extends AbstractWebsocket {
7
10
  protected context: Context;
8
11
  private server;
9
12
  private room;
10
13
  private socket;
11
14
  private rooms;
12
- constructor(context: Context, server: any);
15
+ private serverInstance;
16
+ constructor(context: Context, server: any, options?: StandaloneOptions);
13
17
  connection(listeners?: (data: any) => void): Promise<any>;
14
18
  private _connection;
15
19
  on(key: string, callback: (data: any) => void): void;
@@ -52,6 +56,8 @@ declare class BridgeWebsocket extends AbstractWebsocket {
52
56
  * ```
53
57
  */
54
58
  reconnect(listeners?: (data: any) => void): Promise<void>;
59
+ getServer(): any;
60
+ getSocket(): any;
55
61
  }
56
62
  declare class UpdateMapStandaloneService extends UpdateMapService {
57
63
  private server;
@@ -71,7 +77,7 @@ declare class UpdateMapStandaloneService extends UpdateMapService {
71
77
  */
72
78
  update(map: any): Promise<void>;
73
79
  }
74
- export declare function provideRpg(server: any): (typeof RpgClientEngine | typeof RpgGui | {
80
+ export declare function provideRpg(server: any, options?: StandaloneOptions): (typeof RpgClientEngine | typeof RpgGui | {
75
81
  provide: string;
76
82
  useValue: null;
77
83
  } | {
@@ -1,12 +1,12 @@
1
- import { WebSocketToken, AbstractWebsocket } from './index27.js';
2
- import { ServerIo, ClientIo } from './index31.js';
3
- import { RpgClientEngine } from './index2.js';
1
+ import { WebSocketToken, AbstractWebsocket } from './AbstractSocket.js';
2
+ import { ServerIo, ClientIo } from '../node_modules/.pnpm/@signe_room@2.7.2/node_modules/@signe/room/dist/index.js';
3
+ import { RpgClientEngine } from '../RpgClientEngine.js';
4
4
  import { UpdateMapToken, UpdateMapService } from '@rpgjs/common';
5
- import { RpgGui } from './index9.js';
6
- import { provideKeyboardControls } from './index21.js';
5
+ import { RpgGui } from '../Gui/Gui.js';
6
+ import { provideKeyboardControls } from './keyboardControls.js';
7
7
 
8
8
  class BridgeWebsocket extends AbstractWebsocket {
9
- constructor(context, server) {
9
+ constructor(context, server, options = {}) {
10
10
  super(context);
11
11
  this.context = context;
12
12
  this.server = server;
@@ -17,19 +17,21 @@ class BridgeWebsocket extends AbstractWebsocket {
17
17
  await server.onStart();
18
18
  this.context.set("server", server);
19
19
  return server;
20
- }
20
+ },
21
+ env: {}
21
22
  };
23
+ this.rooms.env = options.env || {};
22
24
  this.room = new ServerIo("lobby-1", this.rooms);
23
25
  }
24
26
  async connection(listeners) {
25
- const server = new this.server(this.room);
26
- await server.onStart();
27
- this.context.set("server", server);
27
+ this.serverInstance = new this.server(this.room);
28
+ await this.serverInstance.onStart();
29
+ this.context.set("server", this.serverInstance);
28
30
  return this._connection(listeners);
29
31
  }
30
32
  async _connection(listeners) {
31
- const server = this.context.get("server");
32
- this.socket = new ClientIo(server, "player-client-id");
33
+ this.serverInstance = this.context.get("server");
34
+ this.socket = new ClientIo(this.serverInstance, "player-client-id");
33
35
  const url = new URL("http://localhost");
34
36
  const request = new Request(url.toString(), {
35
37
  method: "GET",
@@ -38,7 +40,7 @@ class BridgeWebsocket extends AbstractWebsocket {
38
40
  }
39
41
  });
40
42
  listeners?.(this.socket);
41
- await server.onConnect(this.socket.conn, { request });
43
+ await this.serverInstance.onConnect(this.socket.conn, { request });
42
44
  this.room.clients.set(this.socket.id, this.socket);
43
45
  return this.socket;
44
46
  }
@@ -99,6 +101,12 @@ class BridgeWebsocket extends AbstractWebsocket {
99
101
  listeners?.(socket);
100
102
  });
101
103
  }
104
+ getServer() {
105
+ return this.serverInstance;
106
+ }
107
+ getSocket() {
108
+ return this.socket;
109
+ }
102
110
  }
103
111
  class UpdateMapStandaloneService extends UpdateMapService {
104
112
  /**
@@ -129,11 +137,11 @@ class UpdateMapStandaloneService extends UpdateMapService {
129
137
  await this.server.onRequest(req);
130
138
  }
131
139
  }
132
- function provideRpg(server) {
140
+ function provideRpg(server, options = {}) {
133
141
  return [
134
142
  {
135
143
  provide: WebSocketToken,
136
- useFactory: (context) => new BridgeWebsocket(context, server)
144
+ useFactory: (context) => new BridgeWebsocket(context, server, options)
137
145
  },
138
146
  {
139
147
  provide: UpdateMapToken,
@@ -146,4 +154,4 @@ function provideRpg(server) {
146
154
  }
147
155
 
148
156
  export { provideRpg };
149
- //# sourceMappingURL=index3.js.map
157
+ //# sourceMappingURL=standalone.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"standalone.js","sources":["../../src/services/standalone.ts"],"sourcesContent":["import { AbstractWebsocket, 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\";\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 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 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 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 return this.socket\n }\n\n on(key: string, callback: (data: any) => void) {\n this.socket.addEventListener(\"message\", (event) => {\n const object = JSON.parse(event);\n if (object.type === key) {\n callback(object.value);\n }\n });\n }\n\n off(event: string, callback: (data: any) => void) {\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({ room }: { room: any }) {\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) {\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 RpgGui,\n RpgClientEngine,\n ];\n}"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rpgjs/client",
3
- "version": "5.0.0-alpha.24",
3
+ "version": "5.0.0-alpha.26",
4
4
  "description": "RPGJS is a framework for creating RPG/MMORPG games",
5
5
  "main": "dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -22,17 +22,17 @@
22
22
  "pixi.js": "^8.9.2"
23
23
  },
24
24
  "dependencies": {
25
- "@rpgjs/client": "5.0.0-alpha.24",
26
- "@rpgjs/common": "5.0.0-alpha.24",
27
- "@rpgjs/server": "5.0.0-alpha.24",
28
- "@signe/di": "^2.6.0",
29
- "@signe/room": "^2.6.0",
30
- "@signe/sync": "^2.6.0",
25
+ "@rpgjs/client": "5.0.0-alpha.26",
26
+ "@rpgjs/common": "5.0.0-alpha.26",
27
+ "@rpgjs/server": "5.0.0-alpha.26",
28
+ "@signe/di": "^2.7.2",
29
+ "@signe/room": "^2.7.2",
30
+ "@signe/sync": "^2.7.2",
31
31
  "pixi-filters": "^6.1.5",
32
32
  "rxjs": "^7.8.2"
33
33
  },
34
34
  "devDependencies": {
35
- "@canvasengine/compiler": "2.0.0-beta.40",
35
+ "@canvasengine/compiler": "2.0.0-beta.41",
36
36
  "vite": "^7.2.7",
37
37
  "vite-plugin-dts": "^4.5.4",
38
38
  "vitest": "^4.0.15"
@@ -45,6 +45,8 @@ export class RpgClientEngine<T = any> {
45
45
  }
46
46
  renderer: PIXI.Renderer;
47
47
  tick: Observable<number>;
48
+ private canvasApp?: any;
49
+ private canvasElement?: any;
48
50
  playerIdSignal = signal<string | null>(null);
49
51
  spriteComponentsBehind = signal<any[]>([]);
50
52
  spriteComponentsInFront = signal<any[]>([]);
@@ -71,6 +73,10 @@ export class RpgClientEngine<T = any> {
71
73
  private playersReceived$ = new BehaviorSubject<boolean>(false);
72
74
  private eventsReceived$ = new BehaviorSubject<boolean>(false);
73
75
  private onAfterLoadingSubscription?: any;
76
+
77
+ // Store subscriptions and event listeners for cleanup
78
+ private tickSubscriptions: any[] = [];
79
+ private resizeHandler?: () => void;
74
80
 
75
81
  constructor(public context) {
76
82
  this.webSocket = inject(WebSocketToken);
@@ -140,7 +146,7 @@ export class RpgClientEngine<T = any> {
140
146
  ...currentValues,
141
147
  values: new Map([['__default__', controlInstance]])
142
148
  }
143
- this.controlsReady.set(true);
149
+ this.controlsReady.set(undefined);
144
150
  }
145
151
 
146
152
  async start() {
@@ -148,16 +154,19 @@ export class RpgClientEngine<T = any> {
148
154
  this.selector = document.body.querySelector("#rpg") as HTMLElement;
149
155
 
150
156
  const { app, canvasElement } = await bootstrapCanvas(this.selector, Canvas);
157
+ this.canvasApp = app;
158
+ this.canvasElement = canvasElement;
151
159
  this.renderer = app.renderer as PIXI.Renderer;
152
160
  this.tick = canvasElement?.propObservables?.context['tick'].observable
153
161
 
154
- this.tick.subscribe(() => {
162
+ const inputCheckSubscription = this.tick.subscribe(() => {
155
163
  if (Date.now() - this.lastInputTime > 100) {
156
164
  const player = this.getCurrentPlayer();
157
165
  if (!player) return;
158
166
  (this.sceneMap as any).stopMovement(player);
159
167
  }
160
- })
168
+ });
169
+ this.tickSubscriptions.push(inputCheckSubscription);
161
170
 
162
171
 
163
172
  this.hooks.callHooks("client-spritesheets-load", this).subscribe();
@@ -175,11 +184,12 @@ export class RpgClientEngine<T = any> {
175
184
  await lastValueFrom(this.hooks.callHooks("client-engine-onStart", this));
176
185
 
177
186
  // wondow is resize
178
- window.addEventListener('resize', () => {
187
+ this.resizeHandler = () => {
179
188
  this.hooks.callHooks("client-engine-onWindowResize", this).subscribe();
180
- })
189
+ };
190
+ window.addEventListener('resize', this.resizeHandler);
181
191
 
182
- this.tick.subscribe((tick) => {
192
+ const tickSubscription = this.tick.subscribe((tick) => {
183
193
  this.hooks.callHooks("client-engine-onStep", this, tick).subscribe();
184
194
 
185
195
  // Clean up old prediction states and input history every 60 ticks (approximately every second at 60fps)
@@ -188,7 +198,8 @@ export class RpgClientEngine<T = any> {
188
198
  this.prediction?.cleanup(now);
189
199
  this.prediction?.tryApplyPendingSnapshot();
190
200
  }
191
- })
201
+ });
202
+ this.tickSubscriptions.push(tickSubscription);
192
203
 
193
204
  await this.webSocket.connection(() => {
194
205
  this.initListeners()
@@ -1294,4 +1305,179 @@ export class RpgClientEngine<T = any> {
1294
1305
  private async replayUnackedInputsFromFrame(_startFrame: number): Promise<void> {
1295
1306
  // Prediction controller handles replay internally. Kept for backwards compatibility.
1296
1307
  }
1308
+
1309
+ /**
1310
+ * Clear all client resources and reset state
1311
+ *
1312
+ * This method should be called to clean up all client-side resources when
1313
+ * shutting down or resetting the client engine. It:
1314
+ * - Destroys the PIXI renderer
1315
+ * - Stops all sounds
1316
+ * - Cleans up subscriptions and event listeners
1317
+ * - Resets scene map
1318
+ * - Stops ping/pong interval
1319
+ * - Clears prediction states
1320
+ *
1321
+ * ## Design
1322
+ *
1323
+ * This method is used primarily in testing environments to ensure clean
1324
+ * state between tests. In production, the client engine typically persists
1325
+ * for the lifetime of the application.
1326
+ *
1327
+ * @example
1328
+ * ```ts
1329
+ * // In test cleanup
1330
+ * afterEach(() => {
1331
+ * clientEngine.clear();
1332
+ * });
1333
+ * ```
1334
+ */
1335
+ clear(): void {
1336
+ try {
1337
+ // First, unsubscribe from all tick subscriptions to stop rendering attempts
1338
+ for (const subscription of this.tickSubscriptions) {
1339
+ if (subscription && typeof subscription.unsubscribe === 'function') {
1340
+ subscription.unsubscribe();
1341
+ }
1342
+ }
1343
+ this.tickSubscriptions = [];
1344
+
1345
+ // Stop ping/pong interval
1346
+ if (this.pingInterval) {
1347
+ clearInterval(this.pingInterval);
1348
+ this.pingInterval = null;
1349
+ }
1350
+
1351
+ // Clean up onAfterLoading subscription
1352
+ if (this.onAfterLoadingSubscription && typeof this.onAfterLoadingSubscription.unsubscribe === 'function') {
1353
+ this.onAfterLoadingSubscription.unsubscribe();
1354
+ this.onAfterLoadingSubscription = undefined;
1355
+ }
1356
+
1357
+ // Clean up canvasElement (CanvasEngine) BEFORE destroying PIXI app
1358
+ // This prevents CanvasEngine from trying to render after PIXI is destroyed
1359
+ // CanvasEngine manages its own render loop which could try to access PIXI after destruction
1360
+ if (this.canvasElement) {
1361
+ try {
1362
+ // Try to stop or cleanup canvasElement if it has cleanup methods
1363
+ if (typeof (this.canvasElement as any).destroy === 'function') {
1364
+ (this.canvasElement as any).destroy();
1365
+ }
1366
+ // Clear the reference
1367
+ this.canvasElement = undefined;
1368
+ } catch (error) {
1369
+ // Ignore errors during canvasElement cleanup
1370
+ }
1371
+ }
1372
+
1373
+ // Reset scene map if it exists (this should stop any ongoing animations/renders)
1374
+ if (this.sceneMap && typeof (this.sceneMap as any).reset === 'function') {
1375
+ (this.sceneMap as any).reset();
1376
+ }
1377
+
1378
+ // Stop all sounds
1379
+ this.stopAllSounds();
1380
+
1381
+ // Remove resize event listener
1382
+ if (this.resizeHandler && typeof window !== 'undefined') {
1383
+ window.removeEventListener('resize', this.resizeHandler);
1384
+ this.resizeHandler = undefined;
1385
+ }
1386
+
1387
+ // Destroy PIXI app and renderer if they exist
1388
+ // Destroy the app first, which will destroy the renderer
1389
+ // Store renderer reference before destroying app (since app.destroy() will destroy the renderer)
1390
+ const rendererStillExists = this.renderer && typeof this.renderer.destroy === 'function';
1391
+
1392
+ if (this.canvasApp && typeof this.canvasApp.destroy === 'function') {
1393
+ try {
1394
+ // Stop the ticker first to prevent any render calls during destruction
1395
+ if (this.canvasApp.ticker) {
1396
+ if (typeof this.canvasApp.ticker.stop === 'function') {
1397
+ this.canvasApp.ticker.stop();
1398
+ }
1399
+ // Also remove all listeners from ticker to prevent callbacks
1400
+ if (typeof this.canvasApp.ticker.removeAll === 'function') {
1401
+ this.canvasApp.ticker.removeAll();
1402
+ }
1403
+ }
1404
+
1405
+ // Stop the renderer's ticker if it exists separately
1406
+ if (this.renderer && (this.renderer as any).ticker) {
1407
+ if (typeof (this.renderer as any).ticker.stop === 'function') {
1408
+ (this.renderer as any).ticker.stop();
1409
+ }
1410
+ if (typeof (this.renderer as any).ticker.removeAll === 'function') {
1411
+ (this.renderer as any).ticker.removeAll();
1412
+ }
1413
+ }
1414
+
1415
+ // Remove the canvas from DOM before destroying to prevent render attempts
1416
+ if (this.canvasApp.canvas && this.canvasApp.canvas.parentNode) {
1417
+ this.canvasApp.canvas.parentNode.removeChild(this.canvasApp.canvas);
1418
+ }
1419
+
1420
+ // Destroy with minimal options to avoid issues
1421
+ // Don't pass options that might trigger additional cleanup that could fail
1422
+ this.canvasApp.destroy(true);
1423
+ } catch (error) {
1424
+ // Ignore errors during destruction
1425
+ }
1426
+ this.canvasApp = undefined;
1427
+ // canvasApp.destroy() already destroyed the renderer, so just null it
1428
+ this.renderer = null as any;
1429
+ } else if (rendererStillExists) {
1430
+ // Fallback: destroy renderer directly only if app doesn't exist or wasn't destroyed
1431
+ try {
1432
+ // Stop the renderer's ticker if it has one
1433
+ if ((this.renderer as any).ticker) {
1434
+ if (typeof (this.renderer as any).ticker.stop === 'function') {
1435
+ (this.renderer as any).ticker.stop();
1436
+ }
1437
+ if (typeof (this.renderer as any).ticker.removeAll === 'function') {
1438
+ (this.renderer as any).ticker.removeAll();
1439
+ }
1440
+ }
1441
+
1442
+ this.renderer.destroy(true);
1443
+ } catch (error) {
1444
+ // Ignore errors during destruction
1445
+ }
1446
+ this.renderer = null as any;
1447
+ }
1448
+
1449
+ // Clean up prediction controller
1450
+ if (this.prediction) {
1451
+ // Prediction controller cleanup is handled internally when destroyed
1452
+ this.prediction = undefined;
1453
+ }
1454
+
1455
+ // Reset signals
1456
+ this.playerIdSignal.set(null);
1457
+ this.cameraFollowTargetId.set(null);
1458
+ this.spriteComponentsBehind.set([]);
1459
+ this.spriteComponentsInFront.set([]);
1460
+
1461
+ // Clear maps and arrays
1462
+ this.spritesheets.clear();
1463
+ this.sounds.clear();
1464
+ this.componentAnimations = [];
1465
+ this.particleSettings.emitters = [];
1466
+
1467
+ // Reset state
1468
+ this.stopProcessingInput = false;
1469
+ this.lastInputTime = 0;
1470
+ this.inputFrameCounter = 0;
1471
+ this.frameOffset = 0;
1472
+ this.rtt = 0;
1473
+
1474
+ // Reset behavior subjects
1475
+ this.mapLoadCompleted$.next(false);
1476
+ this.playerIdReceived$.next(false);
1477
+ this.playersReceived$.next(false);
1478
+ this.eventsReceived$.next(false);
1479
+ } catch (error) {
1480
+ console.warn('Error during client engine cleanup:', error);
1481
+ }
1482
+ }
1297
1483
  }
@@ -20,15 +20,15 @@
20
20
 
21
21
  const engine = inject(RpgClientEngine);
22
22
  const componentAnimations = engine.componentAnimations
23
- const map = engine.sceneMap.data
23
+ const map = engine.sceneMap?.data
24
24
  const sceneComponent = computed(() => map()?.component)
25
25
  const sceneParams = map()?.params
26
- const mapParams = map().params
26
+ const mapParams = map()?.params
27
27
  const animations = engine.sceneMap.animations
28
28
  const backgroundMusic = { src: mapParams?.backgroundMusic, autoplay: true, loop: true }
29
29
  const backgroundAmbientSound = { src: mapParams?.backgroundAmbientSound, autoplay: true, loop: true }
30
30
 
31
- const data = signal(map().data)
31
+ const data = signal(map()?.data)
32
32
 
33
33
  const scale = mapParams?.scale || 1
34
34
  const worldWidth = (mapParams?.width || 2048) * scale
package/src/index.ts CHANGED
@@ -21,4 +21,5 @@ export { Control } from "./services/keyboardControls";
21
21
  export { RpgClientObject } from "./Game/Object";
22
22
  export { RpgClientPlayer } from "./Game/Player";
23
23
  export { RpgClientEvent } from "./Game/Event";
24
- export { withMobile } from "./components/gui/mobile";
24
+ export { withMobile } from "./components/gui/mobile";
25
+ export * from "./services/AbstractSocket";