@rpgjs/server 4.2.2 → 5.0.0-alpha.0
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/{lib → dist}/Gui/DialogGui.d.ts +1 -2
- package/{lib → dist}/Gui/Gui.d.ts +1 -2
- package/dist/Player/BattleManager.d.ts +22 -0
- package/dist/Player/ClassManager.d.ts +18 -0
- package/dist/Player/Event.d.ts +0 -0
- package/dist/Player/ItemManager.d.ts +17 -0
- package/dist/Player/MoveManager.d.ts +177 -0
- package/dist/Player/ParameterManager.d.ts +42 -0
- package/dist/Player/Player.d.ts +73 -0
- package/dist/Player/SkillManager.d.ts +23 -0
- package/dist/Player/StateManager.d.ts +39 -0
- package/{lib → dist}/RpgServer.d.ts +34 -17
- package/dist/RpgServerEngine.d.ts +5 -0
- package/dist/core/context.d.ts +2 -0
- package/dist/core/inject.d.ts +5 -0
- package/dist/core/setup.d.ts +6 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +29673 -0
- package/dist/index.js.map +1 -0
- package/dist/module.d.ts +2 -0
- package/dist/rooms/lobby.d.ts +6 -0
- package/dist/rooms/map.d.ts +110 -0
- package/package.json +16 -38
- package/src/Gui/DialogGui.ts +3 -4
- package/src/Gui/Gui.ts +4 -6
- package/src/Player/BattleManager.ts +108 -99
- package/src/Player/ClassManager.ts +47 -46
- package/src/Player/ComponentManager.ts +26 -535
- package/src/Player/EffectManager.ts +44 -59
- package/src/Player/ElementManager.ts +70 -72
- package/src/Player/Event.ts +0 -0
- package/src/Player/GoldManager.ts +24 -6
- package/src/Player/GuiManager.ts +106 -97
- package/src/Player/ItemFixture.ts +22 -17
- package/src/Player/ItemManager.ts +234 -225
- package/src/Player/MoveManager.ts +1047 -457
- package/src/Player/ParameterManager.ts +59 -37
- package/src/Player/Player.ts +272 -1058
- package/src/Player/SkillManager.ts +146 -137
- package/src/Player/StateManager.ts +124 -98
- package/src/Player/VariableManager.ts +23 -3
- package/src/RpgServer.ts +38 -14
- package/src/RpgServerEngine.ts +7 -0
- package/src/core/context.ts +3 -0
- package/src/core/inject.ts +17 -0
- package/src/core/setup.ts +20 -0
- package/src/index.ts +9 -31
- package/src/module.ts +32 -0
- package/src/presets/index.ts +1 -3
- package/src/rooms/lobby.ts +24 -0
- package/src/rooms/map.ts +311 -0
- package/tsconfig.json +26 -23
- package/vite.config.ts +21 -0
- package/CHANGELOG.md +0 -163
- package/LICENSE +0 -19
- package/browser/manifest.json +0 -7
- package/browser/rpg.server.js +0 -22372
- package/browser/rpg.server.umd.cjs +0 -22403
- package/lib/Game/EventManager.d.ts +0 -54
- package/lib/Game/EventManager.js +0 -107
- package/lib/Game/EventManager.js.map +0 -1
- package/lib/Game/Map.d.ts +0 -191
- package/lib/Game/Map.js +0 -414
- package/lib/Game/Map.js.map +0 -1
- package/lib/Game/WorldMaps.d.ts +0 -17
- package/lib/Game/WorldMaps.js +0 -28
- package/lib/Game/WorldMaps.js.map +0 -1
- package/lib/Gui/DialogGui.js +0 -57
- package/lib/Gui/DialogGui.js.map +0 -1
- package/lib/Gui/Gui.js +0 -37
- package/lib/Gui/Gui.js.map +0 -1
- package/lib/Gui/MenuGui.js +0 -23
- package/lib/Gui/MenuGui.js.map +0 -1
- package/lib/Gui/NotificationGui.js +0 -8
- package/lib/Gui/NotificationGui.js.map +0 -1
- package/lib/Gui/ShopGui.js +0 -40
- package/lib/Gui/ShopGui.js.map +0 -1
- package/lib/Gui/index.js +0 -7
- package/lib/Gui/index.js.map +0 -1
- package/lib/Interfaces/Gui.d.ts +0 -4
- package/lib/Interfaces/Gui.js +0 -2
- package/lib/Interfaces/Gui.js.map +0 -1
- package/lib/Interfaces/StateStore.d.ts +0 -5
- package/lib/Interfaces/StateStore.js +0 -2
- package/lib/Interfaces/StateStore.js.map +0 -1
- package/lib/MatchMaker.d.ts +0 -24
- package/lib/MatchMaker.js +0 -42
- package/lib/MatchMaker.js.map +0 -1
- package/lib/Monitor/index.d.ts +0 -17
- package/lib/Monitor/index.js +0 -72
- package/lib/Monitor/index.js.map +0 -1
- package/lib/Player/BattleManager.d.ts +0 -36
- package/lib/Player/BattleManager.js +0 -101
- package/lib/Player/BattleManager.js.map +0 -1
- package/lib/Player/ClassManager.d.ts +0 -47
- package/lib/Player/ClassManager.js +0 -65
- package/lib/Player/ClassManager.js.map +0 -1
- package/lib/Player/ComponentManager.d.ts +0 -397
- package/lib/Player/ComponentManager.js +0 -505
- package/lib/Player/ComponentManager.js.map +0 -1
- package/lib/Player/EffectManager.d.ts +0 -46
- package/lib/Player/EffectManager.js +0 -75
- package/lib/Player/EffectManager.js.map +0 -1
- package/lib/Player/ElementManager.d.ts +0 -108
- package/lib/Player/ElementManager.js +0 -120
- package/lib/Player/ElementManager.js.map +0 -1
- package/lib/Player/GoldManager.d.ts +0 -17
- package/lib/Player/GoldManager.js +0 -27
- package/lib/Player/GoldManager.js.map +0 -1
- package/lib/Player/GuiManager.d.ts +0 -247
- package/lib/Player/GuiManager.js +0 -291
- package/lib/Player/GuiManager.js.map +0 -1
- package/lib/Player/ItemFixture.d.ts +0 -7
- package/lib/Player/ItemFixture.js +0 -19
- package/lib/Player/ItemFixture.js.map +0 -1
- package/lib/Player/ItemManager.d.ts +0 -331
- package/lib/Player/ItemManager.js +0 -475
- package/lib/Player/ItemManager.js.map +0 -1
- package/lib/Player/MoveManager.d.ts +0 -333
- package/lib/Player/MoveManager.js +0 -450
- package/lib/Player/MoveManager.js.map +0 -1
- package/lib/Player/ParameterManager.d.ts +0 -316
- package/lib/Player/ParameterManager.js +0 -408
- package/lib/Player/ParameterManager.js.map +0 -1
- package/lib/Player/Player.d.ts +0 -828
- package/lib/Player/Player.js +0 -927
- package/lib/Player/Player.js.map +0 -1
- package/lib/Player/SkillManager.d.ts +0 -163
- package/lib/Player/SkillManager.js +0 -223
- package/lib/Player/SkillManager.js.map +0 -1
- package/lib/Player/StateManager.d.ts +0 -185
- package/lib/Player/StateManager.js +0 -228
- package/lib/Player/StateManager.js.map +0 -1
- package/lib/Player/VariableManager.d.ts +0 -46
- package/lib/Player/VariableManager.js +0 -52
- package/lib/Player/VariableManager.js.map +0 -1
- package/lib/Query.d.ts +0 -127
- package/lib/Query.js +0 -159
- package/lib/Query.js.map +0 -1
- package/lib/RpgServer.js +0 -2
- package/lib/RpgServer.js.map +0 -1
- package/lib/Scenes/Map.d.ts +0 -136
- package/lib/Scenes/Map.js +0 -273
- package/lib/Scenes/Map.js.map +0 -1
- package/lib/decorators/event.d.ts +0 -43
- package/lib/decorators/event.js +0 -13
- package/lib/decorators/event.js.map +0 -1
- package/lib/decorators/map.d.ts +0 -178
- package/lib/decorators/map.js +0 -43
- package/lib/decorators/map.js.map +0 -1
- package/lib/entry-point.d.ts +0 -34
- package/lib/entry-point.js +0 -70
- package/lib/entry-point.js.map +0 -1
- package/lib/express/api.d.ts +0 -3
- package/lib/express/api.js +0 -105
- package/lib/express/api.js.map +0 -1
- package/lib/express/errors/NotAuthorized.d.ts +0 -4
- package/lib/express/errors/NotAuthorized.js +0 -7
- package/lib/express/errors/NotAuthorized.js.map +0 -1
- package/lib/express/errors/NotFound.d.ts +0 -4
- package/lib/express/errors/NotFound.js +0 -7
- package/lib/express/errors/NotFound.js.map +0 -1
- package/lib/express/server.d.ts +0 -16
- package/lib/express/server.js +0 -65
- package/lib/express/server.js.map +0 -1
- package/lib/index.d.ts +0 -20
- package/lib/index.js +0 -19
- package/lib/index.js.map +0 -1
- package/lib/inject.d.ts +0 -22
- package/lib/inject.js +0 -29
- package/lib/inject.js.map +0 -1
- package/lib/logs/index.js +0 -6
- package/lib/logs/index.js.map +0 -1
- package/lib/logs/item.js +0 -34
- package/lib/logs/item.js.map +0 -1
- package/lib/logs/log.js +0 -7
- package/lib/logs/log.js.map +0 -1
- package/lib/logs/skill.js +0 -19
- package/lib/logs/skill.js.map +0 -1
- package/lib/logs/state.js +0 -13
- package/lib/logs/state.js.map +0 -1
- package/lib/models/Item.d.ts +0 -10
- package/lib/models/Item.js +0 -2
- package/lib/models/Item.js.map +0 -1
- package/lib/presets/index.js +0 -65
- package/lib/presets/index.js.map +0 -1
- package/lib/server.d.ts +0 -137
- package/lib/server.js +0 -443
- package/lib/server.js.map +0 -1
- package/rpg.toml +0 -14
- package/src/Game/EventManager.ts +0 -125
- package/src/Game/Map.ts +0 -495
- package/src/Game/WorldMaps.ts +0 -45
- package/src/Interfaces/Gui.ts +0 -4
- package/src/Interfaces/StateStore.ts +0 -5
- package/src/MatchMaker.ts +0 -65
- package/src/Monitor/index.ts +0 -78
- package/src/Query.ts +0 -172
- package/src/Scenes/Map.ts +0 -310
- package/src/decorators/event.ts +0 -58
- package/src/decorators/map.ts +0 -226
- package/src/entry-point.ts +0 -111
- package/src/express/api.ts +0 -118
- package/src/express/errors/NotAuthorized.ts +0 -6
- package/src/express/errors/NotFound.ts +0 -6
- package/src/express/server.ts +0 -87
- package/src/inject.ts +0 -33
- package/src/models/Item.ts +0 -11
- package/src/server.ts +0 -459
- /package/{lib → dist}/Gui/MenuGui.d.ts +0 -0
- /package/{lib → dist}/Gui/NotificationGui.d.ts +0 -0
- /package/{lib → dist}/Gui/ShopGui.d.ts +0 -0
- /package/{lib → dist}/Gui/index.d.ts +0 -0
- /package/{lib → dist}/logs/index.d.ts +0 -0
- /package/{lib → dist}/logs/item.d.ts +0 -0
- /package/{lib → dist}/logs/log.d.ts +0 -0
- /package/{lib → dist}/logs/skill.d.ts +0 -0
- /package/{lib → dist}/logs/state.d.ts +0 -0
- /package/{lib → dist}/presets/index.d.ts +0 -0
package/src/Player/Player.ts
CHANGED
|
@@ -1,1065 +1,279 @@
|
|
|
1
|
-
import { RpgCommonPlayer, Utils, RpgPlugin, RpgCommonGame, RpgCommonMap, Direction } from '@rpgjs/common'
|
|
2
|
-
import { Room, WorldClass } from 'simple-room'
|
|
3
|
-
import { RpgMap, EventPosOption } from '../Game/Map'
|
|
4
|
-
import { Query } from '../Query'
|
|
5
|
-
import merge from 'lodash.merge'
|
|
6
|
-
import { ItemManager } from './ItemManager'
|
|
7
|
-
import { GoldManager } from './GoldManager'
|
|
8
|
-
import { StateManager } from './StateManager';
|
|
9
|
-
import { SkillManager } from './SkillManager'
|
|
10
|
-
import { ParameterManager } from './ParameterManager';
|
|
11
|
-
import { EffectManager } from './EffectManager';
|
|
12
|
-
import { ClassManager } from './ClassManager';
|
|
13
|
-
import { ElementManager } from './ElementManager'
|
|
14
|
-
import { GuiManager } from './GuiManager'
|
|
15
|
-
import { VariableManager } from './VariableManager'
|
|
16
|
-
import { Frequency, MoveManager, Speed } from './MoveManager'
|
|
17
|
-
import { BattleManager } from './BattleManager'
|
|
18
|
-
|
|
19
1
|
import {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
} from
|
|
33
|
-
import {
|
|
34
|
-
import {
|
|
35
|
-
import {
|
|
36
|
-
import {
|
|
37
|
-
import {
|
|
38
|
-
import {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
$permanent: false
|
|
66
|
-
},
|
|
67
|
-
...commonSchemaFeature
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
export const componentSchema = { id: String, value: String }
|
|
71
|
-
export const layoutSchema = {
|
|
72
|
-
width: Number,
|
|
73
|
-
height: Number,
|
|
74
|
-
marginBottom: Number,
|
|
75
|
-
marginTop: Number,
|
|
76
|
-
marginLeft: Number,
|
|
77
|
-
marginRight: Number,
|
|
78
|
-
lines: [{
|
|
79
|
-
col: [componentSchema]
|
|
80
|
-
}]
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
const playerSchemas = {
|
|
84
|
-
position: {
|
|
85
|
-
x: Number,
|
|
86
|
-
y: Number,
|
|
87
|
-
z: Number
|
|
88
|
-
},
|
|
89
|
-
direction: Number,
|
|
90
|
-
|
|
91
|
-
teleported: {
|
|
92
|
-
$permanent: false
|
|
93
|
-
},
|
|
94
|
-
|
|
95
|
-
deleted: {
|
|
96
|
-
$permanent: false
|
|
97
|
-
},
|
|
98
|
-
|
|
99
|
-
moving: {
|
|
100
|
-
$permanent: false
|
|
101
|
-
},
|
|
102
|
-
|
|
103
|
-
param: Object,
|
|
104
|
-
hp: Number,
|
|
105
|
-
sp: Number,
|
|
106
|
-
gold: Number,
|
|
107
|
-
level: {
|
|
108
|
-
$effects: ['$this.expForNextlevel', '$this.param']
|
|
109
|
-
},
|
|
110
|
-
expForNextlevel: {
|
|
111
|
-
$permanent: false
|
|
112
|
-
},
|
|
113
|
-
exp: Number,
|
|
114
|
-
name: String,
|
|
115
|
-
items: [{ nb: Number, item: itemSchemas }],
|
|
116
|
-
_class: commonSchemaFeature,
|
|
117
|
-
equipments: [itemSchemas],
|
|
118
|
-
skills: [
|
|
119
|
-
{
|
|
120
|
-
spCost: {
|
|
121
|
-
$permanent: false
|
|
122
|
-
},
|
|
123
|
-
...commonSchemaFeature
|
|
124
|
-
}
|
|
125
|
-
],
|
|
126
|
-
states: [commonSchemaFeature],
|
|
127
|
-
effects: [String],
|
|
128
|
-
|
|
129
|
-
layout: {
|
|
130
|
-
top: layoutSchema,
|
|
131
|
-
bottom: layoutSchema,
|
|
132
|
-
left: layoutSchema,
|
|
133
|
-
right: layoutSchema,
|
|
134
|
-
center: layoutSchema
|
|
135
|
-
},
|
|
136
|
-
|
|
137
|
-
action: Number,
|
|
138
|
-
map: String,
|
|
139
|
-
|
|
140
|
-
speed: Number,
|
|
141
|
-
frequency: Number,
|
|
142
|
-
canMove: Boolean,
|
|
143
|
-
through: Boolean,
|
|
144
|
-
throughOtherPlayer: Boolean,
|
|
145
|
-
|
|
146
|
-
width: Number,
|
|
147
|
-
height: Number,
|
|
148
|
-
wHitbox: Number,
|
|
149
|
-
hHitbox: Number,
|
|
150
|
-
|
|
151
|
-
// only for server
|
|
152
|
-
|
|
153
|
-
_statesEfficiency: [{
|
|
154
|
-
rate: {
|
|
155
|
-
$syncWithClient: false
|
|
156
|
-
},
|
|
157
|
-
state: {
|
|
158
|
-
$syncWithClient: false
|
|
159
|
-
}
|
|
160
|
-
}],
|
|
161
|
-
tmpPositions: {
|
|
162
|
-
$syncWithClient: false
|
|
163
|
-
},
|
|
164
|
-
initialLevel: {
|
|
165
|
-
$syncWithClient: false
|
|
166
|
-
},
|
|
167
|
-
finalLevel: {
|
|
168
|
-
$syncWithClient: false
|
|
169
|
-
},
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
const layoutObject = {
|
|
173
|
-
lines: []
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
export class RpgPlayer extends RpgCommonPlayer {
|
|
177
|
-
public readonly type: string = 'player'
|
|
178
|
-
static schemas = {
|
|
179
|
-
...playerSchemas,
|
|
180
|
-
events: [playerSchemas]
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
layout: LayoutObject<any> = {
|
|
184
|
-
top: layoutObject,
|
|
185
|
-
bottom: layoutObject,
|
|
186
|
-
left: layoutObject,
|
|
187
|
-
right: layoutObject,
|
|
188
|
-
center: layoutObject
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
private _name
|
|
192
|
-
public events: any = {}
|
|
193
|
-
public param: any
|
|
194
|
-
public _rooms = []
|
|
195
|
-
public session: string | null = null
|
|
196
|
-
public prevMap: string = ''
|
|
197
|
-
|
|
198
|
-
/**
|
|
199
|
-
* ```ts
|
|
200
|
-
* retreive the server instance
|
|
201
|
-
* ```
|
|
202
|
-
* @title Server Instance
|
|
203
|
-
* @prop {RpgServerEngine} player.server
|
|
204
|
-
* @deprecated Use `inject(RpgServerEngine)` instead. Will be removed in v5
|
|
205
|
-
* @memberof Player
|
|
206
|
-
* */
|
|
207
|
-
public server: RpgServerEngine
|
|
208
|
-
private touchSide: boolean = false
|
|
209
|
-
|
|
210
|
-
/** @internal */
|
|
211
|
-
public tmpPositions: Position | string | null = null
|
|
212
|
-
public otherPossessedPlayer: RpgPlayer | RpgEvent | null = null
|
|
213
|
-
public followingId: string | null = null
|
|
214
|
-
|
|
215
|
-
// Indicates whether to load data with load(). In this case, hooks are not triggered.
|
|
216
|
-
private _dataLoading: boolean = false
|
|
217
|
-
|
|
218
|
-
_lastFramePositions: {
|
|
219
|
-
frame: number
|
|
220
|
-
position: Position
|
|
221
|
-
} | undefined
|
|
222
|
-
|
|
223
|
-
/**
|
|
224
|
-
* @deprecated Use `inject(RpgCommonGame)` instead. Will be removed in v5
|
|
225
|
-
*/
|
|
226
|
-
public gameEngine: RpgCommonGame = inject(RpgCommonGame)
|
|
227
|
-
|
|
228
|
-
// redefine type (as RpgPlayer)
|
|
229
|
-
get otherPlayersCollision(): RpgPlayer[] {
|
|
230
|
-
return super.otherPlayersCollision as RpgPlayer[]
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
get world(): WorldClass | undefined {
|
|
234
|
-
return this.server?.world
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
// As soon as a teleport has been made, the value is changed to force the client to change the positions on the map without making a move.
|
|
238
|
-
teleported: number = 0
|
|
239
|
-
|
|
240
|
-
// a flag that lets the client know if the event is suppressed. The client can, for example, end animations before completely deleting the object (client side).
|
|
241
|
-
deleted: boolean = false
|
|
242
|
-
|
|
243
|
-
constructor(public playerId: string) {
|
|
244
|
-
super(inject(RpgCommonGame), playerId)
|
|
245
|
-
this.initialize()
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
/** @internal */
|
|
249
|
-
initialize() {
|
|
250
|
-
this.server = inject(RpgServerEngine)
|
|
251
|
-
this.expCurve = {
|
|
252
|
-
basis: 30,
|
|
253
|
-
extra: 20,
|
|
254
|
-
accelerationA: 30,
|
|
255
|
-
accelerationB: 30
|
|
256
|
-
}
|
|
257
|
-
this.parameters = new Map()
|
|
258
|
-
this.variables = new Map()
|
|
259
|
-
this.states = []
|
|
260
|
-
this.equipments = []
|
|
261
|
-
this._effects = []
|
|
262
|
-
this.items = []
|
|
263
|
-
this.skills = []
|
|
264
|
-
this.gold = 0
|
|
265
|
-
this.exp = 0
|
|
266
|
-
this.speed = Speed.Normal
|
|
267
|
-
this.frequency = Frequency.None
|
|
268
|
-
this.canMove = true
|
|
269
|
-
this.through = false
|
|
270
|
-
this.throughOtherPlayer = true
|
|
271
|
-
this.initialLevel = 1
|
|
272
|
-
this.finalLevel = 99
|
|
273
|
-
this.level = this.initialLevel
|
|
274
|
-
this._gui = {}
|
|
275
|
-
this._elementsEfficiency = []
|
|
276
|
-
this._statesEfficiency = []
|
|
277
|
-
this.moving = false
|
|
278
|
-
|
|
279
|
-
this.addParameter(MAXHP, MAXHP_CURVE)
|
|
280
|
-
this.addParameter(MAXSP, MAXSP_CURVE)
|
|
281
|
-
this.addParameter(STR, STR_CURVE)
|
|
282
|
-
this.addParameter(INT, INT_CURVE)
|
|
283
|
-
this.addParameter(DEX, DEX_CURVE)
|
|
284
|
-
this.addParameter(AGI, AGI_CURVE)
|
|
285
|
-
this.allRecovery()
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
_init() {
|
|
289
|
-
this._socket.on('gui.interaction', ({ guiId, name, data }) => {
|
|
290
|
-
if (this._gui[guiId]) {
|
|
291
|
-
this._gui[guiId].emit(name, data)
|
|
292
|
-
this.syncChanges()
|
|
293
|
-
}
|
|
294
|
-
})
|
|
295
|
-
this._socket.on('gui.exit', ({ guiId, data }) => {
|
|
296
|
-
this.removeGui(guiId, data)
|
|
297
|
-
})
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
private get schema() {
|
|
301
|
-
return {
|
|
302
|
-
...RpgPlayer.schemas,
|
|
303
|
-
...this.server['playerProps']
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
/**
|
|
308
|
-
* ```ts
|
|
309
|
-
* player.name = 'Link'
|
|
310
|
-
* ```
|
|
311
|
-
* @title Read/Give a name
|
|
312
|
-
* @prop {string} player.name
|
|
313
|
-
* @memberof Player
|
|
314
|
-
* */
|
|
315
|
-
get name(): string {
|
|
316
|
-
return this._name
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
set name(val: string) {
|
|
320
|
-
this._name = val
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
/**
|
|
324
|
-
* Change your map. Indicate the positions to put the player at a place on the map
|
|
325
|
-
*
|
|
326
|
-
* > The map must be added to RpgServer beforehand. Guide: [Create Map](/guide/create-map.html)
|
|
327
|
-
*
|
|
328
|
-
* You don't have to give positions but you can put a starting position in the TMX file. Guide: [Start Position](/guide/player-start.html)
|
|
329
|
-
*
|
|
330
|
-
* @title Change Map
|
|
331
|
-
* @method player.changeMap(mapId,positions)
|
|
332
|
-
* @param {string} mapId
|
|
333
|
-
* @param { {x: number, y: number, z?: number} | string } [positions]
|
|
334
|
-
* @returns {Promise<RpgMap | null>} null if map not exists
|
|
335
|
-
* @memberof Player
|
|
336
|
-
*/
|
|
337
|
-
changeMap(mapId: string, positions?: { x: number, y: number, z?: number } | string): Promise<RpgMap | null | boolean> {
|
|
338
|
-
return this.server.sceneMap.changeMap(mapId, this, positions)
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
async autoChangeMap(nextPosition: Position): Promise<boolean> {
|
|
342
|
-
const map = this.getCurrentMap()
|
|
343
|
-
const worldMaps = map?.getInWorldMaps()
|
|
344
|
-
let ret: boolean = false
|
|
345
|
-
if (worldMaps && map) {
|
|
346
|
-
const direction = this.getDirection()
|
|
347
|
-
const marginLeftRight = map.tileWidth / 2
|
|
348
|
-
const marginTopDown = map.tileHeight / 2
|
|
349
|
-
|
|
350
|
-
const changeMap = async (adjacent, to) => {
|
|
351
|
-
if (this.touchSide) {
|
|
352
|
-
return false
|
|
353
|
-
}
|
|
354
|
-
this.touchSide = true
|
|
355
|
-
const [nextMap] = worldMaps.getAdjacentMaps(map, adjacent) as RpgClassMap<RpgMap>[]
|
|
356
|
-
if (!nextMap) return false
|
|
357
|
-
const id = nextMap.id as string
|
|
358
|
-
const nextMapInfo = worldMaps.getMapInfo(id) as RpgTiledWorldMap
|
|
359
|
-
return !!(await this.changeMap(id, to(nextMapInfo)))
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
if (nextPosition.x < marginLeftRight && direction == Direction.Left) {
|
|
363
|
-
ret = await changeMap({
|
|
364
|
-
x: map.worldX - 1,
|
|
365
|
-
y: this.worldPositionY + 1
|
|
366
|
-
}, nextMapInfo => ({
|
|
367
|
-
x: (nextMapInfo.width) - this.wHitbox - marginLeftRight,
|
|
368
|
-
y: map.worldY - nextMapInfo.y + nextPosition.y
|
|
369
|
-
}))
|
|
370
|
-
}
|
|
371
|
-
else if (nextPosition.x > map.widthPx - this.wHitbox - marginLeftRight && direction == Direction.Right) {
|
|
372
|
-
ret = await changeMap({
|
|
373
|
-
x: map.worldX + map.widthPx + 1,
|
|
374
|
-
y: this.worldPositionY + 1
|
|
375
|
-
}, nextMapInfo => ({
|
|
376
|
-
x: marginLeftRight,
|
|
377
|
-
y: map.worldY - nextMapInfo.y + nextPosition.y
|
|
378
|
-
}))
|
|
379
|
-
}
|
|
380
|
-
else if (nextPosition.y < marginTopDown && direction == Direction.Up) {
|
|
381
|
-
ret = await changeMap({
|
|
382
|
-
x: this.worldPositionX + 1,
|
|
383
|
-
y: map.worldY - 1
|
|
384
|
-
}, nextMapInfo => ({
|
|
385
|
-
x: map.worldX - nextMapInfo.x + nextPosition.x,
|
|
386
|
-
y: (nextMapInfo.height) - this.hHitbox - marginTopDown,
|
|
387
|
-
}))
|
|
388
|
-
}
|
|
389
|
-
else if (nextPosition.y > map.heightPx - this.hHitbox - marginTopDown && direction == Direction.Down) {
|
|
390
|
-
ret = await changeMap({
|
|
391
|
-
x: this.worldPositionX + 1,
|
|
392
|
-
y: map.worldY + map.heightPx + 1
|
|
393
|
-
}, nextMapInfo => ({
|
|
394
|
-
x: map.worldX - nextMapInfo.x + nextPosition.x,
|
|
395
|
-
y: marginTopDown,
|
|
396
|
-
}))
|
|
397
|
-
}
|
|
398
|
-
else {
|
|
399
|
-
this.touchSide = false
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
return ret
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
/**
|
|
406
|
-
* Dynamically create an event in Scenario mode on the current map
|
|
407
|
-
*
|
|
408
|
-
* ```ts
|
|
409
|
-
* @EventData({
|
|
410
|
-
* name: 'EV-1'
|
|
411
|
-
* })
|
|
412
|
-
* class MyEvent extends RpgEvent {
|
|
413
|
-
* onAction() {
|
|
414
|
-
* console.log('ok')
|
|
415
|
-
* }
|
|
416
|
-
* }
|
|
417
|
-
*
|
|
418
|
-
* player.createDynamicEvent({
|
|
419
|
-
* x: 100,
|
|
420
|
-
* y: 100,
|
|
421
|
-
* event: MyEvent
|
|
422
|
-
* })
|
|
423
|
-
* ```
|
|
424
|
-
*
|
|
425
|
-
* You can also put an array of objects to create several events at once
|
|
426
|
-
*
|
|
427
|
-
* @title Create Dynamic Event
|
|
428
|
-
* @since 3.0.0-beta.4
|
|
429
|
-
* @method player.createDynamicEvent(eventObj | eventObj[])
|
|
430
|
-
* @param { { x: number, y: number, z?: number, event: eventClass } } [eventsList]
|
|
431
|
-
* @returns { { [eventId: string]: RpgEvent } }
|
|
432
|
-
* @memberof Player
|
|
433
|
-
*/
|
|
434
|
-
createDynamicEvent(eventsList: EventPosOption | EventPosOption[], forceMode: boolean = true): {
|
|
435
|
-
[eventId: string]: RpgEvent
|
|
436
|
-
} {
|
|
437
|
-
if (!eventsList) return {}
|
|
438
|
-
const mapInstance = this.getCurrentMap<RpgMap>()
|
|
439
|
-
if (!mapInstance) {
|
|
440
|
-
throw 'The player is not assigned to any map'
|
|
441
|
-
}
|
|
442
|
-
if (!Utils.isArray(eventsList)) {
|
|
443
|
-
eventsList = [eventsList as EventPosOption]
|
|
444
|
-
}
|
|
445
|
-
let eventsListMode = eventsList
|
|
446
|
-
if (forceMode) {
|
|
447
|
-
eventsListMode = (eventsList as EventPosOption[]).map(event => {
|
|
448
|
-
event.event.mode = EventMode.Scenario
|
|
449
|
-
return event
|
|
450
|
-
})
|
|
451
|
-
}
|
|
452
|
-
const events = mapInstance.createEvents(eventsListMode as EventPosOption[], EventMode.Scenario)
|
|
453
|
-
let ret = {}
|
|
454
|
-
for (let key in events) {
|
|
455
|
-
this.events[key] = events[key]
|
|
456
|
-
this.events[key].playerRelated = this
|
|
457
|
-
this.events[key].execMethod('onInit', [this])
|
|
458
|
-
// force to get Proxy object to sync with client
|
|
459
|
-
ret = { ...ret, [key]: this.events[key] }
|
|
460
|
-
}
|
|
461
|
-
return ret
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
/**
|
|
465
|
-
* Allows to change the positions of the player on the current map.
|
|
466
|
-
* You can put the X and Y positions or the name of the created shape on Tiled Map Editor.
|
|
467
|
-
* If you have several shapes with the same name, one position will be chosen randomly.
|
|
468
|
-
*
|
|
469
|
-
* ```ts
|
|
470
|
-
* player.teleport({ x: 100, y: 500 })
|
|
471
|
-
* ```
|
|
472
|
-
*
|
|
473
|
-
* or
|
|
474
|
-
*
|
|
475
|
-
* ```ts
|
|
476
|
-
* player.teleport('my-shape-name')
|
|
477
|
-
* ```
|
|
478
|
-
*
|
|
479
|
-
* If no parameter:
|
|
480
|
-
*
|
|
481
|
-
* ```ts
|
|
482
|
-
* player.teleport() // { x: 0, y: 0, z: 0 }
|
|
483
|
-
* ```
|
|
484
|
-
*
|
|
485
|
-
* @title Teleport on the map
|
|
486
|
-
* @method player.teleport(positions)
|
|
487
|
-
* @param { {x: number, y: number, z?: number} | string } [positions]
|
|
488
|
-
* @returns {Promise<{ {x: number, y: number, z: number} }>}
|
|
489
|
-
* @memberof Player
|
|
490
|
-
*/
|
|
491
|
-
async teleport(positions?: PositionXY_OptionalZ | string): Promise<Position> {
|
|
492
|
-
if (isString(positions)) positions = <Position>this.getCurrentMap()?.getPositionByShape(shape => shape.name == positions || shape.getType() == positions)
|
|
493
|
-
if (!positions) positions = { x: 0, y: 0, z: 0 }
|
|
494
|
-
if (!(positions as Position).z) (positions as Position).z = 0
|
|
495
|
-
this.teleported++
|
|
496
|
-
this.position = positions as Position
|
|
497
|
-
// delete last frame positions because when the character is teleported, no server reconciliation is needed on the client side
|
|
498
|
-
this._lastFramePositions = undefined
|
|
499
|
-
// force interaction with event or shape
|
|
500
|
-
await this.isCollided(this.position)
|
|
501
|
-
return (positions as Position)
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
/**
|
|
505
|
-
* Load the saved data with the method save()
|
|
506
|
-
* If the player was on a map, it repositions the player on the map.
|
|
507
|
-
*
|
|
508
|
-
* ```ts
|
|
509
|
-
* const json = player.save()
|
|
510
|
-
* player.load(json)
|
|
511
|
-
* ```
|
|
512
|
-
*
|
|
513
|
-
* @title Load progress
|
|
514
|
-
* @method player.load(json)
|
|
515
|
-
* @param {string} json The JSON sent by the method save()
|
|
516
|
-
* @returns {Promise<boolean | RpgMap | null>}
|
|
517
|
-
* @memberof Player
|
|
518
|
-
*/
|
|
519
|
-
async load(json: any): Promise<boolean | RpgMap | null> {
|
|
520
|
-
this._dataLoading = true
|
|
521
|
-
|
|
522
|
-
if (isString(json)) json = JSON.parse(json)
|
|
523
|
-
|
|
524
|
-
const getData = (id) => new (this.databaseById(id))()
|
|
525
|
-
|
|
526
|
-
for (let key in json) {
|
|
527
|
-
const val = json[key]
|
|
528
|
-
if (Utils.isObject(val) && val.hasOwnProperty('0')) {
|
|
529
|
-
json[key] = Object.values(val)
|
|
530
|
-
}
|
|
531
|
-
}
|
|
532
|
-
|
|
533
|
-
const items = {}
|
|
534
|
-
|
|
535
|
-
if (json.items) {
|
|
536
|
-
for (let it of json.items) {
|
|
537
|
-
items[it.item.id] = getData(it.item.id)
|
|
538
|
-
}
|
|
539
|
-
json.items = json.items.map(it => ({ nb: it.nb, item: items[it.item.id] }))
|
|
540
|
-
if (Array.isArray(json.equipments)) {
|
|
541
|
-
json.equipments = json.equipments.map(it => {
|
|
542
|
-
items[it.id].equipped = true
|
|
543
|
-
return items[it.id]
|
|
544
|
-
})
|
|
545
|
-
}
|
|
546
|
-
}
|
|
547
|
-
if (json.states) json.states = json.states.map(state => getData(state.id))
|
|
548
|
-
if (json.skills) json.skills = json.skills.map(skill => getData(skill.id))
|
|
549
|
-
if (json.variables) json.variables = new Map(json.variables)
|
|
550
|
-
|
|
551
|
-
merge(this, json)
|
|
552
|
-
|
|
553
|
-
this.position = json.position
|
|
554
|
-
|
|
555
|
-
if (json.map) {
|
|
556
|
-
this.map = ''
|
|
557
|
-
const map = await this.changeMap(json.map, json.tmpPositions || json.position)
|
|
558
|
-
this._dataLoading = false
|
|
559
|
-
return map
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
this._dataLoading = false
|
|
563
|
-
|
|
564
|
-
return null
|
|
565
|
-
}
|
|
566
|
-
|
|
567
|
-
/**
|
|
568
|
-
* Returns a JSON with all the data to keep in memory. Then use the `load()` method to load the data
|
|
569
|
-
*
|
|
570
|
-
* You can also use the JSON.stringify
|
|
571
|
-
*
|
|
572
|
-
* ```ts
|
|
573
|
-
* const json = player.save() // or JSON.stringify(player)
|
|
574
|
-
* player.load(json)
|
|
575
|
-
* ```
|
|
576
|
-
*
|
|
577
|
-
* @title Save progress
|
|
578
|
-
* @method player.save()
|
|
579
|
-
* @returns {string}
|
|
580
|
-
* @memberof Player
|
|
581
|
-
*/
|
|
582
|
-
save() {
|
|
583
|
-
return JSON.stringify(this)
|
|
584
|
-
}
|
|
585
|
-
|
|
586
|
-
// TODO
|
|
587
|
-
toObject() {
|
|
588
|
-
return {
|
|
589
|
-
direction: this.direction,
|
|
590
|
-
id: this.id,
|
|
591
|
-
canMove: this.canMove,
|
|
592
|
-
position: {
|
|
593
|
-
x: this.position.x,
|
|
594
|
-
y: this.position.y,
|
|
595
|
-
z: this.position.z
|
|
596
|
-
},
|
|
597
|
-
hitbox: {
|
|
598
|
-
width: this.wHitbox,
|
|
599
|
-
height: this.hHitbox
|
|
600
|
-
},
|
|
601
|
-
map: this.map,
|
|
602
|
-
pendingMove: this.pendingMove,
|
|
603
|
-
speed: this.speed
|
|
604
|
-
}
|
|
605
|
-
}
|
|
606
|
-
|
|
607
|
-
toJSON() {
|
|
608
|
-
const { permanentObject } = Room.compileSchema(this.schema)
|
|
609
|
-
const snapshot = Room.extractObjectOfRoom(this, permanentObject)
|
|
610
|
-
snapshot.variables = [...this.variables]
|
|
611
|
-
return snapshot
|
|
612
|
-
}
|
|
613
|
-
|
|
614
|
-
/**
|
|
615
|
-
* Run the change detection cycle. Normally, as soon as a hook is called in a class, the cycle is started. But you can start it manually
|
|
616
|
-
* The method calls the `onChanges` method on events and synchronizes all map data with the client.
|
|
617
|
-
|
|
618
|
-
* @title Run Sync Changes
|
|
619
|
-
* @method player.syncChanges()
|
|
620
|
-
* @returns {void}
|
|
621
|
-
* @memberof Player
|
|
622
|
-
*/
|
|
623
|
-
syncChanges() {
|
|
624
|
-
this._eventChanges()
|
|
625
|
-
}
|
|
626
|
-
|
|
627
|
-
databaseById(id: string) {
|
|
628
|
-
const data = this.server.database[id]
|
|
629
|
-
if (!data) throw new Error(`The ID=${id} data is not found in the database. Add the data in the property "database" of @RpgServer decorator.`)
|
|
630
|
-
return data
|
|
631
|
-
}
|
|
632
|
-
|
|
633
|
-
/**
|
|
634
|
-
* Retrieves data from the current map
|
|
635
|
-
*
|
|
636
|
-
* returns null if the player is not assigned to a map
|
|
637
|
-
*
|
|
638
|
-
* @title Get Current Map
|
|
639
|
-
* @method player.getCurrentMap()
|
|
640
|
-
* @returns {RpgMap | null}
|
|
641
|
-
* @memberof Player
|
|
642
|
-
*/
|
|
643
|
-
getCurrentMap<T extends RpgMap = RpgMap>(): T | null {
|
|
644
|
-
return this._getMap(this.map)
|
|
645
|
-
}
|
|
646
|
-
|
|
647
|
-
loadScene(name: string, data: any): void {
|
|
648
|
-
this.emit(SocketEvents.LoadScene, {
|
|
649
|
-
name,
|
|
650
|
-
data
|
|
651
|
-
})
|
|
652
|
-
}
|
|
653
|
-
|
|
654
|
-
emitSceneMap() {
|
|
655
|
-
const mapInstance = this.getCurrentMap<RpgMap>()
|
|
656
|
-
if (!mapInstance) {
|
|
657
|
-
throw '[Emit] The player is not assigned to any map'
|
|
658
|
-
}
|
|
659
|
-
let { data: serializeMap } = Object.assign({}, mapInstance) as any
|
|
660
|
-
delete serializeMap.shapes
|
|
661
|
-
delete serializeMap.events
|
|
662
|
-
delete serializeMap._events
|
|
663
|
-
|
|
664
|
-
for (let layer of serializeMap.layers) {
|
|
665
|
-
delete layer.map
|
|
666
|
-
}
|
|
667
|
-
|
|
668
|
-
this.loadScene('map', {
|
|
669
|
-
id: mapInstance.id,
|
|
670
|
-
sounds: mapInstance.sounds,
|
|
671
|
-
...serializeMap
|
|
672
|
-
})
|
|
673
|
-
}
|
|
674
|
-
|
|
675
|
-
gameReload() {
|
|
676
|
-
this.emit(SocketEvents.GameReload)
|
|
677
|
-
}
|
|
678
|
-
|
|
679
|
-
changeServer(url: string, port: number) {
|
|
680
|
-
this.emit(SocketEvents.ChangeServer, {
|
|
681
|
-
url,
|
|
682
|
-
port
|
|
683
|
-
})
|
|
684
|
-
}
|
|
685
|
-
|
|
686
|
-
private _getMap(id) {
|
|
687
|
-
return RpgCommonMap.buffer.get(id)
|
|
688
|
-
}
|
|
689
|
-
|
|
690
|
-
/**
|
|
691
|
-
* Calls the showAnimation() method on the client side to display an animation on the player
|
|
692
|
-
* You must remember to create the spritesheet beforehand
|
|
693
|
-
*
|
|
694
|
-
* For this type of spritesheet:
|
|
695
|
-
*
|
|
696
|
-
* ```ts
|
|
697
|
-
* @Spritesheet({
|
|
698
|
-
* id: 'fire',
|
|
699
|
-
* image: require('')
|
|
700
|
-
* textures: {
|
|
701
|
-
* default: {
|
|
702
|
-
* animations: [
|
|
703
|
-
*
|
|
704
|
-
* ]
|
|
705
|
-
* }
|
|
706
|
-
* }
|
|
707
|
-
* })
|
|
708
|
-
* export class FireAnimation {}
|
|
709
|
-
* ```
|
|
710
|
-
*
|
|
711
|
-
* Here is the call of the method:
|
|
712
|
-
*
|
|
713
|
-
* ```ts
|
|
714
|
-
* player.showAnimation('fire', 'default')
|
|
715
|
-
* ```
|
|
716
|
-
*
|
|
717
|
-
* If you don't want to put an animation on top of the event but replace the event graphic with another one, set true as last parameter.
|
|
718
|
-
* This is useful, if for example, you want to make an animated character (sword stroke when pressing a key)
|
|
719
|
-
* When the animation is finished, the original graphic is displayed again
|
|
720
|
-
*
|
|
721
|
-
*
|
|
722
|
-
* ```ts
|
|
723
|
-
* player.showAnimation('sword_stroke', 'default', true)
|
|
724
|
-
* ```
|
|
725
|
-
*
|
|
726
|
-
* Since version 3.0.0-rc, you can define several graphic elements. This allows you to animate them all at once
|
|
727
|
-
*
|
|
728
|
-
* ```ts
|
|
729
|
-
* player.showAnimation(['body', 'sword_stroke'], 'default', true)
|
|
730
|
-
* ```
|
|
731
|
-
*
|
|
732
|
-
* ::: tip
|
|
733
|
-
* For this to work, the animations must have been previously defined in `setGraphic`.
|
|
734
|
-
* :::
|
|
735
|
-
*
|
|
736
|
-
* @title Show Animation
|
|
737
|
-
* @method player.showAnimation(graphic,animationName,replaceGraphic=false)
|
|
738
|
-
* @param {string | string[]} graphic spritesheet identifier
|
|
739
|
-
* @param {string} animationName Name of the animation in the spritesheet
|
|
740
|
-
* @param {boolean} [replaceGraphic] Replace the event graphic with the animation. After the end of the animation, the original graphic is reapplied
|
|
741
|
-
* @returns {void}
|
|
742
|
-
* @memberof Player
|
|
743
|
-
*/
|
|
744
|
-
showAnimation(graphic: string | string[], animationName: string, replaceGraphic: boolean = false) {
|
|
745
|
-
this.emitToMap('callMethod', {
|
|
746
|
-
name: SocketMethods.ShowAnimation,
|
|
747
|
-
params: [graphic, animationName, replaceGraphic]
|
|
748
|
-
})
|
|
749
|
-
}
|
|
750
|
-
|
|
751
|
-
/**
|
|
752
|
-
* TODO:
|
|
753
|
-
* 1. It is necessary, on the client side, to make the character move even if controlled by someone else (problem: same playerId so, one will not move because of the client side prediction. Solution: create a new Id ? like session Id ?
|
|
754
|
-
* 2. You would need several sockets per character. If the character changes map or changes server, all players controlling the character must be able to see it
|
|
755
|
-
* 3. If the player regains control, what happens, do we return to the previous map?
|
|
756
|
-
* 4. If it's an event, you must be able to get the event by id in GameEngine
|
|
757
|
-
*/
|
|
758
|
-
takePossessionOf(otherPlayer: RpgPlayer | RpgEvent) {
|
|
759
|
-
this.otherPossessedPlayer = otherPlayer
|
|
760
|
-
this._socket.emit('playerJoined', { playerId: otherPlayer.id, session: this.session })
|
|
761
|
-
this.cameraFollow(otherPlayer)
|
|
762
|
-
}
|
|
763
|
-
|
|
764
|
-
/**
|
|
765
|
-
* Sends the client which event or player the camera should follow. You can set options to perform a motion animation
|
|
766
|
-
*
|
|
767
|
-
* @title Camera Follow
|
|
768
|
-
* @method player.cameraFollow(otherPlayer,options)
|
|
769
|
-
* @param {RpgPlayer | RpgEvent} otherPlayer
|
|
770
|
-
* @param {options} options
|
|
771
|
-
* @param {object | boolean} [options.smoothMove] - animate. Set a boolean to use default parameters
|
|
772
|
-
* @param {number} [options.smoothMove.time=1000] - time to animate
|
|
773
|
-
* @param {string} [options.smoothMove.ease=linear] - easing to use. Go to https://easings.net to get function name
|
|
774
|
-
* @returns {void}
|
|
775
|
-
* @since 3.1.0
|
|
776
|
-
* @memberof Player
|
|
777
|
-
*/
|
|
778
|
-
cameraFollow(otherPlayer: RpgPlayer | RpgEvent, options: CameraOptions = {}) {
|
|
779
|
-
if (otherPlayer.id == this.id) {
|
|
780
|
-
this.followingId = null
|
|
781
|
-
}
|
|
782
|
-
else {
|
|
783
|
-
this.followingId = otherPlayer.id
|
|
784
|
-
}
|
|
785
|
-
this.emit(SocketEvents.CallMethod, {
|
|
786
|
-
objectId: this.playerId,
|
|
787
|
-
name: SocketMethods.CameraFollow,
|
|
788
|
-
params: [otherPlayer.id, options]
|
|
789
|
-
})
|
|
790
|
-
}
|
|
791
|
-
|
|
792
|
-
/**
|
|
793
|
-
* Emit data to clients with socket
|
|
794
|
-
*
|
|
795
|
-
* @title Emit to client
|
|
796
|
-
* @method player.emit(key,value)
|
|
797
|
-
* @param {string} key
|
|
798
|
-
* @param {any} value
|
|
799
|
-
* @returns {void}
|
|
800
|
-
* @memberof Player
|
|
801
|
-
*/
|
|
802
|
-
public emit(key: string, value?: any): void {
|
|
803
|
-
if (this._socket) this._socket.emit(key, value)
|
|
804
|
-
}
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
/**
|
|
808
|
-
* Listen to the data (socket) sent by the client
|
|
809
|
-
*
|
|
810
|
-
* @title Listen to data from the client
|
|
811
|
-
* @method player.on(key,cb)
|
|
812
|
-
* @param {string} key
|
|
813
|
-
* @param {function} cb
|
|
814
|
-
* @returns {void}
|
|
815
|
-
* @memberof Player
|
|
816
|
-
*/
|
|
817
|
-
public on(key: string, cb: Function) {
|
|
818
|
-
if (this._socket) this._socket.on(key, cb)
|
|
819
|
-
}
|
|
820
|
-
|
|
821
|
-
/**
|
|
822
|
-
* Adds a one-time listener function for the event named eventName
|
|
823
|
-
*
|
|
824
|
-
* @title Listen one-time to data from the client
|
|
825
|
-
* @method player.once(key,cb)
|
|
826
|
-
* @since 3.0.0-beta.5
|
|
827
|
-
* @param {string} key
|
|
828
|
-
* @param {function} cb
|
|
829
|
-
* @returns {void}
|
|
830
|
-
* @memberof Player
|
|
831
|
-
*/
|
|
832
|
-
public once(key: string, cb: Function) {
|
|
833
|
-
if (this._socket) this._socket.once(key, cb)
|
|
834
|
-
}
|
|
835
|
-
|
|
836
|
-
/**
|
|
837
|
-
* Removes all listeners of the specified eventName.
|
|
838
|
-
*
|
|
839
|
-
* @title Removes all listeners of the client
|
|
840
|
-
* @method player.off(key)
|
|
841
|
-
* @since 3.0.0-beta.5
|
|
842
|
-
* @param {string} key
|
|
843
|
-
* @returns {void}
|
|
844
|
-
* @memberof Player
|
|
845
|
-
*/
|
|
846
|
-
public off(key: string) {
|
|
847
|
-
if (this._socket) this._socket.removeAllListeners(key)
|
|
848
|
-
}
|
|
849
|
-
|
|
850
|
-
disconnect() {
|
|
851
|
-
if (this._socket) this._socket.disconnect()
|
|
852
|
-
}
|
|
853
|
-
|
|
854
|
-
emitToMap(key: string, value: any) {
|
|
855
|
-
const map = this.getCurrentMap()
|
|
856
|
-
if (map) {
|
|
857
|
-
map.$setCurrentState(`users.${this.id}.${key}`, value)
|
|
858
|
-
}
|
|
859
|
-
}
|
|
860
|
-
|
|
861
|
-
private execMethodSync<T>(methodName: string, methodData = [], target?: any): T {
|
|
862
|
-
let ret
|
|
863
|
-
if (target && target[methodName]) {
|
|
864
|
-
ret = target[methodName](...methodData)
|
|
865
|
-
}
|
|
866
|
-
return ret
|
|
867
|
-
}
|
|
868
|
-
|
|
869
|
-
async execMethod(methodName: string, methodData = [], target?: any) {
|
|
870
|
-
const ignoreIfDataLoading = ['onLevelUp', 'onDead']
|
|
871
|
-
if (ignoreIfDataLoading.includes(methodName) && this._dataLoading) {
|
|
872
|
-
return
|
|
873
|
-
}
|
|
874
|
-
let ret
|
|
875
|
-
if (target && target[methodName]) {
|
|
876
|
-
ret = target[methodName](...methodData)
|
|
877
|
-
if (isPromise(ret)) await ret
|
|
878
|
-
}
|
|
879
|
-
else {
|
|
880
|
-
ret = await RpgPlugin.emit(`Server.${methodName}`, [this, ...methodData], true)
|
|
881
|
-
}
|
|
882
|
-
this.syncChanges()
|
|
883
|
-
return ret
|
|
884
|
-
}
|
|
885
|
-
|
|
886
|
-
_triggerHook(name, val?) {
|
|
887
|
-
if (this[name]) this[name](val)
|
|
888
|
-
this.emit('Player.' + name, val)
|
|
889
|
-
}
|
|
890
|
-
|
|
891
|
-
// @internal
|
|
892
|
-
/**
|
|
893
|
-
* Allows you to manually update a status in the rooms that will then be sent to the customer.
|
|
894
|
-
* @param path
|
|
895
|
-
* @example
|
|
896
|
-
* ```ts
|
|
897
|
-
* player.changeRoomState('hp')
|
|
898
|
-
* ```
|
|
899
|
-
*/
|
|
900
|
-
changeRoomState(path: string) {
|
|
901
|
-
this.world?.forEachUserRooms(this.id, (room) => {
|
|
902
|
-
(room as any).$setCurrentState(`users.${this.id}.${path}`)
|
|
903
|
-
})
|
|
904
|
-
}
|
|
905
|
-
|
|
906
|
-
private _eventChanges() {
|
|
907
|
-
if (!this._getMap(this.map)) return
|
|
908
|
-
const {
|
|
909
|
-
events
|
|
910
|
-
} = this._getMap(this.map)
|
|
911
|
-
const arrayEvents: any[] = [...Object.values(this.events), ...Object.values(events)]
|
|
912
|
-
for (let event of arrayEvents) {
|
|
913
|
-
if (event.onChanges) event.onChanges(this)
|
|
914
|
-
}
|
|
915
|
-
}
|
|
916
|
-
|
|
917
|
-
/**
|
|
918
|
-
* Allows to play a sound, heard only by the player or by the players of the map
|
|
919
|
-
*
|
|
920
|
-
* Here is a sound, client side:
|
|
921
|
-
*
|
|
922
|
-
* ```ts
|
|
923
|
-
* import { Sound } from '@rpgjs/client'
|
|
924
|
-
* @Sound({
|
|
925
|
-
* id: 'town-music',
|
|
926
|
-
* sound: require('./sound/town.ogg')
|
|
927
|
-
* })
|
|
928
|
-
* export class TownMusic {}
|
|
929
|
-
* ```
|
|
930
|
-
*
|
|
931
|
-
* Here is the call of the method, server side:
|
|
932
|
-
*
|
|
933
|
-
* ```ts
|
|
934
|
-
* player.playSound('town-music')
|
|
935
|
-
* ```
|
|
936
|
-
*
|
|
937
|
-
* If you want everyone to listen to the sound on the map:
|
|
938
|
-
*
|
|
939
|
-
* ```ts
|
|
940
|
-
* player.playSound('town-music', true)
|
|
941
|
-
* ```
|
|
942
|
-
*
|
|
943
|
-
* @title Play Sound
|
|
944
|
-
* @method player.playSound(soundId,allMap=false)
|
|
945
|
-
* @param {string} soundId Sound identifier, defined on the client side
|
|
946
|
-
* @param {boolean} [forEveryone=false] Indicate if the sound is heard by the players on the map
|
|
947
|
-
* @since 3.0.0-alpha.9
|
|
948
|
-
* @returns {void}
|
|
949
|
-
* @memberof Player
|
|
950
|
-
*/
|
|
951
|
-
playSound(soundId: string, forEveryone: boolean = false) {
|
|
952
|
-
const obj = {
|
|
953
|
-
objectId: this.playerId,
|
|
954
|
-
name: SocketMethods.PlaySound,
|
|
955
|
-
params: [soundId]
|
|
956
|
-
}
|
|
957
|
-
if (!forEveryone) {
|
|
958
|
-
this.emit(SocketEvents.CallMethod, obj)
|
|
959
|
-
return
|
|
960
|
-
}
|
|
961
|
-
this.emitToMap(SocketEvents.CallMethod, obj)
|
|
962
|
-
}
|
|
963
|
-
|
|
2
|
+
combineMixins,
|
|
3
|
+
Hooks,
|
|
4
|
+
ModulesToken,
|
|
5
|
+
RpgCommonPlayer,
|
|
6
|
+
ShowAnimationParams,
|
|
7
|
+
Constructor,
|
|
8
|
+
ZoneOptions,
|
|
9
|
+
} from "@rpgjs/common";
|
|
10
|
+
import { WithComponentManager, IComponentManager } from "./ComponentManager";
|
|
11
|
+
import { RpgMap } from "../rooms/map";
|
|
12
|
+
import { Context, inject } from "@signe/di";
|
|
13
|
+
import { IGuiManager, WithGuiManager } from "./GuiManager";
|
|
14
|
+
import { MockConnection } from "@signe/room";
|
|
15
|
+
import { IMoveManager, WithMoveManager } from "./MoveManager";
|
|
16
|
+
import { IGoldManager, WithGoldManager } from "./GoldManager";
|
|
17
|
+
import { IWithVariableManager, WithVariableManager } from "./VariableManager";
|
|
18
|
+
import { sync } from "@signe/sync";
|
|
19
|
+
import { signal } from "@signe/reactive";
|
|
20
|
+
import {
|
|
21
|
+
IWithParameterManager,
|
|
22
|
+
WithParameterManager,
|
|
23
|
+
} from "./ParameterManager";
|
|
24
|
+
import { WithItemFixture } from "./ItemFixture";
|
|
25
|
+
import { WithStateManager } from "./StateManager";
|
|
26
|
+
import { WithItemManager } from "./ItemManager";
|
|
27
|
+
import { lastValueFrom } from "rxjs";
|
|
28
|
+
import { WithBattleManager } from "./BattleManager";
|
|
29
|
+
import { WithEffectManager } from "./EffectManager";
|
|
30
|
+
import { WithSkillManager, IWithSkillManager } from "./SkillManager";
|
|
31
|
+
import { AGI, AGI_CURVE, DEX, DEX_CURVE, INT, INT_CURVE, MAXHP, MAXHP_CURVE, MAXSP, MAXSP_CURVE, STR, STR_CURVE } from "../presets";
|
|
32
|
+
import { WithClassManager } from "./ClassManager";
|
|
33
|
+
import { WithElementManager } from "./ElementManager";
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Combines multiple RpgCommonPlayer mixins into one
|
|
38
|
+
*
|
|
39
|
+
* @param mixins - Array of mixin functions that extend RpgCommonPlayer
|
|
40
|
+
* @returns A single mixin function that applies all mixins
|
|
41
|
+
*/
|
|
42
|
+
function combinePlayerMixins<T extends Constructor<RpgCommonPlayer>>(
|
|
43
|
+
mixins: Array<(Base: T) => any>
|
|
44
|
+
) {
|
|
45
|
+
return (Base: T) =>
|
|
46
|
+
mixins.reduce((ExtendedClass, mixin) => mixin(ExtendedClass), Base);
|
|
964
47
|
}
|
|
965
48
|
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
49
|
+
const PlayerMixins = combinePlayerMixins([
|
|
50
|
+
WithComponentManager,
|
|
51
|
+
WithEffectManager,
|
|
52
|
+
WithGuiManager,
|
|
53
|
+
WithMoveManager,
|
|
54
|
+
WithGoldManager,
|
|
55
|
+
WithVariableManager,
|
|
56
|
+
WithParameterManager,
|
|
57
|
+
WithItemFixture,
|
|
58
|
+
WithStateManager,
|
|
59
|
+
WithItemManager,
|
|
60
|
+
WithSkillManager,
|
|
61
|
+
WithClassManager,
|
|
62
|
+
WithBattleManager,
|
|
63
|
+
WithElementManager,
|
|
64
|
+
]);
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* RPG Player class with component management capabilities
|
|
68
|
+
*/
|
|
69
|
+
export class RpgPlayer extends PlayerMixins(RpgCommonPlayer) {
|
|
70
|
+
map: RpgMap | null = null;
|
|
71
|
+
context?: Context;
|
|
72
|
+
conn: MockConnection | null = null;
|
|
73
|
+
|
|
74
|
+
@sync(RpgPlayer) events = signal<RpgEvent[]>([]);
|
|
75
|
+
|
|
76
|
+
constructor() {
|
|
77
|
+
super();
|
|
78
|
+
this.expCurve = {
|
|
79
|
+
basis: 30,
|
|
80
|
+
extra: 20,
|
|
81
|
+
accelerationA: 30,
|
|
82
|
+
accelerationB: 30
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
this.addParameter(MAXHP, MAXHP_CURVE)
|
|
86
|
+
this.addParameter(MAXSP, MAXSP_CURVE)
|
|
87
|
+
this.addParameter(STR, STR_CURVE)
|
|
88
|
+
this.addParameter(INT, INT_CURVE)
|
|
89
|
+
this.addParameter(DEX, DEX_CURVE)
|
|
90
|
+
this.addParameter(AGI, AGI_CURVE)
|
|
91
|
+
this.allRecovery()
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async execMethod(method: string, methodData: any[] = [], target?: any) {
|
|
95
|
+
let ret: any;
|
|
96
|
+
if (target) {
|
|
97
|
+
ret = await target[method](...methodData);
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
const hooks = inject<Hooks>(this.context as any, ModulesToken);
|
|
101
|
+
ret = await lastValueFrom(hooks
|
|
102
|
+
.callHooks(`server-player-${method}`, target ?? this, ...methodData));
|
|
103
|
+
}
|
|
104
|
+
this.syncChanges()
|
|
105
|
+
return ret;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Change the map for this player
|
|
110
|
+
*
|
|
111
|
+
* @param mapId - The ID of the map to change to
|
|
112
|
+
* @param positions - Optional positions to place the player at
|
|
113
|
+
* @returns A promise that resolves when the map change is complete
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* ```ts
|
|
117
|
+
* // Change player to map "town" at position {x: 10, y: 20}
|
|
118
|
+
* await player.changeMap("town", {x: 10, y: 20});
|
|
119
|
+
*
|
|
120
|
+
* // Change player to map "dungeon" at a named position
|
|
121
|
+
* await player.changeMap("dungeon", "entrance");
|
|
122
|
+
* ```
|
|
123
|
+
*/
|
|
124
|
+
async changeMap(
|
|
125
|
+
mapId: string,
|
|
126
|
+
positions?: { x: number; y: number; z?: number } | string
|
|
127
|
+
): Promise<any | null | boolean> {
|
|
128
|
+
this.emit("changeMap", {
|
|
129
|
+
mapId: 'map-' + mapId,
|
|
130
|
+
positions,
|
|
131
|
+
});
|
|
132
|
+
return true;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
async teleport(positions: { x: number; y: number }) {
|
|
136
|
+
if (!this.map) return false;
|
|
137
|
+
// For movable objects like players, the position represents the center
|
|
138
|
+
this.map.physic.updateHitbox(this.id, positions.x, positions.y);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
getCurrentMap<T extends RpgMap = RpgMap>(): T | null {
|
|
142
|
+
return this.map as T | null;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
emit(type: string, value?: any) {
|
|
146
|
+
const map = this.getCurrentMap();
|
|
147
|
+
if (!map || !this.conn) return;
|
|
148
|
+
map.$send(this.conn, {
|
|
149
|
+
type,
|
|
150
|
+
value,
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
showAnimation(params: ShowAnimationParams) {}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Run the change detection cycle. Normally, as soon as a hook is called in a class, the cycle is started. But you can start it manually
|
|
158
|
+
* The method calls the `onChanges` method on events and synchronizes all map data with the client.
|
|
159
|
+
|
|
160
|
+
* @title Run Sync Changes
|
|
161
|
+
* @method player.syncChanges()
|
|
162
|
+
* @returns {void}
|
|
163
|
+
* @memberof Player
|
|
164
|
+
*/
|
|
165
|
+
syncChanges() {
|
|
166
|
+
this._eventChanges();
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
databaseById(id: string) {
|
|
170
|
+
const map = this.getCurrentMap();
|
|
171
|
+
if (!map) return;
|
|
172
|
+
const data = map.database()[id];
|
|
173
|
+
if (!data)
|
|
174
|
+
throw new Error(
|
|
175
|
+
`The ID=${id} data is not found in the database. Add the data in the property "database"`
|
|
176
|
+
);
|
|
177
|
+
return data;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
private _eventChanges() {
|
|
181
|
+
const map = this.getCurrentMap();
|
|
182
|
+
if (!map) return;
|
|
183
|
+
const { events } = map;
|
|
184
|
+
const arrayEvents: any[] = [
|
|
185
|
+
...Object.values(this.events()),
|
|
186
|
+
...Object.values(events()),
|
|
187
|
+
];
|
|
188
|
+
for (let event of arrayEvents) {
|
|
189
|
+
if (event.onChanges) event.onChanges(this);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
attachShape(id: string, options: ZoneOptions) {
|
|
194
|
+
const map = this.getCurrentMap();
|
|
195
|
+
if (!map) return;
|
|
196
|
+
|
|
197
|
+
const physic = map.physic;
|
|
198
|
+
|
|
199
|
+
const zoneId = physic.addZone(id, {
|
|
200
|
+
linkedTo: this.id,
|
|
201
|
+
...options,
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
physic.registerZoneEvents(
|
|
205
|
+
id,
|
|
206
|
+
(hitIds) => {
|
|
207
|
+
hitIds.forEach((id) => {
|
|
208
|
+
const event = map.getEvent<RpgEvent>(id);
|
|
209
|
+
const player = map.getPlayer(id);
|
|
210
|
+
const zone = physic.getZone(zoneId);
|
|
211
|
+
if (event) {
|
|
212
|
+
event.execMethod("onInShape", [zone, this]);
|
|
213
|
+
}
|
|
214
|
+
if (player) this.execMethod("onDetectInShape", [player, zone]);
|
|
215
|
+
});
|
|
216
|
+
},
|
|
217
|
+
(hitIds) => {
|
|
218
|
+
hitIds.forEach((id) => {
|
|
219
|
+
const event = map.getEvent<RpgEvent>(id);
|
|
220
|
+
const zone = physic.getZone(zoneId);
|
|
221
|
+
const player = map.getPlayer(id);
|
|
222
|
+
if (event) {
|
|
223
|
+
event.execMethod("onOutShape", [zone, this]);
|
|
224
|
+
}
|
|
225
|
+
if (player) this.execMethod("onDetectOutShape", [player, zone]);
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
broadcastEffect(id: string, params: any) {
|
|
232
|
+
const map = this.getCurrentMap();
|
|
233
|
+
if (!map) return;
|
|
234
|
+
map.$broadcast({
|
|
235
|
+
type: "showEffect",
|
|
236
|
+
value: {
|
|
237
|
+
id,
|
|
238
|
+
params,
|
|
239
|
+
object: this.id,
|
|
240
|
+
},
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
showHit(text: string) {
|
|
245
|
+
this.broadcastEffect("hit", {
|
|
246
|
+
text,
|
|
247
|
+
direction: this.direction(),
|
|
248
|
+
});
|
|
249
|
+
}
|
|
1006
250
|
}
|
|
1007
251
|
|
|
1008
252
|
export class RpgEvent extends RpgPlayer {
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
}
|
|
1026
|
-
|
|
1027
|
-
changeRoomState(path: string) {
|
|
1028
|
-
const room = this.getCurrentMap()
|
|
1029
|
-
if (room) {
|
|
1030
|
-
(room as any).$setCurrentState(`events.${this.id}.${path}`)
|
|
1031
|
-
}
|
|
1032
|
-
}
|
|
1033
|
-
|
|
1034
|
-
/**
|
|
1035
|
-
* Deletes the event from the map (in shared or scenario mode)
|
|
1036
|
-
*
|
|
1037
|
-
* @title Remove
|
|
1038
|
-
* @since 4.0.0
|
|
1039
|
-
* @method event.remove()
|
|
1040
|
-
* @returns {boolean} true if the event has been removed. If false, the event is not on the map
|
|
1041
|
-
* @memberof RpgEvent
|
|
1042
|
-
*/
|
|
1043
|
-
remove(): boolean {
|
|
1044
|
-
let bool = false
|
|
1045
|
-
if (this.playerRelated) bool = this.playerRelated.removeEvent(this.id)
|
|
1046
|
-
const map = this.getCurrentMap()
|
|
1047
|
-
if (map) {
|
|
1048
|
-
bool = map.removeEvent(this.id)
|
|
1049
|
-
}
|
|
1050
|
-
return bool
|
|
1051
|
-
}
|
|
1052
|
-
|
|
1053
|
-
override emitToMap(key: string, value: any) {
|
|
1054
|
-
const map = this.getCurrentMap()
|
|
1055
|
-
if (map) {
|
|
1056
|
-
const eventPath = `events.${this.id}.${key}`
|
|
1057
|
-
if (this.playerRelated) {
|
|
1058
|
-
map.$setCurrentState(`users.${this.playerRelated.id}.${eventPath}`, value)
|
|
1059
|
-
}
|
|
1060
|
-
else {
|
|
1061
|
-
map.$setCurrentState(eventPath, value)
|
|
1062
|
-
}
|
|
1063
|
-
}
|
|
1064
|
-
}
|
|
253
|
+
override async execMethod(methodName: string, methodData: any[] = [], instance = this) {
|
|
254
|
+
const hooks = inject<Hooks>(this.context as any, ModulesToken);
|
|
255
|
+
await lastValueFrom(hooks
|
|
256
|
+
.callHooks(`server-event-${methodName}`, instance, ...methodData));
|
|
257
|
+
if (!instance[methodName]) {
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
const ret = instance[methodName](...methodData);
|
|
261
|
+
return ret;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
remove() {
|
|
265
|
+
const map = this.getCurrentMap();
|
|
266
|
+
if (!map) return;
|
|
267
|
+
map.removeEvent(this.id);
|
|
268
|
+
}
|
|
1065
269
|
}
|
|
270
|
+
|
|
271
|
+
export interface RpgPlayer
|
|
272
|
+
extends RpgCommonPlayer,
|
|
273
|
+
IComponentManager,
|
|
274
|
+
IGuiManager,
|
|
275
|
+
IMoveManager,
|
|
276
|
+
IGoldManager,
|
|
277
|
+
IWithVariableManager,
|
|
278
|
+
IWithParameterManager,
|
|
279
|
+
IWithSkillManager {}
|