@rpgjs/server 3.3.2 → 4.0.0-beta.10

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 (154) hide show
  1. package/LICENSE +19 -0
  2. package/lib/Game/Map.d.ts +58 -5
  3. package/lib/Game/Map.js +185 -80
  4. package/lib/Game/Map.js.map +1 -1
  5. package/lib/Game/WorldMaps.d.ts +3 -2
  6. package/lib/Game/WorldMaps.js +6 -11
  7. package/lib/Game/WorldMaps.js.map +1 -1
  8. package/lib/Gui/DialogGui.d.ts +1 -1
  9. package/lib/Gui/DialogGui.js +12 -13
  10. package/lib/Gui/DialogGui.js.map +1 -1
  11. package/lib/Gui/Gui.js +2 -6
  12. package/lib/Gui/Gui.js.map +1 -1
  13. package/lib/Gui/MenuGui.js +4 -8
  14. package/lib/Gui/MenuGui.js.map +1 -1
  15. package/lib/Gui/NotificationGui.js +4 -8
  16. package/lib/Gui/NotificationGui.js.map +1 -1
  17. package/lib/Gui/ShopGui.js +4 -8
  18. package/lib/Gui/ShopGui.js.map +1 -1
  19. package/lib/Gui/index.js +6 -13
  20. package/lib/Gui/index.js.map +1 -1
  21. package/lib/Interfaces/Gui.js +1 -2
  22. package/lib/Interfaces/StateStore.js +1 -2
  23. package/lib/MatchMaker.js +28 -46
  24. package/lib/MatchMaker.js.map +1 -1
  25. package/lib/Monitor/index.js +3 -5
  26. package/lib/Monitor/index.js.map +1 -1
  27. package/lib/Player/BattleManager.js +17 -16
  28. package/lib/Player/BattleManager.js.map +1 -1
  29. package/lib/Player/ClassManager.js +6 -10
  30. package/lib/Player/ClassManager.js.map +1 -1
  31. package/lib/Player/ComponentManager.d.ts +4 -4
  32. package/lib/Player/ComponentManager.js +37 -24
  33. package/lib/Player/ComponentManager.js.map +1 -1
  34. package/lib/Player/EffectManager.js +8 -12
  35. package/lib/Player/EffectManager.js.map +1 -1
  36. package/lib/Player/ElementManager.js +5 -9
  37. package/lib/Player/ElementManager.js.map +1 -1
  38. package/lib/Player/GoldManager.js +1 -5
  39. package/lib/Player/GoldManager.js.map +1 -1
  40. package/lib/Player/GuiManager.js +17 -15
  41. package/lib/Player/GuiManager.js.map +1 -1
  42. package/lib/Player/ItemFixture.js +1 -5
  43. package/lib/Player/ItemFixture.js.map +1 -1
  44. package/lib/Player/ItemManager.d.ts +3 -3
  45. package/lib/Player/ItemManager.js +29 -31
  46. package/lib/Player/ItemManager.js.map +1 -1
  47. package/lib/Player/MoveManager.d.ts +7 -6
  48. package/lib/Player/MoveManager.js +67 -74
  49. package/lib/Player/MoveManager.js.map +1 -1
  50. package/lib/Player/ParameterManager.js +10 -14
  51. package/lib/Player/ParameterManager.js.map +1 -1
  52. package/lib/Player/Player.d.ts +7 -1
  53. package/lib/Player/Player.js +193 -191
  54. package/lib/Player/Player.js.map +1 -1
  55. package/lib/Player/SkillManager.js +18 -22
  56. package/lib/Player/SkillManager.js.map +1 -1
  57. package/lib/Player/StateManager.js +9 -13
  58. package/lib/Player/StateManager.js.map +1 -1
  59. package/lib/Player/VariableManager.js +1 -5
  60. package/lib/Player/VariableManager.js.map +1 -1
  61. package/lib/Query.d.ts +2 -1
  62. package/lib/Query.js +19 -15
  63. package/lib/Query.js.map +1 -1
  64. package/lib/RpgServer.d.ts +11 -3
  65. package/lib/RpgServer.js +1 -2
  66. package/lib/Scenes/Map.d.ts +27 -4
  67. package/lib/Scenes/Map.js +117 -122
  68. package/lib/Scenes/Map.js.map +1 -1
  69. package/lib/decorators/event.js +4 -7
  70. package/lib/decorators/event.js.map +1 -1
  71. package/lib/decorators/map.d.ts +1 -1
  72. package/lib/decorators/map.js +5 -9
  73. package/lib/decorators/map.js.map +1 -1
  74. package/lib/entry-point.d.ts +1 -0
  75. package/lib/entry-point.js +59 -65
  76. package/lib/entry-point.js.map +1 -1
  77. package/lib/express/api.d.ts +3 -0
  78. package/lib/express/api.js +105 -0
  79. package/lib/express/api.js.map +1 -0
  80. package/lib/express/errors/NotAuthorized.d.ts +4 -0
  81. package/lib/express/errors/NotAuthorized.js +7 -0
  82. package/lib/express/errors/NotAuthorized.js.map +1 -0
  83. package/lib/express/errors/NotFound.d.ts +4 -0
  84. package/lib/express/errors/NotFound.js +7 -0
  85. package/lib/express/errors/NotFound.js.map +1 -0
  86. package/lib/express/server.d.ts +1 -0
  87. package/lib/express/server.js +22 -6
  88. package/lib/express/server.js.map +1 -1
  89. package/lib/index.js +15 -68
  90. package/lib/index.js.map +1 -1
  91. package/lib/logs/index.js +5 -11
  92. package/lib/logs/index.js.map +1 -1
  93. package/lib/logs/item.js +11 -15
  94. package/lib/logs/item.js.map +1 -1
  95. package/lib/logs/log.js +1 -5
  96. package/lib/logs/log.js.map +1 -1
  97. package/lib/logs/skill.js +6 -10
  98. package/lib/logs/skill.js.map +1 -1
  99. package/lib/logs/state.js +5 -9
  100. package/lib/logs/state.js.map +1 -1
  101. package/lib/models/Item.js +1 -2
  102. package/lib/presets/index.js +28 -36
  103. package/lib/presets/index.js.map +1 -1
  104. package/lib/server.d.ts +24 -2
  105. package/lib/server.js +229 -134
  106. package/lib/server.js.map +1 -1
  107. package/package.json +30 -15
  108. package/src/Game/Map.ts +513 -0
  109. package/src/Game/WorldMaps.ts +45 -0
  110. package/src/Gui/DialogGui.ts +67 -0
  111. package/src/Gui/Gui.ts +45 -0
  112. package/src/Gui/MenuGui.ts +26 -0
  113. package/src/Gui/NotificationGui.ts +10 -0
  114. package/src/Gui/ShopGui.ts +43 -0
  115. package/src/Gui/index.ts +13 -0
  116. package/src/Interfaces/Gui.ts +4 -0
  117. package/src/Interfaces/StateStore.ts +5 -0
  118. package/src/MatchMaker.ts +63 -0
  119. package/src/Monitor/index.ts +78 -0
  120. package/src/Player/BattleManager.ts +123 -0
  121. package/src/Player/ClassManager.ts +72 -0
  122. package/src/Player/ComponentManager.ts +538 -0
  123. package/src/Player/EffectManager.ts +94 -0
  124. package/src/Player/ElementManager.ts +142 -0
  125. package/src/Player/GoldManager.ts +26 -0
  126. package/src/Player/GuiManager.ts +308 -0
  127. package/src/Player/ItemFixture.ts +24 -0
  128. package/src/Player/ItemManager.ts +474 -0
  129. package/src/Player/MoveManager.ts +635 -0
  130. package/src/Player/ParameterManager.ts +468 -0
  131. package/src/Player/Player.ts +931 -0
  132. package/src/Player/SkillManager.ts +229 -0
  133. package/src/Player/StateManager.ts +230 -0
  134. package/src/Player/VariableManager.ts +55 -0
  135. package/src/Query.ts +172 -0
  136. package/src/RpgServer.ts +429 -0
  137. package/src/Scenes/Map.ts +302 -0
  138. package/src/decorators/event.ts +57 -0
  139. package/src/decorators/map.ts +223 -0
  140. package/src/entry-point.ts +104 -0
  141. package/src/express/api.ts +118 -0
  142. package/src/express/errors/NotAuthorized.ts +6 -0
  143. package/src/express/errors/NotFound.ts +6 -0
  144. package/src/express/server.ts +95 -0
  145. package/src/index.ts +28 -0
  146. package/src/logs/index.ts +11 -0
  147. package/src/logs/item.ts +31 -0
  148. package/src/logs/log.ts +3 -0
  149. package/src/logs/skill.ts +16 -0
  150. package/src/logs/state.ts +13 -0
  151. package/src/models/Item.ts +11 -0
  152. package/src/presets/index.ts +71 -0
  153. package/src/server.ts +396 -0
  154. package/tsconfig.json +27 -0
