@rpgjs/client 5.0.0-alpha.43 → 5.0.0-alpha.44

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 (137) hide show
  1. package/dist/Game/AnimationManager.js +25 -24
  2. package/dist/Game/AnimationManager.js.map +1 -1
  3. package/dist/Game/Event.js +11 -10
  4. package/dist/Game/Event.js.map +1 -1
  5. package/dist/Game/Map.js +78 -94
  6. package/dist/Game/Map.js.map +1 -1
  7. package/dist/Game/Object.js +182 -216
  8. package/dist/Game/Object.js.map +1 -1
  9. package/dist/Game/Player.js +11 -10
  10. package/dist/Game/Player.js.map +1 -1
  11. package/dist/Gui/Gui.js +440 -473
  12. package/dist/Gui/Gui.js.map +1 -1
  13. package/dist/Gui/NotificationManager.js +48 -50
  14. package/dist/Gui/NotificationManager.js.map +1 -1
  15. package/dist/Resource.js +132 -113
  16. package/dist/Resource.js.map +1 -1
  17. package/dist/RpgClientEngine.js +1333 -1486
  18. package/dist/RpgClientEngine.js.map +1 -1
  19. package/dist/Sound.js +162 -92
  20. package/dist/Sound.js.map +1 -1
  21. package/dist/_virtual/_@oxc-project_runtime@0.115.0/helpers/decorate.js +9 -0
  22. package/dist/_virtual/_@oxc-project_runtime@0.115.0/helpers/decorateMetadata.js +6 -0
  23. package/dist/components/animations/animation.ce.js +22 -19
  24. package/dist/components/animations/animation.ce.js.map +1 -1
  25. package/dist/components/animations/hit.ce.js +67 -68
  26. package/dist/components/animations/hit.ce.js.map +1 -1
  27. package/dist/components/animations/index.js +9 -8
  28. package/dist/components/animations/index.js.map +1 -1
  29. package/dist/components/character.ce.js +390 -314
  30. package/dist/components/character.ce.js.map +1 -1
  31. package/dist/components/dynamics/parse-value.js +42 -52
  32. package/dist/components/dynamics/parse-value.js.map +1 -1
  33. package/dist/components/dynamics/text.ce.js +71 -139
  34. package/dist/components/dynamics/text.ce.js.map +1 -1
  35. package/dist/components/gui/box.ce.js +26 -25
  36. package/dist/components/gui/box.ce.js.map +1 -1
  37. package/dist/components/gui/dialogbox/index.ce.js +202 -149
  38. package/dist/components/gui/dialogbox/index.ce.js.map +1 -1
  39. package/dist/components/gui/gameover.ce.js +190 -138
  40. package/dist/components/gui/gameover.ce.js.map +1 -1
  41. package/dist/components/gui/hud/hud.ce.js +90 -33
  42. package/dist/components/gui/hud/hud.ce.js.map +1 -1
  43. package/dist/components/gui/index.js +14 -0
  44. package/dist/components/gui/menu/equip-menu.ce.js +478 -346
  45. package/dist/components/gui/menu/equip-menu.ce.js.map +1 -1
  46. package/dist/components/gui/menu/exit-menu.ce.js +52 -33
  47. package/dist/components/gui/menu/exit-menu.ce.js.map +1 -1
  48. package/dist/components/gui/menu/items-menu.ce.js +341 -226
  49. package/dist/components/gui/menu/items-menu.ce.js.map +1 -1
  50. package/dist/components/gui/menu/main-menu.ce.js +414 -205
  51. package/dist/components/gui/menu/main-menu.ce.js.map +1 -1
  52. package/dist/components/gui/menu/options-menu.ce.js +46 -26
  53. package/dist/components/gui/menu/options-menu.ce.js.map +1 -1
  54. package/dist/components/gui/menu/skills-menu.ce.js +104 -50
  55. package/dist/components/gui/menu/skills-menu.ce.js.map +1 -1
  56. package/dist/components/gui/mobile/index.js +18 -21
  57. package/dist/components/gui/mobile/index.js.map +1 -1
  58. package/dist/components/gui/mobile/mobile.ce.js +76 -15
  59. package/dist/components/gui/mobile/mobile.ce.js.map +1 -1
  60. package/dist/components/gui/notification/notification.ce.js +62 -36
  61. package/dist/components/gui/notification/notification.ce.js.map +1 -1
  62. package/dist/components/gui/save-load.ce.js +386 -239
  63. package/dist/components/gui/save-load.ce.js.map +1 -1
  64. package/dist/components/gui/shop/shop.ce.js +649 -319
  65. package/dist/components/gui/shop/shop.ce.js.map +1 -1
  66. package/dist/components/gui/title-screen.ce.js +187 -145
  67. package/dist/components/gui/title-screen.ce.js.map +1 -1
  68. package/dist/components/index.js +4 -0
  69. package/dist/components/prebuilt/hp-bar.ce.js +114 -104
  70. package/dist/components/prebuilt/hp-bar.ce.js.map +1 -1
  71. package/dist/components/prebuilt/index.js +2 -0
  72. package/dist/components/prebuilt/light-halo.ce.js +92 -74
  73. package/dist/components/prebuilt/light-halo.ce.js.map +1 -1
  74. package/dist/components/scenes/canvas.ce.js +58 -42
  75. package/dist/components/scenes/canvas.ce.js.map +1 -1
  76. package/dist/components/scenes/draw-map.ce.js +87 -64
  77. package/dist/components/scenes/draw-map.ce.js.map +1 -1
  78. package/dist/components/scenes/event-layer.ce.js +26 -16
  79. package/dist/components/scenes/event-layer.ce.js.map +1 -1
  80. package/dist/core/inject.js +11 -10
  81. package/dist/core/inject.js.map +1 -1
  82. package/dist/core/setup.js +13 -13
  83. package/dist/core/setup.js.map +1 -1
  84. package/dist/index.js +44 -41
  85. package/dist/module.js +169 -168
  86. package/dist/module.js.map +1 -1
  87. package/dist/node_modules/.pnpm/@signe_di@2.8.3/node_modules/@signe/di/dist/index.js +209 -298
  88. package/dist/node_modules/.pnpm/@signe_di@2.8.3/node_modules/@signe/di/dist/index.js.map +1 -1
  89. package/dist/node_modules/.pnpm/@signe_reactive@2.8.3/node_modules/@signe/reactive/dist/index.js +430 -507
  90. package/dist/node_modules/.pnpm/@signe_reactive@2.8.3/node_modules/@signe/reactive/dist/index.js.map +1 -1
  91. package/dist/node_modules/.pnpm/@signe_room@2.8.3/node_modules/@signe/room/dist/index.js +2062 -2571
  92. package/dist/node_modules/.pnpm/@signe_room@2.8.3/node_modules/@signe/room/dist/index.js.map +1 -1
  93. package/dist/node_modules/.pnpm/@signe_sync@2.8.3/node_modules/@signe/sync/dist/chunk-7QVYU63E.js +8 -3
  94. package/dist/node_modules/.pnpm/@signe_sync@2.8.3/node_modules/@signe/sync/dist/chunk-7QVYU63E.js.map +1 -1
  95. package/dist/node_modules/.pnpm/@signe_sync@2.8.3/node_modules/@signe/sync/dist/client/index.js +78 -101
  96. package/dist/node_modules/.pnpm/@signe_sync@2.8.3/node_modules/@signe/sync/dist/client/index.js.map +1 -1
  97. package/dist/node_modules/.pnpm/@signe_sync@2.8.3/node_modules/@signe/sync/dist/index.js +264 -401
  98. package/dist/node_modules/.pnpm/@signe_sync@2.8.3/node_modules/@signe/sync/dist/index.js.map +1 -1
  99. package/dist/node_modules/.pnpm/dset@3.1.4/node_modules/dset/dist/index.js +9 -7
  100. package/dist/node_modules/.pnpm/dset@3.1.4/node_modules/dset/dist/index.js.map +1 -1
  101. package/dist/node_modules/.pnpm/partysocket@1.1.3/node_modules/partysocket/dist/chunk-HAC622V3.js +106 -165
  102. package/dist/node_modules/.pnpm/partysocket@1.1.3/node_modules/partysocket/dist/chunk-HAC622V3.js.map +1 -1
  103. package/dist/node_modules/.pnpm/partysocket@1.1.3/node_modules/partysocket/dist/chunk-S74YV6PU.js +361 -461
  104. package/dist/node_modules/.pnpm/partysocket@1.1.3/node_modules/partysocket/dist/chunk-S74YV6PU.js.map +1 -1
  105. package/dist/node_modules/.pnpm/partysocket@1.1.3/node_modules/partysocket/dist/index.js +2 -0
  106. package/dist/node_modules/.pnpm/zod@3.24.2/node_modules/zod/lib/index.js +3633 -4280
  107. package/dist/node_modules/.pnpm/zod@3.24.2/node_modules/zod/lib/index.js.map +1 -1
  108. package/dist/presets/animation.js +37 -25
  109. package/dist/presets/animation.js.map +1 -1
  110. package/dist/presets/faceset.js +49 -22
  111. package/dist/presets/faceset.js.map +1 -1
  112. package/dist/presets/icon.js +13 -13
  113. package/dist/presets/icon.js.map +1 -1
  114. package/dist/presets/index.js +15 -14
  115. package/dist/presets/index.js.map +1 -1
  116. package/dist/presets/lpc.js +96 -93
  117. package/dist/presets/lpc.js.map +1 -1
  118. package/dist/presets/rmspritesheet.js +40 -39
  119. package/dist/presets/rmspritesheet.js.map +1 -1
  120. package/dist/services/AbstractSocket.js +10 -8
  121. package/dist/services/AbstractSocket.js.map +1 -1
  122. package/dist/services/keyboardControls.js +20 -18
  123. package/dist/services/keyboardControls.js.map +1 -1
  124. package/dist/services/loadMap.js +120 -36
  125. package/dist/services/loadMap.js.map +1 -1
  126. package/dist/services/mmorpg.js +128 -136
  127. package/dist/services/mmorpg.js.map +1 -1
  128. package/dist/services/save.js +74 -66
  129. package/dist/services/save.js.map +1 -1
  130. package/dist/services/standalone.js +165 -167
  131. package/dist/services/standalone.js.map +1 -1
  132. package/dist/utils/getEntityProp.js +49 -51
  133. package/dist/utils/getEntityProp.js.map +1 -1
  134. package/package.json +8 -8
  135. package/src/components/character.ce +1 -1
  136. package/src/components/scenes/draw-map.ce +3 -1
  137. package/dist/index.js.map +0 -1
