@rpgjs/server 5.0.0-alpha.9 → 5.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. package/dist/Gui/DialogGui.d.ts +5 -0
  2. package/dist/Gui/GameoverGui.d.ts +23 -0
  3. package/dist/Gui/Gui.d.ts +6 -0
  4. package/dist/Gui/MenuGui.d.ts +22 -3
  5. package/dist/Gui/NotificationGui.d.ts +1 -2
  6. package/dist/Gui/SaveLoadGui.d.ts +13 -0
  7. package/dist/Gui/ShopGui.d.ts +28 -3
  8. package/dist/Gui/TitleGui.d.ts +23 -0
  9. package/dist/Gui/index.d.ts +10 -1
  10. package/dist/Player/BattleManager.d.ts +44 -32
  11. package/dist/Player/ClassManager.d.ts +24 -4
  12. package/dist/Player/ComponentManager.d.ts +95 -32
  13. package/dist/Player/Components.d.ts +345 -0
  14. package/dist/Player/EffectManager.d.ts +50 -4
  15. package/dist/Player/ElementManager.d.ts +77 -4
  16. package/dist/Player/GoldManager.d.ts +1 -1
  17. package/dist/Player/GuiManager.d.ts +87 -4
  18. package/dist/Player/ItemFixture.d.ts +1 -1
  19. package/dist/Player/ItemManager.d.ts +431 -4
  20. package/dist/Player/MoveManager.d.ts +301 -34
  21. package/dist/Player/ParameterManager.d.ts +364 -28
  22. package/dist/Player/Player.d.ts +558 -14
  23. package/dist/Player/SkillManager.d.ts +187 -13
  24. package/dist/Player/StateManager.d.ts +75 -4
  25. package/dist/Player/VariableManager.d.ts +62 -4
  26. package/dist/RpgServer.d.ts +278 -63
  27. package/dist/RpgServerEngine.d.ts +2 -1
  28. package/dist/decorators/event.d.ts +46 -0
  29. package/dist/decorators/map.d.ts +299 -0
  30. package/dist/index.d.ts +10 -0
  31. package/dist/index.js +17920 -29711
  32. package/dist/index.js.map +1 -1
  33. package/dist/logs/log.d.ts +2 -3
  34. package/dist/module-CaCW1SDh.js +11018 -0
  35. package/dist/module-CaCW1SDh.js.map +1 -0
  36. package/dist/module.d.ts +43 -1
  37. package/dist/node/connection.d.ts +51 -0
  38. package/dist/node/index.d.ts +5 -0
  39. package/dist/node/index.js +551 -0
  40. package/dist/node/index.js.map +1 -0
  41. package/dist/node/map.d.ts +16 -0
  42. package/dist/node/room.d.ts +21 -0
  43. package/dist/node/transport.d.ts +28 -0
  44. package/dist/node/types.d.ts +47 -0
  45. package/dist/presets/index.d.ts +0 -9
  46. package/dist/rooms/BaseRoom.d.ts +132 -0
  47. package/dist/rooms/lobby.d.ts +10 -2
  48. package/dist/rooms/map.d.ts +1359 -32
  49. package/dist/services/save.d.ts +43 -0
  50. package/dist/storage/index.d.ts +1 -0
  51. package/dist/storage/localStorage.d.ts +23 -0
  52. package/package.json +25 -10
  53. package/src/Gui/DialogGui.ts +19 -4
  54. package/src/Gui/GameoverGui.ts +39 -0
  55. package/src/Gui/Gui.ts +23 -1
  56. package/src/Gui/MenuGui.ts +155 -6
  57. package/src/Gui/NotificationGui.ts +1 -2
  58. package/src/Gui/SaveLoadGui.ts +60 -0
  59. package/src/Gui/ShopGui.ts +146 -16
  60. package/src/Gui/TitleGui.ts +39 -0
  61. package/src/Gui/index.ts +15 -2
  62. package/src/Player/BattleManager.ts +39 -56
  63. package/src/Player/ClassManager.ts +82 -74
  64. package/src/Player/ComponentManager.ts +394 -32
  65. package/src/Player/Components.ts +380 -0
  66. package/src/Player/EffectManager.ts +50 -96
  67. package/src/Player/ElementManager.ts +74 -152
  68. package/src/Player/GuiManager.ts +125 -14
  69. package/src/Player/ItemManager.ts +747 -341
  70. package/src/Player/MoveManager.ts +1532 -750
  71. package/src/Player/ParameterManager.ts +636 -106
  72. package/src/Player/Player.ts +1273 -79
  73. package/src/Player/SkillManager.ts +558 -197
  74. package/src/Player/StateManager.ts +131 -258
  75. package/src/Player/VariableManager.ts +85 -157
  76. package/src/RpgServer.ts +293 -62
  77. package/src/decorators/event.ts +61 -0
  78. package/src/decorators/map.ts +343 -0
  79. package/src/index.ts +11 -1
  80. package/src/logs/log.ts +10 -3
  81. package/src/module.ts +126 -3
  82. package/src/node/connection.ts +254 -0
  83. package/src/node/index.ts +22 -0
  84. package/src/node/map.ts +328 -0
  85. package/src/node/room.ts +63 -0
  86. package/src/node/transport.ts +532 -0
  87. package/src/node/types.ts +61 -0
  88. package/src/presets/index.ts +1 -10
  89. package/src/rooms/BaseRoom.ts +232 -0
  90. package/src/rooms/lobby.ts +25 -7
  91. package/src/rooms/map.ts +2682 -206
  92. package/src/services/save.ts +147 -0
  93. package/src/storage/index.ts +1 -0
  94. package/src/storage/localStorage.ts +76 -0
  95. package/tests/battle.spec.ts +375 -0
  96. package/tests/change-map.spec.ts +72 -0
  97. package/tests/class.spec.ts +274 -0
  98. package/tests/custom-websocket.spec.ts +127 -0
  99. package/tests/effect.spec.ts +219 -0
  100. package/tests/element.spec.ts +221 -0
  101. package/tests/event.spec.ts +80 -0
  102. package/tests/gold.spec.ts +99 -0
  103. package/tests/item.spec.ts +609 -0
  104. package/tests/module.spec.ts +38 -0
  105. package/tests/move.spec.ts +601 -0
  106. package/tests/node-transport.spec.ts +223 -0
  107. package/tests/player-param.spec.ts +45 -0
  108. package/tests/prediction-reconciliation.spec.ts +182 -0
  109. package/tests/random-move.spec.ts +65 -0
  110. package/tests/skill.spec.ts +658 -0
  111. package/tests/state.spec.ts +467 -0
  112. package/tests/variable.spec.ts +185 -0
  113. package/tests/world-maps.spec.ts +896 -0
  114. package/vite.config.ts +36 -3
