@rpgjs/server 4.0.0-rc.9 → 4.0.2

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 (50) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/browser/manifest.json +7 -0
  3. package/browser/rpg.server.js +21963 -0
  4. package/browser/rpg.server.umd.cjs +21994 -0
  5. package/lib/Game/EventManager.d.ts +1 -0
  6. package/lib/Game/EventManager.js +16 -2
  7. package/lib/Game/EventManager.js.map +1 -1
  8. package/lib/Player/ClassManager.d.ts +2 -2
  9. package/lib/Player/ClassManager.js +8 -7
  10. package/lib/Player/ClassManager.js.map +1 -1
  11. package/lib/Player/ElementManager.d.ts +2 -2
  12. package/lib/Player/ElementManager.js.map +1 -1
  13. package/lib/Player/ItemFixture.d.ts +2 -2
  14. package/lib/Player/ItemManager.d.ts +4 -9
  15. package/lib/Player/ItemManager.js +8 -2
  16. package/lib/Player/ItemManager.js.map +1 -1
  17. package/lib/Player/Player.d.ts +108 -32
  18. package/lib/Player/Player.js +55 -16
  19. package/lib/Player/Player.js.map +1 -1
  20. package/lib/Player/SkillManager.d.ts +9 -1
  21. package/lib/Player/SkillManager.js +13 -7
  22. package/lib/Player/SkillManager.js.map +1 -1
  23. package/lib/express/server.js +9 -12
  24. package/lib/express/server.js.map +1 -1
  25. package/lib/index.d.ts +3 -3
  26. package/lib/index.js.map +1 -1
  27. package/lib/logs/item.d.ts +1 -0
  28. package/lib/logs/item.js +3 -0
  29. package/lib/logs/item.js.map +1 -1
  30. package/lib/logs/skill.d.ts +1 -0
  31. package/lib/logs/skill.js +3 -0
  32. package/lib/logs/skill.js.map +1 -1
  33. package/lib/server.d.ts +1 -1
  34. package/lib/server.js +7 -3
  35. package/lib/server.js.map +1 -1
  36. package/package.json +9 -7
  37. package/rpg.toml +14 -0
  38. package/src/Game/EventManager.ts +17 -2
  39. package/src/Player/ClassManager.ts +7 -8
  40. package/src/Player/ElementManager.ts +2 -2
  41. package/src/Player/ItemFixture.ts +2 -2
  42. package/src/Player/ItemManager.ts +15 -7
  43. package/src/Player/ParameterManager.ts +1 -1
  44. package/src/Player/Player.ts +73 -19
  45. package/src/Player/SkillManager.ts +13 -9
  46. package/src/express/server.ts +9 -13
  47. package/src/index.ts +3 -3
  48. package/src/logs/item.ts +3 -0
  49. package/src/logs/skill.ts +3 -0
  50. package/src/server.ts +6 -3
@@ -1,7 +1,6 @@
1
1
  import { Utils } from '@rpgjs/common'
2
- import { Effect, ItemOptions } from '@rpgjs/database'
2
+ import { Effect, ClassHooks, ItemClass, ItemInstance, WeaponInstance, ArmorInstance, WeaponClass, ArmorClass } from '@rpgjs/database'
3
3
  import { ItemLog } from '../logs'
4
- import { ItemModel } from '../models/Item'
5
4
  import { EffectManager } from './EffectManager'
6
5
  import { GoldManager } from './GoldManager'
7
6
  import { StateManager } from './StateManager'
@@ -18,13 +17,13 @@ const {
18
17
  applyMixins
19
18
  } = Utils
20
19
 
21
- type ItemClass = { new(...args: any[]), price?: number, _type?: string }
22
- type Inventory = { nb: number, item: ItemModel }
20
+
21
+ type Inventory = { nb: number, item: ItemInstance }
23
22
 
