@rpgjs/server 5.0.0-alpha.27 → 5.0.0-alpha.28

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.
@@ -1,8 +1,9 @@
1
- import { PlayerCtor, ProjectileType, RpgCommonPlayer, Direction, MovementStrategy } from '../../../common/src';
1
+ import { PlayerCtor, ProjectileType, RpgCommonPlayer, Direction, MovementStrategy, MovementOptions } from '../../../common/src';
2
2
  import { RpgPlayer } from './Player';
3
3
  type CallbackTileMove = (player: RpgPlayer, map: any) => Direction[];
4
4
  type CallbackTurnMove = (player: RpgPlayer, map: any) => string;
5
5
  type Routes = (string | Promise<any> | Direction | Direction[] | Function)[];
6
+ export type { MovementOptions };
6
7
  /**
7
8
  * Options for moveRoutes method
8
9
  */
@@ -66,49 +67,39 @@ export declare enum Speed {
66
67
  Faster = 7,
67
68
  Fastest = 10
68
69
  }
69
- /**
70
- * @title Move
71
- * @enum {Object}
72
- *
73
- * Move.right(repeat=1) | Movement of a number of pixels on the right
74
- * Move.left(repeat=1) | Movement of a number of pixels on the left
75
- * Move.up(repeat=1) | Movement of a number of pixels on the up
76
- * Move.down(repeat=1) | Movement of a number of pixels on the down
77
- * Move.random(repeat=1) | Movement of a number of pixels in a random direction
78
- * Move.towardPlayer(player, repeat=1) | Moves a number of pixels in the direction of the designated player
79
- * Move.awayFromPlayer(player, repeat=1) | Moves a number of pixels in the opposite direction of the designated player
80
- * Move.tileRight(repeat=1) | Movement of a number of tiles on the right
81
- * Move.tileLeft(repeat=1) | Movement of a number of tiles on the left
82
- * Move.tileUp(repeat=1) | Movement of a number of tiles on the up
83
- * Move.tileDown(repeat=1) | Movement of a number of tiles on the down
84
- * Move.tileRandom(repeat=1) | Movement of a number of tiles in a random direction
85
- * Move.tileTowardPlayer(player, repeat=1) | Moves a number of tiles in the direction of the designated player
86
- * Move.tileAwayFromPlayer(player, repeat=1) | Moves a number of tiles in the opposite direction of the designated player
87
- * Move.turnRight() | Turn to the right
88
- * Move.turnLeft() | Turn to the left
89
- * Move.turnUp() | Turn to the up
90
- * Move.turnDown() | Turn to the down
91
- * Move.turnRandom() | Turn to random direction
92
- * Move.turnAwayFromPlayer(player) | Turns in the opposite direction of the designated player
93
- * Move.turnTowardPlayer(player) | Turns in the direction of the designated player
94
- * @memberof Move
95
- * */
96
70
  declare class MoveList {
97
71
  private static perlinNoise;
98
72
  private static randomCounter;
99
73
  private static callCounter;
74
+ private static playerMoveStates;
75
+ private static readonly STUCK_THRESHOLD;
76
+ /**
77
+ * Clears the movement state for a specific player
78
+ *
79
+ * Should be called when a player changes map or is destroyed to prevent
80
+ * memory leaks and stale stuck detection data.
81
+ *
82
+ * @param playerId - The ID of the player to clear state for
83
+ *
84
+ * @example
85
+ * ```ts
86
+ * // Clear state when player leaves map
87
+ * Move.clearPlayerState(player.id);
88
+ * ```
89
+ */
90
+ static clearPlayerState(playerId: string): void;
100
91
  /**
101
- * Gets a random direction index (0-3) using a hybrid approach for balanced randomness
92
+ * Clears all player movement states
102
93
  *
103
- * Uses a combination of hash-based pseudo-randomness and Perlin noise to ensure
104
- * fair distribution of directions while maintaining smooth, natural-looking movement patterns.
105
- * The hash function guarantees uniform distribution, while Perlin noise adds spatial/temporal coherence.
94
+ * Useful for cleanup during server shutdown or when resetting game state.
106
95
  *
107
- * @param player - Optional player instance for coordinate-based noise
108
- * @param index - Optional index for array-based calls to ensure variation
109
- * @returns Direction index (0-3) corresponding to Right, Left, Up, Down
96
+ * @example
97
+ * ```ts
98
+ * // Clear all states on server shutdown
99
+ * Move.clearAllPlayerStates();
100
+ * ```
110
101
  */
111
- private getRandomDirectionIndex;
102
+ static clearAllPlayerStates(): void;
112
103
  repeatMove(direction: Direction, repeat: number): Direction[];
113
104
  private repeatTileMove;
114
105
  right(repeat?: number): Direction[];
@@ -226,18 +217,77 @@ export declare function WithMoveManager<TBase extends PlayerCtor>(Base: TBase):
226
217
  * This interface defines the public API of the MoveManager mixin.
227
218
  */
228
219
  export interface IMoveManager {
229
- /** Whether the player passes through other players */
220
+ /**
221
+ * Whether the player passes through other players
222
+ *
223
+ * When `true`, the player can walk through other player entities without collision.
224
+ * This is useful for busy areas where players shouldn't block each other.
225
+ *
226
+ * @default true
227
+ *
228
+ * @example
229
+ * ```ts
230
+ * // Disable player-to-player collision
231
+ * player.throughOtherPlayer = true;
232
+ *
233
+ * // Enable player-to-player collision
234
+ * player.throughOtherPlayer = false;
235
+ * ```
236
+ */
230
237
  throughOtherPlayer: boolean;
231
- /** Whether the player goes through events or other players */
238
+ /**
239
+ * Whether the player goes through all characters (players and events)
240
+ *
241
+ * When `true`, the player can walk through all character entities (both players and events)
242
+ * without collision. Walls and obstacles still block movement.
243
+ * This takes precedence over `throughOtherPlayer` and `throughEvent`.
244
+ *
245
+ * @default false
246
+ *
247
+ * @example
248
+ * ```ts
249
+ * // Enable ghost mode - pass through all characters
250
+ * player.through = true;
251
+ *
252
+ * // Disable ghost mode
253
+ * player.through = false;
254
+ * ```
255
+ */
232
256
  through: boolean;
257
+ /**
258
+ * Whether the player passes through events (NPCs, objects)
259
+ *
260
+ * When `true`, the player can walk through event entities without collision.
261
+ * This is useful for NPCs that shouldn't block player movement.
262
+ *
263
+ * @default false
264
+ *
265
+ * @example
266
+ * ```ts
267
+ * // Allow passing through events
268
+ * player.throughEvent = true;
269
+ *
270
+ * // Block passage through events
271
+ * player.throughEvent = false;
272
+ * ```
273
+ */
274
+ throughEvent: boolean;
233
275
  /** Frequency for movement timing (milliseconds between movements) */
234
276
  frequency: number;
277
+ /** Whether direction changes are locked (prevents automatic direction changes) */
278
+ directionFixed: boolean;
279
+ /** Whether animation changes are locked (prevents automatic animation changes) */
280
+ animationFixed: boolean;
235
281
  /**
236
282
  * Add a custom movement strategy to this entity
237
283
  *
284
+ * Returns a Promise that resolves when the movement completes.
285
+ *
238
286
  * @param strategy - The movement strategy to add
287
+ * @param options - Optional callbacks for movement lifecycle events
288
+ * @returns Promise that resolves when the movement completes
239
289
  */
240
- addMovement(strategy: MovementStrategy): void;
290
+ addMovement(strategy: MovementStrategy, options?: MovementOptions): Promise<void>;
241
291
  /**
242
292
  * Remove a specific movement strategy from this entity
243
293
  *
@@ -277,36 +327,48 @@ export interface IMoveManager {
277
327
  /**
278
328
  * Perform a dash movement in the specified direction
279
329
  *
330
+ * The total speed is calculated by adding the player's base speed to the additional speed.
331
+ * Returns a Promise that resolves when the dash completes.
332
+ *
280
333
  * @param direction - Normalized direction vector
281
- * @param speed - Movement speed (default: 8)
334
+ * @param additionalSpeed - Extra speed added on top of base speed (default: 4)
282
335
  * @param duration - Duration in milliseconds (default: 200)
336
+ * @param options - Optional callbacks for movement lifecycle events
337
+ * @returns Promise that resolves when the dash completes
283
338
  */
284
339
  dash(direction: {
285
340
  x: number;
286
341
  y: number;
287
- }, speed?: number, duration?: number): void;
342
+ }, additionalSpeed?: number, duration?: number, options?: MovementOptions): Promise<void>;
288
343
  /**
289
344
  * Apply knockback effect in the specified direction
290
345
  *
346
+ * The force is scaled by the player's base speed for consistent behavior.
347
+ * Returns a Promise that resolves when the knockback completes.
348
+ *
291
349
  * @param direction - Normalized direction vector
292
- * @param force - Initial knockback force (default: 5)
350
+ * @param force - Force multiplier applied to base speed (default: 5)
293
351
  * @param duration - Duration in milliseconds (default: 300)
352
+ * @param options - Optional callbacks for movement lifecycle events
353
+ * @returns Promise that resolves when the knockback completes
294
354
  */