@@ -0,0 +1,343 @@
1
+ import type { WeatherState } from "@rpgjs/common";
2
+ import type { MapEventDefinition, MapEventPlacement } from "../rooms/map";
3
+
4
+ export interface MapOptions {
5
+ /**
6
+ * Map identifier. Allows to go to the map (for example with player.changeMap())
7
+ *
8
+ * @prop {string} [id]
9
+ * @memberof MapData
10
+ * */
11
+ id?: string,
12
+
13
+ /**
14
+ * the path to the .tmx file (Tiled Map Editor)
15
+ *
16
+ * Remember to use `require()` function
17
+ *
18
+ * ```ts
19
+ * import { MapData, RpgMap } from '@rpgjs/server'
20
+ *
21
+ * @MapData({
22
+ * id: 'town',
23
+ * file: require('./tmx/town.tmx')
24
+ * })
25
+ * class TownMap extends RpgMap { }
26
+ * ```
27
+ * @prop {string} file
28
+ * @memberof MapData
29
+ * */
30
+ file?: any,
31
+
32
+ /**
33
+ * The name of the map.
34
+ * @prop {string} [name]
35
+ * @memberof MapData
36
+ * */
37
+ name?: string,
38
+
39
+ /**
40
+ * Map events. This is an array containing `RpgEvent` classes.
41
+ * You can also give an object that will indicate the positions of the event on the map.
42
+ *
43
+ * ```ts
44
+ * import { MapData, RpgMap, EventData, RpgEvent } from '@rpgjs/server'
45
+ *
46
+ * @EventData({
47
+ * name: 'Ev-1'
48
+ * })
49
+ * class NpcEvent extends RpgEvent { }
50
+ *
51
+ * @MapData({
52
+ * id: 'medieval',
53
+ * file: require('./tmx/town.tmx'),
54
+ * events: [NpcEvent]
55
+ * })
56
+ * class TownMap extends RpgMap {}
57
+ * ```
58
+ *
59
+ * If the positions are not defined, the event will be placed on a Tiled Map Editor shape ([/guide/create-event.html#position-the-event-on-the-map](Guide)). Otherwise, it will be placed at `{x:0, y:0 }`
60
+ *
61
+ * You can give positions:
62
+ *
63
+ * ```ts
64
+ * events: [{ event: NpcEvent, x: 10, y: 30 }]
65
+ * ```
66
+ *
67
+ * For object-based events, put the hooks in the `event` property and keep map placement
68
+ * (`x`, `y`, `id`) at the wrapper level:
69
+ *
70
+ * ```ts
71
+ * events: [{
72
+ * x: 200,
73
+ * y: 120,
74
+ * event: {
75
+ * onInit() {
76
+ * this.setGraphic('female')
77
+ * }
78
+ * }
79
+ * }]
80
+ * ```
81
+ *
82
+ * @prop {(MapEventDefinition | MapEventPlacement)[]} [events]
83
+ * @memberof MapData
84
+ * */
85
+ events?: (MapEventDefinition | MapEventPlacement)[],
86
+
87
+ /**
88
+ * The sounds that will be played when the map is open. Sounds must be defined on the client side. Then, put the name of the sound identifier
89
+ *
90
+ * So, it is possible to play several sounds (in loop or not) on the card. You can put a background music (BGM) and a background noise (BGS) for example
91
+ *
92
+ * ```ts
93
+ * sounds: ['my-bgm', 'my-bgs']
94
+ * ```
95
+ *
96
+ * And client side:
97
+ *
98
+ * ```ts
99
+ * import { Sound } from '@rpgjs/client'
100
+ *
101
+ * @Sound({
102
+ * sounds: {
103
+ * 'my-bgm': require('./assets/bgm.ogg'),
104
+ * 'my-bgs': require('./assets/bgs.ogg')
105
+ * },
106
+ * loop: true
107
+ * })
108
+ * export class Sounds {}
109
+ * ```
110
+ *
111
+ * See [https://docs.rpgjs.dev/classes/sound.html#properties](RpgSound Decorator)
112
+ *
113
+ * @prop {Array<string>} [sounds]
114
+ * @memberof MapData
115
+ * */
116
+ sounds?: string[]
117
+
118
+ /**
119
+ * Initial weather state for this map.
120
+ *
121
+ * This value is applied when the map is loaded and can later be updated
122
+ * at runtime with `map.setWeather()` from server logic.
123
+ *
124
+ * ```ts
125
+ * @MapData({
126
+ * id: 'forest',
127
+ * file: require('./tmx/forest.tmx'),
128
+ * weather: {
129
+ * effect: 'fog',
130
+ * preset: 'rpgForestFog',
131
+ * params: { density: 1.2, height: 0.75 },
132
+ * transitionMs: 1200
133
+ * }
134
+ * })
135
+ * class ForestMap extends RpgMap {}
136
+ * ```
137
+ */
138
+ weather?: WeatherState | null
139
+
140
+ /**
141
+ * Whether to stop all sounds before playing the map sounds when a player joins.
142
+ *
143
+ * If set to `true`, all currently playing sounds will be stopped before playing the new map sounds.
144
+ * This prevents sound overlap when changing maps.
145
+ *
146
+ * By default, this is `false`, meaning sounds from the previous map will continue playing.
147
+ *
148
+ * ```ts
149
+ * @MapData({
150
+ * id: 'battle-map',
151
+ * sounds: ['battle-theme'],
152
+ * stopAllSoundsBeforeJoin: true // Stop all sounds before playing battle theme
153
+ * })
154
+ * class BattleMap extends RpgMap {}
155
+ * ```
156
+ *
157
+ * @prop {boolean} [stopAllSoundsBeforeJoin=false]
158
+ * @memberof MapData
159
+ * @since 5.0.0
160
+ * */
161
+ stopAllSoundsBeforeJoin?: boolean
162
+
163
+ /**
164
+ * Specify which properties will be synchronized with the client. On the client side, you can retrieve the values synchronized with the valueChanges property on the scene
165
+ *
166
+ * You must create the schema:
167
+ *
168
+ * ```ts
169
+ * import { MapData, RpgMap } from '@rpgjs/server'
170
+ *
171
+ * @MapData({
172
+ * id: 'medieval',
173
+ * file: require('./tmx/town.tmx'),
174
+ * syncSchema: {
175
+ * count: Number
176
+ * }
177
+ * })
178
+ * export class TownMap extends RpgMap {
179
+ * count: number = 0
180
+ *
181
+ * onLoad() {}
182
+ *
183
+ * onJoin() {
184
+ * this.count++
185
+ * }
186
+ *
187
+ * onLeave(player) {
188
+ * super.onLeave(player)
189
+ * this.count--
190
+ * }
191
+ * }
192
+ *
193
+ * ```
194
+ *
195
+ * If you want to change the scheme of players and events, consider overwriting the existing scheme
196
+ *
197
+ * ```ts
198
+ * import { MapData, RpgMap, RpgPlayer } from '@rpgjs/server'
199
+ *
200
+ *
201
+ * declare module '@rpgjs/server' {
202
+ * export interface RpgPlayer {
203
+ * customProp: string
204
+ * }
205
+ * }
206
+ *
207
+ * @MapData({
208
+ * id: 'medieval',
209
+ * file: require('./tmx/town.tmx'),
210
+ * syncSchema: {
211
+ * users: [
212
+ * {
213
+ * customProp: String,
214
+ * ...RpgPlayer.schemas
215
+ * }
216
+ * ]
217
+ * }
218
+ * })
219
+ * export class TownMap extends RpgMap {}
220
+ * ```
221
+ *
222
+ * The properties are called `users` and `events`. Their scheme is identical and defined in `RpgPlayer.schemas`. To write schematics, refer to the [documentation of the simple-room](https://github.com/RSamaium/simple-room) module
223
+ *
224
+ * @prop {object} [syncSchema]
225
+ * @memberof MapData
226
+ * */
227
+ syncSchema?: any
228
+
229
+ /**
230
+ * Decreases the RAM of the map. In this case, some instructions will be different.
231
+ *
232
+ * `map.getTileByIndex()` will not return all tiles of an index but only the tile of the highest layer
233
+ *
234
+ * > You can also use the `low-memory` property in Tiled maps
235
+ *
236
+ * @prop {boolean} [lowMemory=false]
237
+ * @since 3.1.0
238
+ * @memberof MapData
239
+ * */
240
+ lowMemory?: boolean
241
+
242
+ /**
243
+ * Called when the map is loaded and initialized
244
+ *
245
+ * This hook is executed once when the map data is loaded and ready.
246
+ * Use this to initialize map-specific properties or setup.
247
+ *
248
+ * @prop { () => any } [onLoad]
249
+ * @memberof MapData
250
+ * @example
251
+ * ```ts
252
+ * @MapData({
253
+ * id: 'town',
254
+ * file: require('./tmx/town.tmx'),
255
+ * onLoad() {
256
+ * console.log('Town map loaded')
257
+ * // Initialize map properties
258
+ * }
259
+ * })
260
+ * class TownMap extends RpgMap {}
261
+ * ```
262
+ * */
263
+ onLoad?: () => any
264
+
265
+ /**
266
+ * Called when a player joins the map
267
+ *
268
+ * This hook is executed each time a player joins the map.
269
+ * Use this to perform actions when a player enters the map.
270
+ *
271
+ * @prop { (player: RpgPlayer) => any } [onJoin]
272
+ * @memberof MapData
273
+ * @example
274
+ * ```ts
275
+ * @MapData({
276
+ * id: 'town',
277
+ * file: require('./tmx/town.tmx'),
278
+ * onJoin(player: RpgPlayer) {
279
+ * console.log(`${player.name} joined the town`)
280
+ * // Perform actions when player joins
281
+ * }
282
+ * })
283
+ * class TownMap extends RpgMap {}
284
+ * ```
285
+ * */
286
+ onJoin?: (player: RpgPlayer) => any
287
+
288
+ /**
289
+ * Called when a player leaves the map
290
+ *
291
+ * This hook is executed each time a player leaves the map.
292
+ * Use this to perform cleanup or actions when a player exits the map.
293
+ *
294
+ * @prop { (player: RpgPlayer) => any } [onLeave]
295
+ * @memberof MapData
296
+ * @example
297
+ * ```ts
298
+ * @MapData({
299
+ * id: 'town',
300
+ * file: require('./tmx/town.tmx'),
301
+ * onLeave(player: RpgPlayer) {
302
+ * console.log(`${player.name} left the town`)
303
+ * // Perform cleanup when player leaves
304
+ * }
305
+ * })
306
+ * class TownMap extends RpgMap {}
307
+ * ```
308
+ * */
309
+ onLeave?: (player: RpgPlayer) => any
310
+ }
311
+
312
+ export function MapData(options: MapOptions) {
313
+ return (target) => {
314
+ target.file = options.file
315
+ target.id = options.id
316
+ target.type = 'map'
317
+ target.prototype.name = options.name
318
+ target.prototype.file = options.file
319
+ target.prototype.id = options.id
320
+ target.prototype.sounds = options.sounds
321
+ target.prototype.weather = options.weather
322
+ target.prototype.lowMemory = options.lowMemory
323
+ target.prototype.stopAllSoundsBeforeJoin = options.stopAllSoundsBeforeJoin
324
+
325
+ target.prototype.$schema = {}
326
+
327
+ if (options.syncSchema) {
328
+ target.prototype.$schema = options.syncSchema
329
+ }
330
+ target.prototype._events = options.events
331
+
332
+ // Store hooks on prototype
333
+ if (options.onLoad) {
334
+ target.prototype.onLoad = options.onLoad
335
+ }
336
+ if (options.onJoin) {
337
+ target.prototype.onJoin = options.onJoin
338
+ }
339
+ if (options.onLeave) {
340
+ target.prototype.onLeave = options.onLeave
341
+ }
342
+ }
343
+ }
package/src/index.ts CHANGED
@@ -4,6 +4,16 @@ export * from "./RpgServer";
4
4
  export * from "./core/setup";