@@ -1,21 +1,23 @@
1
- var Control = /* @__PURE__ */ ((Control2) => {
2
- Control2["Action"] = "action";
3
- Control2["Attack"] = "attack";
4
- Control2["Defense"] = "defense";
5
- Control2["Skill"] = "skill";
6
- Control2["Back"] = "back";
7
- Control2[Control2["Up"] = 1] = "Up";
8
- Control2[Control2["Down"] = 3] = "Down";
9
- Control2[Control2["Right"] = 2] = "Right";
10
- Control2[Control2["Left"] = 4] = "Left";
11
- return Control2;
12
- })(Control || {});
1
+ //#region src/services/keyboardControls.ts
2
+ var Control = /* @__PURE__ */ function(Control) {
3
+ Control["Action"] = "action";
4
+ Control["Attack"] = "attack";
5
+ Control["Defense"] = "defense";
6
+ Control["Skill"] = "skill";
7
+ Control["Back"] = "back";
8
+ Control[Control["Up"] = 1] = "Up";
9
+ Control[Control["Down"] = 3] = "Down";
10
+ Control[Control["Right"] = 2] = "Right";
11
+ Control[Control["Left"] = 4] = "Left";
12
+ return Control;
13
+ }({});
13
14
  function provideKeyboardControls() {
14
- return {
15
- provide: "KeyboardControls",
16
- useValue: null
17
- };
15
+ return {
16
+ provide: "KeyboardControls",
17
+ useValue: null
18
+ };
18
19
  }
