@rpgjs/server 4.1.3 → 4.2.1
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/CHANGELOG.md +24 -0
- package/browser/rpg.server.js +768 -366
- package/browser/rpg.server.umd.cjs +754 -352
- package/lib/Game/EventManager.js +1 -1
- package/lib/Game/EventManager.js.map +1 -1
- package/lib/Game/Map.d.ts +4 -0
- package/lib/Game/Map.js +11 -1
- package/lib/Game/Map.js.map +1 -1
- package/lib/Gui/Gui.js +1 -0
- package/lib/Gui/Gui.js.map +1 -1
- package/lib/MatchMaker.js +3 -1
- package/lib/MatchMaker.js.map +1 -1
- package/lib/Player/Player.d.ts +9 -3
- package/lib/Player/Player.js +24 -16
- package/lib/Player/Player.js.map +1 -1
- package/lib/RpgServer.d.ts +29 -0
- package/lib/Scenes/Map.d.ts +2 -3
- package/lib/Scenes/Map.js +7 -3
- package/lib/Scenes/Map.js.map +1 -1
- package/lib/entry-point.js +18 -12
- package/lib/entry-point.js.map +1 -1
- package/lib/express/server.js +0 -10
- package/lib/express/server.js.map +1 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/index.js.map +1 -1
- package/lib/inject.d.ts +22 -0
- package/lib/inject.js +29 -0
- package/lib/inject.js.map +1 -0
- package/lib/server.d.ts +7 -5
- package/lib/server.js +82 -38
- package/lib/server.js.map +1 -1
- package/package.json +7 -8
- package/src/Game/EventManager.ts +1 -1
- package/src/Game/Map.ts +15 -1
- package/src/Gui/Gui.ts +1 -0
- package/src/MatchMaker.ts +3 -1
- package/src/Player/Player.ts +18 -10
- package/src/RpgServer.ts +30 -1
- package/src/Scenes/Map.ts +6 -2
- package/src/entry-point.ts +19 -12
- package/src/express/server.ts +0 -10
- package/src/index.ts +1 -0
- package/src/inject.ts +33 -0
- package/src/server.ts +86 -35
package/src/entry-point.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { RpgCommonGame, HookServer, loadModules, ModuleType, GameSide, RpgPlugin } from '@rpgjs/common'
|
|
1
|
+
import { RpgCommonGame, HookServer, loadModules, ModuleType, GameSide, RpgPlugin, InjectContext } from '@rpgjs/common'
|
|
2
2
|
import { RpgServerEngine } from './server'
|
|
3
3
|
import { RpgPlayer } from './Player/Player'
|
|
4
4
|
import { RpgMatchMaker } from './MatchMaker'
|
|
5
|
+
import { inject, setInject } from './inject'
|
|
5
6
|
|
|
6
7
|
interface RpgServerEntryPointOptions {
|
|
7
8
|
/**
|
|
@@ -39,7 +40,10 @@ interface RpgServerEntryPointOptions {
|
|
|
39
40
|
}
|
|
40
41
|
|
|
41
42
|
export default async function (modules: ModuleType[], options: RpgServerEntryPointOptions): Promise<RpgServerEngine> {
|
|
42
|
-
const
|
|
43
|
+
const context = new InjectContext()
|
|
44
|
+
setInject(context)
|
|
45
|
+
|
|
46
|
+
inject(RpgCommonGame, [GameSide.Server])
|
|
43
47
|
|
|
44
48
|
if (!options.globalConfig) options.globalConfig = {}
|
|
45
49
|
|
|
@@ -59,7 +63,8 @@ export default async function (modules: ModuleType[], options: RpgServerEntryPoi
|
|
|
59
63
|
|
|
60
64
|
const relationsEngine = {
|
|
61
65
|
onStart: HookServer.Start,
|
|
62
|
-
onStep: HookServer.Step
|
|
66
|
+
onStep: HookServer.Step,
|
|
67
|
+
auth: HookServer.Auth
|
|
63
68
|
}
|
|
64
69
|
|
|
65
70
|
const { playerProps } = await loadModules(modules, {
|
|
@@ -91,14 +96,16 @@ export default async function (modules: ModuleType[], options: RpgServerEntryPoi
|
|
|
91
96
|
return mod
|
|
92
97
|
})
|
|
93
98
|
|
|
94
|
-
const serverEngine =
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
99
|
+
const serverEngine = inject(RpgServerEngine, [
|
|
100
|
+
options.io, {
|
|
101
|
+
debug: {},
|
|
102
|
+
updateRate: 10,
|
|
103
|
+
stepRate: 60,
|
|
104
|
+
timeoutInterval: 0,
|
|
105
|
+
countConnections: false,
|
|
106
|
+
playerProps,
|
|
107
|
+
...options
|
|
108
|
+
}
|
|
109
|
+
])
|
|
103
110
|
return serverEngine
|
|
104
111
|
}
|
package/src/express/server.ts
CHANGED
|
@@ -83,15 +83,5 @@ export function expressServer(modules: ModuleType[], options: ExpressServerOptio
|
|
|
83
83
|
process.on('unhandledRejection', function (reason: any) {
|
|
84
84
|
console.log(pe.render(reason))
|
|
85
85
|
})
|
|
86
|
-
|
|
87
|
-
if (import.meta['hot']) {
|
|
88
|
-
import.meta['hot'].on("vite:beforeFullReload", () => {
|
|
89
|
-
server.close()
|
|
90
|
-
Query.getPlayers().forEach(player => {
|
|
91
|
-
player.gameReload()
|
|
92
|
-
})
|
|
93
|
-
rpgGame.stop()
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
86
|
})
|
|
97
87
|
}
|
package/src/index.ts
CHANGED
package/src/inject.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { InjectContext } from "@rpgjs/common";
|
|
2
|
+
|
|
3
|
+
let instanceContext: InjectContext | null = null
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Dependency injection function for RPGJS server side.
|
|
7
|
+
*
|
|
8
|
+
* The server-side `inject` function is designed for retrieving instances of server-related classes in the RPGJS framework.
|
|
9
|
+
* This function is crucial for accessing singleton instances of classes like `RpgServerEngine` on the server. It facilitates
|
|
10
|
+
* a clean and efficient approach to handling dependencies within server modules, contributing to a more organized codebase.
|
|
11
|
+
*
|
|
12
|
+
* @template T The class type that you want to retrieve an instance of, specific to server-side modules.
|
|
13
|
+
* @returns {T} Returns the singleton instance of the specified class, ensuring consistent server-side behavior and state management.
|
|
14
|
+
* @since 4.2.0
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* // Example of injecting the RpgServerEngine
|
|
19
|
+
* import { inject, RpgServerEngine } from '@rpgjs/server'
|
|
20
|
+
* const server = inject(RpgServerEngine)
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export function inject<T>(service: new (...args: any[]) => T, args: any[] = []): T {
|
|
24
|
+
return instanceContext!.inject(service, args);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function setInject(context: InjectContext) {
|
|
28
|
+
instanceContext = context;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function clearInject() {
|
|
32
|
+
instanceContext = null
|
|
33
|
+
}
|
package/src/server.ts
CHANGED
|
@@ -2,11 +2,12 @@ import { SceneMap } from './Scenes/Map';
|
|
|
2
2
|
import { RpgPlayer } from './Player/Player'
|
|
3
3
|
import { Query } from './Query'
|
|
4
4
|
import { DAMAGE_SKILL, DAMAGE_PHYSIC, DAMAGE_CRITICAL, COEFFICIENT_ELEMENTS } from './presets'
|
|
5
|
-
import { World, WorldClass } from 'simple-room'
|
|
5
|
+
import { World, WorldClass, Transport } from 'simple-room'
|
|
6
6
|
import { Utils, RpgPlugin, Scheduler, HookServer, RpgCommonGame, DefaultInput } from '@rpgjs/common'
|
|
7
7
|
import { Observable } from 'rxjs';
|
|
8
8
|
import { Tick } from '@rpgjs/types';
|
|
9
9
|
import { Actor, Armor, Class, DatabaseTypes, Item, Skill, State, Weapon } from '@rpgjs/database';
|
|
10
|
+
import { inject } from './inject';
|
|
10
11
|
|
|
11
12
|
export class RpgServerEngine {
|
|
12
13
|
|
|
@@ -49,10 +50,13 @@ export class RpgServerEngine {
|
|
|
49
50
|
protected totalConnected: number = 0
|
|
50
51
|
private scheduler: Scheduler = new Scheduler()
|
|
51
52
|
private playerProps: any
|
|
53
|
+
public gameEngine: RpgCommonGame = inject(RpgCommonGame)
|
|
52
54
|
|
|
53
55
|
world: WorldClass = World
|
|
54
56
|
workers: any
|
|
55
57
|
envs: any = {}
|
|
58
|
+
io: any
|
|
59
|
+
inputOptions: any = {}
|
|
56
60
|
|
|
57
61
|
/**
|
|
58
62
|
* Combat formulas
|
|
@@ -60,7 +64,9 @@ export class RpgServerEngine {
|
|
|
60
64
|
* @prop {Socket Io Server} [io]
|
|
61
65
|
* @memberof RpgServerEngine
|
|
62
66
|
*/
|
|
63
|
-
|
|
67
|
+
initialize(io, inputOptions) {
|
|
68
|
+
this.io = io
|
|
69
|
+
this.inputOptions = inputOptions
|
|
64
70
|
this.envs = inputOptions.envs || {}
|
|
65
71
|
if (this.inputOptions.workers) {
|
|
66
72
|
console.log('workers enabled')
|
|
@@ -237,10 +243,31 @@ export class RpgServerEngine {
|
|
|
237
243
|
return Query._getShapesOfMap(map)
|
|
238
244
|
}
|
|
239
245
|
})
|
|
240
|
-
this.io.on('connection', this.onPlayerConnected.bind(this))
|
|
246
|
+
//this.io.on('connection', this.onPlayerConnected.bind(this))
|
|
247
|
+
this.transport(this.io)
|
|
241
248
|
await RpgPlugin.emit(HookServer.Start, this)
|
|
242
249
|
}
|
|
243
250
|
|
|
251
|
+
private transport(io): Transport {
|
|
252
|
+
const timeoutDisconnect = this.globalConfig.timeoutDisconnect ?? 0
|
|
253
|
+
const auth = this.globalConfig.disableAuth ? () => Utils.generateUID() :
|
|
254
|
+
async (socket) => {
|
|
255
|
+
const val = await RpgPlugin.emit(HookServer.Auth, [this, socket], true)
|
|
256
|
+
if (val.length == 0) {
|
|
257
|
+
return Utils.generateUID()
|
|
258
|
+
}
|
|
259
|
+
return val[val.length - 1]
|
|
260
|
+
}
|
|
261
|
+
const transport = new Transport(io, {
|
|
262
|
+
timeoutDisconnect,
|
|
263
|
+
auth
|
|
264
|
+
})
|
|
265
|
+
this.world.timeoutDisconnect = timeoutDisconnect
|
|
266
|
+
transport.onConnected(this.onPlayerConnected.bind(this))
|
|
267
|
+
transport.onDisconnected(this.onPlayerDisconnected.bind(this))
|
|
268
|
+
return transport
|
|
269
|
+
}
|
|
270
|
+
|
|
244
271
|
get tick(): Observable<Tick> {
|
|
245
272
|
return this.scheduler.tick as any
|
|
246
273
|
}
|
|
@@ -253,8 +280,8 @@ export class RpgServerEngine {
|
|
|
253
280
|
* @returns {void}
|
|
254
281
|
* @memberof RpgServerEngine
|
|
255
282
|
*/
|
|
256
|
-
send() {
|
|
257
|
-
this.world.send()
|
|
283
|
+
send(): Promise<void> {
|
|
284
|
+
return this.world.send()
|
|
258
285
|
}
|
|
259
286
|
|
|
260
287
|
private async updatePlayersMove(deltaTimeInt: number) {
|
|
@@ -266,7 +293,7 @@ export class RpgServerEngine {
|
|
|
266
293
|
if (!playerInstance) continue
|
|
267
294
|
const player = playerInstance.otherPossessedPlayer ?? playerInstance
|
|
268
295
|
if (player.pendingMove.length > 0) {
|
|
269
|
-
|
|
296
|
+
|
|
270
297
|
const lastFrame = player.pendingMove[player.pendingMove.length - 1]
|
|
271
298
|
if (this.inputOptions.workers) obj.push(player.toObject())
|
|
272
299
|
else {
|
|
@@ -320,8 +347,7 @@ export class RpgServerEngine {
|
|
|
320
347
|
maps: this.inputOptions.maps,
|
|
321
348
|
events: this.inputOptions.events,
|
|
322
349
|
worldMaps: this.inputOptions.worldMaps
|
|
323
|
-
}
|
|
324
|
-
this
|
|
350
|
+
}
|
|
325
351
|
))
|
|
326
352
|
}
|
|
327
353
|
|
|
@@ -351,11 +377,58 @@ export class RpgServerEngine {
|
|
|
351
377
|
currentPlayer._socket.emit(eventName, data)
|
|
352
378
|
}
|
|
353
379
|
|
|
354
|
-
private
|
|
355
|
-
const
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
380
|
+
private getPlayerBySession(session: string): RpgPlayer | null {
|
|
381
|
+
const users = this.world.getUsers<RpgPlayer>()
|
|
382
|
+
for (let userId in users) {
|
|
383
|
+
const user = users[userId]
|
|
384
|
+
if (user.session === session) {
|
|
385
|
+
return user
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
return null
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
private onPlayerConnected(socket, playerId: string) {
|
|
392
|
+
const existingUser = this.world.getUser<RpgPlayer>(playerId, false)
|
|
393
|
+
|
|
394
|
+
this.world.connectUser(socket, playerId)
|
|
395
|
+
|
|
396
|
+
let player: RpgPlayer
|
|
397
|
+
|
|
398
|
+
if (!existingUser) {
|
|
399
|
+
const { token } = socket.handshake.auth
|
|
400
|
+
player = new RpgPlayer(playerId)
|
|
401
|
+
player.session = token
|
|
402
|
+
|
|
403
|
+
this.world.setUser(player, socket)
|
|
404
|
+
|
|
405
|
+
player._init()
|
|
406
|
+
|
|
407
|
+
if (!token) {
|
|
408
|
+
const newToken = Utils.generateUID() + '-' + Utils.generateUID() + '-' + Utils.generateUID()
|
|
409
|
+
player.session = newToken
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
if (!token) {
|
|
413
|
+
player.execMethod('onConnected')
|
|
414
|
+
}
|
|
415
|
+
else {
|
|
416
|
+
RpgPlugin.emit(HookServer.ScalabilityPlayerConnected, player)
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
else {
|
|
420
|
+
player = existingUser
|
|
421
|
+
if (player.map) {
|
|
422
|
+
player.emit('preLoadScene', {
|
|
423
|
+
reconnect: true,
|
|
424
|
+
id: player.map
|
|
425
|
+
})
|
|
426
|
+
player.emitSceneMap()
|
|
427
|
+
this.world.joinRoom(player.map, playerId)
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
socket.emit('playerJoined', { playerId, session: player.session })
|
|
359
432
|
|
|
360
433
|
socket.on('move', (data: { input: string[], frame: number }) => {
|
|
361
434
|
if (!data?.input) return
|
|
@@ -372,28 +445,6 @@ export class RpgServerEngine {
|
|
|
372
445
|
}
|
|
373
446
|
})
|
|
374
447
|
|
|
375
|
-
socket.on('disconnect', () => {
|
|
376
|
-
this.onPlayerDisconnected(playerId)
|
|
377
|
-
})
|
|
378
|
-
|
|
379
|
-
this.world.setUser(player, socket)
|
|
380
|
-
|
|
381
|
-
player.server = this
|
|
382
|
-
player._init()
|
|
383
|
-
|
|
384
|
-
if (!token) {
|
|
385
|
-
const newToken = Utils.generateUID() + '-' + Utils.generateUID() + '-' + Utils.generateUID()
|
|
386
|
-
player.session = newToken
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
socket.emit('playerJoined', { playerId, session: player.session })
|
|
390
|
-
|
|
391
|
-
if (!token) {
|
|
392
|
-
player.execMethod('onConnected')
|
|
393
|
-
}
|
|
394
|
-
else {
|
|
395
|
-
RpgPlugin.emit(HookServer.ScalabilityPlayerConnected, player)
|
|
396
|
-
}
|
|
397
448
|
}
|
|
398
449
|
|
|
399
450
|
private onPlayerDisconnected(playerId: string) {
|