24
23
  export class ItemManager {
25
24
 
26
25
  items: Inventory[]
27
- equipments: ItemModel[] = []
26
+ equipments: ItemInstance[] = []
28
27
 
29
28
  /**
30
29
  * Retrieves the information of an object: the number and the instance
@@ -464,7 +463,7 @@ export class ItemManager {
464
463
  * }
465
464
  * ```
466
465
  */
467
- equip(itemClass: ItemClass | string, equip: boolean = true): void {
466
+ equip(itemClass: WeaponClass | ArmorClass | string, equip: boolean = true): void {
468
467
  const inventory: Inventory = this.getItem(itemClass)
469
468
  if (!inventory) {
470
469
  throw ItemLog.notInInventory(itemClass)
@@ -472,7 +471,16 @@ export class ItemManager {
472
471
  if ((itemClass as ItemClass)._type == 'item') {
473
472
  throw ItemLog.invalidToEquiped(itemClass)
474
473
  }
475
- const { item } = inventory
474
+
475
+ if (this._class && this._class[ClassHooks.canEquip]) {
476
+ const canEquip = this['execMethodSync'](ClassHooks.canEquip, [inventory.item, this], this._class)
477
+ if (!canEquip) {
478
+ throw ItemLog.canNotEquip(itemClass)
479
+ }
480
+ }
481
+
482
+ const item: WeaponInstance | ArmorInstance = inventory.item as any
483
+
476
484
  if (item.equipped && equip) {
477
485
  throw ItemLog.isAlreadyEquiped(itemClass)
478
486
  }
@@ -95,7 +95,7 @@ export class ParameterManager {
95
95
  if (val > this.param[MAXHP]) {
96
96
  val = this.param[MAXHP]
97
97
  }
98
- else if (val <= 0) {
98
+ else if (val <= 0) {
99
99
  this['execMethod']('onDead')
100
100
  val = 0
101
101
  }
@@ -46,14 +46,26 @@ const {
46
46
 
47
47
  export interface Position { x: number, y: number, z: number }
48
48
 
49
- const itemSchemas = {
50
- name: String,
51
- description: String,
52
- price: Number,
53
- consumable: Boolean,
49
+ const commonSchemaFeature = {
50
+ name: {
51
+ $permanent: false
52
+ },
53
+ description: {
54
+ $permanent: false
55
+ },
54
56
  id: String
55
57
  }
56
58
 
59
+ const itemSchemas = {
60
+ price: {
61
+ $permanent: false
62
+ },
63
+ consumable: {
64
+ $permanent: false
65
+ },
66
+ ...commonSchemaFeature
67
+ }
68
+
57
69
  export const componentSchema = { id: String, value: String }
58
70
  export const layoutSchema = {
59
71
  width: Number,
@@ -74,7 +86,7 @@ const playerSchemas = {
74
86
  z: Number
75
87
  },
76
88
  direction: Number,
77
-
89
+
78
90
  teleported: {
79
91
  $permanent: false
80
92
  },
@@ -90,14 +102,23 @@ const playerSchemas = {
90
102
  level: {
91
103
  $effects: ['$this.expForNextlevel']
92
104
  },
93
- expForNextlevel: Number,
105
+ expForNextlevel: {
106
+ $permanent: false
107
+ },
94
108
  exp: Number,
95
109
  name: String,
96
110
  items: [{ nb: Number, item: itemSchemas }],
97
- _class: { name: String, description: String, id: String },
111
+ _class: commonSchemaFeature,
98
112
  equipments: [itemSchemas],
99
- skills: [{ name: String, description: String, spCost: Number, id: String }],
100
- states: [{ name: String, description: String, id: String }],
113
+ skills: [
114
+ {
115
+ spCost: {
116
+ $permanent: false
117
+ },
118
+ ...commonSchemaFeature
119
+ }
120
+ ],
121
+ states: [commonSchemaFeature],
101
122
  effects: [String],
102
123
 
103
124
  layout: {
@@ -168,14 +189,26 @@ export class RpgPlayer extends RpgCommonPlayer {
168
189
  public _rooms = []
169
190
  public session: string | null = null
170
191
  public prevMap: string = ''
171
- /** @internal */
192
+
193
+ /**
194
+ * ```ts
195
+ * retreive the server instance
196
+ * ```
197
+ * @title Server Instance
198
+ * @prop {RpgServerEngine} player.server
199
+ * @memberof Player
200
+ * */
172
201
  public server: RpgServerEngine
173
202
  private touchSide: boolean = false
203
+
174
204
  /** @internal */
175
205
  public tmpPositions: Position | string | null = null
176
206
  public otherPossessedPlayer: RpgPlayer | RpgEvent | null = null
177
207
  public following: RpgPlayer | RpgEvent | null = null
178
208
 
209
+ // Indicates whether to load data with load(). In this case, hooks are not triggered.
210
+ private _dataLoading: boolean = false
211
+
179
212
  _lastFramePositions: {
180
213
  frame: number
181
214
  position: Position
@@ -470,7 +503,9 @@ export class RpgPlayer extends RpgCommonPlayer {
470
503
  * @returns {Promise<boolean | RpgMap | null>}
471
504
  * @memberof Player
472
505
  */
473
- load(json: any): Promise<boolean | RpgMap | null> {
506
+ async load(json: any): Promise<boolean | RpgMap | null> {
507
+ this._dataLoading = true
508
+
474
509
  if (isString(json)) json = JSON.parse(json)
475
510
 
476
511
  const getData = (id) => new (this.databaseById(id))()
@@ -489,10 +524,12 @@ export class RpgPlayer extends RpgCommonPlayer {
489
524
  items[it.item.id] = getData(it.item.id)
490
525
  }
491
526
  json.items = json.items.map(it => ({ nb: it.nb, item: items[it.item.id] }))
492
- json.equipments = json.equipments.map(it => {
493
- items[it.id].equipped = true
494
- return items[it.id]
495
- })
527
+ if (Array.isArray(json.equipments)) {
528
+ json.equipments = json.equipments.map(it => {
529
+ items[it.id].equipped = true
530
+ return items[it.id]
531
+ })
532
+ }
496
533
  }
497
534
  if (json.states) json.states = json.states.map(state => getData(state.id))
498
535
  if (json.skills) json.skills = json.skills.map(skill => getData(skill.id))
@@ -501,12 +538,17 @@ export class RpgPlayer extends RpgCommonPlayer {
501
538
  merge(this, json)
502
539
 
503
540
  this.position = json.position
541
+
504
542
  if (json.map) {
505
543
  this.map = ''
506
- return this.changeMap(json.map, json.tmpPositions || json.position)
544
+ const map = await this.changeMap(json.map, json.tmpPositions || json.position)
545
+ this._dataLoading = false
546
+ return map
507
547
  }
508
548
 
509
- return Promise.resolve(null)
549
+ this._dataLoading = false
550
+
551
+ return null
510
552
  }
511
553
 
512
554
  /**
@@ -803,7 +845,19 @@ export class RpgPlayer extends RpgCommonPlayer {
803
845
  }
804
846
  }
805
847
 
848
+ private execMethodSync<T>(methodName: string, methodData = [], target?: any): T {
849
+ let ret
850
+ if (target && target[methodName]) {
851
+ ret = target[methodName](...methodData)
852
+ }
853
+ return ret
854
+ }
855
+
806
856
  async execMethod(methodName: string, methodData = [], target?: any) {
857
+ const ignoreIfDataLoading = ['onLevelUp', 'onDead']
858
+ if (ignoreIfDataLoading.includes(methodName) && this._dataLoading) {
859
+ return
860
+ }
807
861
  let ret
808
862
  if (target && target[methodName]) {
809
863
  ret = target[methodName](...methodData)
@@ -995,4 +1049,4 @@ export class RpgEvent extends RpgPlayer {
995
1049
  }
996
1050
  }
997
1051
  }
998
- }
1052
+ }
@@ -6,10 +6,6 @@ import { EffectManager } from './EffectManager'
6
6
  import { ParameterManager } from './ParameterManager';
7
7
  import { RpgPlayer } from './Player';
8
8
 
9
- import {
10
- INT
11
- } from '../presets'
12
-
13
9
  const {
14
10
  isArray,
15
11
  isString,
@@ -29,14 +25,14 @@ export class SkillManager {
29
25
  return skill.id == skillClass
30
26
  }
31
27
  if (isString(skillClass)) {
32
- return skillClass == skill.id || skill
28
+ return skillClass == (skill.id || skill)
33
29
  }
34
30
  return isInstanceOf(skill, skillClass)
35
31
  })
36
32
  }
37
33
 
38
34
  /**
39
- * Retrieves a skill. Returns null, if not found
35
+ * Retrieves a learned skill. Returns null, if not found
40
36
  * ```ts
41
37
  * import Fire from 'your-database/skills/fire'
42
38
  *
@@ -68,15 +64,23 @@ export class SkillManager {
68
64
  * @title Learn Skill
69
65
  * @method player.learnSkill(skillClass)
70
66
  * @param {SkillClass | string} skillClass or data id
67
+ * @throws {SkillLog} alreadyLearned
68
+ * If the player already knows the skill
69
+ * ```
70
+ {
71
+ id: SKILL_ALREADY_LEARNED,
72
+ msg: '...'
73
+ }
74
+ ```
71
75
  * @returns {instance of SkillClass}
72
76
  * @memberof SkillManager
73
77
  */
74
78
  learnSkill(skillClass: SkillClass | string) {
79
+ if (this.getSkill(skillClass)) {
80
+ throw SkillLog.alreadyLearned(skillClass)
81
+ }
75
82
  if (isString(skillClass)) skillClass = this.databaseById(skillClass)
76
83
  const instance = new (skillClass as SkillClass)()
77
- if (!instance.coefficient) instance.coefficient = {
78
- [INT]: 1
79
- }
80
84
  this.skills.push(instance)
81
85
  this['execMethod']('onLearn', [this], instance)
82
86
  return instance
@@ -23,8 +23,9 @@ export function expressServer(modules: ModuleType[], options: ExpressServerOptio
23
23
  }> {
24
24
  return new Promise((resolve, reject) => {
25
25
  const envs = options.envs || {}
26
+ const { express: expressConfig = {} } = options.globalConfig || {}
26
27
  const dirname = options.basePath
27
- const PORT = process.env.PORT || 3000
28
+ const PORT = process.env.PORT || expressConfig.port || 3000
28
29
  const pe = new PrettyError()
29
30
  const app = express()
30
31
  const server = http.createServer(app)
@@ -33,7 +34,8 @@ export function expressServer(modules: ModuleType[], options: ExpressServerOptio
33
34
  cors: {
34
35
  origin: "*",
35
36
  methods: ["GET", "POST"]
36
- }
37
+ },
38
+ ...(expressConfig.socketIo || {})
37
39
  })
38
40
 
39
41
  // @ts-ignore
@@ -41,20 +43,14 @@ export function expressServer(modules: ModuleType[], options: ExpressServerOptio
41
43
 
42
44
  // @ts-ignore
43
45
  const hasStatic = process.env.STATIC_DIRECTORY_ENABLED
44
- const staticDirectory = isBuilt ? '' : 'dist'
46
+ const staticDirectory = isBuilt ? expressConfig.static ?? '' : 'dist'
45
47
  // @ts-ignore
46
48
  const staticEnabled = (isBuilt && hasStatic === undefined) || hasStatic === 'true'
47
49
 
48
- if (!isBuilt) {
49
- app.use(express.json({
50
- // TODO
51
- limit: '50mb'
52
- }))
53
- }
54
-
55
- app.use(cors())
50
+ app.use(express.json(expressConfig.json))
51
+ app.use(cors(expressConfig.cors))
56
52
 
57
- if (staticEnabled) {
53
+ if (staticEnabled || expressConfig.static) {
58
54
  app.use('/', express.static(path.join(dirname, '..', staticDirectory, 'client')))
59
55
  }
60
56
 
@@ -77,7 +73,7 @@ export function expressServer(modules: ModuleType[], options: ExpressServerOptio
77
73
  }
78
74
 
79
75
  // @ts-ignore
80
- const serverPort = (envs.VITE_SERVER_URL || '').split(':')[1] || PORT
76
+ const serverPort = !isBuilt ? (envs.VITE_SERVER_URL || '').split(':')[1] || PORT : PORT
81
77
  server.listen(serverPort, start)
82
78
 
83
79
  process.on('uncaughtException', function (error) {
package/src/index.ts CHANGED
@@ -11,7 +11,7 @@ export {
11
11
  ShapePositioning,
12
12
  AbstractObject
13
13
  } from '@rpgjs/common'
14
- export { RpgServer, RpgPlayerHooks, RpgServerEngineHooks } from './RpgServer'
14
+ export type { RpgServer, RpgPlayerHooks, RpgServerEngineHooks } from './RpgServer'
15
15
  export { EventData } from './decorators/event'
16
16
  export { MapData } from './decorators/map'
17
17
  export { RpgPlayer, RpgEvent } from './Player/Player'
@@ -23,8 +23,8 @@ export { default as Monitor } from './Monitor'
23
23
  export * as Presets from './presets'
24
24
  export { Move, Frequency, Speed } from './Player/MoveManager'
25
25
  export { RpgServerEngine } from './server'
26
- export { SceneMap as RpgSceneMap, RpgClassMap } from './Scenes/Map'
26
+ export { SceneMap as RpgSceneMap, type RpgClassMap } from './Scenes/Map'
27
27
  export { RpgMatchMaker } from './MatchMaker'
28
- export { IStoreState } from './Interfaces/StateStore'
28
+ export type { IStoreState } from './Interfaces/StateStore'
29
29
  export { Components } from './Player/ComponentManager'
30
30
  export { Gui } from './Gui/Gui'
package/src/logs/item.ts CHANGED
@@ -13,6 +13,9 @@ export class ItemLog {
13
13
  static invalidToEquiped(itemClass) {
14
14
  return new Log('INVALID_ITEM_TO_EQUIP', `The item ${itemClass.name} is not a weapon or armor`)
15
15
  }
16
+ static canNotEquip(itemClass) {
17
+ return new Log('CANNOT_EQUIP', `The item ${itemClass.name} cannot be equiped`)
18
+ }
16
19
  static isAlreadyEquiped(itemClass) {
17
20
  return new Log('ITEM_ALREADY_EQUIPED', `The item ${itemClass.name} is already equiped`)
18
21
  }
package/src/logs/skill.ts CHANGED
@@ -13,4 +13,7 @@ export class SkillLog {
13
13
  static restriction(skillClass) {
14
14
  return new Log('RESTRICTION_SKILL', `A state blocks the use of the ${skillClass.name} skill`)
15
15
  }
16
+ static alreadyLearned(skillClass) {
17
+ return new Log('SKILL_ALREADY_LEARNED', `The ${skillClass.name} skill is already learned`)
18
+ }
16
19
  }
package/src/server.ts CHANGED
@@ -35,8 +35,6 @@ export class RpgServerEngine {
35
35
  * */
36
36
  public globalConfig: any = {}
37
37
 
38
- public assetsPath: string = 'assets'
39
-
40
38
  /**
41
39
  * Combat formulas
42
40
  *
@@ -81,7 +79,6 @@ export class RpgServerEngine {
81
79
  }
82
80
 
83
81
  this.globalConfig = this.inputOptions.globalConfig
84
- if (this.globalConfig.assetsPath !== undefined) this.assetsPath = this.globalConfig.assetsPath
85
82
 
86
83
  if (!this.inputOptions.maps) this.inputOptions.maps = []
87
84
  if (!this.inputOptions.events) this.inputOptions.events = []
@@ -340,6 +337,10 @@ export class RpgServerEngine {
340
337
  return RpgPlugin
341
338
  }
342
339
 
340
+ get assetsPath(): string {
341
+ return this.envs?.['VITE_ASSETS_PATH'] || 'assets'
342
+ }
343
+
343
344
  sendToPlayer(currentPlayer, eventName, data) {
344
345
  currentPlayer._socket.emit(eventName, data)
345
346
  }
@@ -351,6 +352,8 @@ export class RpgServerEngine {
351
352
  player.session = token
352
353
 
353
354
  socket.on('move', (data: { input: string[], frame: number }) => {
355
+ if (!data?.input) return
356
+ if (!Array.isArray(data.input)) return
354
357
  const controlPlayer = player.otherPossessedPlayer ?? player
355
358
  if (!controlPlayer.canMove) {
356
359
  return