19
-
20
+ //#endregion
20
21
  export { Control, provideKeyboardControls };
21
- //# sourceMappingURL=keyboardControls.js.map
22
+
23
+ //# sourceMappingURL=keyboardControls.js.map
@@ -1 +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
+ {"version":3,"file":"keyboardControls.js","names":[],"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}"],"mappings":";AAEA,IAAY,UAAL,yBAAA,SAAA;AACL,SAAA,YAAA;AACA,SAAA,YAAA;AACA,SAAA,aAAA;AACA,SAAA,WAAA;AACA,SAAA,UAAA;AACA,SAAA,QAAA,QAAA,KAAA;AACA,SAAA,QAAA,UAAA,KAAA;AACA,SAAA,QAAA,WAAA,KAAA;AACA,SAAA,QAAA,UAAA,KAAA;;KACD;AAED,SAAgB,0BAA0B;AACxC,QAAO;EACL,SAAS;EACT,UAAU;EACX"}
@@ -1,39 +1,123 @@
1
- import { inject } from '../node_modules/.pnpm/@signe_di@2.8.3/node_modules/@signe/di/dist/index.js';
2
- import { UpdateMapToken } from '@rpgjs/common';
3
-
4
- const LoadMapToken = "LoadMapToken";
5
- class LoadMapService {
6
- constructor(context, options) {
7
- this.context = context;
8
- this.options = options;
9
- if (context["side"] === "server") {
10
- return;
11
- }
12
- this.updateMapService = inject(context, UpdateMapToken);
13
- }
14
- async load(mapId) {
15
- const map = await this.options(mapId.replace("map-", ""));
16
- await this.updateMapService.update(map);
17
- return map;
18
- }
19
- }
1
+ import { inject } from "../node_modules/.pnpm/@signe_di@2.8.3/node_modules/@signe/di/dist/index.js";
2
+ import { UpdateMapToken } from "@rpgjs/common";
3
+ //#region src/services/loadMap.ts
4
+ var LoadMapToken = "LoadMapToken";
5
+ var LoadMapService = class {
6
+ constructor(context, options) {
7
+ this.context = context;
8
+ this.options = options;
9
+ if (context["side"] === "server") return;
10
+ this.updateMapService = inject(context, UpdateMapToken);
11
+ }
12
+ async load(mapId) {
13
+ const map = await this.options(mapId.replace("map-", ""));
14
+ await this.updateMapService.update(map);
15
+ return map;
16
+ }
17
+ };
18
+ /**
19
+ * Creates a dependency injection configuration for custom map loading on the client side.
20
+ *
21
+ * This function allows you to customize how maps are loaded and displayed by providing
22
+ * a callback that defines custom map data and rendering components. It's designed to work
23
+ * with the RPG-JS dependency injection system and enables integration of custom map formats
24
+ * like Tiled TMX files or any other map data structure.
25
+ *
26
+ * The function sets up the necessary service providers for map loading, including:
27
+ * - UpdateMapToken: Handles map updates in the client context
28
+ * - LoadMapToken: Provides the LoadMapService with your custom loading logic
29
+ *
30
+ * **Design Concept:**
31
+ * The function follows the provider pattern, creating a modular way to inject custom
32
+ * map loading behavior into the RPG-JS client engine. It separates the concern of
33
+ * map data fetching from map rendering, allowing developers to focus on their specific
34
+ * map format while leveraging the engine's rendering capabilities.
35
+ *
36
+ * @param {LoadMapOptions} options - Callback function that handles map loading logic
37
+ * @returns {Array<Object>} Array of dependency injection provider configurations
38
+ *
39
+ * @example
40
+ * ```typescript
41
+ * import { provideLoadMap } from '@rpgjs/client'
42
+ * import { createModule } from '@rpgjs/common'
43
+ * import MyTiledMapComponent from './MyTiledMapComponent.ce'
44
+ *
45
+ * // Basic usage with JSON map data
46
+ * export function provideCustomMap() {
47
+ * return createModule("CustomMap", [
48
+ * provideLoadMap(async (mapId) => {
49
+ * const response = await fetch(`/maps/${mapId}.json`)
50
+ * const mapData = await response.json()
51
+ *
52
+ * return {
53
+ * data: mapData,
54
+ * component: MyTiledMapComponent,
55
+ * width: mapData.width,
56
+ * height: mapData.height,
57
+ * events: mapData.events
58
+ * }
59
+ * })
60
+ * ])
61
+ * }
62
+ *
63
+ * // Advanced usage with Tiled TMX files
64
+ * export function provideTiledMap() {
65
+ * return createModule("TiledMap", [
66
+ * provideLoadMap(async (mapId) => {
67
+ * // Load TMX file
68
+ * const tmxResponse = await fetch(`/tiled/${mapId}.tmx`)
69
+ * const tmxData = await tmxResponse.text()
70
+ *
71
+ * // Parse TMX data (using a TMX parser)
72
+ * const parsedMap = parseTMX(tmxData)
73
+ *
74
+ * return {
75
+ * data: parsedMap,
76
+ * component: TiledMapRenderer,
77
+ * width: parsedMap.width * parsedMap.tilewidth,
78
+ * height: parsedMap.height * parsedMap.tileheight,
79
+ * events: parsedMap.objectGroups?.find(g => g.name === 'events')?.objects
80
+ * }
81
+ * })
82
+ * ])
83
+ * }
84
+ *
85
+ * // Synchronous usage for static maps
86
+ * export function provideStaticMap() {
87
+ * return createModule("StaticMap", [
88
+ * provideLoadMap((mapId) => {
89
+ * const staticMaps = {
90
+ * 'town': { tiles: [...], npcs: [...] },
91
+ * 'dungeon': { tiles: [...], monsters: [...] }
92
+ * }
93
+ *
94
+ * return {
95
+ * data: staticMaps[mapId],
96
+ * component: StaticMapComponent,
97
+ * width: 800,
98
+ * height: 600
99
+ * }
100
+ * })
101
+ * ])
102
+ * }
103
+ * ```
104
+ *
105
+ * @since 4.0.0
106
+ * @see {@link LoadMapOptions} for callback function signature
107
+ * @see {@link MapData} for return data structure
108
+ */
20
109
  function provideLoadMap(options) {
21
- return [
22
- {
23
- provide: UpdateMapToken,
24
- useFactory: (context) => {
25
- if (context["side"] === "client") {
26
- console.warn("UpdateMapToken is not overridden");
27
- }
28
- return;
29
- }
30
- },
31
- {
32
- provide: LoadMapToken,
33
- useFactory: (context) => new LoadMapService(context, options)
34
- }
35
- ];
110
+ return [{
111
+ provide: UpdateMapToken,
112
+ useFactory: (context) => {
113
+ if (context["side"] === "client") console.warn("UpdateMapToken is not overridden");
114
+ }
115
+ }, {
116
+ provide: LoadMapToken,
117
+ useFactory: (context) => new LoadMapService(context, options)
118
+ }];
36
119
  }
