@rpgjs/server 5.0.0-alpha.2 → 5.0.0-alpha.20
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/dist/Gui/DialogGui.d.ts +4 -0
- package/dist/Gui/index.d.ts +1 -0
- package/dist/Player/BattleManager.d.ts +32 -22
- package/dist/Player/ClassManager.d.ts +31 -18
- package/dist/Player/ComponentManager.d.ts +123 -0
- package/dist/Player/Components.d.ts +345 -0
- package/dist/Player/EffectManager.d.ts +40 -0
- package/dist/Player/ElementManager.d.ts +31 -0
- package/dist/Player/GoldManager.d.ts +22 -0
- package/dist/Player/GuiManager.d.ts +176 -0
- package/dist/Player/ItemFixture.d.ts +6 -0
- package/dist/Player/ItemManager.d.ts +164 -10
- package/dist/Player/MoveManager.d.ts +32 -44
- package/dist/Player/ParameterManager.d.ts +343 -14
- package/dist/Player/Player.d.ts +266 -8
- package/dist/Player/SkillManager.d.ts +27 -19
- package/dist/Player/StateManager.d.ts +28 -35
- package/dist/Player/VariableManager.d.ts +30 -0
- package/dist/RpgServer.d.ts +227 -1
- package/dist/decorators/event.d.ts +46 -0
- package/dist/decorators/map.d.ts +177 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +17436 -18167
- package/dist/index.js.map +1 -1
- package/dist/rooms/map.d.ts +486 -8
- package/package.json +17 -15
- package/src/Gui/DialogGui.ts +7 -2
- package/src/Gui/index.ts +3 -1
- package/src/Player/BattleManager.ts +97 -38
- package/src/Player/ClassManager.ts +95 -35
- package/src/Player/ComponentManager.ts +425 -19
- package/src/Player/Components.ts +380 -0
- package/src/Player/EffectManager.ts +110 -27
- package/src/Player/ElementManager.ts +126 -25
- package/src/Player/GoldManager.ts +32 -35
- package/src/Player/GuiManager.ts +187 -140
- package/src/Player/ItemFixture.ts +4 -5
- package/src/Player/ItemManager.ts +363 -48
- package/src/Player/MoveManager.ts +323 -308
- package/src/Player/ParameterManager.ts +499 -99
- package/src/Player/Player.ts +719 -80
- package/src/Player/SkillManager.ts +44 -23
- package/src/Player/StateManager.ts +210 -95
- package/src/Player/VariableManager.ts +180 -48
- package/src/RpgServer.ts +236 -1
- package/src/core/context.ts +1 -0
- package/src/decorators/event.ts +61 -0
- package/src/decorators/map.ts +198 -0
- package/src/index.ts +5 -1
- package/src/module.ts +24 -0
- package/src/rooms/map.ts +1054 -54
- package/dist/Player/Event.d.ts +0 -0
- package/src/Player/Event.ts +0 -0
package/dist/rooms/map.d.ts
CHANGED
|
@@ -1,7 +1,22 @@
|
|
|
1
1
|
import { MockConnection, RoomOnJoin } from '@signe/room';
|
|
2
|
-
import { Hooks, RpgCommonMap,
|
|
2
|
+
import { Hooks, RpgCommonMap, RpgShape, WorldMapsManager, WorldMapConfig } from '@rpgjs/common';
|
|
3
3
|
import { RpgPlayer, RpgEvent } from '../Player/Player';
|
|
4
4
|
import { BehaviorSubject } from 'rxjs';
|
|
5
|
+
/**
|
|
6
|
+
* Interface for input controls configuration
|
|
7
|
+
*
|
|
8
|
+
* Defines the structure for input validation and anti-cheat controls
|
|
9
|
+
*/
|
|
10
|
+
export interface Controls {
|
|
11
|
+
/** Maximum allowed time delta between inputs in milliseconds */
|
|
12
|
+
maxTimeDelta?: number;
|
|
13
|
+
/** Maximum allowed frame delta between inputs */
|
|
14
|
+
maxFrameDelta?: number;
|
|
15
|
+
/** Minimum time between inputs in milliseconds */
|
|
16
|
+
minTimeBetweenInputs?: number;
|
|
17
|
+
/** Whether to enable anti-cheat validation */
|
|
18
|
+
enableAntiCheat?: boolean;
|
|
19
|
+
}
|
|
5
20
|
/**
|
|
6
21
|
* Interface representing hook methods available for map events
|
|
7
22
|
*
|
|
@@ -17,11 +32,11 @@ export interface EventHooks {
|
|
|
17
32
|
/** Called when a player touches this event */
|
|
18
33
|
onPlayerTouch?: (player: RpgPlayer) => void;
|
|
19
34
|
/** Called when a player enters a shape */
|
|
20
|
-
onInShape?: (zone:
|
|
35
|
+
onInShape?: (zone: RpgShape, player: RpgPlayer) => void;
|
|
21
36
|
/** Called when a player exits a shape */
|
|
22
|
-
onOutShape?: (zone:
|
|
23
|
-
onDetectInShape?: (player: RpgPlayer, shape:
|
|
24
|
-
onDetectOutShape?: (player: RpgPlayer, shape:
|
|
37
|
+
onOutShape?: (zone: RpgShape, player: RpgPlayer) => void;
|
|
38
|
+
onDetectInShape?: (player: RpgPlayer, shape: RpgShape) => void;
|
|
39
|
+
onDetectOutShape?: (player: RpgPlayer, shape: RpgShape) => void;
|
|
25
40
|
}
|
|
26
41
|
/** Type for event class constructor */
|
|
27
42
|
export type EventConstructor = new () => RpgPlayer;
|
|
@@ -48,17 +63,190 @@ export declare class RpgMap extends RpgCommonMap<RpgPlayer> implements RoomOnJoi
|
|
|
48
63
|
dataIsReady$: BehaviorSubject<void>;
|
|
49
64
|
globalConfig: any;
|
|
50
65
|
damageFormulas: any;
|
|
66
|
+
/** Internal: Map of shapes by name */
|
|
67
|
+
private _shapes;
|
|
68
|
+
/** Internal: Map of shape entity UUIDs to RpgShape instances */
|
|
69
|
+
private _shapeEntities;
|
|
70
|
+
constructor();
|
|
71
|
+
/**
|
|
72
|
+
* Setup collision detection between players, events, and shapes
|
|
73
|
+
*
|
|
74
|
+
* This method listens to physics collision events and triggers hooks:
|
|
75
|
+
* - `onPlayerTouch` on events when a player collides with them
|
|
76
|
+
* - `onInShape` on players and events when they enter a shape
|
|
77
|
+
* - `onOutShape` on players and events when they exit a shape
|
|
78
|
+
*
|
|
79
|
+
* ## Architecture
|
|
80
|
+
*
|
|
81
|
+
* Uses the physics engine's collision event system to detect when entities collide.
|
|
82
|
+
* When a collision is detected:
|
|
83
|
+
* - Between a player and an event: triggers `onPlayerTouch` on the event
|
|
84
|
+
* - Between a player/event and a shape: triggers `onInShape`/`onOutShape` hooks
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* ```ts
|
|
88
|
+
* // Event with onPlayerTouch hook
|
|
89
|
+
* map.createDynamicEvent({
|
|
90
|
+
* x: 100,
|
|
91
|
+
* y: 200,
|
|
92
|
+
* event: {
|
|
93
|
+
* onPlayerTouch(player) {
|
|
94
|
+
* console.log(`Player ${player.id} touched this event!`);
|
|
95
|
+
* }
|
|
96
|
+
* }
|
|
97
|
+
* });
|
|
98
|
+
*
|
|
99
|
+
* // Player with onInShape hook
|
|
100
|
+
* const player: RpgPlayerHooks = {
|
|
101
|
+
* onInShape(player: RpgPlayer, shape: RpgShape) {
|
|
102
|
+
* console.log('in', player.name, shape.name);
|
|
103
|
+
* },
|
|
104
|
+
* onOutShape(player: RpgPlayer, shape: RpgShape) {
|
|
105
|
+
* console.log('out', player.name, shape.name);
|
|
106
|
+
* }
|
|
107
|
+
* };
|
|
108
|
+
* ```
|
|
109
|
+
*/
|
|
110
|
+
private setupCollisionDetection;
|
|
111
|
+
interceptorPacket(player: RpgPlayer, packet: any, conn: MockConnection): any;
|
|
51
112
|
onJoin(player: RpgPlayer, conn: MockConnection): void;
|
|
113
|
+
onLeave(player: RpgPlayer, conn: MockConnection): void;
|
|
52
114
|
get hooks(): Hooks;
|
|
115
|
+
get widthPx(): number;
|
|
116
|
+
get heightPx(): number;
|
|
117
|
+
get id(): string;
|
|
118
|
+
get worldX(): number;
|
|
119
|
+
get worldY(): number;
|
|
53
120
|
guiInteraction(player: RpgPlayer, value: any): void;
|
|
54
121
|
guiExit(player: RpgPlayer, { guiId, data }: {
|
|
55
122
|
guiId: any;
|
|
56
123
|
data: any;
|
|
57
124
|
}): void;
|
|
58
125
|
onAction(player: RpgPlayer, action: any): void;
|
|
59
|
-
onInput(player: RpgPlayer, input: any): void
|
|
126
|
+
onInput(player: RpgPlayer, input: any): Promise<void>;
|
|
60
127
|
updateMap(request: Request): Promise<void>;
|
|
61
|
-
|
|
128
|
+
/**
|
|
129
|
+
* Update (or create) a world configuration and propagate to all maps in that world
|
|
130
|
+
*
|
|
131
|
+
* Body must contain the world config as defined by Tiled world import or an array of maps.
|
|
132
|
+
* If the world does not exist yet for this scene, it is created (auto-create).
|
|
133
|
+
*
|
|
134
|
+
* Expected payload examples:
|
|
135
|
+
* - { id: string, maps: WorldMapConfig[] }
|
|
136
|
+
* - WorldMapConfig[]
|
|
137
|
+
*/
|
|
138
|
+
updateWorld(request: Request): Promise<any>;
|
|
139
|
+
/**
|
|
140
|
+
* Process pending inputs for a player with anti-cheat validation
|
|
141
|
+
*
|
|
142
|
+
* This method processes all pending inputs for a player while performing
|
|
143
|
+
* anti-cheat validation to prevent time manipulation and frame skipping.
|
|
144
|
+
* It validates the time deltas between inputs and ensures they are within
|
|
145
|
+
* acceptable ranges.
|
|
146
|
+
*
|
|
147
|
+
* ## Architecture
|
|
148
|
+
*
|
|
149
|
+
* **Important**: This method only updates entity velocities - it does NOT step
|
|
150
|
+
* the physics engine. Physics simulation is handled centrally by the game loop
|
|
151
|
+
* (`tick$` -> `runFixedTicks`). This ensures:
|
|
152
|
+
* - Consistent physics timing (60fps fixed timestep)
|
|
153
|
+
* - No double-stepping when multiple inputs are processed
|
|
154
|
+
* - Deterministic physics regardless of input frequency
|
|
155
|
+
*
|
|
156
|
+
* @param playerId - The ID of the player to process inputs for
|
|
157
|
+
* @param controls - Optional anti-cheat configuration
|
|
158
|
+
* @returns Promise containing the player and processed input strings
|
|
159
|
+
*
|
|
160
|
+
* @example
|
|
161
|
+
* ```ts
|
|
162
|
+
* // Process inputs with default anti-cheat settings
|
|
163
|
+
* const result = await map.processInput('player1');
|
|
164
|
+
* console.log('Processed inputs:', result.inputs);
|
|
165
|
+
*
|
|
166
|
+
* // Process inputs with custom anti-cheat configuration
|
|
167
|
+
* const result = await map.processInput('player1', {
|
|
168
|
+
* maxTimeDelta: 100,
|
|
169
|
+
* maxFrameDelta: 5,
|
|
170
|
+
* minTimeBetweenInputs: 16,
|
|
171
|
+
* enableAntiCheat: true
|
|
172
|
+
* });
|
|
173
|
+
* ```
|
|
174
|
+
*/
|
|
175
|
+
processInput(playerId: string, controls?: Controls): Promise<{
|
|
176
|
+
player: RpgPlayer;
|
|
177
|
+
inputs: string[];
|
|
178
|
+
}>;
|
|
179
|
+
private loop;
|
|
180
|
+
/**
|
|
181
|
+
* Get a world manager by id (if multiple supported in future)
|
|
182
|
+
*/
|
|
183
|
+
getWorldMaps(id: string): WorldMapsManager | null;
|
|
184
|
+
/**
|
|
185
|
+
* Delete a world manager by id
|
|
186
|
+
*/
|
|
187
|
+
deleteWorldMaps(id: string): boolean;
|
|
188
|
+
/**
|
|
189
|
+
* Create a world manager dynamically
|
|
190
|
+
*/
|
|
191
|
+
createDynamicWorldMaps(world: {
|
|
192
|
+
id?: string;
|
|
193
|
+
maps: WorldMapConfig[];
|
|
194
|
+
}): WorldMapsManager;
|
|
195
|
+
/**
|
|
196
|
+
* Update world maps by id. Auto-create when missing.
|
|
197
|
+
*/
|
|
198
|
+
updateWorldMaps(id: string, maps: WorldMapConfig[]): Promise<void>;
|
|
199
|
+
/**
|
|
200
|
+
* Add data to the map's database
|
|
201
|
+
*
|
|
202
|
+
* This method allows you to dynamically add items, classes, or any data to the map's database.
|
|
203
|
+
* By default, if an ID already exists, the operation is ignored to prevent overwriting existing data.
|
|
204
|
+
*
|
|
205
|
+
* @param id - Unique identifier for the data
|
|
206
|
+
* @param data - The data to store (can be a class, object, or any value)
|
|
207
|
+
* @param options - Optional configuration
|
|
208
|
+
* @param options.force - If true, overwrites existing data even if ID already exists (default: false)
|
|
209
|
+
* @returns true if data was added, false if ignored (ID already exists)
|
|
210
|
+
*
|
|
211
|
+
* @example
|
|
212
|
+
* ```ts
|
|
213
|
+
* // Add an item class to the database
|
|
214
|
+
* map.addInDatabase('Potion', PotionClass);
|
|
215
|
+
*
|
|
216
|
+
* // Add an item object to the database
|
|
217
|
+
* map.addInDatabase('custom-item', {
|
|
218
|
+
* name: 'Custom Item',
|
|
219
|
+
* price: 100
|
|
220
|
+
* });
|
|
221
|
+
*
|
|
222
|
+
* // Force overwrite existing data
|
|
223
|
+
* map.addInDatabase('Potion', UpdatedPotionClass, { force: true });
|
|
224
|
+
* ```
|
|
225
|
+
*/
|
|
226
|
+
addInDatabase(id: string, data: any, options?: {
|
|
227
|
+
force?: boolean;
|
|
228
|
+
}): boolean;
|
|
229
|
+
/**
|
|
230
|
+
* Remove data from the map's database
|
|
231
|
+
*
|
|
232
|
+
* This method allows you to remove items or data from the map's database.
|
|
233
|
+
*
|
|
234
|
+
* @param id - Unique identifier of the data to remove
|
|
235
|
+
* @returns true if data was removed, false if ID didn't exist
|
|
236
|
+
*
|
|
237
|
+
* @example
|
|
238
|
+
* ```ts
|
|
239
|
+
* // Remove an item from the database
|
|
240
|
+
* map.removeInDatabase('Potion');
|
|
241
|
+
*
|
|
242
|
+
* // Check if removal was successful
|
|
243
|
+
* const removed = map.removeInDatabase('custom-item');
|
|
244
|
+
* if (removed) {
|
|
245
|
+
* console.log('Item removed successfully');
|
|
246
|
+
* }
|
|
247
|
+
* ```
|
|
248
|
+
*/
|
|
249
|
+
removeInDatabase(id: string): boolean;
|
|
62
250
|
/**
|
|
63
251
|
* Creates a dynamic event on the map
|
|
64
252
|
*
|
|
@@ -100,11 +288,301 @@ export declare class RpgMap extends RpgCommonMap<RpgPlayer> implements RoomOnJoi
|
|
|
100
288
|
createDynamicEvent(eventObj: EventPosOption): Promise<void>;
|
|
101
289
|
getEvent<T extends RpgPlayer>(eventId: string): T | undefined;
|
|
102
290
|
getPlayer(playerId: string): RpgPlayer | undefined;
|
|
291
|
+
getPlayers(): RpgPlayer[];
|
|
103
292
|
getEvents(): RpgEvent[];
|
|
293
|
+
getEventBy(cb: (event: RpgEvent) => boolean): RpgEvent | undefined;
|
|
294
|
+
getEventsBy(cb: (event: RpgEvent) => boolean): RpgEvent[];
|
|
104
295
|
removeEvent(eventId: string): void;
|
|
105
|
-
|
|
296
|
+
/**
|
|
297
|
+
* Display a component animation at a specific position on the map
|
|
298
|
+
*
|
|
299
|
+
* This method broadcasts a component animation to all clients connected to the map,
|
|
300
|
+
* allowing temporary visual effects to be displayed at any location on the map.
|
|
301
|
+
* Component animations are custom Canvas Engine components that can display
|
|
302
|
+
* complex effects with custom logic and parameters.
|
|
303
|
+
*
|
|
304
|
+
* @param id - The ID of the component animation to display
|
|
305
|
+
* @param position - The x, y coordinates where to display the animation
|
|
306
|
+
* @param params - Parameters to pass to the component animation
|
|
307
|
+
*
|
|
308
|
+
* @example
|
|
309
|
+
* ```ts
|
|
310
|
+
* // Show explosion at specific coordinates
|
|
311
|
+
* map.showComponentAnimation("explosion", { x: 300, y: 400 }, {
|
|
312
|
+
* intensity: 2.5,
|
|
313
|
+
* duration: 1500
|
|
314
|
+
* });
|
|
315
|
+
*
|
|
316
|
+
* // Show area damage effect
|
|
317
|
+
* map.showComponentAnimation("area-damage", { x: player.x, y: player.y }, {
|
|
318
|
+
* radius: 100,
|
|
319
|
+
* color: "red",
|
|
320
|
+
* damage: 50
|
|
321
|
+
* });
|
|
322
|
+
*
|
|
323
|
+
* // Show treasure spawn effect
|
|
324
|
+
* map.showComponentAnimation("treasure-spawn", { x: 150, y: 200 }, {
|
|
325
|
+
* sparkle: true,
|
|
326
|
+
* sound: "treasure-appear"
|
|
327
|
+
* });
|
|
328
|
+
* ```
|
|
329
|
+
*/
|
|
330
|
+
showComponentAnimation(id: string, position: {
|
|
331
|
+
x: number;
|
|
332
|
+
y: number;
|
|
333
|
+
}, params: any): void;
|
|
334
|
+
/**
|
|
335
|
+
* Display a spritesheet animation at a specific position on the map
|
|
336
|
+
*
|
|
337
|
+
* This method displays a temporary visual animation using a spritesheet at any
|
|
338
|
+
* location on the map. It's a convenience method that internally uses showComponentAnimation
|
|
339
|
+
* with the built-in 'animation' component. This is useful for spell effects, environmental
|
|
340
|
+
* animations, or any visual feedback that uses predefined spritesheets.
|
|
341
|
+
*
|
|
342
|
+
* @param position - The x, y coordinates where to display the animation
|
|
343
|
+
* @param graphic - The ID of the spritesheet to use for the animation
|
|
344
|
+
* @param animationName - The name of the animation within the spritesheet (default: 'default')
|
|
345
|
+
*
|
|
346
|
+
* @example
|
|
347
|
+
* ```ts
|
|
348
|
+
* // Show explosion at specific coordinates
|
|
349
|
+
* map.showAnimation({ x: 100, y: 200 }, "explosion");
|
|
350
|
+
*
|
|
351
|
+
* // Show spell effect at player position
|
|
352
|
+
* const playerPos = { x: player.x, y: player.y };
|
|
353
|
+
* map.showAnimation(playerPos, "spell-effects", "lightning");
|
|
354
|
+
*
|
|
355
|
+
* // Show environmental effect
|
|
356
|
+
* map.showAnimation({ x: 300, y: 150 }, "nature-effects", "wind-gust");
|
|
357
|
+
*
|
|
358
|
+
* // Show portal opening animation
|
|
359
|
+
* map.showAnimation({ x: 500, y: 400 }, "portals", "opening");
|
|
360
|
+
* ```
|
|
361
|
+
*/
|
|
362
|
+
showAnimation(position: {
|
|
363
|
+
x: number;
|
|
364
|
+
y: number;
|
|
365
|
+
}, graphic: string, animationName?: string): void;
|
|
366
|
+
/**
|
|
367
|
+
* Set the sync schema for the map
|
|
368
|
+
* @param schema - The schema to set
|
|
369
|
+
*/
|
|
370
|
+
/**
|
|
371
|
+
* Configure runtime synchronized properties on the map
|
|
372
|
+
*
|
|
373
|
+
* Design
|
|
374
|
+
* - Reads a schema object shaped like module props
|
|
375
|
+
* - Creates typed sync signals with @signe/sync
|
|
376
|
+
*/
|
|
377
|
+
setSync(schema: Record<string, any>): void;
|
|
378
|
+
/**
|
|
379
|
+
* Create a shape dynamically on the map
|
|
380
|
+
*
|
|
381
|
+
* This method creates a static hitbox on the map that can be used for
|
|
382
|
+
* collision detection, area triggers, or visual boundaries. The shape is
|
|
383
|
+
* backed by the physics engine's static entity system for accurate collision detection.
|
|
384
|
+
*
|
|
385
|
+
* ## Architecture
|
|
386
|
+
*
|
|
387
|
+
* Creates a static entity (hitbox) in the physics engine at the specified position and size.
|
|
388
|
+
* The shape is stored internally and can be retrieved by name. When players or events
|
|
389
|
+
* collide with this hitbox, the `onInShape` and `onOutShape` hooks are automatically
|
|
390
|
+
* triggered on both the player and the event.
|
|
391
|
+
*
|
|
392
|
+
* @param obj - Shape configuration object
|
|
393
|
+
* @param obj.x - X position of the shape (top-left corner) (required)
|
|
394
|
+
* @param obj.y - Y position of the shape (top-left corner) (required)
|
|
395
|
+
* @param obj.width - Width of the shape in pixels (required)
|
|
396
|
+
* @param obj.height - Height of the shape in pixels (required)
|
|
397
|
+
* @param obj.name - Name of the shape (optional, auto-generated if not provided)
|
|
398
|
+
* @param obj.z - Z position/depth for rendering (optional)
|
|
399
|
+
* @param obj.color - Color in hexadecimal format, shared with client (optional)
|
|
400
|
+
* @param obj.collision - Whether the shape has collision (optional)
|
|
401
|
+
* @param obj.properties - Additional custom properties (optional)
|
|
402
|
+
* @returns The created RpgShape instance
|
|
403
|
+
*
|
|
404
|
+
* @example
|
|
405
|
+
* ```ts
|
|
406
|
+
* // Create a simple rectangular shape
|
|
407
|
+
* const shape = map.createShape({
|
|
408
|
+
* x: 100,
|
|
409
|
+
* y: 200,
|
|
410
|
+
* width: 50,
|
|
411
|
+
* height: 50,
|
|
412
|
+
* name: "spawn-zone"
|
|
413
|
+
* });
|
|
414
|
+
*
|
|
415
|
+
* // Create a shape with visual properties
|
|
416
|
+
* const triggerZone = map.createShape({
|
|
417
|
+
* x: 300,
|
|
418
|
+
* y: 400,
|
|
419
|
+
* width: 100,
|
|
420
|
+
* height: 100,
|
|
421
|
+
* name: "treasure-area",
|
|
422
|
+
* color: "#FFD700",
|
|
423
|
+
* z: 1,
|
|
424
|
+
* collision: false,
|
|
425
|
+
* properties: {
|
|
426
|
+
* type: "treasure",
|
|
427
|
+
* value: 100
|
|
428
|
+
* }
|
|
429
|
+
* });
|
|
430
|
+
*
|
|
431
|
+
* // Player hooks will be triggered automatically
|
|
432
|
+
* const player: RpgPlayerHooks = {
|
|
433
|
+
* onInShape(player: RpgPlayer, shape: RpgShape) {
|
|
434
|
+
* console.log('in', player.name, shape.name);
|
|
435
|
+
* },
|
|
436
|
+
* onOutShape(player: RpgPlayer, shape: RpgShape) {
|
|
437
|
+
* console.log('out', player.name, shape.name);
|
|
438
|
+
* }
|
|
439
|
+
* };
|
|
440
|
+
* ```
|
|
441
|
+
*/
|
|
442
|
+
createShape(obj: {
|
|
443
|
+
x: number;
|
|
444
|
+
y: number;
|
|
445
|
+
width: number;
|
|
446
|
+
height: number;
|
|
447
|
+
name?: string;
|
|
448
|
+
z?: number;
|
|
449
|
+
color?: string;
|
|
450
|
+
collision?: boolean;
|
|
451
|
+
properties?: Record<string, any>;
|
|
452
|
+
}): RpgShape;
|
|
453
|
+
/**
|
|
454
|
+
* Delete a shape from the map
|
|
455
|
+
*
|
|
456
|
+
* Removes a shape by its name and cleans up the associated static hitbox entity.
|
|
457
|
+
* If the shape doesn't exist, the method does nothing.
|
|
458
|
+
*
|
|
459
|
+
* @param name - Name of the shape to remove
|
|
460
|
+
* @returns void
|
|
461
|
+
*
|
|
462
|
+
* @example
|
|
463
|
+
* ```ts
|
|
464
|
+
* // Create and then remove a shape
|
|
465
|
+
* const shape = map.createShape({
|
|
466
|
+
* x: 100,
|
|
467
|
+
* y: 200,
|
|
468
|
+
* width: 50,
|
|
469
|
+
* height: 50,
|
|
470
|
+
* name: "temp-zone"
|
|
471
|
+
* });
|
|
472
|
+
*
|
|
473
|
+
* // Later, remove it
|
|
474
|
+
* map.removeShape("temp-zone");
|
|
475
|
+
* ```
|
|
476
|
+
*/
|
|
477
|
+
removeShape(name: string): void;
|
|
478
|
+
/**
|
|
479
|
+
* Get all shapes on the map
|
|
480
|
+
*
|
|
481
|
+
* Returns an array of all shapes that have been created on this map,
|
|
482
|
+
* regardless of whether they are static shapes or player-attached shapes.
|
|
483
|
+
*
|
|
484
|
+
* @returns Array of RpgShape instances
|
|
485
|
+
*
|
|
486
|
+
* @example
|
|
487
|
+
* ```ts
|
|
488
|
+
* // Create multiple shapes
|
|
489
|
+
* map.createShape({ x: 0, y: 0, width: 50, height: 50, name: "zone1" });
|
|
490
|
+
* map.createShape({ x: 100, y: 100, width: 50, height: 50, name: "zone2" });
|
|
491
|
+
*
|
|
492
|
+
* // Get all shapes
|
|
493
|
+
* const allShapes = map.getShapes();
|
|
494
|
+
* console.log(allShapes.length); // 2
|
|
495
|
+
* ```
|
|
496
|
+
*/
|
|
497
|
+
getShapes(): RpgShape[];
|
|
498
|
+
/**
|
|
499
|
+
* Get a shape by its name
|
|
500
|
+
*
|
|
501
|
+
* Returns a shape with the specified name, or undefined if no shape
|
|
502
|
+
* with that name exists on the map.
|
|
503
|
+
*
|
|
504
|
+
* @param name - Name of the shape to retrieve
|
|
505
|
+
* @returns The RpgShape instance, or undefined if not found
|
|
506
|
+
*
|
|
507
|
+
* @example
|
|
508
|
+
* ```ts
|
|
509
|
+
* // Create a shape with a specific name
|
|
510
|
+
* map.createShape({
|
|
511
|
+
* x: 100,
|
|
512
|
+
* y: 200,
|
|
513
|
+
* width: 50,
|
|
514
|
+
* height: 50,
|
|
515
|
+
* name: "spawn-point"
|
|
516
|
+
* });
|
|
517
|
+
*
|
|
518
|
+
* // Retrieve it later
|
|
519
|
+
* const spawnZone = map.getShape("spawn-point");
|
|
520
|
+
* if (spawnZone) {
|
|
521
|
+
* console.log(`Spawn zone at (${spawnZone.x}, ${spawnZone.y})`);
|
|
522
|
+
* }
|
|
523
|
+
* ```
|
|
524
|
+
*/
|
|
525
|
+
getShape(name: string): RpgShape | undefined;
|
|
526
|
+
/**
|
|
527
|
+
* Play a sound for all players on the map
|
|
528
|
+
*
|
|
529
|
+
* This method plays a sound for all players currently on the map by iterating
|
|
530
|
+
* over each player and calling `player.playSound()`. The sound must be defined
|
|
531
|
+
* on the client side (in the client module configuration).
|
|
532
|
+
* This is ideal for environmental sounds, battle music, or map-wide events that
|
|
533
|
+
* all players should hear simultaneously.
|
|
534
|
+
*
|
|
535
|
+
* ## Design
|
|
536
|
+
*
|
|
537
|
+
* Iterates over all players on the map and calls `player.playSound()` for each one.
|
|
538
|
+
* This avoids code duplication and reuses the existing player sound logic.
|
|
539
|
+
* For player-specific sounds, use `player.playSound()` directly.
|
|
540
|
+
*
|
|
541
|
+
* @param soundId - Sound identifier, defined on the client side
|
|
542
|
+
* @param options - Optional sound configuration
|
|
543
|
+
* @param options.volume - Volume level (0.0 to 1.0, default: 1.0)
|
|
544
|
+
* @param options.loop - Whether the sound should loop (default: false)
|
|
545
|
+
*
|
|
546
|
+
* @example
|
|
547
|
+
* ```ts
|
|
548
|
+
* // Play a sound for all players on the map
|
|
549
|
+
* map.playSound("explosion");
|
|
550
|
+
*
|
|
551
|
+
* // Play background music for everyone with volume and loop
|
|
552
|
+
* map.playSound("battle-theme", {
|
|
553
|
+
* volume: 0.7,
|
|
554
|
+
* loop: true
|
|
555
|
+
* });
|
|
556
|
+
*
|
|
557
|
+
* // Play a door opening sound at low volume
|
|
558
|
+
* map.playSound("door-open", { volume: 0.4 });
|
|
559
|
+
* ```
|
|
560
|
+
*/
|
|
561
|
+
playSound(soundId: string, options?: {
|
|
562
|
+
volume?: number;
|
|
563
|
+
loop?: boolean;
|
|
564
|
+
}): void;
|
|
565
|
+
/**
|
|
566
|
+
* Stop a sound for all players on the map
|
|
567
|
+
*
|
|
568
|
+
* This method stops a sound that was previously started with `map.playSound()`
|
|
569
|
+
* for all players on the map by iterating over each player and calling `player.stopSound()`.
|
|
570
|
+
*
|
|
571
|
+
* @param soundId - Sound identifier to stop
|
|
572
|
+
*
|
|
573
|
+
* @example
|
|
574
|
+
* ```ts
|
|
575
|
+
* // Start background music for everyone
|
|
576
|
+
* map.playSound("battle-theme", { loop: true });
|
|
577
|
+
*
|
|
578
|
+
* // Later, stop it for everyone
|
|
579
|
+
* map.stopSound("battle-theme");
|
|
580
|
+
* ```
|
|
581
|
+
*/
|
|
582
|
+
stopSound(soundId: string): void;
|
|
106
583
|
}
|
|
107
584
|
export interface RpgMap {
|
|
108
585
|
$send: (conn: MockConnection, data: any) => void;
|
|
109
586
|
$broadcast: (data: any) => void;
|
|
587
|
+
$sessionTransfer: (userOrPublicId: any | string, targetRoomId: string) => void;
|
|
110
588
|
}
|
package/package.json
CHANGED
|
@@ -1,31 +1,33 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rpgjs/server",
|
|
3
|
-
"version": "5.0.0-alpha.
|
|
3
|
+
"version": "5.0.0-alpha.20",
|
|
4
4
|
"main": "./dist/index.js",
|
|
5
5
|
"types": "./dist/index.d.ts",
|
|
6
6
|
"publishConfig": {
|
|
7
7
|
"access": "public"
|
|
8
8
|
},
|
|
9
|
-
"scripts": {
|
|
10
|
-
"dev": "vite build --watch",
|
|
11
|
-
"build": "vite build"
|
|
12
|
-
},
|
|
13
9
|
"keywords": [],
|
|
14
10
|
"author": "",
|
|
15
11
|
"license": "MIT",
|
|
16
12
|
"description": "",
|
|
17
13
|
"dependencies": {
|
|
18
|
-
"@rpgjs/common": "
|
|
14
|
+
"@rpgjs/common": "5.0.0-alpha.20",
|
|
15
|
+
"@rpgjs/physic": "5.0.0-alpha.20",
|
|
19
16
|
"@rpgjs/database": "^4.3.0",
|
|
20
|
-
"@signe/di": "^2.
|
|
21
|
-
"@signe/reactive": "^2.
|
|
22
|
-
"@signe/room": "^2.
|
|
23
|
-
"@signe/sync": "^2.
|
|
24
|
-
"rxjs": "^7.8.2"
|
|
17
|
+
"@signe/di": "^2.5.1",
|
|
18
|
+
"@signe/reactive": "^2.5.1",
|
|
19
|
+
"@signe/room": "^2.5.1",
|
|
20
|
+
"@signe/sync": "^2.5.1",
|
|
21
|
+
"rxjs": "^7.8.2",
|
|
22
|
+
"zod": "^4.1.13"
|
|
25
23
|
},
|
|
26
24
|
"devDependencies": {
|
|
27
|
-
"vite": "^
|
|
28
|
-
"vite-plugin-dts": "^4.5.
|
|
25
|
+
"vite": "^7.2.4",
|
|
26
|
+
"vite-plugin-dts": "^4.5.4"
|
|
29
27
|
},
|
|
30
|
-
"type": "module"
|
|
31
|
-
|
|
28
|
+
"type": "module",
|
|
29
|
+
"scripts": {
|
|
30
|
+
"dev": "vite build --watch",
|
|
31
|
+
"build": "vite build"
|
|
32
|
+
}
|
|
33
|
+
}
|
package/src/Gui/DialogGui.ts
CHANGED
|
@@ -18,7 +18,11 @@ export interface DialogOptions {
|
|
|
18
18
|
autoClose?: boolean,
|
|
19
19
|
tranparent?: boolean,
|
|
20
20
|
typewriterEffect?: boolean,
|
|
21
|
-
talkWith?: RpgPlayer
|
|
21
|
+
talkWith?: RpgPlayer,
|
|
22
|
+
face?: {
|
|
23
|
+
id: string,
|
|
24
|
+
expression: string
|
|
25
|
+
},
|
|
22
26
|
}
|
|
23
27
|
|
|
24
28
|
export class DialogGui extends Gui {
|
|
@@ -47,7 +51,8 @@ export class DialogGui extends Gui {
|
|
|
47
51
|
// remove value property. It is not useful to know this on the client side.
|
|
48
52
|
choices: options.choices.map(choice => ({
|
|
49
53
|
text: choice.text
|
|
50
|
-
}))
|
|
54
|
+
})),
|
|
55
|
+
face: options.face
|
|
51
56
|
}
|
|
52
57
|
return super.open({
|
|
53
58
|
message,
|