package/src/server.ts ADDED
@@ -0,0 +1,396 @@
1
+ import { SceneMap } from './Scenes/Map';
2
+ import { RpgPlayer } from './Player/Player'
3
+ import { Query } from './Query'
4
+ import { DAMAGE_SKILL, DAMAGE_PHYSIC, DAMAGE_CRITICAL, COEFFICIENT_ELEMENTS } from './presets'
5
+ import { World, WorldClass } from 'simple-room'
6
+ import { Utils, RpgPlugin, Scheduler, HookServer, RpgCommonGame, DefaultInput } from '@rpgjs/common'
7
+ import { Observable } from 'rxjs';
8
+ import { Tick } from '@rpgjs/types';
9
+ import { Actor, Armor, Class, DatabaseTypes, Item, Skill, State, Weapon } from '@rpgjs/database';
10
+
11
+ export class RpgServerEngine {
12
+
13
+ /**
14
+ * Express App Instance. If you have assigned this variable before starting the game, you can get the instance of Express
15
+ *
16
+ * @prop {Express App} [app]
17
+ * @memberof RpgServerEngine
18
+ */
19
+ app
20
+
21
+ /**
22
+ * List of the data
23
+ *
24
+ * @prop {object} [database]
25
+ * @memberof RpgServerEngine
26
+ */
27
+ public database: any = {}
28
+
29
+ /**
30
+ * retrieve the global configurations assigned at the entry point
31
+ *
32
+ * @prop {object} [globalConfig]
33
+ * @readonly
34
+ * @memberof RpgServerEngine
35
+ * */
36
+ public globalConfig: any = {}
37
+
38
+ public assetsPath: string = 'assets'
39
+
40
+ /**
41
+ * Combat formulas
42
+ *
43
+ * @prop {object} [damageFormulas]
44
+ * @memberof RpgServerEngine
45
+ */
46
+ public damageFormulas: any = {}
47
+
48
+ public serverId: string = process.env.SERVER_ID || Utils.generateUID()
49
+
50
+ private scenes: Map<string, any> = new Map()
51
+ protected totalConnected: number = 0
52
+ private scheduler: Scheduler = new Scheduler()
53
+ private playerProps: any
54
+
55
+ world: WorldClass = World
56
+ workers: any
57
+ envs: any = {}
58
+
59
+ /**
60
+ * Combat formulas
61
+ *
62
+ * @prop {Socket Io Server} [io]
63
+ * @memberof RpgServerEngine
64
+ */
65
+ constructor(public io, public gameEngine: RpgCommonGame, public inputOptions) {
66
+ this.envs = inputOptions.envs || {}
67
+ if (this.inputOptions.workers) {
68
+ console.log('workers enabled')
69
+ this.workers = this.gameEngine.createWorkers(this.inputOptions.workers).load()
70
+ }
71
+ }
72
+
73
+ private async _init() {
74
+ this.damageFormulas = this.inputOptions.damageFormulas || {}
75
+ this.damageFormulas = {
76
+ damageSkill: DAMAGE_SKILL,
77
+ damagePhysic: DAMAGE_PHYSIC,
78
+ damageCritical: DAMAGE_CRITICAL,
79
+ coefficientElements: COEFFICIENT_ELEMENTS,
80
+ ...this.damageFormulas
81
+ }
82
+
83
+ this.globalConfig = this.inputOptions.globalConfig
84
+ if (this.globalConfig.assetsPath !== undefined) this.assetsPath = this.globalConfig.assetsPath
85
+
86
+ if (!this.inputOptions.maps) this.inputOptions.maps = []
87
+ if (!this.inputOptions.events) this.inputOptions.events = []
88
+ if (!this.inputOptions.worldMaps) this.inputOptions.worldMaps = []
89
+ this.playerProps = this.inputOptions.playerProps
90
+
91
+ this.inputOptions.maps = [
92
+ ...Utils.arrayFlat(await RpgPlugin.emit(HookServer.AddMap, this.inputOptions.maps)) || [],
93
+ ...this.inputOptions.maps
94
+ ]
95
+
96
+ this.inputOptions.events = [
97
+ ...Utils.arrayFlat(await RpgPlugin.emit(HookServer.AddEvent, this.inputOptions.events)) || [],
98
+ ...this.inputOptions.events
99
+ ]
100
+
101
+ this.inputOptions.worldMaps = [
102
+ ...Utils.arrayFlat(await RpgPlugin.emit(HookServer.AddWorldMaps, this.inputOptions.worldMaps)) || [],
103
+ ...this.inputOptions.worldMaps
104
+ ]
105
+
106
+ this.globalConfig.inputs = {
107
+ ...DefaultInput,
108
+ ...(this.globalConfig.inputs || {})
109
+ }
110
+
111
+ if (!this.inputOptions.database) this.inputOptions.database = {}
112
+
113
+ const datas = await RpgPlugin.emit(HookServer.AddDatabase, this.inputOptions.database) || []
114
+
115
+ for (let plug of datas) {
116
+ this.inputOptions.database = {
117
+ ...plug,
118
+ ...this.inputOptions.database
119
+ }
120
+ }
121
+
122
+ for (let key in this.inputOptions.database) {
123
+ const data = this.inputOptions.database[key]
124
+ this.addInDatabase(data.id, data)
125
+ }
126
+
127
+ this.loadScenes()
128
+ }
129
+
130
+ /**
131
+ * Adds data to the server's database (in RAM) for later use
132
+ *
133
+ *
134
+ * @method server.addInDatabase(id,data)
135
+ * @title Add in database
136
+ * @param {number} id resource id
137
+ * @param {class | object} dataClass A class representing the data. You can just add a object if you specify the type
138
+ * @enum {string} [type] The type of data
139
+ *
140
+ * item
141
+ * weapon
142
+ * armor
143
+ * skill
144
+ * class
145
+ * state
146
+ * actor
147
+ *
148
+ * @since 3.0.0-beta.4
149
+ * @example
150
+ * ```ts
151
+ * @Item({
152
+ * name: 'Potion',
153
+ * description: 'Gives 100 HP',
154
+ * })
155
+ * class MyItem() {}
156
+ *
157
+ * server.addInDatabase('dynamic_item', MyItem)
158
+ * ```
159
+ *
160
+ * or with an object
161
+ *
162
+ * ```ts
163
+ * server.addInDatabase('dynamic_item', {
164
+ * name: 'Potion',
165
+ * description: 'Gives 100 HP',
166
+ * }, 'item')
167
+ *
168
+ * @returns {void}
169
+ * @memberof RpgServerEngine
170
+ */
171
+ addInDatabase(id: string, dataClass: any, type?: DatabaseTypes) {
172
+ if (Utils.isClass(dataClass)) {
173
+ this.database[id] = dataClass
174
+ return
175
+ }
176
+ if (!type) {
177
+ throw new Error(`You must specify a type for the database ${id}`)
178
+ }
179
+ switch (type) {
180
+ case 'item':
181
+ @Item(dataClass) class ItemClass { }
182
+ this.database[id] = ItemClass
183
+ break;
184
+ case 'weapon':
185
+ @Weapon(dataClass) class WeaponClass { }
186
+ this.database[id] = WeaponClass
187
+ break;
188
+ case 'armor':
189
+ @Armor(dataClass) class ArmorClass { }
190
+ this.database[id] = ArmorClass
191
+ break;
192
+ case 'skill':
193
+ @Skill(dataClass) class SkillClass { }
194
+ this.database[id] = SkillClass
195
+ break;
196
+ case 'class':
197
+ @Class(dataClass) class ClassClass { }
198
+ this.database[id] = ClassClass
199
+ break;
200
+ case 'state':
201
+ @State(dataClass) class StateClass { }
202
+ this.database[id] = StateClass
203
+ break;
204
+ case 'actor':
205
+ @Actor(dataClass) class ActorClass { }
206
+ this.database[id] = ActorClass
207
+ break;
208
+ }
209
+ }
210
+
211
+ /**
212
+ * Start the RPG server
213
+ *
214
+ * @method server.start()
215
+ * @title Start Server
216
+ * @returns {void}
217
+ * @memberof RpgServerEngine
218
+ */
219
+ async start(inputOptions?, scheduler = true) {
220
+ if (inputOptions) this.inputOptions = inputOptions
221
+ await this._init()
222
+ this.tick.subscribe(({ timestamp, deltaTime }) => {
223
+ this.step(timestamp, deltaTime)
224
+ })
225
+ if (scheduler) this.scheduler.start({
226
+ fps: inputOptions?.fps || 60
227
+ })
228
+ this.gameEngine.start({
229
+ getObject(id) {
230
+ return Query.getPlayer(id)
231
+ },
232
+ getObjectsOfGroup(groupId: string, player: RpgPlayer) {
233
+ return Query._getObjectsOfMap(groupId, player)
234
+ },
235
+ getShapesOfGroup(map: string) {
236
+ return Query._getShapesOfMap(map)
237
+ }
238
+ })
239
+ this.io.on('connection', this.onPlayerConnected.bind(this))
240
+ await RpgPlugin.emit(HookServer.Start, this)
241
+ }
242
+
243
+ get tick(): Observable<Tick> {
244
+ return this.scheduler.tick as any
245
+ }
246
+
247
+ /**
248
+ * Sends all packages to clients. The sending is done automatically but you can decide to send yourself by calling this method (for example, for unit tests)
249
+ *
250
+ * @method server.send()
251
+ * @title Send All Packets
252
+ * @returns {void}
253
+ * @memberof RpgServerEngine
254
+ */
255
+ send() {
256
+ this.world.send()
257
+ }
258
+
259
+ private async updatePlayersMove(deltaTimeInt: number) {
260
+ const players = this.world.getUsers()
261
+ const obj: any = []
262
+ let p: Promise<RpgPlayer>[] = []
263
+ for (let playerId in players) {
264
+ const playerInstance = players[playerId]['proxy'] as RpgPlayer
265
+ if (!playerInstance) continue
266
+ const player = playerInstance.otherPossessedPlayer ?? playerInstance
267
+ if (player.pendingMove.length > 0) {
268
+ const lastFrame = player.pendingMove[player.pendingMove.length - 1]
269
+ if (this.inputOptions.workers) obj.push(player.toObject())
270
+ else {
271
+ p.push(this.gameEngine.processInput(player.playerId, this.globalConfig.inputs).then((val) => {
272
+ player.pendingMove = []
273
+ player._lastFramePositions = {
274
+ frame: lastFrame.frame,
275
+ position: { ...player.position }
276
+ }
277
+ return player
278
+ }))
279
+ }
280
+ }
281
+ }
282
+ // TODO
283
+ if (this.inputOptions.workers) {
284
+ this.workers.call('movePlayers', obj).then((players) => {
285
+ for (let playerId in players) {
286
+ const player = this.world.getUser(playerId) as RpgPlayer
287
+ const data = players[playerId]
288
+ if (player) {
289
+ player.position = data.position
290
+ player.direction = data.direction
291
+ }
292
+ RpgPlugin.emit('Server.onInput', [player, {
293
+ input: data.direction,
294
+ moving: true
295
+ }], true)
296
+ }
297
+ })
298
+ }
299
+ return Promise.all(p)
300
+ }
301
+
302
+ nextTick(timestamp: number) {
303
+ this.scheduler.nextTick(timestamp)
304
+ }
305
+
306
+ step(t: number, dt: number) {
307
+ this.updatePlayersMove(1)
308
+ if (this.scheduler.frame % 4 === 0) {
309
+ this.send()
310
+ }
311
+ RpgPlugin.emit(HookServer.Step, this)
312
+ }
313
+
314
+ private loadScenes() {
315
+ this.scenes.set(SceneMap.id, new SceneMap(
316
+ {
317
+ maps: this.inputOptions.maps,
318
+ events: this.inputOptions.events,
319
+ worldMaps: this.inputOptions.worldMaps
320
+ },
321
+ this
322
+ ))
323
+ }
324
+
325
+ getScene<T>(name: string): T {
326
+ return this.scenes.get(name)
327
+ }
328
+
329
+ /**
330
+ * Return the scene that manages the maps of the game
331
+ * @prop {SceneMap} [sceneMap]
332
+ * @since 3.0.0-beta.4
333
+ * @memberof RpgServerEngine
334
+ */
335
+ get sceneMap(): SceneMap {
336
+ return this.getScene<SceneMap>(SceneMap.id)
337
+ }
338
+
339
+ sendToPlayer(currentPlayer, eventName, data) {
340
+ currentPlayer._socket.emit(eventName, data)
341
+ }
342
+
343
+ private onPlayerConnected(socket) {
344
+ const { token } = socket.handshake.auth
345
+ const playerId = Utils.generateUID()
346
+ const player: RpgPlayer = new RpgPlayer(this.gameEngine, playerId)
347
+ player.session = token
348
+
349
+ socket.on('move', (data: { input: string[], frame: number }) => {
350
+ const controlPlayer = player.otherPossessedPlayer ?? player
351
+ if (!controlPlayer.canMove) {
352
+ return
353
+ }
354
+ for (let input of data.input) {
355
+ controlPlayer.pendingMove.push({
356
+ input,
357
+ frame: data.frame
358
+ })
359
+ }
360
+ })
361
+
362
+ socket.on('disconnect', () => {
363
+ this.onPlayerDisconnected(socket.id, playerId)
364
+ })
365
+
366
+ this.world.setUser(player, socket)
367
+
368
+ player.server = this
369
+ player._init()
370
+
371
+ if (!token) {
372
+ const newToken = Utils.generateUID() + '-' + Utils.generateUID() + '-' + Utils.generateUID()
373
+ player.session = newToken
374
+ }
375
+
376
+ socket.emit('playerJoined', { playerId, session: player.session })
377
+
378
+ if (!token) {
379
+ player.execMethod('onConnected')
380
+ }
381
+ else {
382
+ RpgPlugin.emit(HookServer.ScalabilityPlayerConnected, player)
383
+ }
384
+ }
385
+
386
+ /**
387
+ *
388
+ * @param {string} socketId - The socketId of the player that disconnected
389
+ * @param {string} playerId - The playerId of the player that disconnected
390
+ */
391
+ private onPlayerDisconnected(socketId, playerId: string) {
392
+ const player: RpgPlayer = World.getUser(playerId) as RpgPlayer
393
+ player.execMethod('onDisconnected')
394
+ this.world.disconnectUser(playerId)
395
+ }
396
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,27 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "module": "ES2020",
5
+ "outDir": "./lib",
6
+ "rootDir": "./src",
7
+ "strict": true,
8
+ "sourceMap": true,
9
+ "strictNullChecks": true,
10
+ "strictPropertyInitialization": false,
11
+ "moduleResolution": "node",
12
+ "esModuleInterop": true,
13
+ "removeComments": false,
14
+ "noUnusedParameters": false,
15
+ "noUnusedLocals": false,
16
+ "noImplicitThis": false,
17
+ "noImplicitAny": false,
18
+ "noImplicitReturns": false,
19
+ "declaration": true,
20
+ "experimentalDecorators": true,
21
+ "emitDecoratorMetadata": true,
22
+ "stripInternal": true
23
+ },
24
+ "include": [
25
+ "src"
26
+ ]
27
+ }