5
5
  export * from "./core/inject";
6
6
  export * from "./Player/Player";
7
+ export * from "./Player/Components";
7
8
  export * from "./module";
8
9
  export * from "./rooms/map";
9
- export * from "./presets";
10
+ export * from "./presets";
11
+ export * from "@signe/reactive";
12
+ export * from "./Gui";
13
+ export * from "./services/save";
14
+ export * from "./storage";
15
+ export { RpgShape, RpgModule, MAXHP, MAXSP, ATK, PDEF, SDEF, STR, AGI, INT, DEX } from "@rpgjs/common";
16
+ export * from "./decorators/event";
17
+ export * from "./decorators/map";
18
+ export * from "./Player/MoveManager";
19
+ export * from "./presets";
package/src/logs/log.ts CHANGED
@@ -1,3 +1,10 @@
1
- export class Log {
2
- constructor(private id: string, private msg: string) {}
3
- }
1
+ export class Log extends Error {
2
+ readonly id: string;
3
+
4
+ constructor(id: string, msg: string) {
5
+ super(`[${id}] ${msg}`);
6
+ this.name = "RpgLog";
7
+ this.id = id;
8
+ Object.setPrototypeOf(this, new.target.prototype);
9
+ }
10
+ }
package/src/module.ts CHANGED
@@ -2,15 +2,80 @@ import { findModules, provideModules } from "@rpgjs/common";
2
2
  import { FactoryProvider } from "@signe/di";
