@rpgjs/server 5.0.0-alpha.4 → 5.0.0-alpha.41

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 (101) 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 +34 -12
  11. package/dist/Player/ClassManager.d.ts +46 -13
  12. package/dist/Player/ComponentManager.d.ts +123 -0
  13. package/dist/Player/Components.d.ts +345 -0
  14. package/dist/Player/EffectManager.d.ts +86 -0
  15. package/dist/Player/ElementManager.d.ts +104 -0
  16. package/dist/Player/GoldManager.d.ts +22 -0
  17. package/dist/Player/GuiManager.d.ts +259 -0
  18. package/dist/Player/ItemFixture.d.ts +6 -0
  19. package/dist/Player/ItemManager.d.ts +450 -9
  20. package/dist/Player/MoveManager.d.ts +324 -69
  21. package/dist/Player/ParameterManager.d.ts +344 -14
  22. package/dist/Player/Player.d.ts +460 -8
  23. package/dist/Player/SkillManager.d.ts +197 -15
  24. package/dist/Player/StateManager.d.ts +89 -25
  25. package/dist/Player/VariableManager.d.ts +74 -0
  26. package/dist/RpgServer.d.ts +502 -64
  27. package/dist/RpgServerEngine.d.ts +2 -1
  28. package/dist/decorators/event.d.ts +46 -0
  29. package/dist/decorators/map.d.ts +287 -0
  30. package/dist/index.d.ts +10 -0
  31. package/dist/index.js +21653 -20900
  32. package/dist/index.js.map +1 -1
  33. package/dist/logs/log.d.ts +2 -3
  34. package/dist/module.d.ts +43 -1
  35. package/dist/presets/index.d.ts +0 -9
  36. package/dist/rooms/BaseRoom.d.ts +132 -0
  37. package/dist/rooms/lobby.d.ts +10 -2
  38. package/dist/rooms/map.d.ts +1236 -17
  39. package/dist/services/save.d.ts +43 -0
  40. package/dist/storage/index.d.ts +1 -0
  41. package/dist/storage/localStorage.d.ts +23 -0
  42. package/package.json +14 -10
  43. package/src/Gui/DialogGui.ts +19 -4
  44. package/src/Gui/GameoverGui.ts +39 -0
  45. package/src/Gui/Gui.ts +23 -1
  46. package/src/Gui/MenuGui.ts +155 -6
  47. package/src/Gui/NotificationGui.ts +1 -2
  48. package/src/Gui/SaveLoadGui.ts +60 -0
  49. package/src/Gui/ShopGui.ts +146 -16
  50. package/src/Gui/TitleGui.ts +39 -0
  51. package/src/Gui/index.ts +15 -2
  52. package/src/Player/BattleManager.ts +91 -49
  53. package/src/Player/ClassManager.ts +118 -50
  54. package/src/Player/ComponentManager.ts +425 -19
  55. package/src/Player/Components.ts +380 -0
  56. package/src/Player/EffectManager.ts +81 -44
  57. package/src/Player/ElementManager.ts +109 -86
  58. package/src/Player/GoldManager.ts +32 -35
  59. package/src/Player/GuiManager.ts +308 -150
  60. package/src/Player/ItemFixture.ts +4 -5
  61. package/src/Player/ItemManager.ts +774 -355
  62. package/src/Player/MoveManager.ts +1544 -774
  63. package/src/Player/ParameterManager.ts +546 -104
  64. package/src/Player/Player.ts +1163 -88
  65. package/src/Player/SkillManager.ts +520 -195
  66. package/src/Player/StateManager.ts +170 -182
  67. package/src/Player/VariableManager.ts +101 -63
  68. package/src/RpgServer.ts +525 -63
  69. package/src/core/context.ts +1 -0
  70. package/src/decorators/event.ts +61 -0
  71. package/src/decorators/map.ts +327 -0
  72. package/src/index.ts +11 -1
  73. package/src/logs/log.ts +10 -3
  74. package/src/module.ts +126 -3
  75. package/src/presets/index.ts +1 -10
  76. package/src/rooms/BaseRoom.ts +232 -0
  77. package/src/rooms/lobby.ts +25 -7
  78. package/src/rooms/map.ts +2502 -194
  79. package/src/services/save.ts +147 -0
  80. package/src/storage/index.ts +1 -0
  81. package/src/storage/localStorage.ts +76 -0
  82. package/tests/battle.spec.ts +375 -0
  83. package/tests/change-map.spec.ts +72 -0
  84. package/tests/class.spec.ts +274 -0
  85. package/tests/effect.spec.ts +219 -0
  86. package/tests/element.spec.ts +221 -0
  87. package/tests/event.spec.ts +80 -0
  88. package/tests/gold.spec.ts +99 -0
  89. package/tests/item.spec.ts +609 -0
  90. package/tests/module.spec.ts +38 -0
  91. package/tests/move.spec.ts +601 -0
  92. package/tests/player-param.spec.ts +28 -0
  93. package/tests/prediction-reconciliation.spec.ts +182 -0
  94. package/tests/random-move.spec.ts +65 -0
  95. package/tests/skill.spec.ts +658 -0
  96. package/tests/state.spec.ts +467 -0
  97. package/tests/variable.spec.ts +185 -0
  98. package/tests/world-maps.spec.ts +896 -0
  99. package/vite.config.ts +16 -0
  100. package/dist/Player/Event.d.ts +0 -0
  101. package/src/Player/Event.ts +0 -0