37
-
120
+ //#endregion
38
121
  export { LoadMapService, LoadMapToken, provideLoadMap };
39
- //# sourceMappingURL=loadMap.js.map
122
+
123
+ //# sourceMappingURL=loadMap.js.map
@@ -1 +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
+ {"version":3,"file":"loadMap.js","names":[],"sources":["../../src/services/loadMap.ts"],"sourcesContent":["import { Context, inject } from \"@signe/di\";\nimport { UpdateMapToken, UpdateMapService } from \"@rpgjs/common\";\n\nexport const LoadMapToken = 'LoadMapToken'\n\n/**\n * Represents the structure of map data that should be returned by the load map callback.\n * This interface defines all the properties that can be provided when loading a custom map.\n * \n * @interface MapData\n */\ntype MapData = {\n /** Raw map data that will be passed to the map component */\n data: any;\n /** CanvasEngine component that will render the map */\n component: any;\n /** Optional map width in pixels, used for viewport calculations */\n width?: number;\n /** Optional map height in pixels, used for viewport calculations */\n height?: number;\n /** Optional map events data (NPCs, interactive objects, etc.) */\n events?: any;\n /** Optional map identifier, defaults to the mapId parameter if not provided */\n id?: string;\n}\n\n/**\n * Callback function type for loading map data.\n * This function receives a map ID and should return either a MapData object directly\n * or a Promise that resolves to a MapData object.\n * \n * @callback LoadMapOptions\n * @param {string} mapId - The identifier of the map to load\n * @returns {Promise<MapData> | MapData} The map data object or a promise resolving to it\n */\nexport type LoadMapOptions = (mapId: string) => Promise<MapData> | MapData \n\nexport class LoadMapService {\n private updateMapService: UpdateMapService;\n\n constructor(private context: Context, private options: LoadMapOptions) {\n if (context['side'] === 'server') {\n return\n }\n this.updateMapService = inject(context, UpdateMapToken);\n }\n\n async load(mapId: string) {\n const map = await this.options(mapId.replace('map-', ''))\n await this.updateMapService.update(map);\n return map;\n }\n}\n\n/**\n * Creates a dependency injection configuration for custom map loading on the client side.\n * \n * This function allows you to customize how maps are loaded and displayed by providing\n * a callback that defines custom map data and rendering components. It's designed to work\n * with the RPG-JS dependency injection system and enables integration of custom map formats\n * like Tiled TMX files or any other map data structure.\n * \n * The function sets up the necessary service providers for map loading, including:\n * - UpdateMapToken: Handles map updates in the client context\n * - LoadMapToken: Provides the LoadMapService with your custom loading logic\n * \n * **Design Concept:**\n * The function follows the provider pattern, creating a modular way to inject custom\n * map loading behavior into the RPG-JS client engine. It separates the concern of\n * map data fetching from map rendering, allowing developers to focus on their specific\n * map format while leveraging the engine's rendering capabilities.\n * \n * @param {LoadMapOptions} options - Callback function that handles map loading logic\n * @returns {Array<Object>} Array of dependency injection provider configurations\n * \n * @example\n * ```typescript\n * import { provideLoadMap } from '@rpgjs/client'\n * import { createModule } from '@rpgjs/common'\n * import MyTiledMapComponent from './MyTiledMapComponent.ce'\n * \n * // Basic usage with JSON map data\n * export function provideCustomMap() {\n * return createModule(\"CustomMap\", [\n * provideLoadMap(async (mapId) => {\n * const response = await fetch(`/maps/${mapId}.json`)\n * const mapData = await response.json()\n * \n * return {\n * data: mapData,\n * component: MyTiledMapComponent,\n * width: mapData.width,\n * height: mapData.height,\n * events: mapData.events\n * }\n * })\n * ])\n * }\n * \n * // Advanced usage with Tiled TMX files\n * export function provideTiledMap() {\n * return createModule(\"TiledMap\", [\n * provideLoadMap(async (mapId) => {\n * // Load TMX file\n * const tmxResponse = await fetch(`/tiled/${mapId}.tmx`)\n * const tmxData = await tmxResponse.text()\n * \n * // Parse TMX data (using a TMX parser)\n * const parsedMap = parseTMX(tmxData)\n * \n * return {\n * data: parsedMap,\n * component: TiledMapRenderer,\n * width: parsedMap.width * parsedMap.tilewidth,\n * height: parsedMap.height * parsedMap.tileheight,\n * events: parsedMap.objectGroups?.find(g => g.name === 'events')?.objects\n * }\n * })\n * ])\n * }\n * \n * // Synchronous usage for static maps\n * export function provideStaticMap() {\n * return createModule(\"StaticMap\", [\n * provideLoadMap((mapId) => {\n * const staticMaps = {\n * 'town': { tiles: [...], npcs: [...] },\n * 'dungeon': { tiles: [...], monsters: [...] }\n * }\n * \n * return {\n * data: staticMaps[mapId],\n * component: StaticMapComponent,\n * width: 800,\n * height: 600\n * }\n * })\n * ])\n * }\n * ```\n * \n * @since 4.0.0\n * @see {@link LoadMapOptions} for callback function signature\n * @see {@link MapData} for return data structure\n */\nexport function provideLoadMap(options: LoadMapOptions) {\n return [\n {\n provide: UpdateMapToken,\n useFactory: (context: Context) => {\n if (context['side'] === 'client') {\n console.warn('UpdateMapToken is not overridden')\n }\n return\n },\n },\n {\n provide: LoadMapToken,\n useFactory: (context: Context) => new LoadMapService(context, options),\n },\n ];\n}\n"],"mappings":";;;AAGA,IAAa,eAAe;AAkC5B,IAAa,iBAAb,MAA4B;CAG1B,YAAY,SAA0B,SAAiC;AAAnD,OAAA,UAAA;AAA0B,OAAA,UAAA;AAC5C,MAAI,QAAQ,YAAY,SACtB;AAEF,OAAK,mBAAmB,OAAO,SAAS,eAAe;;CAGzD,MAAM,KAAK,OAAe;EACxB,MAAM,MAAM,MAAM,KAAK,QAAQ,MAAM,QAAQ,QAAQ,GAAG,CAAC;AACzD,QAAM,KAAK,iBAAiB,OAAO,IAAI;AACvC,SAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+FX,SAAgB,eAAe,SAAyB;AACtD,QAAO,CACL;EACE,SAAS;EACT,aAAa,YAAqB;AAChC,OAAI,QAAQ,YAAY,SACtB,SAAQ,KAAK,mCAAmC;;EAIrD,EACD;EACE,SAAS;EACT,aAAa,YAAqB,IAAI,eAAe,SAAS,QAAQ;EACvE,CACF"}
@@ -1,139 +1,131 @@
1
- import { connectionRoom } from '../node_modules/.pnpm/@signe_sync@2.8.3/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
- import { UpdateMapToken, UpdateMapService } from '@rpgjs/common';
6
- import { provideKeyboardControls } from './keyboardControls.js';
7
- import { provideSaveClient } from './save.js';
8
-
9
- class BridgeWebsocket extends AbstractWebsocket {
10
- constructor(context, options = {}) {
11
- super(context);
12
- this.context = context;
13
- this.options = options;
14
- this.pendingOn = [];
15
- this.targetRoom = "lobby-1";
16
- this.privateId = this.resolveConnectionId();
17
- }
18
- resolveConnectionId() {
19
- if (this.options.connectionId) {
20
- return this.options.connectionId;
21
- }
22
- const scope = this.options.connectionIdScope ?? "local";
23
- const key = "rpgjs-user-id";
24
- if (scope === "ephemeral") {
25
- return crypto.randomUUID();
26
- }
27
- const storage = scope === "session" ? window.sessionStorage : window.localStorage;
28
- const existing = storage.getItem(key);
29
- if (existing) {
30
- return existing;
31
- }
32
- const id = crypto.randomUUID();
33
- storage.setItem(key, id);
34
- return id;
35
- }
36
- async connection(listeners) {
37
- class Room {
38
- }
39
- const instance = new Room();
40
- const host = this.options.host || window.location.host;
41
- this.socket = await connectionRoom({
42
- host,
43
- room: this.targetRoom,
44
- id: this.privateId
45
- }, instance);
46
- listeners?.(this.socket);
47
- this.pendingOn.forEach(({ event, callback }) => this.socket.on(event, callback));
48
- this.pendingOn = [];
49
- }
50
- on(key, callback) {
51
- if (!this.socket) {
52
- this.pendingOn.push({ event: key, callback });
53
- return;
54
- }
55
- this.socket.on(key, callback);
56
- }
57
- off(event, callback) {
58
- if (!this.socket) return;
59
- this.socket.off(event, callback);
60
- }
61
- emit(event, data) {
62
- this.socket.emit(event, data);
63
- }
64
- updateProperties({ room, host, query }) {
65
- if (!this.socket?.conn) return;
66
- this.targetRoom = room;
67
- this.socket.conn.updateProperties({
68
- room,
69
- id: this.privateId,
70
- host: host || this.options.host || window.location.host,
71
- query
72
- });
73
- }
74
- waitForNextOpen(conn, timeoutMs = 1e4) {
75
- return new Promise((resolve, reject) => {
76
- let timeoutId;
77
- const onOpen = () => {
78
- cleanup();
79
- resolve();
80
- };
81
- const onError = () => {
82
- cleanup();
83
- reject(new Error("WebSocket reconnect failed"));
84
- };
85
- const cleanup = () => {
86
- conn.removeEventListener("open", onOpen);
87
- conn.removeEventListener("error", onError);
88
- if (timeoutId !== void 0) {
89
- window.clearTimeout(timeoutId);
90
- }
91
- };
92
- conn.addEventListener("open", onOpen);
93
- conn.addEventListener("error", onError);
94
- timeoutId = window.setTimeout(() => {
95
- cleanup();
96
- reject(new Error("WebSocket reconnect timeout"));
97
- }, timeoutMs);
98
- });
99
- }
100
- async reconnect(_listeners) {
101
- if (!this.socket?.conn) return;
102
- const conn = this.socket.conn;
103
- const opened = this.waitForNextOpen(conn);
104
- conn.reconnect();
105
- await opened;
106
- }
107
- getCurrentRoom() {
108
- return this.targetRoom || this.socket?.conn?.room || "lobby-1";
109
- }
110
- }
111
- class UpdateMapStandaloneService extends UpdateMapService {
112
- constructor(context, _options) {
113
- super(context);
114
- this.context = context;
115
- this._options = _options;
116
- }
117
- async update(_map) {
118
- return;
119
- }
120
- }
1
+ import { AbstractWebsocket, WebSocketToken } from "./AbstractSocket.js";
2
+ import { provideSaveClient } from "./save.js";
3
+ import { RpgGui } from "../Gui/Gui.js";
4
+ import { RpgClientEngine } from "../RpgClientEngine.js";
5
+ import { provideKeyboardControls } from "./keyboardControls.js";
6
+ import { connectionRoom } from "../node_modules/.pnpm/@signe_sync@2.8.3/node_modules/@signe/sync/dist/client/index.js";
7
+ import { UpdateMapService, UpdateMapToken } from "@rpgjs/common";
8
+ //#region src/services/mmorpg.ts
9
+ var BridgeWebsocket = class extends AbstractWebsocket {
10
+ constructor(context, options = {}) {
11
+ super(context);
12
+ this.context = context;
13
+ this.options = options;
14
+ this.pendingOn = [];
15
+ this.targetRoom = "lobby-1";
16
+ this.privateId = this.resolveConnectionId();
17
+ }
18
+ resolveConnectionId() {
19
+ if (this.options.connectionId) return this.options.connectionId;
20
+ const scope = this.options.connectionIdScope ?? "local";
21
+ const key = "rpgjs-user-id";
22
+ if (scope === "ephemeral") return crypto.randomUUID();
23
+ const storage = scope === "session" ? window.sessionStorage : window.localStorage;
24
+ const existing = storage.getItem(key);
25
+ if (existing) return existing;
26
+ const id = crypto.randomUUID();
27
+ storage.setItem(key, id);
28
+ return id;
29
+ }
30
+ async connection(listeners) {
31
+ class Room {}
32
+ const instance = new Room();
33
+ this.socket = await connectionRoom({
34
+ host: this.options.host || window.location.host,
35
+ room: this.targetRoom,
36
+ id: this.privateId
37
+ }, instance);
38
+ listeners?.(this.socket);
39
+ this.pendingOn.forEach(({ event, callback }) => this.socket.on(event, callback));
40
+ this.pendingOn = [];
41
+ }
42
+ on(key, callback) {
43
+ if (!this.socket) {
44
+ this.pendingOn.push({
45
+ event: key,
46
+ callback
47
+ });
48
+ return;
49
+ }
50
+ this.socket.on(key, callback);
51
+ }
52
+ off(event, callback) {
53
+ if (!this.socket) return;
54
+ this.socket.off(event, callback);
55
+ }
56
+ emit(event, data) {
57
+ this.socket.emit(event, data);
58
+ }
59
+ updateProperties({ room, host, query }) {
60
+ if (!this.socket?.conn) return;
61
+ this.targetRoom = room;
62
+ this.socket.conn.updateProperties({
63
+ room,
64
+ id: this.privateId,
65
+ host: host || this.options.host || window.location.host,
66
+ query
67
+ });
68
+ }
69
+ waitForNextOpen(conn, timeoutMs = 1e4) {
70
+ return new Promise((resolve, reject) => {
71
+ let timeoutId;
72
+ const onOpen = () => {
73
+ cleanup();
74
+ resolve();
75
+ };
76
+ const onError = () => {
77
+ cleanup();
78
+ reject(/* @__PURE__ */ new Error("WebSocket reconnect failed"));
79
+ };
80
+ const cleanup = () => {
81
+ conn.removeEventListener("open", onOpen);
82
+ conn.removeEventListener("error", onError);
83
+ if (timeoutId !== void 0) window.clearTimeout(timeoutId);
84
+ };
85
+ conn.addEventListener("open", onOpen);
86
+ conn.addEventListener("error", onError);
87
+ timeoutId = window.setTimeout(() => {
88
+ cleanup();
89
+ reject(/* @__PURE__ */ new Error("WebSocket reconnect timeout"));
90
+ }, timeoutMs);
91
+ });
92
+ }
93
+ async reconnect(_listeners) {
94
+ if (!this.socket?.conn) return;
95
+ const conn = this.socket.conn;
96
+ const opened = this.waitForNextOpen(conn);
97
+ conn.reconnect();
98
+ await opened;
99
+ }
100
+ getCurrentRoom() {
101
+ return this.targetRoom || this.socket?.conn?.room || "lobby-1";
102
+ }
103
+ };
104
+ var UpdateMapStandaloneService = class extends UpdateMapService {
105
+ constructor(context, _options) {
106
+ super(context);
107
+ this.context = context;
108
+ this._options = _options;
109
+ }
110
+ async update(_map) {}
111
+ };
121
112
  function provideMmorpg(options) {
122
- return [
123
- {
124
- provide: WebSocketToken,
125
- useFactory: (context) => new BridgeWebsocket(context, options)
126
- },
127
- {
128
- provide: UpdateMapToken,
129
- useFactory: (context) => new UpdateMapStandaloneService(context, options)
130
- },
131
- provideKeyboardControls(),
132
- provideSaveClient(),
133
- RpgGui,
134
- RpgClientEngine
135
- ];
113
+ return [
114
+ {
115
+ provide: WebSocketToken,
116
+ useFactory: (context) => new BridgeWebsocket(context, options)
117
+ },
118
+ {
119
+ provide: UpdateMapToken,
120
+ useFactory: (context) => new UpdateMapStandaloneService(context, options)
121
+ },
122
+ provideKeyboardControls(),
123
+ provideSaveClient(),
124
+ RpgGui,
125
+ RpgClientEngine
126
+ ];
136
127
  }