3
3
  import { RpgServerEngine } from "./RpgServerEngine";
4
4
  import { RpgMap } from "./rooms/map";
5
+ import { RpgPlayer } from "./Player/Player";
6
+ import { RpgServer } from "./RpgServer";
5
7
 
6
- export function provideServerModules(modules: any[]): FactoryProvider {
8
+ /**
9
+ * Type for server modules that can be either:
10
+ * - An object implementing RpgServer interface
11
+ * - A class decorated with @RpgModule decorator
12
+ */
13
+ export type RpgServerModule = RpgServer | (new () => any);
14
+
15
+ /**
16
+ * Provides server modules configuration to Angular Dependency Injection
17
+ *
18
+ * This function accepts an array of server modules that can be either:
19
+ * - Objects implementing the RpgServer interface
20
+ * - Classes decorated with the @RpgModule decorator (which will be instantiated)
21
+ *
22
+ * @param modules - Array of server modules (objects or classes)
23
+ * @returns FactoryProvider configuration for Angular DI
24
+ * @example
25
+ * ```ts
26
+ * // Using an object
27
+ * provideServerModules([
28
+ * {
29
+ * player: {
30
+ * onConnected(player) {
31
+ * console.log('Player connected')
32
+ * }
33
+ * }
34
+ * }
35
+ * ])
36
+ *
37
+ * // Using a decorated class
38
+ * @RpgModule<RpgServer>({
39
+ * engine: {
40
+ * onStart(server) {
41
+ * console.log('Server started')
42
+ * }
43
+ * }
44
+ * })
45
+ * class MyServerModule {}
46
+ *
47
+ * provideServerModules([MyServerModule])
48
+ * ```
49
+ */
50
+ export function provideServerModules(modules: RpgServerModule[]): FactoryProvider {
7
51
  return provideModules(modules, "server", (modules, context) => {
8
52
  const mainModuleServer = findModules(context, 'Server')
9
53
  modules = [...mainModuleServer, ...modules]
10
54
  modules = modules.map((module) => {
55
+ // If module is a class (constructor function), instantiate it
56
+ // The RpgModule decorator adds properties to the prototype, which will be accessible via the instance
57
+ if (typeof module === 'function') {
58
+ const instance = new module() as any;
59
+ // Copy all enumerable properties (including from prototype) to a plain object
60
+ const moduleObj: any = {};
61
+ for (const key in instance) {
62
+ moduleObj[key] = instance[key];
63
+ }
64
+ module = moduleObj;
65
+ }
11
66
  if ('server' in module) {
12
67
  module = module.server as any;
13
68
  }
69
+ if (module.player?.props) {
70
+ module = {
71
+ ...module,
72
+ playerProps: {
73
+ load: (player: RpgPlayer) => {
74
+ player.setSync(module.player.props)
75
+ },
76
+ }
77
+ };
78
+ }
14
79
  if (module.maps && Array.isArray(module.maps)) {
15
80
  const maps = [...module.maps];
16
81
  module = {
@@ -18,15 +83,73 @@ export function provideServerModules(modules: any[]): FactoryProvider {
18
83
  maps: {
19
84
  load: (engine: RpgMap) => {
20
85
  maps.forEach((map) => {
21
- engine.maps.push(map);
86
+ // If map is a class (constructor function), extract properties from class and prototype
87
+ // Otherwise, use the object directly
88
+ let mapInstance: any;
89
+ if (typeof map === 'function') {
90
+ // Extract properties from the class (static properties set by @MapData decorator)
91
+ // and from the prototype (instance properties like _events)
92
+ // The decorator sets properties on both the class and prototype, so we check both
93
+ const MapClass = map as any;
94
+ mapInstance = {
95
+ id: MapClass.prototype?.id ?? MapClass.id,
96
+ file: MapClass.prototype?.file ?? MapClass.file,
97
+ type: MapClass.type,
98
+ name: MapClass.prototype?.name,
99
+ sounds: MapClass.prototype?.sounds,
100
+ weather: MapClass.prototype?.weather,
101
+ lowMemory: MapClass.prototype?.lowMemory,
102
+ stopAllSoundsBeforeJoin: MapClass.prototype?.stopAllSoundsBeforeJoin,
103
+ events: MapClass.prototype?._events,
104
+ syncSchema: MapClass.prototype?.$schema,
105
+ onLoad: MapClass.prototype?.onLoad,
106
+ onJoin: MapClass.prototype?.onJoin,
107
+ onLeave: MapClass.prototype?.onLeave,
108
+ };
109
+ } else {
110
+ mapInstance = map;
111
+ }
112
+ engine.maps.push(mapInstance);
113
+ });
114
+ },
115
+ }
116
+ };
117
+ }
118
+ if (module.worldMaps && Array.isArray(module.worldMaps)) {
119
+ const worldMaps = [...module.worldMaps];
120
+ module = {
121
+ ...module,
122
+ worldMaps: {
123
+ load: (engine: RpgMap) => {
124
+ worldMaps.forEach((worldMap) => {
125
+ engine.createDynamicWorldMaps(worldMap)
22
126
  });
23
127
  },
24
128
  }
25
129
  };
26
130
  }
131
+ if (module.database) {
132
+ const database = module.database;
133
+ module = {
134
+ ...module,
135
+ databaseHooks: {
136
+ load: async (engine: RpgMap) => {
137
+ const data = typeof database === 'function'
138
+ ? await database(engine)
139
+ : database;
140
+ if (!data || typeof data !== 'object') {
141
+ return;
142
+ }
143
+ for (const key in data) {
144
+ engine.addInDatabase(key, data[key]);
145
+ }
146
+ },
147
+ }
148
+ };
149
+ }
27
150
  return module;
28
151
  })
29
152
  return modules
30
153
  });
31
154
  }
32
-
155
+