package/src/RpgServer.ts CHANGED
@@ -1,17 +1,45 @@
1
+ import { MapOptions } from "./decorators/map"
1
2
  import { RpgPlayer } from "./Player/Player"
2
3
  import { type RpgMap } from "./rooms/map"
3
4
  import { RpgServerEngine } from "./RpgServerEngine"
5
+ import { WorldMapConfig, RpgShape, type MapPhysicsInitContext, type MapPhysicsEntityContext } from "@rpgjs/common"
6
+ import { RpgEvent } from "./Player/Player"
4
7
 
5
- type RpgShape = any
6
- type RpgClassMap<T> = any
7
- type RpgClassEvent<T> = any
8
- type RpgEvent = any
8
+ type RpgClassMap<T> = new () => T
9
+ type RpgClassEvent<T> = RpgEvent
9
10
  type MatchMakerOption = any
10
11
  type RpgMatchMaker = any
11
12
  type IStoreState = any
12
- type TiledMap = any
13
- type WorldMap = any
14
- type MapOptions = any
13
+
14
+ /**
15
+ * Interface for world map configuration
16
+ *
17
+ * Represents a world that contains multiple maps with their spatial relationships.
18
+ * This is typically used with Tiled Map Editor's world files.
19
+ *
20
+ * @interface WorldMap
21
+ * @example
22
+ * ```ts
23
+ * const worldMap: WorldMap = {
24
+ * id: 'my-world',
25
+ * maps: [
26
+ * { id: 'map1', worldX: 0, worldY: 0, width: 800, height: 600 },
27
+ * { id: 'map2', worldX: 800, worldY: 0, width: 800, height: 600 }
28
+ * ]
29
+ * }
30
+ * ```
31
+ */
32
+ export interface WorldMap {
33
+ /** Optional world identifier */
34
+ id?: string;
35
+ /** Array of map configurations that belong to this world */
36
+ maps: WorldMapConfig[];
37
+ /** Only show adjacent maps (used by Tiled Map Editor) */
38
+ onlyShowAdjacentMaps?: boolean;
39
+ /** Type identifier (used by Tiled Map Editor, should be 'world') */
40
+ type?: 'world';
41
+ }
42
+
15
43
 
