@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.
- package/dist/Player/BattleManager.d.ts +43 -31
- package/dist/Player/ClassManager.d.ts +23 -3
- package/dist/Player/EffectManager.d.ts +49 -3
- package/dist/Player/ElementManager.d.ts +76 -3
- package/dist/Player/ItemManager.d.ts +292 -4
- package/dist/Player/MoveManager.d.ts +145 -4
- package/dist/Player/Player.d.ts +135 -0
- package/dist/Player/SkillManager.d.ts +42 -3
- package/dist/Player/StateManager.d.ts +74 -3
- package/dist/Player/VariableManager.d.ts +47 -3
- package/dist/RpgServer.d.ts +228 -61
- package/dist/decorators/map.d.ts +89 -1
- package/dist/index.js +804 -1703
- package/dist/index.js.map +1 -1
- package/dist/module.d.ts +43 -1
- package/dist/rooms/map.d.ts +676 -12
- package/package.json +8 -8
- package/src/Player/BattleManager.ts +38 -55
- package/src/Player/ClassManager.ts +21 -71
- package/src/Player/EffectManager.ts +50 -96
- package/src/Player/ElementManager.ts +74 -152
- package/src/Player/ItemManager.ts +302 -359
- package/src/Player/MoveManager.ts +141 -438
- package/src/Player/Player.ts +217 -0
- package/src/Player/SkillManager.ts +44 -147
- package/src/Player/StateManager.ts +63 -259
- package/src/Player/VariableManager.ts +53 -150
- package/src/RpgServer.ts +237 -60
- package/src/decorators/map.ts +105 -1
- package/src/module.ts +81 -2
- package/src/rooms/map.ts +757 -23
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 } from "@rpgjs/common"
|
|
6
|
+
import { RpgEvent } from "./Player/Player"
|
|
4
7
|
|
|
5
|
-
type
|
|
6
|
-
type
|
|
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
|
-
|
|
13
|
-
|
|
14
|
-
|
|
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
|
/**
|
|
@@ -420,6 +448,9 @@ export interface RpgEventHooks {
|
|
|
420
448
|
/**
|
|
421
449
|
* Map hooks interface for handling map lifecycle events
|
|
422
450
|
*
|
|
451
|
+
* These hooks are global hooks that apply to all maps in the game.
|
|
452
|
+
* They are defined in the RpgModule configuration and executed for every map instance.
|
|
453
|
+
*
|
|
423
454
|
* @interface RpgMapHooks
|
|
424
455
|
* @since 4.0.0
|
|
425
456
|
*/
|
|
@@ -472,6 +503,74 @@ export interface RpgMapHooks {
|
|
|
472
503
|
* ```
|
|
473
504
|
*/
|
|
474
505
|
onBeforeUpdate<T, U = RpgMap>(mapData: T, map: U): U | Promise<U>
|
|
506
|
+
|
|
507
|
+
/**
|
|
508
|
+
* Called when a map is loaded and initialized
|
|
509
|
+
*
|
|
510
|
+
* This hook is executed once when the map data is loaded and ready.
|
|
511
|
+
* It applies to all maps globally. Use this to initialize map-specific properties
|
|
512
|
+
* or setup that should happen for every map.
|
|
513
|
+
*
|
|
514
|
+
* @param {RpgMap} map - The map instance that was loaded
|
|
515
|
+
* @returns {any}
|
|
516
|
+
* @memberof RpgMapHooks
|
|
517
|
+
* @example
|
|
518
|
+
* ```ts
|
|
519
|
+
* const mapHooks: RpgMapHooks = {
|
|
520
|
+
* onLoad(map: RpgMap) {
|
|
521
|
+
* console.log(`Map ${map.id} loaded`)
|
|
522
|
+
* // Initialize global map properties
|
|
523
|
+
* }
|
|
524
|
+
* }
|
|
525
|
+
* ```
|
|
526
|
+
*/
|
|
527
|
+
onLoad?: (map: RpgMap) => any
|
|
528
|
+
|
|
529
|
+
/**
|
|
530
|
+
* Called when a player joins any map
|
|
531
|
+
*
|
|
532
|
+
* This hook is executed each time a player joins any map in the game.
|
|
533
|
+
* It applies globally to all maps. Use this to perform actions that should
|
|
534
|
+
* happen whenever a player enters any map.
|
|
535
|
+
*
|
|
536
|
+
* @param {RpgPlayer} player - The player joining the map
|
|
537
|
+
* @param {RpgMap} map - The map instance the player joined
|
|
538
|
+
* @returns {any}
|
|
539
|
+
* @memberof RpgMapHooks
|
|
540
|
+
* @example
|
|
541
|
+
* ```ts
|
|
542
|
+
* const mapHooks: RpgMapHooks = {
|
|
543
|
+
* onJoin(player: RpgPlayer, map: RpgMap) {
|
|
544
|
+
* console.log(`${player.name} joined map ${map.id}`)
|
|
545
|
+
* // Perform global actions when player joins any map
|
|
546
|
+
* }
|
|
547
|
+
* }
|
|
548
|
+
* ```
|
|
549
|
+
*/
|
|
550
|
+
onJoin?: (player: RpgPlayer, map: RpgMap) => any
|
|
551
|
+
|
|
552
|
+
/**
|
|
553
|
+
* Called when a player leaves any map
|
|
554
|
+
*
|
|
555
|
+
* This hook is executed each time a player leaves any map in the game.
|
|
556
|
+
* It applies globally to all maps. Use this to perform cleanup or actions
|
|
557
|
+
* that should happen whenever a player exits any map.
|
|
558
|
+
*
|
|
559
|
+
* @param {RpgPlayer} player - The player leaving the map
|
|
560
|
+
* @param {RpgMap} map - The map instance the player left
|
|
561
|
+
* @returns {any}
|
|
562
|
+
* @memberof RpgMapHooks
|
|
563
|
+
* @example
|
|
564
|
+
* ```ts
|
|
565
|
+
* const mapHooks: RpgMapHooks = {
|
|
566
|
+
* onLeave(player: RpgPlayer, map: RpgMap) {
|
|
567
|
+
* console.log(`${player.name} left map ${map.id}`)
|
|
568
|
+
* // Perform global cleanup when player leaves any map
|
|
569
|
+
* }
|
|
570
|
+
* }
|
|
571
|
+
* ```
|
|
572
|
+
*/
|
|
573
|
+
onLeave?: (player: RpgPlayer, map: RpgMap) => any
|
|
475
574
|
}
|
|
476
575
|
|
|
477
576
|
export interface RpgServer {
|
|
@@ -485,14 +584,14 @@ export interface RpgServer {
|
|
|
485
584
|
* @example
|
|
486
585
|
*
|
|
487
586
|
* ```ts
|
|
488
|
-
* import { RpgServer
|
|
587
|
+
* import { RpgServer } from '@rpgjs/server'
|
|
588
|
+
* import { defineModule } from '@rpgjs/common'
|
|
489
589
|
*
|
|
490
|
-
*
|
|
590
|
+
* export default defineModule<RpgServer>({
|
|
491
591
|
* hooks: {
|
|
492
592
|
* player: ['onAuth']
|
|
493
593
|
* }
|
|
494
594
|
* })
|
|
495
|
-
* class RpgServerEngine { }
|
|
496
595
|
* ```
|
|
497
596
|
*
|
|
498
597
|
* Emit the hook:
|
|
@@ -532,18 +631,18 @@ export interface RpgServer {
|
|
|
532
631
|
* Object containing the hooks concerning the engine
|
|
533
632
|
*
|
|
534
633
|
* ```ts
|
|
535
|
-
* import { RpgServerEngine, RpgServerEngineHooks,
|
|
634
|
+
* import { RpgServerEngine, RpgServerEngineHooks, RpgServer } from '@rpgjs/server'
|
|
635
|
+
* import { defineModule } from '@rpgjs/common'
|
|
536
636
|
*
|
|
537
|
-
* const engine:
|
|
637
|
+
* const engine: RpgServerEngineHooks = {
|
|
538
638
|
* onStart(server: RpgServerEngine) {
|
|
539
639
|
* console.log('server is started')
|
|
540
640
|
* }
|
|
541
641
|
* }
|
|
542
642
|
*
|
|
543
|
-
*
|
|
643
|
+
* export default defineModule<RpgServer>({
|
|
544
644
|
* engine
|
|
545
645
|
* })
|
|
546
|
-
* class RpgServerModule {}
|
|
547
646
|
* ```
|
|
548
647
|
*
|
|
549
648
|
* @prop {RpgServerEngineHooks} [engine]
|
|
@@ -555,7 +654,8 @@ export interface RpgServer {
|
|
|
555
654
|
* Give the `player` object hooks. Each time a player connects, an instance of `RpgPlayer` is created.
|
|
556
655
|
*
|
|
557
656
|
* ```ts
|
|
558
|
-
* import { RpgPlayer, RpgServer, RpgPlayerHooks
|
|
657
|
+
* import { RpgPlayer, RpgServer, RpgPlayerHooks } from '@rpgjs/server'
|
|
658
|
+
* import { defineModule } from '@rpgjs/common'
|
|
559
659
|
*
|
|
560
660
|
* const player: RpgPlayerHooks = {
|
|
561
661
|
* onConnected(player: RpgPlayer) {
|
|
@@ -563,10 +663,9 @@ export interface RpgServer {
|
|
|
563
663
|
* }
|
|
564
664
|
* }
|
|
565
665
|
*
|
|
566
|
-
*
|
|
666
|
+
* export default defineModule<RpgServer>({
|
|
567
667
|
* player
|
|
568
668
|
* })
|
|
569
|
-
* class RpgServerEngine { }
|
|
570
669
|
* ```
|
|
571
670
|
*
|
|
572
671
|
* @prop {RpgClassPlayer<RpgPlayer>} [player]
|
|
@@ -578,15 +677,15 @@ export interface RpgServer {
|
|
|
578
677
|
* References all data in the server. it is mainly used to retrieve data according to their identifier
|
|
579
678
|
*
|
|
580
679
|
* ```ts
|
|
581
|
-
* import { RpgServer
|
|
680
|
+
* import { RpgServer } from '@rpgjs/server'
|
|
681
|
+
* import { defineModule } from '@rpgjs/common'
|
|
582
682
|
* import { Potion } from 'my-database/items/potion'
|
|
583
683
|
*
|
|
584
|
-
*
|
|
684
|
+
* export default defineModule<RpgServer>({
|
|
585
685
|
* database: {
|
|
586
686
|
* Potion
|
|
587
687
|
* }
|
|
588
688
|
* })
|
|
589
|
-
* class RpgServerEngine { }
|
|
590
689
|
* ```
|
|
591
690
|
*
|
|
592
691
|
* @prop { { [dataName]: data } } [database]
|
|
@@ -595,11 +694,13 @@ export interface RpgServer {
|
|
|
595
694
|
database?: object | any[],
|
|
596
695
|
|
|
597
696
|
/**
|
|
598
|
-
* Array of all maps. Each element
|
|
697
|
+
* Array of all maps. Each element can be either a class (decorated with `@MapData` or not) or a `MapOptions` object
|
|
599
698
|
*
|
|
600
699
|
* ```ts
|
|
601
|
-
* import { RpgMap, MapData, RpgServer
|
|
700
|
+
* import { RpgMap, MapData, RpgServer } from '@rpgjs/server'
|
|
701
|
+
* import { defineModule } from '@rpgjs/common'
|
|
602
702
|
*
|
|
703
|
+
* // Class that extends RpgMap (optional)
|
|
603
704
|
* @MapData({
|
|
604
705
|
* id: 'town',
|
|
605
706
|
* file: require('./tmx/mymap.tmx'),
|
|
@@ -607,18 +708,29 @@ export interface RpgServer {
|
|
|
607
708
|
* })
|
|
608
709
|
* class TownMap extends RpgMap { }
|
|
609
710
|
*
|
|
610
|
-
*
|
|
711
|
+
* // Or a simple class without extending RpgMap
|
|
712
|
+
* @MapData({
|
|
713
|
+
* id: 'map',
|
|
714
|
+
* file: '',
|
|
715
|
+
* events: [{ event: Event() }]
|
|
716
|
+
* })
|
|
717
|
+
* class SimpleMap {}
|
|
718
|
+
*
|
|
719
|
+
* export default defineModule<RpgServer>({
|
|
611
720
|
* maps: [
|
|
612
|
-
* TownMap
|
|
721
|
+
* TownMap,
|
|
722
|
+
* SimpleMap
|
|
613
723
|
* ]
|
|
614
724
|
* })
|
|
615
|
-
* class RpgServerEngine { }
|
|
616
725
|
* ```
|
|
617
726
|
*
|
|
618
727
|
* It is possible to just give the object as well
|
|
619
728
|
*
|
|
620
729
|
* ```ts
|
|
621
|
-
* @
|
|
730
|
+
* import { RpgServer } from '@rpgjs/server'
|
|
731
|
+
* import { defineModule } from '@rpgjs/common'
|
|
732
|
+
*
|
|
733
|
+
* export default defineModule<RpgServer>({
|
|
622
734
|
* maps: [
|
|
623
735
|
* {
|
|
624
736
|
* id: 'town',
|
|
@@ -627,25 +739,65 @@ export interface RpgServer {
|
|
|
627
739
|
* }
|
|
628
740
|
* ]
|
|
629
741
|
* })
|
|
630
|
-
* class RpgServerEngine { }
|
|
631
742
|
* ```
|
|
632
743
|
*
|
|
633
744
|
* 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
|
|
634
745
|
*
|
|
635
746
|
* ```ts
|
|
636
|
-
* @
|
|
747
|
+
* import { RpgServer } from '@rpgjs/server'
|
|
748
|
+
* import { defineModule } from '@rpgjs/common'
|
|
749
|
+
*
|
|
750
|
+
* export default defineModule<RpgServer>({
|
|
637
751
|
* maps: [
|
|
638
752
|
* require('./tmx/mymap.tmx') // id is "mymap"
|
|
639
753
|
* ]
|
|
640
754
|
* })
|
|
641
|
-
* class RpgServerEngine { }
|
|
642
755
|
* ```
|
|
643
756
|
*
|
|
644
|
-
* @prop {
|
|
757
|
+
* @prop {(new () => any) | MapOptions)[]} [maps]
|
|
645
758
|
* @memberof RpgServer
|
|
646
759
|
* */
|
|
647
|
-
maps?:
|
|
760
|
+
maps?: ((new () => any) | MapOptions)[],
|
|
648
761
|
|
|
762
|
+
/**
|
|
763
|
+
* Global map hooks that apply to all maps in the game
|
|
764
|
+
*
|
|
765
|
+
* These hooks are executed for every map instance and allow you to define
|
|
766
|
+
* global behavior that should happen for all maps. They are different from
|
|
767
|
+
* map-specific hooks defined in `@MapData` which only apply to a specific map class.
|
|
768
|
+
*
|
|
769
|
+
* ```ts
|
|
770
|
+
* import { RpgServer, RpgMapHooks, RpgMap, RpgPlayer } from '@rpgjs/server'
|
|
771
|
+
* import { defineModule } from '@rpgjs/common'
|
|
772
|
+
*
|
|
773
|
+
* const mapHooks: RpgMapHooks = {
|
|
774
|
+
* onLoad(map: RpgMap) {
|
|
775
|
+
* console.log(`Map ${map.id} loaded`)
|
|
776
|
+
* // Initialize global map properties
|
|
777
|
+
* },
|
|
778
|
+
* onJoin(player: RpgPlayer, map: RpgMap) {
|
|
779
|
+
* console.log(`${player.name} joined map ${map.id}`)
|
|
780
|
+
* // Perform global actions when player joins any map
|
|
781
|
+
* },
|
|
782
|
+
* onLeave(player: RpgPlayer, map: RpgMap) {
|
|
783
|
+
* console.log(`${player.name} left map ${map.id}`)
|
|
784
|
+
* // Perform global cleanup when player leaves any map
|
|
785
|
+
* },
|
|
786
|
+
* onBeforeUpdate(mapData, map) {
|
|
787
|
+
* // Modify map data before update
|
|
788
|
+
* return map
|
|
789
|
+
* }
|
|
790
|
+
* }
|
|
791
|
+
*
|
|
792
|
+
* export default defineModule<RpgServer>({
|
|
793
|
+
* map: mapHooks
|
|
794
|
+
* })
|
|
795
|
+
* ```
|
|
796
|
+
*
|
|
797
|
+
* @prop {RpgMapHooks} [map]
|
|
798
|
+
* @memberof RpgServer
|
|
799
|
+
* @since 4.0.0
|
|
800
|
+
* */
|
|
649
801
|
map?: RpgMapHooks
|
|
650
802
|
|
|
651
803
|
event?: RpgEventHooks
|
|
@@ -661,41 +813,62 @@ export interface RpgServer {
|
|
|
661
813
|
events?: RpgClassEvent<RpgEvent>[]
|
|
662
814
|
|
|
663
815
|
/**
|
|
664
|
-
*
|
|
816
|
+
* Array of world map configurations
|
|
665
817
|
*
|
|
666
|
-
*
|
|
818
|
+
* Loads the content of a `.world` file from Tiled Map Editor into the map scene.
|
|
819
|
+
* Each world contains multiple maps with their spatial relationships.
|
|
667
820
|
*
|
|
668
|
-
*
|
|
669
|
-
*
|
|
670
|
-
*
|
|
671
|
-
* {
|
|
672
|
-
* id?: string
|
|
673
|
-
* maps: {
|
|
674
|
-
* id?: string
|
|
675
|
-
* properties?: object
|
|
676
|
-
* fileName: string;
|
|
677
|
-
height: number;
|
|
678
|
-
width: number;
|
|
679
|
-
x: number;
|
|
680
|
-
y: number;
|
|
681
|
-
* }[],
|
|
682
|
-
onlyShowAdjacentMaps: boolean, // only for Tiled Map Editor
|
|
683
|
-
type: 'world' // only for Tiled Map Editor
|
|
684
|
-
* }
|
|
685
|
-
* ```
|
|
821
|
+
* > Note: If a map already exists (i.e. you have already defined an RpgMap),
|
|
822
|
+
* > the world will retrieve the already existing map. Otherwise it will create a new map.
|
|
823
|
+
*
|
|
824
|
+
* @prop {WorldMap[]} [worldMaps]
|
|
686
825
|
* @since 3.0.0-beta.8
|
|
826
|
+
* @memberof RpgServer
|
|
687
827
|
* @example
|
|
688
828
|
* ```ts
|
|
829
|
+
* import { RpgServer } from '@rpgjs/server'
|
|
830
|
+
* import { defineModule } from '@rpgjs/common'
|
|
689
831
|
* import myworld from 'myworld.world'
|
|
690
832
|
*
|
|
691
|
-
*
|
|
692
|
-
*
|
|
693
|
-
*
|
|
694
|
-
*
|
|
833
|
+
* export default defineModule<RpgServer>({
|
|
834
|
+
* worldMaps: [
|
|
835
|
+
* myworld
|
|
836
|
+
* ]
|
|
837
|
+
* })
|
|
838
|
+
* ```
|
|
839
|
+
*
|
|
840
|
+
* @example
|
|
841
|
+
* ```ts
|
|
842
|
+
* import { RpgServer } from '@rpgjs/server'
|
|
843
|
+
* import { defineModule } from '@rpgjs/common'
|
|
844
|
+
*
|
|
845
|
+
* // Manual world configuration
|
|
846
|
+
* export default defineModule<RpgServer>({
|
|
847
|
+
* worldMaps: [
|
|
848
|
+
* {
|
|
849
|
+
* id: 'my-world',
|
|
850
|
+
* maps: [
|
|
851
|
+
* {
|
|
852
|
+
* id: 'map1',
|
|
853
|
+
* worldX: 0,
|
|
854
|
+
* worldY: 0,
|
|
855
|
+
* width: 800,
|
|
856
|
+
* height: 600,
|
|
857
|
+
* tileWidth: 32,
|
|
858
|
+
* tileHeight: 32
|
|
859
|
+
* },
|
|
860
|
+
* {
|
|
861
|
+
* id: 'map2',
|
|
862
|
+
* worldX: 800,
|
|
863
|
+
* worldY: 0,
|
|
864
|
+
* width: 800,
|
|
865
|
+
* height: 600
|
|
866
|
+
* }
|
|
867
|
+
* ]
|
|
868
|
+
* }
|
|
869
|
+
* ]
|
|
695
870
|
* })
|
|
696
|
-
* class RpgServerEngine { }
|
|
697
871
|
* ```
|
|
698
|
-
* @memberof RpgServer
|
|
699
872
|
*/
|
|
700
873
|
worldMaps?: WorldMap[]
|
|
701
874
|
|
|
@@ -720,11 +893,12 @@ export interface RpgServer {
|
|
|
720
893
|
* Example:
|
|
721
894
|
*
|
|
722
895
|
* ```ts
|
|
723
|
-
* import {
|
|
896
|
+
* import { RpgServer, Presets } from '@rpgjs/server'
|
|
897
|
+
* import { defineModule } from '@rpgjs/common'
|
|
724
898
|
*
|
|
725
899
|
* const { ATK, PDEF } = Presets
|
|
726
900
|
*
|
|
727
|
-
*
|
|
901
|
+
* export default defineModule<RpgServer>({
|
|
728
902
|
* damageFormulas: {
|
|
729
903
|
* damagePhysic(a, b) {
|
|
730
904
|
* let damage = a[ATK] - b[PDEF]
|
|
@@ -733,7 +907,6 @@ export interface RpgServer {
|
|
|
733
907
|
* }
|
|
734
908
|
* }
|
|
735
909
|
* })
|
|
736
|
-
* class RpgServerEngine { }
|
|
737
910
|
* ```
|
|
738
911
|
* @prop {object} damageFormulas
|
|
739
912
|
* @memberof RpgServer
|
|
@@ -745,6 +918,10 @@ export interface RpgServer {
|
|
|
745
918
|
coefficientElements?: (a, b, bDef) => number
|
|
746
919
|
}
|
|
747
920
|
|
|
921
|
+
/*
|
|
922
|
+
* Scalability configuration for the server
|
|
923
|
+
* @deprecated
|
|
924
|
+
*/
|
|
748
925
|
scalability?: {
|
|
749
926
|
matchMaker: MatchMakerOption,
|
|
750
927
|
stateStore: IStoreState
|
package/src/decorators/map.ts
CHANGED
|
@@ -24,7 +24,7 @@ export interface MapOptions {
|
|
|
24
24
|
* @prop {string} file
|
|
25
25
|
* @memberof MapData
|
|
26
26
|
* */
|
|
27
|
-
file
|
|
27
|
+
file?: any,
|
|
28
28
|
|
|
29
29
|
/**
|
|
30
30
|
* The name of the map.
|
|
@@ -97,6 +97,29 @@ export interface MapOptions {
|
|
|
97
97
|
* */
|
|
98
98
|
sounds?: string[]
|
|
99
99
|
|
|
100
|
+
/**
|
|
101
|
+
* Whether to stop all sounds before playing the map sounds when a player joins.
|
|
102
|
+
*
|
|
103
|
+
* If set to `true`, all currently playing sounds will be stopped before playing the new map sounds.
|
|
104
|
+
* This prevents sound overlap when changing maps.
|
|
105
|
+
*
|
|
106
|
+
* By default, this is `false`, meaning sounds from the previous map will continue playing.
|
|
107
|
+
*
|
|
108
|
+
* ```ts
|
|
109
|
+
* @MapData({
|
|
110
|
+
* id: 'battle-map',
|
|
111
|
+
* sounds: ['battle-theme'],
|
|
112
|
+
* stopAllSoundsBeforeJoin: true // Stop all sounds before playing battle theme
|
|
113
|
+
* })
|
|
114
|
+
* class BattleMap extends RpgMap {}
|
|
115
|
+
* ```
|
|
116
|
+
*
|
|
117
|
+
* @prop {boolean} [stopAllSoundsBeforeJoin=false]
|
|
118
|
+
* @memberof MapData
|
|
119
|
+
* @since 5.0.0
|
|
120
|
+
* */
|
|
121
|
+
stopAllSoundsBeforeJoin?: boolean
|
|
122
|
+
|
|
100
123
|
/**
|
|
101
124
|
* 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
|
|
102
125
|
*
|
|
@@ -175,6 +198,75 @@ export interface MapOptions {
|
|
|
175
198
|
* @memberof MapData
|
|
176
199
|
* */
|
|
177
200
|
lowMemory?: boolean
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Called when the map is loaded and initialized
|
|
204
|
+
*
|
|
205
|
+
* This hook is executed once when the map data is loaded and ready.
|
|
206
|
+
* Use this to initialize map-specific properties or setup.
|
|
207
|
+
*
|
|
208
|
+
* @prop { () => any } [onLoad]
|
|
209
|
+
* @memberof MapData
|
|
210
|
+
* @example
|
|
211
|
+
* ```ts
|
|
212
|
+
* @MapData({
|
|
213
|
+
* id: 'town',
|
|
214
|
+
* file: require('./tmx/town.tmx'),
|
|
215
|
+
* onLoad() {
|
|
216
|
+
* console.log('Town map loaded')
|
|
217
|
+
* // Initialize map properties
|
|
218
|
+
* }
|
|
219
|
+
* })
|
|
220
|
+
* class TownMap extends RpgMap {}
|
|
221
|
+
* ```
|
|
222
|
+
* */
|
|
223
|
+
onLoad?: () => any
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Called when a player joins the map
|
|
227
|
+
*
|
|
228
|
+
* This hook is executed each time a player joins the map.
|
|
229
|
+
* Use this to perform actions when a player enters the map.
|
|
230
|
+
*
|
|
231
|
+
* @prop { (player: RpgPlayer) => any } [onJoin]
|
|
232
|
+
* @memberof MapData
|
|
233
|
+
* @example
|
|
234
|
+
* ```ts
|
|
235
|
+
* @MapData({
|
|
236
|
+
* id: 'town',
|
|
237
|
+
* file: require('./tmx/town.tmx'),
|
|
238
|
+
* onJoin(player: RpgPlayer) {
|
|
239
|
+
* console.log(`${player.name} joined the town`)
|
|
240
|
+
* // Perform actions when player joins
|
|
241
|
+
* }
|
|
242
|
+
* })
|
|
243
|
+
* class TownMap extends RpgMap {}
|
|
244
|
+
* ```
|
|
245
|
+
* */
|
|
246
|
+
onJoin?: (player: RpgPlayer) => any
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Called when a player leaves the map
|
|
250
|
+
*
|
|
251
|
+
* This hook is executed each time a player leaves the map.
|
|
252
|
+
* Use this to perform cleanup or actions when a player exits the map.
|
|
253
|
+
*
|
|
254
|
+
* @prop { (player: RpgPlayer) => any } [onLeave]
|
|
255
|
+
* @memberof MapData
|
|
256
|
+
* @example
|
|
257
|
+
* ```ts
|
|
258
|
+
* @MapData({
|
|
259
|
+
* id: 'town',
|
|
260
|
+
* file: require('./tmx/town.tmx'),
|
|
261
|
+
* onLeave(player: RpgPlayer) {
|
|
262
|
+
* console.log(`${player.name} left the town`)
|
|
263
|
+
* // Perform cleanup when player leaves
|
|
264
|
+
* }
|
|
265
|
+
* })
|
|
266
|
+
* class TownMap extends RpgMap {}
|
|
267
|
+
* ```
|
|
268
|
+
* */
|
|
269
|
+
onLeave?: (player: RpgPlayer) => any
|
|
178
270
|
}
|
|
179
271
|
|
|
180
272
|
export function MapData(options: MapOptions) {
|
|
@@ -187,6 +279,7 @@ export function MapData(options: MapOptions) {
|
|
|
187
279
|
target.prototype.id = options.id
|
|
188
280
|
target.prototype.sounds = options.sounds
|
|
189
281
|
target.prototype.lowMemory = options.lowMemory
|
|
282
|
+
target.prototype.stopAllSoundsBeforeJoin = options.stopAllSoundsBeforeJoin
|
|
190
283
|
|
|
191
284
|
target.prototype.$schema = {}
|
|
192
285
|
|
|
@@ -194,5 +287,16 @@ export function MapData(options: MapOptions) {
|
|
|
194
287
|
target.prototype.$schema = options.syncSchema
|
|
195
288
|
}
|
|
196
289
|
target.prototype._events = options.events
|
|
290
|
+
|
|
291
|
+
// Store hooks on prototype
|
|
292
|
+
if (options.onLoad) {
|
|
293
|
+
target.prototype.onLoad = options.onLoad
|
|
294
|
+
}
|
|
295
|
+
if (options.onJoin) {
|
|
296
|
+
target.prototype.onJoin = options.onJoin
|
|
297
|
+
}
|
|
298
|
+
if (options.onLeave) {
|
|
299
|
+
target.prototype.onLeave = options.onLeave
|
|
300
|
+
}
|
|
197
301
|
}
|
|
198
302
|
}
|
package/src/module.ts
CHANGED
|
@@ -3,12 +3,66 @@ import { FactoryProvider } from "@signe/di";
|
|
|
3
3
|
import { RpgServerEngine } from "./RpgServerEngine";
|
|
4
4
|
import { RpgMap } from "./rooms/map";
|
|
5
5
|
import { RpgPlayer } from "./Player/Player";
|
|
6
|
+
import { RpgServer } from "./RpgServer";
|
|
6
7
|
|
|
7
|
-
|
|
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 {
|
|
8
51
|
return provideModules(modules, "server", (modules, context) => {
|
|
9
52
|
const mainModuleServer = findModules(context, 'Server')
|
|
10
53
|
modules = [...mainModuleServer, ...modules]
|
|
11
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
|
+
}
|
|
12
66
|
if ('server' in module) {
|
|
13
67
|
module = module.server as any;
|
|
14
68
|
}
|
|
@@ -29,7 +83,32 @@ export function provideServerModules(modules: any[]): FactoryProvider {
|
|
|
29
83
|
maps: {
|
|
30
84
|
load: (engine: RpgMap) => {
|
|
31
85
|
maps.forEach((map) => {
|
|
32
|
-
|
|
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
|
+
lowMemory: MapClass.prototype?.lowMemory,
|
|
101
|
+
stopAllSoundsBeforeJoin: MapClass.prototype?.stopAllSoundsBeforeJoin,
|
|
102
|
+
events: MapClass.prototype?._events,
|
|
103
|
+
syncSchema: MapClass.prototype?.$schema,
|
|
104
|
+
onLoad: MapClass.prototype?.onLoad,
|
|
105
|
+
onJoin: MapClass.prototype?.onJoin,
|
|
106
|
+
onLeave: MapClass.prototype?.onLeave,
|
|
107
|
+
};
|
|
108
|
+
} else {
|
|
109
|
+
mapInstance = map;
|
|
110
|
+
}
|
|
111
|
+
engine.maps.push(mapInstance);
|
|
33
112
|
});
|
|
34
113
|
},
|
|
35
114
|
}
|