@rpgjs/server 5.0.0-alpha.21 → 5.0.0-alpha.23

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.
@@ -1,16 +1,41 @@
1
- import { RpgPlayer } from './Player/Player';
1
+ import { MapOptions } from './decorators/map';
2
+ import { RpgPlayer, RpgEvent } from './Player/Player';
2
3
  import { RpgMap } from './rooms/map';
3
4
  import { RpgServerEngine } from './RpgServerEngine';
4
- type RpgShape = any;
5
- type RpgClassMap<T> = any;
6
- type RpgClassEvent<T> = any;
7
- type RpgEvent = any;
5
+ import { WorldMapConfig, RpgShape } from '@rpgjs/common';
6
+ type RpgClassMap<T> = new () => T;
7
+ type RpgClassEvent<T> = RpgEvent;
8
8
  type MatchMakerOption = any;
9
9
  type RpgMatchMaker = any;
10
10
  type IStoreState = any;
11
- type TiledMap = any;
12
- type WorldMap = any;
13
- type MapOptions = any;
11
+ /**
12
+ * Interface for world map configuration
13
+ *
14
+ * Represents a world that contains multiple maps with their spatial relationships.
15
+ * This is typically used with Tiled Map Editor's world files.
16
+ *
17
+ * @interface WorldMap
18
+ * @example
19
+ * ```ts
20
+ * const worldMap: WorldMap = {
21
+ * id: 'my-world',
22
+ * maps: [
23
+ * { id: 'map1', worldX: 0, worldY: 0, width: 800, height: 600 },
24
+ * { id: 'map2', worldX: 800, worldY: 0, width: 800, height: 600 }
25
+ * ]
26
+ * }
27
+ * ```
28
+ */
29
+ export interface WorldMap {
30
+ /** Optional world identifier */
31
+ id?: string;
32
+ /** Array of map configurations that belong to this world */
33
+ maps: WorldMapConfig[];
34
+ /** Only show adjacent maps (used by Tiled Map Editor) */
35
+ onlyShowAdjacentMaps?: boolean;
36
+ /** Type identifier (used by Tiled Map Editor, should be 'world') */
37
+ type?: 'world';
38
+ }
14
39
  export interface RpgServerEngineHooks {
15
40
  /**
16
41
  * When the server starts
@@ -394,6 +419,9 @@ export interface RpgEventHooks {
394
419
  /**
395
420
  * Map hooks interface for handling map lifecycle events
396
421
  *
422
+ * These hooks are global hooks that apply to all maps in the game.
423
+ * They are defined in the RpgModule configuration and executed for every map instance.
424
+ *
397
425
  * @interface RpgMapHooks
398
426
  * @since 4.0.0
399
427
  */
@@ -446,6 +474,71 @@ export interface RpgMapHooks {
446
474
  * ```
447
475
  */
448
476
  onBeforeUpdate<T, U = RpgMap>(mapData: T, map: U): U | Promise<U>;
477
+ /**
478
+ * Called when a map is loaded and initialized
479
+ *
480
+ * This hook is executed once when the map data is loaded and ready.
481
+ * It applies to all maps globally. Use this to initialize map-specific properties
482
+ * or setup that should happen for every map.
483
+ *
484
+ * @param {RpgMap} map - The map instance that was loaded
485
+ * @returns {any}
486
+ * @memberof RpgMapHooks
487
+ * @example
488
+ * ```ts
489
+ * const mapHooks: RpgMapHooks = {
490
+ * onLoad(map: RpgMap) {
491
+ * console.log(`Map ${map.id} loaded`)
492
+ * // Initialize global map properties
493
+ * }
494
+ * }
495
+ * ```
496
+ */
497
+ onLoad?: (map: RpgMap) => any;
498
+ /**
499
+ * Called when a player joins any map
500
+ *
501
+ * This hook is executed each time a player joins any map in the game.
502
+ * It applies globally to all maps. Use this to perform actions that should
503
+ * happen whenever a player enters any map.
504
+ *
505
+ * @param {RpgPlayer} player - The player joining the map
506
+ * @param {RpgMap} map - The map instance the player joined
507
+ * @returns {any}
508
+ * @memberof RpgMapHooks
509
+ * @example
510
+ * ```ts
511
+ * const mapHooks: RpgMapHooks = {
512
+ * onJoin(player: RpgPlayer, map: RpgMap) {
513
+ * console.log(`${player.name} joined map ${map.id}`)
514
+ * // Perform global actions when player joins any map
515
+ * }
516
+ * }
517
+ * ```
518
+ */
519
+ onJoin?: (player: RpgPlayer, map: RpgMap) => any;
520
+ /**
521
+ * Called when a player leaves any map
522
+ *
523
+ * This hook is executed each time a player leaves any map in the game.
524
+ * It applies globally to all maps. Use this to perform cleanup or actions
525
+ * that should happen whenever a player exits any map.
526
+ *
527
+ * @param {RpgPlayer} player - The player leaving the map
528
+ * @param {RpgMap} map - The map instance the player left
529
+ * @returns {any}
530
+ * @memberof RpgMapHooks
531
+ * @example
532
+ * ```ts
533
+ * const mapHooks: RpgMapHooks = {
534
+ * onLeave(player: RpgPlayer, map: RpgMap) {
535
+ * console.log(`${player.name} left map ${map.id}`)
536
+ * // Perform global cleanup when player leaves any map
537
+ * }
538
+ * }
539
+ * ```
540
+ */
541
+ onLeave?: (player: RpgPlayer, map: RpgMap) => any;
449
542
  }
450
543
  export interface RpgServer {
451
544
  /**
@@ -458,14 +551,14 @@ export interface RpgServer {
458
551
  * @example
459
552
  *
460
553
  * ```ts
461
- * import { RpgServer, RpgModule } from '@rpgjs/server'
554
+ * import { RpgServer } from '@rpgjs/server'
555
+ * import { defineModule } from '@rpgjs/common'
462
556
  *
463
- * @RpgModule<RpgServer>({
557
+ * export default defineModule<RpgServer>({
464
558
  * hooks: {
465
559
  * player: ['onAuth']
466
560
  * }
467
561
  * })
468
- * class RpgServerEngine { }
469
562
  * ```
470
563
  *
471
564
  * Emit the hook:
@@ -504,18 +597,18 @@ export interface RpgServer {
504
597
  * Object containing the hooks concerning the engine
505
598
  *
506
599
  * ```ts
507
- * import { RpgServerEngine, RpgServerEngineHooks, RpgModule, RpgClient } from '@rpgjs/server'
600
+ * import { RpgServerEngine, RpgServerEngineHooks, RpgServer } from '@rpgjs/server'
601
+ * import { defineModule } from '@rpgjs/common'
508
602
  *
509
- * const engine: RpgEngineHooks = {
603
+ * const engine: RpgServerEngineHooks = {
510
604
  * onStart(server: RpgServerEngine) {
511
605
  * console.log('server is started')
512
606
  * }
513
607
  * }
514
608
  *
515
- * @RpgModule<RpgServer>({
609
+ * export default defineModule<RpgServer>({
516
610
  * engine
517
611
  * })
518
- * class RpgServerModule {}
519
612
  * ```
520
613
  *
521
614
  * @prop {RpgServerEngineHooks} [engine]
@@ -526,7 +619,8 @@ export interface RpgServer {
526
619
  * Give the `player` object hooks. Each time a player connects, an instance of `RpgPlayer` is created.
527
620
  *
528
621
  * ```ts
529
- * import { RpgPlayer, RpgServer, RpgPlayerHooks, RpgModule } from '@rpgjs/server'
622
+ * import { RpgPlayer, RpgServer, RpgPlayerHooks } from '@rpgjs/server'
623
+ * import { defineModule } from '@rpgjs/common'
530
624
  *
531
625
  * const player: RpgPlayerHooks = {
532
626
  * onConnected(player: RpgPlayer) {
@@ -534,10 +628,9 @@ export interface RpgServer {
534
628
  * }
535
629
  * }
536
630
  *
537
- * @RpgModule<RpgServer>({
631
+ * export default defineModule<RpgServer>({
538
632
  * player
539
633
  * })
540
- * class RpgServerEngine { }
541
634
  * ```
542
635
  *
543
636
  * @prop {RpgClassPlayer<RpgPlayer>} [player]
@@ -548,15 +641,15 @@ export interface RpgServer {
548
641
  * References all data in the server. it is mainly used to retrieve data according to their identifier
549
642
  *
550
643
  * ```ts
551
- * import { RpgServer, RpgModule } from '@rpgjs/server'
644
+ * import { RpgServer } from '@rpgjs/server'
645
+ * import { defineModule } from '@rpgjs/common'
552
646
  * import { Potion } from 'my-database/items/potion'
553
647
  *
554
- * @RpgModule<RpgServer>({
648
+ * export default defineModule<RpgServer>({
555
649
  * database: {
556
650
  * Potion
557
651
  * }
558
652
  * })
559
- * class RpgServerEngine { }
560
653
  * ```
561
654
  *
562
655
  * @prop { { [dataName]: data } } [database]
@@ -564,11 +657,13 @@ export interface RpgServer {
564
657
  * */
565
658
  database?: object | any[];
566
659
  /**
567
- * Array of all maps. Each element is an `RpgMap` class
660
+ * Array of all maps. Each element can be either a class (decorated with `@MapData` or not) or a `MapOptions` object
568
661
  *
569
662
  * ```ts
570
- * import { RpgMap, MapData, RpgServer, RpgModule } from '@rpgjs/server'
663
+ * import { RpgMap, MapData, RpgServer } from '@rpgjs/server'
664
+ * import { defineModule } from '@rpgjs/common'
571
665
  *
666
+ * // Class that extends RpgMap (optional)
572
667
  * @MapData({
573
668
  * id: 'town',
574
669
  * file: require('./tmx/mymap.tmx'),
@@ -576,18 +671,29 @@ export interface RpgServer {
576
671
  * })
577
672
  * class TownMap extends RpgMap { }
578
673
  *
579
- * @RpgModule<RpgServer>({
674
+ * // Or a simple class without extending RpgMap
675
+ * @MapData({
676
+ * id: 'map',
677
+ * file: '',
678
+ * events: [{ event: Event() }]
679
+ * })
680
+ * class SimpleMap {}
681
+ *
682
+ * export default defineModule<RpgServer>({
580
683
  * maps: [
581
- * TownMap
684
+ * TownMap,
685
+ * SimpleMap
582
686
  * ]
583
687
  * })
584
- * class RpgServerEngine { }
585
688
  * ```
586
689
  *
587
690
  * It is possible to just give the object as well
588
691
  *
589
692
  * ```ts
590
- * @RpgModule<RpgServer>({
693
+ * import { RpgServer } from '@rpgjs/server'
694
+ * import { defineModule } from '@rpgjs/common'
695
+ *
696
+ * export default defineModule<RpgServer>({
591
697
  * maps: [
592
698
  * {
593
699
  * id: 'town',
@@ -596,24 +702,64 @@ export interface RpgServer {
596
702
  * }
597
703
  * ]
598
704
  * })
599
- * class RpgServerEngine { }
600
705
  * ```
601
706
  *
602
707
  * 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
603
708
  *
604
709
  * ```ts
605
- * @RpgModule<RpgServer>({
710
+ * import { RpgServer } from '@rpgjs/server'
711
+ * import { defineModule } from '@rpgjs/common'
712
+ *
713
+ * export default defineModule<RpgServer>({
606
714
  * maps: [
607
715
  * require('./tmx/mymap.tmx') // id is "mymap"
608
716
  * ]
609
717
  * })
610
- * class RpgServerEngine { }
611
718
  * ```
612
719
  *
613
- * @prop {RpgClassMap<RpgMap>[]} [maps]
720
+ * @prop {(new () => any) | MapOptions)[]} [maps]
721
+ * @memberof RpgServer
722
+ * */
723
+ maps?: ((new () => any) | MapOptions)[];
724
+ /**
725
+ * Global map hooks that apply to all maps in the game
726
+ *
727
+ * These hooks are executed for every map instance and allow you to define
728
+ * global behavior that should happen for all maps. They are different from
729
+ * map-specific hooks defined in `@MapData` which only apply to a specific map class.
730
+ *
731
+ * ```ts
732
+ * import { RpgServer, RpgMapHooks, RpgMap, RpgPlayer } from '@rpgjs/server'
733
+ * import { defineModule } from '@rpgjs/common'
734
+ *
735
+ * const mapHooks: RpgMapHooks = {
736
+ * onLoad(map: RpgMap) {
737
+ * console.log(`Map ${map.id} loaded`)
738
+ * // Initialize global map properties
739
+ * },
740
+ * onJoin(player: RpgPlayer, map: RpgMap) {
741
+ * console.log(`${player.name} joined map ${map.id}`)
742
+ * // Perform global actions when player joins any map
743
+ * },
744
+ * onLeave(player: RpgPlayer, map: RpgMap) {
745
+ * console.log(`${player.name} left map ${map.id}`)
746
+ * // Perform global cleanup when player leaves any map
747
+ * },
748
+ * onBeforeUpdate(mapData, map) {
749
+ * // Modify map data before update
750
+ * return map
751
+ * }
752
+ * }
753
+ *
754
+ * export default defineModule<RpgServer>({
755
+ * map: mapHooks
756
+ * })
757
+ * ```
758
+ *
759
+ * @prop {RpgMapHooks} [map]
614
760
  * @memberof RpgServer
761
+ * @since 4.0.0
615
762
  * */
616
- maps?: RpgClassMap<RpgMap>[] | MapOptions[] | string[] | TiledMap[];
617
763
  map?: RpgMapHooks;
618
764
  event?: RpgEventHooks;
619
765
  /**
@@ -626,41 +772,62 @@ export interface RpgServer {
626
772
  */
627
773
  events?: RpgClassEvent<RpgEvent>[];
628
774
  /**
629
- * Loads the content of a `.world` file from Tiled Map Editor into the map scene
775
+ * Array of world map configurations
630
776
  *
631
- * > 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
777
+ * Loads the content of a `.world` file from Tiled Map Editor into the map scene.
778
+ * Each world contains multiple maps with their spatial relationships.
632
779
  *
633
- * @prop {object[]} [worldMaps]
634
- * object is
635
- * ```ts
636
- * {
637
- * id?: string
638
- * maps: {
639
- * id?: string
640
- * properties?: object
641
- * fileName: string;
642
- height: number;
643
- width: number;
644
- x: number;
645
- y: number;
646
- * }[],
647
- onlyShowAdjacentMaps: boolean, // only for Tiled Map Editor
648
- type: 'world' // only for Tiled Map Editor
649
- * }
650
- * ```
780
+ * > Note: If a map already exists (i.e. you have already defined an RpgMap),
781
+ * > the world will retrieve the already existing map. Otherwise it will create a new map.
782
+ *
783
+ * @prop {WorldMap[]} [worldMaps]
651
784
  * @since 3.0.0-beta.8
785
+ * @memberof RpgServer
652
786
  * @example
653
787
  * ```ts
788
+ * import { RpgServer } from '@rpgjs/server'
789
+ * import { defineModule } from '@rpgjs/common'
654
790
  * import myworld from 'myworld.world'
655
791
  *
656
- * @RpgModule<RpgServer>({
657
- * worldMaps: [
658
- * myworld
659
- * ]
792
+ * export default defineModule<RpgServer>({
793
+ * worldMaps: [
794
+ * myworld
795
+ * ]
796
+ * })
797
+ * ```
798
+ *
799
+ * @example
800
+ * ```ts
801
+ * import { RpgServer } from '@rpgjs/server'
802
+ * import { defineModule } from '@rpgjs/common'
803
+ *
804
+ * // Manual world configuration
805
+ * export default defineModule<RpgServer>({
806
+ * worldMaps: [
807
+ * {
808
+ * id: 'my-world',
809
+ * maps: [
810
+ * {
811
+ * id: 'map1',
812
+ * worldX: 0,
813
+ * worldY: 0,
814
+ * width: 800,
815
+ * height: 600,
816
+ * tileWidth: 32,
817
+ * tileHeight: 32
818
+ * },
819
+ * {
820
+ * id: 'map2',
821
+ * worldX: 800,
822
+ * worldY: 0,
823
+ * width: 800,
824
+ * height: 600
825
+ * }
826
+ * ]
827
+ * }
828
+ * ]
660
829
  * })
661
- * class RpgServerEngine { }
662
830
  * ```
663
- * @memberof RpgServer
664
831
  */
665
832
  worldMaps?: WorldMap[];
666
833
  /**
@@ -683,11 +850,12 @@ export interface RpgServer {
683
850
  * Example:
684
851
  *
685
852
  * ```ts
686
- * import { RpgModule, RpgServer, Presets } from '@rpgjs/server'
853
+ * import { RpgServer, Presets } from '@rpgjs/server'
854
+ * import { defineModule } from '@rpgjs/common'
687
855
  *
688
856
  * const { ATK, PDEF } = Presets
689
857
  *
690
- * @RpgModule<RpgServer>({
858
+ * export default defineModule<RpgServer>({
691
859
  * damageFormulas: {
692
860
  * damagePhysic(a, b) {
693
861
  * let damage = a[ATK] - b[PDEF]
@@ -696,7 +864,6 @@ export interface RpgServer {
696
864
  * }
697
865
  * }
698
866
  * })
699
- * class RpgServerEngine { }
700
867
  * ```
701
868
  * @prop {object} damageFormulas
702
869
  * @memberof RpgServer
@@ -23,7 +23,7 @@ export interface MapOptions {
23
23
  * @prop {string} file
24
24
  * @memberof MapData
25
25
  * */
26
- file: any;
26
+ file?: any;
27
27
  /**
28
28
  * The name of the map.
29
29
  * @prop {string} [name]
@@ -96,6 +96,28 @@ export interface MapOptions {
96
96
  * @memberof MapData
97
97
  * */
98
98
  sounds?: string[];
99
+ /**
100
+ * Whether to stop all sounds before playing the map sounds when a player joins.
101
+ *
102
+ * If set to `true`, all currently playing sounds will be stopped before playing the new map sounds.
103
+ * This prevents sound overlap when changing maps.
104
+ *
105
+ * By default, this is `false`, meaning sounds from the previous map will continue playing.
106
+ *
107
+ * ```ts
108
+ * @MapData({
109
+ * id: 'battle-map',
110
+ * sounds: ['battle-theme'],
111
+ * stopAllSoundsBeforeJoin: true // Stop all sounds before playing battle theme
112
+ * })
113
+ * class BattleMap extends RpgMap {}
114
+ * ```
115
+ *
116
+ * @prop {boolean} [stopAllSoundsBeforeJoin=false]
117
+ * @memberof MapData
118
+ * @since 5.0.0
119
+ * */
120
+ stopAllSoundsBeforeJoin?: boolean;
99
121
  /**
100
122
  * 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
101
123
  *
@@ -173,5 +195,71 @@ export interface MapOptions {
173
195
  * @memberof MapData
174
196
  * */
175
197
  lowMemory?: boolean;
198
+ /**
199
+ * Called when the map is loaded and initialized
200
+ *
201
+ * This hook is executed once when the map data is loaded and ready.
202
+ * Use this to initialize map-specific properties or setup.
203
+ *
204
+ * @prop { () => any } [onLoad]
205
+ * @memberof MapData
206
+ * @example
207
+ * ```ts
208
+ * @MapData({
209
+ * id: 'town',
210
+ * file: require('./tmx/town.tmx'),
211
+ * onLoad() {
212
+ * console.log('Town map loaded')
213
+ * // Initialize map properties
214
+ * }
215
+ * })
216
+ * class TownMap extends RpgMap {}
217
+ * ```
218
+ * */
219
+ onLoad?: () => any;
220
+ /**
221
+ * Called when a player joins the map
222
+ *
223
+ * This hook is executed each time a player joins the map.
224
+ * Use this to perform actions when a player enters the map.
225
+ *
226
+ * @prop { (player: RpgPlayer) => any } [onJoin]
227
+ * @memberof MapData
228
+ * @example
229
+ * ```ts
230
+ * @MapData({
231
+ * id: 'town',
232
+ * file: require('./tmx/town.tmx'),
233
+ * onJoin(player: RpgPlayer) {
234
+ * console.log(`${player.name} joined the town`)
235
+ * // Perform actions when player joins
236
+ * }
237
+ * })
238
+ * class TownMap extends RpgMap {}
239
+ * ```
240
+ * */
241
+ onJoin?: (player: RpgPlayer) => any;
242
+ /**
243
+ * Called when a player leaves the map
244
+ *
245
+ * This hook is executed each time a player leaves the map.
246
+ * Use this to perform cleanup or actions when a player exits the map.
247
+ *
248
+ * @prop { (player: RpgPlayer) => any } [onLeave]
249
+ * @memberof MapData
250
+ * @example
251
+ * ```ts
252
+ * @MapData({
253
+ * id: 'town',
254
+ * file: require('./tmx/town.tmx'),
255
+ * onLeave(player: RpgPlayer) {
256
+ * console.log(`${player.name} left the town`)
257
+ * // Perform cleanup when player leaves
258
+ * }
259
+ * })
260
+ * class TownMap extends RpgMap {}
261
+ * ```
262
+ * */
263
+ onLeave?: (player: RpgPlayer) => any;
176
264
  }
177
265
  export declare function MapData(options: MapOptions): (target: any) => void;