295
355
  knockback(direction: {
296
356
  x: number;
297
357
  y: number;
298
- }, force?: number, duration?: number): void;
358
+ }, force?: number, duration?: number, options?: MovementOptions): Promise<void>;
299
359
  /**
300
360
  * Follow a sequence of waypoints
301
361
  *
362
+ * Speed is calculated from the player's base speed multiplied by the speedMultiplier.
363
+ *
302
364
  * @param waypoints - Array of x,y positions to follow
303
- * @param speed - Movement speed (default: 2)
365
+ * @param speedMultiplier - Multiplier applied to base speed (default: 0.5)
304
366
  * @param loop - Whether to loop back to start (default: false)
305
367
  */
306
368
  followPath(waypoints: Array<{
307
369
  x: number;
308
370
  y: number;
309
- }>, speed?: number, loop?: boolean): void;
371
+ }>, speedMultiplier?: number, loop?: boolean): void;
310
372
  /**
311
373
  * Apply oscillating movement pattern
312
374
  *
@@ -321,24 +383,28 @@ export interface IMoveManager {
321
383
  /**
322
384
  * Apply ice movement physics
323
385
  *
386
+ * Max speed is calculated from the player's base speed multiplied by the speedFactor.
387
+ *
324
388
  * @param direction - Target movement direction
325
- * @param maxSpeed - Maximum speed when fully accelerated (default: 4)
389
+ * @param speedFactor - Factor multiplied with base speed for max speed (default: 1.0)
326
390
  */