16
44
  export interface RpgServerEngineHooks {
17
45
  /**
@@ -150,6 +178,14 @@ export interface RpgPlayerHooks {
150
178
  */
151
179
  onConnected?: (player: RpgPlayer) => any
152
180
 
181
+ /**
182
+ * When the player starts the game from the lobby
183
+ *
184
+ * @prop { (player: RpgPlayer) => any } [onStart]
185
+ * @memberof RpgPlayerHooks
186
+ */
187
+ onStart?: (player: RpgPlayer) => any
188
+
153
189
  /**
154
190
  * When the player presses a key on the client side
155
191
  *
@@ -227,20 +263,364 @@ export interface RpgPlayerHooks {
227
263
  canChangeMap?: (player: RpgPlayer, nextMap: RpgClassMap<RpgMap>) => boolean | Promise<boolean>
228
264
  }
229
265
 
266
+ /**
267
+ * Event hooks interface for handling various event lifecycle methods
268
+ *
269
+ * @interface RpgEventHooks
270
+ * @since 4.0.0
271
+ */
230
272
  export interface RpgEventHooks {
273
+ /**
274
+ * Called as soon as the event is created on the map
275
+ *
276
+ * @param {RpgEvent} event - The event instance being initialized
277
+ * @returns {any}
278
+ * @memberof RpgEventHooks
279
+ * @example
280
+ * ```ts
281
+ * const eventHooks: RpgEventHooks = {
282
+ * onInit(event) {
283
+ * console.log(`Event ${event.name} initialized`)
284
+ * event.graphic('default-sprite')
285
+ * }
286
+ * }
287
+ * ```
288
+ */
231
289
  onInit?: (event: RpgEvent) => any,
290
+
291
+ /**
292
+ * Called when the event collides with a player and the player presses the action key
293
+ *
294
+ * @param {RpgEvent} event - The event being interacted with
295
+ * @param {RpgPlayer} player - The player performing the action
296
+ * @returns {any}
297
+ * @memberof RpgEventHooks
298
+ * @example
299
+ * ```ts
300
+ * const eventHooks: RpgEventHooks = {
301
+ * onAction(event, player) {
302
+ * player.showText('You activated the chest!')
303
+ * player.addItem('POTION', 1)
304
+ * }
305
+ * }
306
+ * ```
307
+ */
232
308
  onAction?: (event: RpgEvent, player: RpgPlayer) => any
309
+
310
+ /**
311
+ * Called before an event object is created and added to the map
312
+ * Allows modification of event properties before instantiation
313
+ *
314
+ * @param {any} object - The event object data before creation
315
+ * @param {RpgMap} map - The map where the event will be created
316
+ * @returns {any}
317
+ * @memberof RpgEventHooks
318
+ * @example
319
+ * ```ts
320
+ * const eventHooks: RpgEventHooks = {
321
+ * onBeforeCreated(object, map) {
322
+ * // Modify event properties based on map conditions
323
+ * if (map.id === 'dungeon') {
324
+ * object.graphic = 'monster-sprite'
325
+ * }
326
+ * }
327
+ * }
328
+ * ```
329
+ */
233
330
  onBeforeCreated?: (object: any, map: RpgMap) => any
331
+
332
+ /**
333
+ * Called when a player or another event enters a shape attached to this event
334
+ *
335
+ * @param {RpgEvent} event - The event with the attached shape
336
+ * @param {RpgPlayer} player - The player entering the shape
337
+ * @param {RpgShape} shape - The shape being entered
338
+ * @returns {any}
339
+ * @since 4.1.0
340
+ * @memberof RpgEventHooks
341
+ * @example
342
+ * ```ts
343
+ * const eventHooks: RpgEventHooks = {
344
+ * onDetectInShape(event, player, shape) {
345
+ * console.log(`Player ${player.name} entered detection zone`)
346
+ * player.showText('You are being watched...')
347
+ * }
348
+ * }
349
+ * ```
350
+ */
234
351
  onDetectInShape?: (event: RpgEvent, player: RpgPlayer, shape: RpgShape) => any
352
+
353
+ /**
354
+ * Called when a player or another event leaves a shape attached to this event
355
+ *
356
+ * @param {RpgEvent} event - The event with the attached shape
357
+ * @param {RpgPlayer} player - The player leaving the shape
358
+ * @param {RpgShape} shape - The shape being left
359
+ * @returns {any}
360
+ * @since 4.1.0
361
+ * @memberof RpgEventHooks
362
+ * @example
363
+ * ```ts
364
+ * const eventHooks: RpgEventHooks = {
365
+ * onDetectOutShape(event, player, shape) {
366
+ * console.log(`Player ${player.name} left detection zone`)
367
+ * player.showText('You escaped the watch...')
368
+ * }
369
+ * }
370
+ * ```
371
+ */
235
372
  onDetectOutShape?: (event: RpgEvent, player: RpgPlayer, shape: RpgShape) => any
373
+
374
+ /**
375
+ * Called when the event enters a shape on the map
376
+ *
377
+ * @param {RpgEvent} event - The event entering the shape
378
+ * @param {RpgShape} shape - The shape being entered
379
+ * @returns {any}
380
+ * @memberof RpgEventHooks
381
+ * @example
382
+ * ```ts
383
+ * const eventHooks: RpgEventHooks = {
384
+ * onInShape(event, shape) {
385
+ * console.log(`Event entered shape: ${shape.id}`)
386
+ * event.speed = 1 // Slow down in this area
387
+ * }
388
+ * }
389
+ * ```
390
+ */
236
391
  onInShape?: (event: RpgEvent, shape: RpgShape) => any
392
+
393
+ /**
394
+ * Called when the event leaves a shape on the map
395
+ *
396
+ * @param {RpgEvent} event - The event leaving the shape
397
+ * @param {RpgShape} shape - The shape being left
398
+ * @returns {any}
399
+ * @memberof RpgEventHooks
400
+ * @example
401
+ * ```ts
402
+ * const eventHooks: RpgEventHooks = {
403
+ * onOutShape(event, shape) {
404
+ * console.log(`Event left shape: ${shape.id}`)
405
+ * event.speed = 3 // Resume normal speed
406
+ * }
407
+ * }
408
+ * ```
409
+ */
237
410
  onOutShape?: (event: RpgEvent, shape: RpgShape) => any
411
+
412
+ /**
413
+ * Called when the event collides with a player (without requiring action key press)
414
+ *
415
+ * @param {RpgEvent} event - The event touching the player
416
+ * @param {RpgPlayer} player - The player being touched
417
+ * @returns {any}
418
+ * @memberof RpgEventHooks
419
+ * @example
420
+ * ```ts
421
+ * const eventHooks: RpgEventHooks = {
422
+ * onPlayerTouch(event, player) {
423
+ * player.hp -= 10 // Damage on touch
424
+ * player.showText('Ouch! You touched a spike!')
425
+ * }
426
+ * }
427
+ * ```
428
+ */
238
429
  onPlayerTouch?: (event: RpgEvent, player: RpgPlayer) => any
430
+
431
+ /**
432
+ * Called whenever any event on the map (including itself) is executed or changes state
433
+ * Useful for creating reactive events that respond to map state changes
434
+ *
435
+ * @param {RpgEvent} event - The event listening for changes
436
+ * @param {RpgPlayer} player - The player involved in the change
437
+ * @returns {any}
438
+ * @memberof RpgEventHooks
439
+ * @example
440
+ * ```ts
441
+ * const eventHooks: RpgEventHooks = {
442
+ * onChanges(event, player) {
443
+ * // Change chest graphic based on game state
444
+ * if (player.getVariable('BATTLE_END')) {
445
+ * event.graphic('chest-open')
446
+ * } else {
447
+ * event.graphic('chest-close')
448
+ * }
449
+ * }
450
+ * }
451
+ * ```
452
+ */
239
453
  onChanges?: (event: RpgEvent, player: RpgPlayer) => any
240
454
  }
241
455
 
456
+ /**
457
+ * Map hooks interface for handling map lifecycle events
458
+ *
459
+ * These hooks are global hooks that apply to all maps in the game.
460
+ * They are defined in the RpgModule configuration and executed for every map instance.
461
+ *
462
+ * @interface RpgMapHooks
463
+ * @since 4.0.0
464
+ */
242
465
  export interface RpgMapHooks {
243
- onBeforeUpdate<T = RpgMap>(mapData: any, map: T): T
466
+ /**
467
+ * Called before a map is updated with new data
468
+ * Allows modification of map data before the update is applied
469
+ *
470
+ * The `mapData` parameter contains the loaded map data (retrieved from request body)
471
+ * You can modify the map before the update is processed
472
+ *
473
+ * @template T - Type of the incoming map data
474
+ * @template U - Type of the map instance (defaults to RpgMap)
475
+ * @param {T} mapData - The map data loaded from external source (e.g., request body)
476
+ * @param {U} map - The current map instance being updated
477
+ * @returns {U | Promise<U>} The modified map instance or a promise resolving to it
478
+ * @memberof RpgMapHooks
479
+ * @example
480
+ * ```ts
481
+ * const mapHooks: RpgMapHooks = {
482
+ * onBeforeUpdate(mapData, map) {
483
+ * // Modify map properties based on incoming data
484
+ * if (mapData.weather === 'rain') {
485
+ * map.setWeatherEffect('rain')
486
+ * }
487
+ *
488
+ * // Add custom properties from external data
489
+ * map.customProperty = mapData.customValue
490
+ *
491
+ * return map
492
+ * }
493
+ * }
494
+ * ```
495
+ *
496
+ * @example
497
+ * ```ts
498
+ * // Async example with database operations
499
+ * const mapHooks: RpgMapHooks = {
500
+ * async onBeforeUpdate(mapData, map) {
501
+ * // Load additional data from database
502
+ * const additionalData = await database.getMapExtras(map.id)
503
+ *
504
+ * // Apply modifications
505
+ * map.events = [...map.events, ...additionalData.events]
506
+ * map.npcs = additionalData.npcs
507
+ *
508
+ * return map
509
+ * }
510
+ * }
511
+ * ```
512
+ */
513
+ onBeforeUpdate<T, U = RpgMap>(mapData: T, map: U): U | Promise<U>
514
+
515
+ /**
516
+ * Called when a map is loaded and initialized
517
+ *
518
+ * This hook is executed once when the map data is loaded and ready.
519
+ * It applies to all maps globally. Use this to initialize map-specific properties
520
+ * or setup that should happen for every map.
521
+ *
522
+ * @param {RpgMap} map - The map instance that was loaded
523
+ * @returns {any}
524
+ * @memberof RpgMapHooks
525
+ * @example
526
+ * ```ts
527
+ * const mapHooks: RpgMapHooks = {
528
+ * onLoad(map: RpgMap) {
529
+ * console.log(`Map ${map.id} loaded`)
530
+ * // Initialize global map properties
531
+ * }
532
+ * }
533
+ * ```
534
+ */
535
+ onLoad?: (map: RpgMap) => any
536
+
537
+ /**
538
+ * Called when a player joins any map
539
+ *
540
+ * This hook is executed each time a player joins any map in the game.
541
+ * It applies globally to all maps. Use this to perform actions that should
542
+ * happen whenever a player enters any map.
543
+ *
544
+ * @param {RpgPlayer} player - The player joining the map
545
+ * @param {RpgMap} map - The map instance the player joined
546
+ * @returns {any}
547
+ * @memberof RpgMapHooks
548
+ * @example
549
+ * ```ts
550
+ * const mapHooks: RpgMapHooks = {
551
+ * onJoin(player: RpgPlayer, map: RpgMap) {
552
+ * console.log(`${player.name} joined map ${map.id}`)
553
+ * // Perform global actions when player joins any map
554
+ * }
555
+ * }
556
+ * ```
557
+ */
558
+ onJoin?: (player: RpgPlayer, map: RpgMap) => any
559
+
560
+ /**
561
+ * Called when a player leaves any map
562
+ *
563
+ * This hook is executed each time a player leaves any map in the game.
564
+ * It applies globally to all maps. Use this to perform cleanup or actions
565
+ * that should happen whenever a player exits any map.
566
+ *
567
+ * @param {RpgPlayer} player - The player leaving the map
568
+ * @param {RpgMap} map - The map instance the player left
569
+ * @returns {any}
570
+ * @memberof RpgMapHooks
571
+ * @example
572
+ * ```ts
573
+ * const mapHooks: RpgMapHooks = {
574
+ * onLeave(player: RpgPlayer, map: RpgMap) {
575
+ * console.log(`${player.name} left map ${map.id}`)
576
+ * // Perform global cleanup when player leaves any map
577
+ * }
578
+ * }
579
+ * ```
580
+ */
581
+ onLeave?: (player: RpgPlayer, map: RpgMap) => any
582
+
583
+ /**
584
+ * Called when the map physics world is initialized.
585
+ *
586
+ * This hook runs each time `loadPhysic()` prepares the physics world, after static
587
+ * map hitboxes are created and before dynamic player/event bodies are hydrated.
588
+ *
589
+ * @param {RpgMap} map - The map instance
590
+ * @param {MapPhysicsInitContext} context - Physics initialization context
591
+ * @returns {any}
592
+ * @memberof RpgMapHooks
593
+ */
594
+ onPhysicsInit?: (map: RpgMap, context: MapPhysicsInitContext) => any
595
+
596
+ /**
597
+ * Called when a dynamic character physics body is added to the map.
598
+ *
599
+ * @param {RpgMap} map - The map instance
600
+ * @param {MapPhysicsEntityContext} context - Added entity context
601
+ * @returns {any}
602
+ * @memberof RpgMapHooks
603
+ */
604
+ onPhysicsEntityAdd?: (map: RpgMap, context: MapPhysicsEntityContext) => any
605
+
606
+ /**
607
+ * Called when a dynamic character physics body is removed from the map.
608
+ *
609
+ * @param {RpgMap} map - The map instance
610
+ * @param {MapPhysicsEntityContext} context - Removed entity context
611
+ * @returns {any}
612
+ * @memberof RpgMapHooks
613
+ */
614
+ onPhysicsEntityRemove?: (map: RpgMap, context: MapPhysicsEntityContext) => any
615
+
616
+ /**
617
+ * Called when the map physics world is reset (before reload).
618
+ *
619
+ * @param {RpgMap} map - The map instance
620
+ * @returns {any}
621
+ * @memberof RpgMapHooks
622
+ */
623
+ onPhysicsReset?: (map: RpgMap) => any
244
624
  }
245
625
 
246
626
  export interface RpgServer {
@@ -254,14 +634,14 @@ export interface RpgServer {
254
634
  * @example
255
635
  *
256
636
  * ```ts
257
- * import { RpgServer, RpgModule } from '@rpgjs/server'
637
+ * import { RpgServer } from '@rpgjs/server'
638
+ * import { defineModule } from '@rpgjs/common'
258
639
  *
259
- * @RpgModule<RpgServer>({
640
+ * export default defineModule<RpgServer>({
260
641
  * hooks: {
261
642
  * player: ['onAuth']
262
643
  * }
263
644
  * })
264
- * class RpgServerEngine { }
265
645
  * ```
266
646
  *
267
647
  * Emit the hook:
@@ -301,18 +681,18 @@ export interface RpgServer {
301
681
  * Object containing the hooks concerning the engine
302
682
  *
303
683
  * ```ts
304
- * import { RpgServerEngine, RpgServerEngineHooks, RpgModule, RpgClient } from '@rpgjs/server'
684
+ * import { RpgServerEngine, RpgServerEngineHooks, RpgServer } from '@rpgjs/server'
685
+ * import { defineModule } from '@rpgjs/common'
305
686
  *
306
- * const engine: RpgEngineHooks = {
687
+ * const engine: RpgServerEngineHooks = {
307
688
  * onStart(server: RpgServerEngine) {
308
689
  * console.log('server is started')
309
690
  * }
310
691
  * }
311
692
  *
312
- * @RpgModule<RpgServer>({
693
+ * export default defineModule<RpgServer>({
313
694
  * engine
314
695
  * })
315
- * class RpgServerModule {}
316
696
  * ```
317
697
  *
318
698
  * @prop {RpgServerEngineHooks} [engine]
@@ -324,7 +704,8 @@ export interface RpgServer {
324
704
  * Give the `player` object hooks. Each time a player connects, an instance of `RpgPlayer` is created.
325
705
  *
326
706
  * ```ts
327
- * import { RpgPlayer, RpgServer, RpgPlayerHooks, RpgModule } from '@rpgjs/server'
707
+ * import { RpgPlayer, RpgServer, RpgPlayerHooks } from '@rpgjs/server'
708
+ * import { defineModule } from '@rpgjs/common'
328
709
  *
329
710
  * const player: RpgPlayerHooks = {
330
711
  * onConnected(player: RpgPlayer) {
@@ -332,10 +713,9 @@ export interface RpgServer {
332
713
  * }
333
714
  * }
334
715
  *
335
- * @RpgModule<RpgServer>({
716
+ * export default defineModule<RpgServer>({
336
717
  * player
337
718
  * })
338
- * class RpgServerEngine { }
339
719
  * ```
340
720
  *
341
721
  * @prop {RpgClassPlayer<RpgPlayer>} [player]
@@ -347,28 +727,30 @@ export interface RpgServer {
347
727
  * References all data in the server. it is mainly used to retrieve data according to their identifier
348
728
  *
349
729
  * ```ts
350
- * import { RpgServer, RpgModule } from '@rpgjs/server'
730
+ * import { RpgServer } from '@rpgjs/server'
731
+ * import { defineModule } from '@rpgjs/common'
351
732
  * import { Potion } from 'my-database/items/potion'
352
733
  *
353
- * @RpgModule<RpgServer>({
734
+ * export default defineModule<RpgServer>({
354
735
  * database: {
355
736
  * Potion
356
737
  * }
357
738
  * })
358
- * class RpgServerEngine { }
359
739
  * ```
360
740
  *
361
- * @prop { { [dataName]: data } } [database]
741
+ * @prop { { [dataName]: data } | (engine: RpgMap) => { [dataName]: data } | Promise<{ [dataName]: data }> } [database]
362
742
  * @memberof RpgServer
363
743
  * */
364
- database?: object | any[],
744
+ database?: object | any[] | ((engine: RpgMap) => object | any[] | Promise<object | any[]>),
365
745
 
366
746
  /**
367
- * Array of all maps. Each element is an `RpgMap` class
747
+ * Array of all maps. Each element can be either a class (decorated with `@MapData` or not) or a `MapOptions` object
368
748
  *
369
749
  * ```ts
370
- * import { RpgMap, MapData, RpgServer, RpgModule } from '@rpgjs/server'
750
+ * import { RpgMap, MapData, RpgServer } from '@rpgjs/server'
751
+ * import { defineModule } from '@rpgjs/common'
371
752
  *
753
+ * // Class that extends RpgMap (optional)
372
754
  * @MapData({
373
755
  * id: 'town',
374
756
  * file: require('./tmx/mymap.tmx'),
@@ -376,18 +758,29 @@ export interface RpgServer {
376
758
  * })
377
759
  * class TownMap extends RpgMap { }
378
760
  *
379
- * @RpgModule<RpgServer>({
761
+ * // Or a simple class without extending RpgMap
762
+ * @MapData({
763
+ * id: 'map',
764
+ * file: '',
765
+ * events: [{ event: Event() }]
766
+ * })
767
+ * class SimpleMap {}
768
+ *
769
+ * export default defineModule<RpgServer>({
380
770
  * maps: [
381
- * TownMap
771
+ * TownMap,
772
+ * SimpleMap
382
773
  * ]
383
774
  * })
384
- * class RpgServerEngine { }
385
775
  * ```
386
776
  *
387
777
  * It is possible to just give the object as well
388
778
  *
389
779
  * ```ts
390
- * @RpgModule<RpgServer>({
780
+ * import { RpgServer } from '@rpgjs/server'
781
+ * import { defineModule } from '@rpgjs/common'
782
+ *
783
+ * export default defineModule<RpgServer>({
391
784
  * maps: [
392
785
  * {
393
786
  * id: 'town',
@@ -396,25 +789,65 @@ export interface RpgServer {
396
789
  * }
397
790
  * ]
398
791
  * })
399
- * class RpgServerEngine { }
400
792
  * ```
401
793
  *
402
794
  * Since version 3.0.0-beta.8, you can just pass the path to the file. The identifier will then be the name of the file
403
795
  *
404
796
  * ```ts
405
- * @RpgModule<RpgServer>({
797
+ * import { RpgServer } from '@rpgjs/server'
798
+ * import { defineModule } from '@rpgjs/common'
799
+ *
800
+ * export default defineModule<RpgServer>({
406
801
  * maps: [
407
802
  * require('./tmx/mymap.tmx') // id is "mymap"
408
803
  * ]
409
804
  * })
410
- * class RpgServerEngine { }
411
805
  * ```
412
806
  *
413
- * @prop {RpgClassMap<RpgMap>[]} [maps]
807
+ * @prop {(new () => any) | MapOptions)[]} [maps]
414
808
  * @memberof RpgServer
415
809
  * */
416
- maps?: RpgClassMap<RpgMap>[] | MapOptions[] | string[] | TiledMap[],
810
+ maps?: ((new () => any) | MapOptions)[],
417
811
 
812
+ /**
813
+ * Global map hooks that apply to all maps in the game
814
+ *
815
+ * These hooks are executed for every map instance and allow you to define
816
+ * global behavior that should happen for all maps. They are different from
817
+ * map-specific hooks defined in `@MapData` which only apply to a specific map class.
818
+ *
819
+ * ```ts
820
+ * import { RpgServer, RpgMapHooks, RpgMap, RpgPlayer } from '@rpgjs/server'
821
+ * import { defineModule } from '@rpgjs/common'
822
+ *
823
+ * const mapHooks: RpgMapHooks = {
824
+ * onLoad(map: RpgMap) {
825
+ * console.log(`Map ${map.id} loaded`)
826
+ * // Initialize global map properties
827
+ * },
828
+ * onJoin(player: RpgPlayer, map: RpgMap) {
829
+ * console.log(`${player.name} joined map ${map.id}`)
830
+ * // Perform global actions when player joins any map
831
+ * },
832
+ * onLeave(player: RpgPlayer, map: RpgMap) {
833
+ * console.log(`${player.name} left map ${map.id}`)
834
+ * // Perform global cleanup when player leaves any map
835
+ * },
836
+ * onBeforeUpdate(mapData, map) {
837
+ * // Modify map data before update
838
+ * return map
839
+ * }
840
+ * }
841
+ *
842
+ * export default defineModule<RpgServer>({
843
+ * map: mapHooks
844
+ * })
845
+ * ```
846
+ *
847
+ * @prop {RpgMapHooks} [map]
848
+ * @memberof RpgServer
849
+ * @since 4.0.0
850
+ * */
418
851
  map?: RpgMapHooks
419
852
 
420
853
  event?: RpgEventHooks
@@ -430,41 +863,62 @@ export interface RpgServer {
430
863
  events?: RpgClassEvent<RpgEvent>[]
431
864
 
432
865
  /**
433
- * Loads the content of a `.world` file from Tiled Map Editor into the map scene
866
+ * Array of world map configurations
434
867
  *
435
- * > Note, that if the map already exists (i.e. you have already defined an RpgMap), the world will retrieve the already existing map. Otherwise it will create a new map
868
+ * Loads the content of a `.world` file from Tiled Map Editor into the map scene.
869
+ * Each world contains multiple maps with their spatial relationships.
436
870
  *
437
- * @prop {object[]} [worldMaps]
438
- * object is
439
- * ```ts
440
- * {
441
- * id?: string
442
- * maps: {
443
- * id?: string
444
- * properties?: object
445
- * fileName: string;
446
- height: number;
447
- width: number;
448
- x: number;
449
- y: number;
450
- * }[],
451
- onlyShowAdjacentMaps: boolean, // only for Tiled Map Editor
452
- type: 'world' // only for Tiled Map Editor
453
- * }
454
- * ```
871
+ * > Note: If a map already exists (i.e. you have already defined an RpgMap),
872
+ * > the world will retrieve the already existing map. Otherwise it will create a new map.
873
+ *
874
+ * @prop {WorldMap[]} [worldMaps]
455
875
  * @since 3.0.0-beta.8
876
+ * @memberof RpgServer
456
877
  * @example
457
878
  * ```ts
879
+ * import { RpgServer } from '@rpgjs/server'
880
+ * import { defineModule } from '@rpgjs/common'
458
881
  * import myworld from 'myworld.world'
459
882
  *
460
- * @RpgModule<RpgServer>({
461
- * worldMaps: [
462
- * myworld
463
- * ]
883
+ * export default defineModule<RpgServer>({
884
+ * worldMaps: [
885
+ * myworld
886
+ * ]
887
+ * })
888
+ * ```
889
+ *
890
+ * @example
891
+ * ```ts
892
+ * import { RpgServer } from '@rpgjs/server'
893
+ * import { defineModule } from '@rpgjs/common'
894
+ *
895
+ * // Manual world configuration
896
+ * export default defineModule<RpgServer>({
897
+ * worldMaps: [
898
+ * {
899
+ * id: 'my-world',
900
+ * maps: [
901
+ * {
902
+ * id: 'map1',
903
+ * worldX: 0,
904
+ * worldY: 0,
905
+ * width: 800,
906
+ * height: 600,
907
+ * tileWidth: 32,
908
+ * tileHeight: 32
909
+ * },
910
+ * {
911
+ * id: 'map2',
912
+ * worldX: 800,
913
+ * worldY: 0,
914
+ * width: 800,
915
+ * height: 600
916
+ * }
917
+ * ]
918
+ * }
919
+ * ]
464
920
  * })
465
- * class RpgServerEngine { }
466
921
  * ```
467
- * @memberof RpgServer
468
922
  */
469
923
  worldMaps?: WorldMap[]
470
924
 
@@ -489,11 +943,12 @@ export interface RpgServer {
489
943
  * Example:
490
944
  *
491
945
  * ```ts
492
- * import { RpgModule, RpgServer, Presets } from '@rpgjs/server'
946
+ * import { RpgServer, Presets } from '@rpgjs/server'
947
+ * import { defineModule } from '@rpgjs/common'
493
948
  *
494
949
  * const { ATK, PDEF } = Presets
495
950
  *
496
- * @RpgModule<RpgServer>({
951
+ * export default defineModule<RpgServer>({
497
952
  * damageFormulas: {
498
953
  * damagePhysic(a, b) {
499
954
  * let damage = a[ATK] - b[PDEF]
@@ -502,7 +957,6 @@ export interface RpgServer {
502
957
  * }
503
958
  * }
504
959
  * })
505
- * class RpgServerEngine { }
506
960
  * ```
507
961
  * @prop {object} damageFormulas
508
962
  * @memberof RpgServer
@@ -514,6 +968,10 @@ export interface RpgServer {
514
968
  coefficientElements?: (a, b, bDef) => number
515
969
  }
516
970
 
971
+ /*
972
+ * Scalability configuration for the server
973
+ * @deprecated
974
+ */
517
975
  scalability?: {
518
976
  matchMaker: MatchMakerOption,
519
977
  stateStore: IStoreState
@@ -522,4 +980,8 @@ export interface RpgServer {
522
980
  doChangeServer(store: IStoreState, matchMaker: RpgMatchMaker, player: RpgPlayer): Promise<boolean> | boolean
523
981
  }
524
982
  }
983
+
984
+ throttleSync?: number
985
+ throttleStorage?: number
986
+ sessionExpiryTime?: number
525
987
  }