137
-
128
+ //#endregion
138
129
  export { provideMmorpg };
139
- //# sourceMappingURL=mmorpg.js.map
130
+
131
+ //# sourceMappingURL=mmorpg.js.map
@@ -1 +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, SocketUpdateProperties, WebSocketToken } from \"./AbstractSocket\";\nimport { UpdateMapService, UpdateMapToken } from \"@rpgjs/common\";\nimport { provideKeyboardControls } from \"./keyboardControls\";\nimport { provideSaveClient } from \"./save\";\n\ninterface MmorpgOptions {\n host?: string;\n connectionId?: string;\n connectionIdScope?: \"local\" | \"session\" | \"ephemeral\";\n}\n\nclass BridgeWebsocket extends AbstractWebsocket {\n private socket: any;\n private privateId: string;\n private pendingOn: Array<{ event: string; callback: (data: any) => void }> = [];\n private targetRoom = \"lobby-1\";\n\n constructor(protected context: Context, private options: MmorpgOptions = {}) {\n super(context);\n this.privateId = this.resolveConnectionId();\n }\n\n private resolveConnectionId(): string {\n if (this.options.connectionId) {\n return this.options.connectionId;\n }\n\n const scope = this.options.connectionIdScope ?? \"local\";\n const key = \"rpgjs-user-id\";\n\n if (scope === \"ephemeral\") {\n return crypto.randomUUID();\n }\n\n const storage =\n scope === \"session\"\n ? window.sessionStorage\n : window.localStorage;\n\n const existing = storage.getItem(key);\n if (existing) {\n return existing;\n }\n\n const id = crypto.randomUUID();\n storage.setItem(key, id);\n return id;\n }\n\n async connection(listeners?: (data: any) => void) {\n // tmp\n class Room {\n \n }\n const instance = new Room()\n const host = this.options.host || window.location.host;\n this.socket = await connectionRoom({\n host,\n room: this.targetRoom,\n id: this.privateId\n }, instance)\n\n listeners?.(this.socket)\n this.pendingOn.forEach(({ event, callback }) => this.socket.on(event, callback));\n this.pendingOn = [];\n }\n\n on(key: string, callback: (data: any) => void) {\n if (!this.socket) {\n this.pendingOn.push({ event: key, callback });\n return;\n }\n this.socket.on(key, callback);\n }\n\n off(event: string, callback: (data: any) => void) {\n if (!this.socket) return;\n this.socket.off(event, callback);\n }\n\n emit(event: string, data: any) {\n this.socket.emit(event, data);\n }\n\n updateProperties({ room, host, query }: SocketUpdateProperties) {\n if (!this.socket?.conn) return;\n this.targetRoom = room;\n this.socket.conn.updateProperties({\n room,\n id: this.privateId,\n host: host || this.options.host || window.location.host,\n query,\n })\n }\n\n private waitForNextOpen(conn: any, timeoutMs = 10000): Promise<void> {\n return new Promise((resolve, reject) => {\n let timeoutId: number | undefined;\n const onOpen = () => {\n cleanup();\n resolve();\n };\n const onError = () => {\n cleanup();\n reject(new Error(\"WebSocket reconnect failed\"));\n };\n const cleanup = () => {\n conn.removeEventListener(\"open\", onOpen);\n conn.removeEventListener(\"error\", onError);\n if (timeoutId !== undefined) {\n window.clearTimeout(timeoutId);\n }\n };\n\n conn.addEventListener(\"open\", onOpen);\n conn.addEventListener(\"error\", onError);\n timeoutId = window.setTimeout(() => {\n cleanup();\n reject(new Error(\"WebSocket reconnect timeout\"));\n }, timeoutMs);\n });\n }\n\n async reconnect(_listeners?: (data: any) => void): Promise<void> {\n if (!this.socket?.conn) return;\n const conn = this.socket.conn;\n const opened = this.waitForNextOpen(conn);\n conn.reconnect();\n await opened;\n }\n\n getCurrentRoom(): string {\n return this.targetRoom || this.socket?.conn?.room || \"lobby-1\";\n }\n}\n\nclass UpdateMapStandaloneService extends UpdateMapService {\n constructor(protected context: Context, private _options: MmorpgOptions) {\n super(context);\n }\n\n async update(_map: any) {\n // In MMORPG mode, clients are untrusted and must not push map definitions.\n // Map bootstrap/update is handled server-side by @rpgjs/vite.\n return;\n }\n}\n\nexport function provideMmorpg(options: MmorpgOptions) {\n return [\n {\n provide: WebSocketToken,\n useFactory: (context: Context) => new BridgeWebsocket(context, options),\n },\n {\n provide: UpdateMapToken,\n useFactory: (context: Context) => new UpdateMapStandaloneService(context, options),\n },\n provideKeyboardControls(),\n provideSaveClient(),\n RpgGui,\n RpgClientEngine,\n ];\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mmorpg.js","names":[],"sources":["../../src/services/mmorpg.ts"],"sourcesContent":["import { Context } from \"@signe/di\";\nimport { connectionRoom } from \"@signe/sync/client\";\nimport { RpgGui } from \"../Gui/Gui\";\nimport { RpgClientEngine } from \"../RpgClientEngine\";\nimport { AbstractWebsocket, SocketUpdateProperties, WebSocketToken } from \"./AbstractSocket\";\nimport { UpdateMapService, UpdateMapToken } from \"@rpgjs/common\";\nimport { provideKeyboardControls } from \"./keyboardControls\";\nimport { provideSaveClient } from \"./save\";\n\ninterface MmorpgOptions {\n host?: string;\n connectionId?: string;\n connectionIdScope?: \"local\" | \"session\" | \"ephemeral\";\n}\n\nclass BridgeWebsocket extends AbstractWebsocket {\n private socket: any;\n private privateId: string;\n private pendingOn: Array<{ event: string; callback: (data: any) => void }> = [];\n private targetRoom = \"lobby-1\";\n\n constructor(protected context: Context, private options: MmorpgOptions = {}) {\n super(context);\n this.privateId = this.resolveConnectionId();\n }\n\n private resolveConnectionId(): string {\n if (this.options.connectionId) {\n return this.options.connectionId;\n }\n\n const scope = this.options.connectionIdScope ?? \"local\";\n const key = \"rpgjs-user-id\";\n\n if (scope === \"ephemeral\") {\n return crypto.randomUUID();\n }\n\n const storage =\n scope === \"session\"\n ? window.sessionStorage\n : window.localStorage;\n\n const existing = storage.getItem(key);\n if (existing) {\n return existing;\n }\n\n const id = crypto.randomUUID();\n storage.setItem(key, id);\n return id;\n }\n\n async connection(listeners?: (data: any) => void) {\n // tmp\n class Room {\n \n }\n const instance = new Room()\n const host = this.options.host || window.location.host;\n this.socket = await connectionRoom({\n host,\n room: this.targetRoom,\n id: this.privateId\n }, instance)\n\n listeners?.(this.socket)\n this.pendingOn.forEach(({ event, callback }) => this.socket.on(event, callback));\n this.pendingOn = [];\n }\n\n on(key: string, callback: (data: any) => void) {\n if (!this.socket) {\n this.pendingOn.push({ event: key, callback });\n return;\n }\n this.socket.on(key, callback);\n }\n\n off(event: string, callback: (data: any) => void) {\n if (!this.socket) return;\n this.socket.off(event, callback);\n }\n\n emit(event: string, data: any) {\n this.socket.emit(event, data);\n }\n\n updateProperties({ room, host, query }: SocketUpdateProperties) {\n if (!this.socket?.conn) return;\n this.targetRoom = room;\n this.socket.conn.updateProperties({\n room,\n id: this.privateId,\n host: host || this.options.host || window.location.host,\n query,\n })\n }\n\n private waitForNextOpen(conn: any, timeoutMs = 10000): Promise<void> {\n return new Promise((resolve, reject) => {\n let timeoutId: number | undefined;\n const onOpen = () => {\n cleanup();\n resolve();\n };\n const onError = () => {\n cleanup();\n reject(new Error(\"WebSocket reconnect failed\"));\n };\n const cleanup = () => {\n conn.removeEventListener(\"open\", onOpen);\n conn.removeEventListener(\"error\", onError);\n if (timeoutId !== undefined) {\n window.clearTimeout(timeoutId);\n }\n };\n\n conn.addEventListener(\"open\", onOpen);\n conn.addEventListener(\"error\", onError);\n timeoutId = window.setTimeout(() => {\n cleanup();\n reject(new Error(\"WebSocket reconnect timeout\"));\n }, timeoutMs);\n });\n }\n\n async reconnect(_listeners?: (data: any) => void): Promise<void> {\n if (!this.socket?.conn) return;\n const conn = this.socket.conn;\n const opened = this.waitForNextOpen(conn);\n conn.reconnect();\n await opened;\n }\n\n getCurrentRoom(): string {\n return this.targetRoom || this.socket?.conn?.room || \"lobby-1\";\n }\n}\n\nclass UpdateMapStandaloneService extends UpdateMapService {\n constructor(protected context: Context, private _options: MmorpgOptions) {\n super(context);\n }\n\n async update(_map: any) {\n // In MMORPG mode, clients are untrusted and must not push map definitions.\n // Map bootstrap/update is handled server-side by @rpgjs/vite.\n return;\n }\n}\n\nexport function provideMmorpg(options: MmorpgOptions) {\n return [\n {\n provide: WebSocketToken,\n useFactory: (context: Context) => new BridgeWebsocket(context, options),\n },\n {\n provide: UpdateMapToken,\n useFactory: (context: Context) => new UpdateMapStandaloneService(context, options),\n },\n provideKeyboardControls(),\n provideSaveClient(),\n RpgGui,\n RpgClientEngine,\n ];\n}\n"],"mappings":"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"}