327
391
  applyIceMovement(direction: {
328
392
  x: number;
329
393
  y: number;
330
- }, maxSpeed?: number): void;
394
+ }, speedFactor?: number): void;
331
395
  /**
332
396
  * Shoot a projectile in the specified direction
333
397
  *
398
+ * Speed is calculated from the player's base speed multiplied by the speedFactor.
399
+ *
334
400
  * @param type - Type of projectile trajectory
335
401
  * @param direction - Normalized direction vector
336
- * @param speed - Projectile speed (default: 200)
402
+ * @param speedFactor - Factor multiplied with base speed (default: 50)
337
403
  */
338
404
  shootProjectile(type: ProjectileType, direction: {
339
405
  x: number;
340
406
  y: number;
341
- }, speed?: number): void;
407
+ }, speedFactor?: number): void;
342
408
  /**
343
409
  * Give an itinerary to follow using movement strategies
344
410
  *
@@ -364,4 +430,3 @@ export interface IMoveManager {
364
430
  */
365
431
  replayRoutes(): void;
366
432
  }
367
- export {};
@@ -136,6 +136,8 @@ export declare class RpgPlayer extends RpgPlayer_base {
136
136
  * When `nbTimes` is set to a finite number, the animation will play that many times
137
137
  * before returning to the previous animation state.
138
138
  *
139
+ * If `animationFixed` is true, this method will not change the animation.
140
+ *
139
141
  * @param animationName - The name of the animation to play (e.g., 'attack', 'skill', 'walk')
140
142
  * @param nbTimes - Number of times to repeat the animation (default: Infinity for continuous)
141
143
  *
@@ -147,8 +149,9 @@ export declare class RpgPlayer extends RpgPlayer_base {
147
149
  * // Play attack animation 3 times then return to previous state
148
150
  * player.setAnimation('attack', 3);
149
151
  *
150
- * // Play skill animation once
151
- * player.setAnimation('skill', 1);
152
+ * // Lock animation to prevent automatic changes
153
+ * player.animationFixed = true;
154
+ * player.setAnimation('skill'); // This will be ignored
152
155
  *
153
156
  * // Set idle/stand animation
154
157
  * player.setAnimation('stand');
@@ -463,6 +466,12 @@ export declare class RpgPlayer extends RpgPlayer_base {
463
466
  }
464
467
  export declare class RpgEvent extends RpgPlayer {
465
468
  execMethod(methodName: string, methodData?: any[], instance?: this): Promise<any>;
469
+ /**
470
+ * Remove this event from the map
471
+ *
472
+ * Stops all movements before removing to prevent "unable to resolve entity" errors
473
+ * from the MovementManager when the entity is destroyed while moving.
474
+ */
466
475
  remove(): void;
467
476
  isEvent(): boolean;
468
477
  }
@@ -1,5 +1,124 @@
1
1
  import { PlayerCtor } from '../../../common/src';
2
2
  import { RpgPlayer } from './Player';
3
+ /**
4
+ * Type for skill class constructor
5
+ */
6
+ type SkillClass = {
7
+ new (...args: any[]): any;
8
+ };
9
+ /**
10
+ * Interface defining the hooks that can be implemented on skill classes or objects
11
+ *
12
+ * These hooks are called at specific moments during the skill lifecycle:
13
+ * - `onLearn`: When the skill is learned by the player
14
+ * - `onUse`: When the skill is successfully used
15
+ * - `onUseFailed`: When the skill usage fails (e.g., chance roll failed)
16
+ * - `onForget`: When the skill is forgotten
17
+ *
18
+ * @example
19
+ * ```ts
20
+ * const skillHooks: SkillHooks = {
21
+ * onLearn(player) {
22
+ * console.log('Skill learned!');
23
+ * },
24
+ * onUse(player, target) {
25
+ * console.log('Skill used on target');
26
+ * }
27
+ * };
28
+ * ```
29
+ */
30
+ export interface SkillHooks {
31
+ /**
32
+ * Called when the skill is learned by the player
33
+ *
34
+ * @param player - The player learning the skill
35
+ */
36
+ onLearn?: (player: RpgPlayer) => void | Promise<void>;
37
+ /**
38
+ * Called when the skill is successfully used
39
+ *
40
+ * @param player - The player using the skill
41
+ * @param target - The target player(s) if any
42
+ */
43
+ onUse?: (player: RpgPlayer, target?: RpgPlayer | RpgPlayer[]) => void | Promise<void>;
44
+ /**
45
+ * Called when the skill usage fails (e.g., chance roll failed)
46
+ *
47
+ * @param player - The player attempting to use the skill
48
+ * @param target - The intended target player(s) if any
49
+ */
50
+ onUseFailed?: (player: RpgPlayer, target?: RpgPlayer | RpgPlayer[]) => void | Promise<void>;
51
+ /**
52
+ * Called when the skill is forgotten
53
+ *
54
+ * @param player - The player forgetting the skill
55
+ */
56
+ onForget?: (player: RpgPlayer) => void | Promise<void>;
57
+ }
58
+ /**
59
+ * Interface for skill object definition
60
+ *
61
+ * Defines the properties that a skill can have when defined as an object.
62
+ * Skills can be defined as objects, classes, or string IDs referencing the database.
63
+ *
64
+ * @example
65
+ * ```ts
66
+ * const fireSkill: SkillObject = {
67
+ * id: 'fire',
68
+ * name: 'Fire',
69
+ * description: 'A basic fire spell',
70
+ * spCost: 10,
71
+ * hitRate: 0.9,
72
+ * power: 50,
73
+ * onUse(player) {
74
+ * console.log('Fire spell cast!');
75
+ * }
76
+ * };
77
+ *
78
+ * player.learnSkill(fireSkill);
79
+ * ```
80
+ */
81
+ export interface SkillObject extends SkillHooks {
82
+ /**
83
+ * Unique identifier for the skill
84
+ * If not provided, one will be auto-generated
85
+ */
86
+ id?: string;
87
+ /**
88
+ * Display name of the skill
89
+ */
90
+ name?: string;
91
+ /**
92
+ * Description of the skill
93
+ */
94
+ description?: string;
95
+ /**
96
+ * SP (Skill Points) cost to use the skill
97
+ * @default 0
98
+ */
99
+ spCost?: number;
100
+ /**
101
+ * Hit rate (0-1) - probability of successful skill usage
102
+ * @default 1
103
+ */
104
+ hitRate?: number;
105
+ /**
106
+ * Base power of the skill for damage calculation
107
+ */
108
+ power?: number;
109
+ /**
110
+ * Coefficient multipliers for damage calculation
111
+ */
112
+ coefficient?: Record<string, number>;
113
+ /**
114
+ * Type marker for database
115
+ */
116
+ _type?: 'skill';
117
+ /**
118
+ * Allow additional properties
119
+ */
120
+ [key: string]: any;
121
+ }
3
122
  /**
4
123
  * Skill Manager Mixin
5
124
  *
@@ -7,21 +126,31 @@ import { RpgPlayer } from './Player';
7
126
  * learning, forgetting, and using skills, including SP cost management,
8
127
  * hit rate calculations, and skill effects application.
9
128
  *
129
+ * Supports three input formats for skills:
130
+ * - **String ID**: References a skill in the database
131
+ * - **Class**: A skill class that will be instantiated
132
+ * - **Object**: A skill object with properties and hooks
133
+ *
10
134
  * @param Base - The base class to extend with skill management
11
135
  * @returns Extended class with skill management methods
12
136
  *
13
137
  * @example
14
138
  * ```ts
15
- * class MyPlayer extends WithSkillManager(BasePlayer) {
16
- * constructor() {
17
- * super();
18
- * // Skill system is automatically initialized
19
- * }
20
- * }
139
+ * // Using string ID (from database)
140
+ * player.learnSkill('fire');
21
141
  *
22
- * const player = new MyPlayer();
23
- * player.learnSkill(Fire);
24
- * player.useSkill(Fire, targetPlayer);
142
+ * // Using skill class
143
+ * player.learnSkill(FireSkill);
144
+ *
145
+ * // Using skill object
146
+ * player.learnSkill({
147
+ * id: 'ice',
148
+ * name: 'Ice',
149
+ * spCost: 15,
150
+ * onUse(player) {
151
+ * console.log('Ice spell cast!');
152
+ * }
153
+ * });
25
154
  * ```
26
155
  */
27
156
  export declare function WithSkillManager<TBase extends PlayerCtor>(Base: TBase): TBase;
@@ -35,36 +164,42 @@ export interface ISkillManager {
35
164
  /**
36
165
  * Retrieves a learned skill. Returns null if not found
37
166
  *
38
- * @param skillClass - Skill class or data id
39
- * @returns Instance of SkillClass or null
167
+ * @param skillInput - Skill class, object, or data id
168
+ * @returns The skill data or null
40
169
  */
41
- getSkill(skillClass: any | string): any | null;
170
+ getSkill(skillInput: SkillClass | SkillObject | string): any | null;
42
171
  /**
43
172
  * Learn a skill
44
173
  *
45
- * @param skillId - Skill class or data id
46
- * @returns Instance of SkillClass
174
+ * Supports three input formats:
175
+ * - String ID: Retrieves from database
176
+ * - Class: Creates instance and adds to database
177
+ * - Object: Uses directly and adds to database
178
+ *
179
+ * @param skillInput - Skill class, object, or data id
180
+ * @returns The learned skill data
47
181
  * @throws SkillLog.alreadyLearned if the player already knows the skill
48
182
  */
49
- learnSkill(skillId: any | string): any;
183
+ learnSkill(skillInput: SkillClass | SkillObject | string): any;
50
184
  /**
51
185
  * Forget a skill
52
186
  *
53
- * @param skillId - Skill class or data id
54
- * @returns Instance of SkillClass
187
+ * @param skillInput - Skill class, object, or data id
188
+ * @returns The forgotten skill data
55
189
  * @throws SkillLog.notLearned if trying to forget a skill not learned
56
190
  */
57
- forgetSkill(skillId: any | string): any;
191
+ forgetSkill(skillInput: SkillClass | SkillObject | string): any;
58
192
  /**
59
- * Using a skill
193
+ * Use a skill
60
194
  *
61
- * @param skillId - Skill class or data id
195
+ * @param skillInput - Skill class, object, or data id
62
196
  * @param otherPlayer - Optional target player(s) to apply skill to
63
- * @returns Instance of SkillClass
197
+ * @returns The used skill data
64
198
  * @throws SkillLog.restriction if player has Effect.CAN_NOT_SKILL
65
199
  * @throws SkillLog.notLearned if player tries to use an unlearned skill
66
200
  * @throws SkillLog.notEnoughSp if player does not have enough SP
67
201
  * @throws SkillLog.chanceToUseFailed if the chance to use the skill has failed
68
202
  */
69
- useSkill(skillId: any | string, otherPlayer?: RpgPlayer | RpgPlayer[]): any;
203
+ useSkill(skillInput: SkillClass | SkillObject | string, otherPlayer?: RpgPlayer | RpgPlayer[]): any;
70
204
  }
205
+ export {};