@rpgjs/client 5.0.0-beta.11 → 5.0.0-beta.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/dist/Game/AnimationManager.d.ts +1 -0
- package/dist/Game/AnimationManager.js +3 -0
- package/dist/Game/AnimationManager.js.map +1 -1
- package/dist/Game/ClientVisuals.d.ts +61 -0
- package/dist/Game/ClientVisuals.js +96 -0
- package/dist/Game/ClientVisuals.js.map +1 -0
- package/dist/Game/ClientVisuals.spec.d.ts +1 -0
- package/dist/Game/EventComponentResolver.d.ts +16 -0
- package/dist/Game/EventComponentResolver.js +52 -0
- package/dist/Game/EventComponentResolver.js.map +1 -0
- package/dist/Game/EventComponentResolver.spec.d.ts +1 -0
- package/dist/Game/Map.js +9 -0
- package/dist/Game/Map.js.map +1 -1
- package/dist/Game/Object.js +2 -2
- package/dist/Game/Object.js.map +1 -1
- package/dist/Game/Object.spec.d.ts +1 -0
- package/dist/Game/ProjectileManager.d.ts +11 -2
- package/dist/Game/ProjectileManager.js +19 -2
- package/dist/Game/ProjectileManager.js.map +1 -1
- package/dist/RpgClient.d.ts +64 -0
- package/dist/RpgClientEngine.d.ts +57 -0
- package/dist/RpgClientEngine.js +110 -14
- package/dist/RpgClientEngine.js.map +1 -1
- package/dist/components/animations/fx.ce.js +58 -0
- package/dist/components/animations/fx.ce.js.map +1 -0
- package/dist/components/animations/index.d.ts +1 -0
- package/dist/components/animations/index.js +3 -1
- package/dist/components/animations/index.js.map +1 -1
- package/dist/components/character.ce.js +111 -13
- package/dist/components/character.ce.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +3 -2
- package/dist/module.js +7 -0
- package/dist/module.js.map +1 -1
- package/dist/services/actionInput.d.ts +3 -1
- package/dist/services/actionInput.js +33 -1
- package/dist/services/actionInput.js.map +1 -1
- package/dist/services/standalone.d.ts +3 -1
- package/dist/services/standalone.js +31 -13
- package/dist/services/standalone.js.map +1 -1
- package/dist/utils/mapId.d.ts +1 -0
- package/dist/utils/mapId.js +6 -0
- package/dist/utils/mapId.js.map +1 -0
- package/package.json +3 -3
- package/src/Game/AnimationManager.ts +4 -0
- package/src/Game/ClientVisuals.spec.ts +56 -0
- package/src/Game/ClientVisuals.ts +184 -0
- package/src/Game/EventComponentResolver.spec.ts +84 -0
- package/src/Game/EventComponentResolver.ts +74 -0
- package/src/Game/Map.ts +10 -0
- package/src/Game/Object.spec.ts +46 -0
- package/src/Game/Object.ts +2 -2
- package/src/Game/ProjectileManager.spec.ts +111 -0
- package/src/Game/ProjectileManager.ts +24 -2
- package/src/RpgClient.ts +68 -0
- package/src/RpgClientEngine.ts +130 -16
- package/src/components/animations/fx.ce +101 -0
- package/src/components/animations/index.ts +4 -2
- package/src/components/character.ce +154 -11
- package/src/index.ts +1 -0
- package/src/module.ts +11 -0
- package/src/services/actionInput.spec.ts +54 -0
- package/src/services/actionInput.ts +68 -1
- package/src/services/standalone.ts +39 -10
- package/src/utils/mapId.ts +2 -0
package/dist/RpgClient.d.ts
CHANGED
|
@@ -2,8 +2,10 @@ import { ComponentFunction, Signal } from 'canvasengine';
|
|
|
2
2
|
import { RpgClientEngine } from './RpgClientEngine';
|
|
3
3
|
import { Loader, Container } from 'pixi.js';
|
|
4
4
|
import { RpgClientObject } from './Game/Object';
|
|
5
|
+
import { RpgClientEvent } from './Game/Event';
|
|
5
6
|
import { MapPhysicsEntityContext, MapPhysicsInitContext, RpgActionName } from '@rpgjs/common';
|
|
6
7
|
import { ClientProjectileSpawn, RenderedProjectileProps } from './Game/ProjectileManager';
|
|
8
|
+
import { ClientVisualMap } from './Game/ClientVisuals';
|
|
7
9
|
type RpgComponent = RpgClientObject;
|
|
8
10
|
type SceneMap = Container;
|
|
9
11
|
export type SpriteComponentConfig = ComponentFunction | {
|
|
@@ -12,6 +14,14 @@ export type SpriteComponentConfig = ComponentFunction | {
|
|
|
12
14
|
data?: Record<string, any> | ((object: RpgClientObject) => Record<string, any>);
|
|
13
15
|
dependencies?: (object: RpgClientObject) => any[];
|
|
14
16
|
};
|
|
17
|
+
export type EventComponentSprite = RpgClientEvent & Record<string, any>;
|
|
18
|
+
export type EventComponentConfig = ComponentFunction | {
|
|
19
|
+
component: ComponentFunction;
|
|
20
|
+
props?: Record<string, any> | ((event: EventComponentSprite) => Record<string, any>);
|
|
21
|
+
data?: Record<string, any> | ((event: EventComponentSprite) => Record<string, any>);
|
|
22
|
+
dependencies?: (event: EventComponentSprite) => any[];
|
|
23
|
+
renderGraphic?: boolean;
|
|
24
|
+
};
|
|
15
25
|
export interface RpgSpriteBeforeRemoveContext {
|
|
16
26
|
reason?: string;
|
|
17
27
|
data?: any;
|
|
@@ -131,6 +141,30 @@ export interface RpgSpriteHooks {
|
|
|
131
141
|
* ```
|
|
132
142
|
*/
|
|
133
143
|
components?: Record<string, ComponentFunction>;
|
|
144
|
+
/**
|
|
145
|
+
* Resolve a custom CanvasEngine component for a specific event.
|
|
146
|
+
*
|
|
147
|
+
* The component always receives the synced event object as the `sprite` prop.
|
|
148
|
+
* Custom props are merged in addition to `sprite`, but cannot replace it.
|
|
149
|
+
* Return `null` or `undefined` to keep the default graphic renderer.
|
|
150
|
+
*
|
|
151
|
+
* @prop { (event: EventComponentSprite) => EventComponentConfig | null | undefined } [eventComponent]
|
|
152
|
+
* @memberof RpgSpriteHooks
|
|
153
|
+
* @example
|
|
154
|
+
* ```ts
|
|
155
|
+
* import ChestEvent from './components/chest-event.ce'
|
|
156
|
+
*
|
|
157
|
+
* const sprite: RpgSpriteHooks = {
|
|
158
|
+
* eventComponent(sprite) {
|
|
159
|
+
* if (sprite.name === 'CHEST') {
|
|
160
|
+
* return ChestEvent
|
|
161
|
+
* }
|
|
162
|
+
* return null
|
|
163
|
+
* }
|
|
164
|
+
* }
|
|
165
|
+
* ```
|
|
166
|
+
*/
|
|
167
|
+
eventComponent?: (event: EventComponentSprite) => EventComponentConfig | null | undefined;
|
|
134
168
|
/**
|
|
135
169
|
* As soon as the sprite is initialized
|
|
136
170
|
*
|
|
@@ -675,6 +709,36 @@ export interface RpgClient {
|
|
|
675
709
|
id: string;
|
|
676
710
|
component: ComponentFunction;
|
|
677
711
|
}[];
|
|
712
|
+
/**
|
|
713
|
+
* Named client-side visual macros.
|
|
714
|
+
*
|
|
715
|
+
* Use client visuals when the server needs to trigger a group of existing
|
|
716
|
+
* client visual primitives at once, such as a flash, damage text, sound,
|
|
717
|
+
* component animation, and camera shake. The server sends only the visual
|
|
718
|
+
* name and a serializable payload; the rendering details live on the client.
|
|
719
|
+
*
|
|
720
|
+
* For a single sound, flash, or component animation, prefer the direct
|
|
721
|
+
* server APIs (`playSound`, `flash`, `showComponentAnimation`). Client
|
|
722
|
+
* visuals are meant to group several visual operations and reduce bandwidth.
|
|
723
|
+
*
|
|
724
|
+
* ```ts
|
|
725
|
+
* import { defineModule, RpgClient } from '@rpgjs/client'
|
|
726
|
+
*
|
|
727
|
+
* export default defineModule<RpgClient>({
|
|
728
|
+
* clientVisuals: {
|
|
729
|
+
* hit({ target, data }, helpers) {
|
|
730
|
+
* helpers.flash(target, { type: 'tint', tint: 'red' })
|
|
731
|
+
* helpers.showHit(target, `-${data.damage}`)
|
|
732
|
+
* helpers.sound('hit')
|
|
733
|
+
* }
|
|
734
|
+
* }
|
|
735
|
+
* })
|
|
736
|
+
* ```
|
|
737
|
+
*
|
|
738
|
+
* @prop {Record<string, ClientVisualHandler>} [clientVisuals]
|
|
739
|
+
* @memberof RpgClient
|
|
740
|
+
*/
|
|
741
|
+
clientVisuals?: ClientVisualMap;
|
|
678
742
|
/**
|
|
679
743
|
* Client-side projectile rendering configuration.
|
|
680
744
|
*
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import { Trigger } from 'canvasengine';
|
|
2
2
|
import { AbstractWebsocket } from './services/AbstractSocket';
|
|
3
3
|
import { Direction, RpgActionInput, RpgActionName } from '@rpgjs/common';
|
|
4
|
+
import { EventComponentConfig } from './RpgClient';
|
|
5
|
+
import { RpgClientEvent } from './Game/Event';
|
|
4
6
|
import { RpgClientMap } from './Game/Map';
|
|
5
7
|
import { AnimationManager } from './Game/AnimationManager';
|
|
6
8
|
import { Observable } from 'rxjs';
|
|
7
9
|
import { ProjectileManager } from './Game/ProjectileManager';
|
|
10
|
+
import { ClientVisualRegistry, ClientVisualHandler, ClientVisualMap, ClientVisualPacket } from './Game/ClientVisuals';
|
|
8
11
|
import { ClientPointerContext } from './services/pointerContext';
|
|
12
|
+
import { EventComponentResolver } from './Game/EventComponentResolver';
|
|
9
13
|
import * as PIXI from "pixi.js";
|
|
10
14
|
type ConfigurableTrigger<T> = Omit<Trigger<T>, "start"> & {
|
|
11
15
|
start(config?: T): Promise<void>;
|
|
@@ -33,6 +37,7 @@ export declare class RpgClientEngine<T = any> {
|
|
|
33
37
|
spritesheets: Map<string | number, any>;
|
|
34
38
|
sounds: Map<string, any>;
|
|
35
39
|
componentAnimations: any[];
|
|
40
|
+
clientVisuals: ClientVisualRegistry;
|
|
36
41
|
projectiles: ProjectileManager;
|
|
37
42
|
pointer: ClientPointerContext;
|
|
38
43
|
private spritesheetResolver?;
|
|
@@ -48,6 +53,7 @@ export declare class RpgClientEngine<T = any> {
|
|
|
48
53
|
spriteComponentsBehind: import('canvasengine').WritableArraySignal<any[]>;
|
|
49
54
|
spriteComponentsInFront: import('canvasengine').WritableArraySignal<any[]>;
|
|
50
55
|
spriteComponents: Map<string, any>;
|
|
56
|
+
private eventComponentResolvers;
|
|
51
57
|
/** ID of the sprite that the camera should follow. null means follow the current player */
|
|
52
58
|
cameraFollowTargetId: import('canvasengine').WritableSignal<string | null>;
|
|
53
59
|
/** Trigger for map shake animation */
|
|
@@ -77,6 +83,9 @@ export declare class RpgClientEngine<T = any> {
|
|
|
77
83
|
private eventsReceived$;
|
|
78
84
|
private onAfterLoadingSubscription?;
|
|
79
85
|
private sceneResetQueued;
|
|
86
|
+
private mapTransitionInProgress;
|
|
87
|
+
private currentMapRoomId?;
|
|
88
|
+
private socketListenersInitialized;
|
|
80
89
|
private tickSubscriptions;
|
|
81
90
|
private resizeHandler?;
|
|
82
91
|
private pointerMoveHandler?;
|
|
@@ -125,6 +134,9 @@ export declare class RpgClientEngine<T = any> {
|
|
|
125
134
|
private prepareSyncPayload;
|
|
126
135
|
private normalizeAckWithSyncState;
|
|
127
136
|
private initListeners;
|
|
137
|
+
private beginMapTransfer;
|
|
138
|
+
private clearComponentAnimations;
|
|
139
|
+
private shouldProcessProjectilePacket;
|
|
128
140
|
private callConnectError;
|
|
129
141
|
private flushPendingSyncPackets;
|
|
130
142
|
private applySyncPacket;
|
|
@@ -502,8 +514,52 @@ export declare class RpgClientEngine<T = any> {
|
|
|
502
514
|
* @returns The CanvasEngine component, or undefined when missing
|
|
503
515
|
*/
|
|
504
516
|
getSpriteComponent(id: string): any;
|
|
517
|
+
/**
|
|
518
|
+
* Register a custom event component resolver.
|
|
519
|
+
*
|
|
520
|
+
* The last resolver returning a component wins. This lets later modules
|
|
521
|
+
* override earlier defaults without replacing the whole map scene.
|
|
522
|
+
*
|
|
523
|
+
* @param resolver - Function receiving the synced event object
|
|
524
|
+
* @returns The registered resolver
|
|
525
|
+
*/
|
|
526
|
+
addEventComponentResolver(resolver: EventComponentResolver): EventComponentResolver;
|
|
527
|
+
/**
|
|
528
|
+
* Resolve the custom CanvasEngine component for an event, if any.
|
|
529
|
+
*
|
|
530
|
+
* @param event - Synced client event object
|
|
531
|
+
* @returns The component/config returned by the last matching resolver
|
|
532
|
+
*/
|
|
533
|
+
resolveEventComponent(event: RpgClientEvent): EventComponentConfig | null;
|
|
505
534
|
registerProjectileComponent(type: string, component: any): any;
|
|
506
535
|
getProjectileComponent(type: string): any;
|
|
536
|
+
/**
|
|
537
|
+
* Register a named client visual macro.
|
|
538
|
+
*
|
|
539
|
+
* Client visuals are small client-side functions that group existing visual
|
|
540
|
+
* primitives such as flash, sound, component animations, sprite animation, or
|
|
541
|
+
* map shake. The server sends only the visual name and a serializable payload.
|
|
542
|
+
*
|
|
543
|
+
* @param name - Stable visual name sent by the server
|
|
544
|
+
* @param handler - Client-side visual handler
|
|
545
|
+
* @returns The registered handler
|
|
546
|
+
*/
|
|
547
|
+
registerClientVisual(name: string, handler: ClientVisualHandler): ClientVisualHandler;
|
|
548
|
+
/**
|
|
549
|
+
* Register several named client visual macros.
|
|
550
|
+
*
|
|
551
|
+
* @param visuals - Map of visual names to client-side handlers
|
|
552
|
+
*/
|
|
553
|
+
registerClientVisuals(visuals: ClientVisualMap): void;
|
|
554
|
+
/**
|
|
555
|
+
* Play a registered client visual locally.
|
|
556
|
+
*
|
|
557
|
+
* This is also used by the websocket listener when the server calls
|
|
558
|
+
* `player.clientVisual()` or `map.clientVisual()`.
|
|
559
|
+
*
|
|
560
|
+
* @param packet - Visual name and serializable payload
|
|
561
|
+
*/
|
|
562
|
+
playClientVisual(packet: ClientVisualPacket): Promise<void>;
|
|
507
563
|
/**
|
|
508
564
|
* Add a component animation to the engine
|
|
509
565
|
*
|
|
@@ -588,6 +644,7 @@ export declare class RpgClientEngine<T = any> {
|
|
|
588
644
|
get socket(): AbstractWebsocket;
|
|
589
645
|
get playerId(): string | null;
|
|
590
646
|
get scene(): RpgClientMap;
|
|
647
|
+
getObjectById(id: string): any;
|
|
591
648
|
private getPhysicsTick;
|
|
592
649
|
private getPhysicsTickDurationMs;
|
|
593
650
|
private updateServerTickEstimate;
|
package/dist/RpgClientEngine.js
CHANGED
|
@@ -19,8 +19,11 @@ import __ce_component$3 from "./components/dynamics/bar.ce.js";
|
|
|
19
19
|
import __ce_component$4 from "./components/dynamics/shape.ce.js";
|
|
20
20
|
import __ce_component$5 from "./components/dynamics/image.ce.js";
|
|
21
21
|
import { NotificationManager } from "./Gui/NotificationManager.js";
|
|
22
|
+
import { normalizeRoomMapId } from "./utils/mapId.js";
|
|
22
23
|
import { ProjectileManager } from "./Game/ProjectileManager.js";
|
|
24
|
+
import { ClientVisualRegistry } from "./Game/ClientVisuals.js";
|
|
23
25
|
import { createClientPointerContext } from "./services/pointerContext.js";
|
|
26
|
+
import { EventComponentResolverRegistry } from "./Game/EventComponentResolver.js";
|
|
24
27
|
import { Howl, bootstrapCanvas, signal, trigger } from "canvasengine";
|
|
25
28
|
import { Direction, ModulesToken, PredictionController, Vector2, normalizeLightingState } from "@rpgjs/common";
|
|
26
29
|
import { BehaviorSubject, combineLatest, filter, lastValueFrom, switchMap, take } from "rxjs";
|
|
@@ -36,12 +39,14 @@ var RpgClientEngine = class {
|
|
|
36
39
|
this.spritesheets = /* @__PURE__ */ new Map();
|
|
37
40
|
this.sounds = /* @__PURE__ */ new Map();
|
|
38
41
|
this.componentAnimations = [];
|
|
42
|
+
this.clientVisuals = new ClientVisualRegistry();
|
|
39
43
|
this.pointer = createClientPointerContext();
|
|
40
44
|
this.particleSettings = { emitters: [] };
|
|
41
45
|
this.playerIdSignal = signal(null);
|
|
42
46
|
this.spriteComponentsBehind = signal([]);
|
|
43
47
|
this.spriteComponentsInFront = signal([]);
|
|
44
48
|
this.spriteComponents = /* @__PURE__ */ new Map();
|
|
49
|
+
this.eventComponentResolvers = new EventComponentResolverRegistry();
|
|
45
50
|
this.cameraFollowTargetId = signal(null);
|
|
46
51
|
this.mapShakeTrigger = trigger();
|
|
47
52
|
this.controlsReady = signal(void 0);
|
|
@@ -66,6 +71,8 @@ var RpgClientEngine = class {
|
|
|
66
71
|
this.playersReceived$ = new BehaviorSubject(false);
|
|
67
72
|
this.eventsReceived$ = new BehaviorSubject(false);
|
|
68
73
|
this.sceneResetQueued = false;
|
|
74
|
+
this.mapTransitionInProgress = false;
|
|
75
|
+
this.socketListenersInitialized = false;
|
|
69
76
|
this.tickSubscriptions = [];
|
|
70
77
|
this.pendingSyncPackets = [];
|
|
71
78
|
this.notificationManager = new NotificationManager();
|
|
@@ -178,6 +185,7 @@ var RpgClientEngine = class {
|
|
|
178
185
|
this.hooks.callHooks("client-gui-load", this).subscribe();
|
|
179
186
|
this.hooks.callHooks("client-particles-load", this).subscribe();
|
|
180
187
|
this.hooks.callHooks("client-componentAnimations-load", this).subscribe();
|
|
188
|
+
this.hooks.callHooks("client-clientVisuals-load", this).subscribe();
|
|
181
189
|
this.hooks.callHooks("client-projectiles-load", this).subscribe();
|
|
182
190
|
this.hooks.callHooks("client-sprite-load", this).subscribe();
|
|
183
191
|
await lastValueFrom(this.hooks.callHooks("client-engine-onStart", this));
|
|
@@ -271,6 +279,8 @@ var RpgClientEngine = class {
|
|
|
271
279
|
};
|
|
272
280
|
}
|
|
273
281
|
initListeners() {
|
|
282
|
+
if (this.socketListenersInitialized) return;
|
|
283
|
+
this.socketListenersInitialized = true;
|
|
274
284
|
this.webSocket.on("sync", (data) => {
|
|
275
285
|
if (!this.tick) {
|
|
276
286
|
this.pendingSyncPackets.push(data);
|
|
@@ -288,12 +298,8 @@ var RpgClientEngine = class {
|
|
|
288
298
|
console.debug(`[Ping/Pong] RTT: ${this.rtt}ms, ServerTick: ${data.serverTick}, FrameOffset: ${this.frameOffset}`);
|
|
289
299
|
});
|
|
290
300
|
this.webSocket.on("changeMap", (data) => {
|
|
291
|
-
|
|
292
|
-
this.
|
|
293
|
-
this.sceneMap.lightingState.set(null);
|
|
294
|
-
this.sceneMap.clearLightSpots();
|
|
295
|
-
this.projectiles.clear();
|
|
296
|
-
this.cameraFollowTargetId.set(null);
|
|
301
|
+
const nextMapId = typeof data?.mapId === "string" ? data.mapId : void 0;
|
|
302
|
+
this.beginMapTransfer(nextMapId);
|
|
297
303
|
const transferToken = typeof data?.transferToken === "string" ? data.transferToken : void 0;
|
|
298
304
|
this.loadScene(data.mapId, transferToken);
|
|
299
305
|
});
|
|
@@ -303,19 +309,27 @@ var RpgClientEngine = class {
|
|
|
303
309
|
const player = object ? this.sceneMap.getObjectById(object) : void 0;
|
|
304
310
|
this.getComponentAnimation(id).displayEffect(params, player || position);
|
|
305
311
|
});
|
|
312
|
+
this.webSocket.on("clientVisual", (data) => {
|
|
313
|
+
this.playClientVisual(data);
|
|
314
|
+
});
|
|
306
315
|
this.webSocket.on("projectile:spawnBatch", (data) => {
|
|
316
|
+
if (!this.shouldProcessProjectilePacket(data)) return;
|
|
307
317
|
this.projectiles.spawnBatch(data?.projectiles ?? [], {
|
|
318
|
+
mapId: data?.mapId,
|
|
308
319
|
currentServerTick: this.estimateServerTick(),
|
|
309
320
|
tickDurationMs: this.getPhysicsTickDurationMs()
|
|
310
321
|
});
|
|
311
322
|
});
|
|
312
323
|
this.webSocket.on("projectile:impactBatch", (data) => {
|
|
313
|
-
this.
|
|
324
|
+
if (!this.shouldProcessProjectilePacket(data)) return;
|
|
325
|
+
this.projectiles.impactBatch(data?.impacts ?? [], { mapId: data?.mapId });
|
|
314
326
|
});
|
|
315
327
|
this.webSocket.on("projectile:destroyBatch", (data) => {
|
|
316
|
-
this.
|
|
328
|
+
if (!this.shouldProcessProjectilePacket(data)) return;
|
|
329
|
+
this.projectiles.destroyBatch(data?.projectiles ?? [], { mapId: data?.mapId });
|
|
317
330
|
});
|
|
318
|
-
this.webSocket.on("projectile:clear", () => {
|
|
331
|
+
this.webSocket.on("projectile:clear", (data) => {
|
|
332
|
+
if (!this.shouldProcessProjectilePacket(data)) return;
|
|
319
333
|
this.projectiles.clear();
|
|
320
334
|
});
|
|
321
335
|
this.webSocket.on("notification", (data) => {
|
|
@@ -408,6 +422,31 @@ var RpgClientEngine = class {
|
|
|
408
422
|
this.callConnectError(error);
|
|
409
423
|
});
|
|
410
424
|
}
|
|
425
|
+
beginMapTransfer(nextMapId) {
|
|
426
|
+
this.mapTransitionInProgress = true;
|
|
427
|
+
this.currentMapRoomId = nextMapId;
|
|
428
|
+
this.sceneResetQueued = false;
|
|
429
|
+
this.clearClientPredictionStates();
|
|
430
|
+
this.sceneMap.weatherState.set(null);
|
|
431
|
+
this.sceneMap.lightingState.set(null);
|
|
432
|
+
this.sceneMap.clearLightSpots();
|
|
433
|
+
this.clearComponentAnimations();
|
|
434
|
+
this.projectiles.setMapId(nextMapId);
|
|
435
|
+
this.cameraFollowTargetId.set(null);
|
|
436
|
+
this.sceneMap.reset();
|
|
437
|
+
this.sceneMap.loadPhysic();
|
|
438
|
+
}
|
|
439
|
+
clearComponentAnimations() {
|
|
440
|
+
this.componentAnimations.forEach((componentAnimation) => {
|
|
441
|
+
componentAnimation.instance?.clear?.();
|
|
442
|
+
});
|
|
443
|
+
}
|
|
444
|
+
shouldProcessProjectilePacket(data) {
|
|
445
|
+
if (this.mapTransitionInProgress) return false;
|
|
446
|
+
const packetMapId = normalizeRoomMapId(typeof data?.mapId === "string" ? data.mapId : void 0);
|
|
447
|
+
const currentMapId = normalizeRoomMapId(this.currentMapRoomId);
|
|
448
|
+
return !packetMapId || !currentMapId || packetMapId === currentMapId;
|
|
449
|
+
}
|
|
411
450
|
async callConnectError(error) {
|
|
412
451
|
await lastValueFrom(this.hooks.callHooks("client-engine-onConnectError", this, error, this.socket));
|
|
413
452
|
}
|
|
@@ -522,12 +561,9 @@ var RpgClientEngine = class {
|
|
|
522
561
|
query: transferToken ? { transferToken } : void 0
|
|
523
562
|
});
|
|
524
563
|
try {
|
|
525
|
-
await this.webSocket.reconnect(
|
|
526
|
-
inject(SaveClientService).initialize();
|
|
527
|
-
this.initListeners();
|
|
528
|
-
this.guiService._initialize();
|
|
529
|
-
});
|
|
564
|
+
await this.webSocket.reconnect();
|
|
530
565
|
} catch (error) {
|
|
566
|
+
this.mapTransitionInProgress = false;
|
|
531
567
|
this.stopPingPong();
|
|
532
568
|
await this.callConnectError(error);
|
|
533
569
|
throw error;
|
|
@@ -539,6 +575,8 @@ var RpgClientEngine = class {
|
|
|
539
575
|
if (players && Object.keys(players).length > 0) this.playersReceived$.next(true);
|
|
540
576
|
if (this.sceneMap.events() !== void 0) this.eventsReceived$.next(true);
|
|
541
577
|
this.mapLoadCompleted$.next(true);
|
|
578
|
+
this.currentMapRoomId = mapId;
|
|
579
|
+
this.mapTransitionInProgress = false;
|
|
542
580
|
this.sceneMap.configureClientPrediction(this.predictionEnabled);
|
|
543
581
|
this.sceneMap.loadPhysic();
|
|
544
582
|
}
|
|
@@ -960,6 +998,27 @@ var RpgClientEngine = class {
|
|
|
960
998
|
getSpriteComponent(id) {
|
|
961
999
|
return this.spriteComponents.get(id);
|
|
962
1000
|
}
|
|
1001
|
+
/**
|
|
1002
|
+
* Register a custom event component resolver.
|
|
1003
|
+
*
|
|
1004
|
+
* The last resolver returning a component wins. This lets later modules
|
|
1005
|
+
* override earlier defaults without replacing the whole map scene.
|
|
1006
|
+
*
|
|
1007
|
+
* @param resolver - Function receiving the synced event object
|
|
1008
|
+
* @returns The registered resolver
|
|
1009
|
+
*/
|
|
1010
|
+
addEventComponentResolver(resolver) {
|
|
1011
|
+
return this.eventComponentResolvers.add(resolver);
|
|
1012
|
+
}
|
|
1013
|
+
/**
|
|
1014
|
+
* Resolve the custom CanvasEngine component for an event, if any.
|
|
1015
|
+
*
|
|
1016
|
+
* @param event - Synced client event object
|
|
1017
|
+
* @returns The component/config returned by the last matching resolver
|
|
1018
|
+
*/
|
|
1019
|
+
resolveEventComponent(event) {
|
|
1020
|
+
return this.eventComponentResolvers.resolve(event);
|
|
1021
|
+
}
|
|
963
1022
|
registerProjectileComponent(type, component) {
|
|
964
1023
|
return this.projectiles.register(type, component);
|
|
965
1024
|
}
|
|
@@ -967,6 +1026,39 @@ var RpgClientEngine = class {
|
|
|
967
1026
|
return this.projectiles.get(type);
|
|
968
1027
|
}
|
|
969
1028
|
/**
|
|
1029
|
+
* Register a named client visual macro.
|
|
1030
|
+
*
|
|
1031
|
+
* Client visuals are small client-side functions that group existing visual
|
|
1032
|
+
* primitives such as flash, sound, component animations, sprite animation, or
|
|
1033
|
+
* map shake. The server sends only the visual name and a serializable payload.
|
|
1034
|
+
*
|
|
1035
|
+
* @param name - Stable visual name sent by the server
|
|
1036
|
+
* @param handler - Client-side visual handler
|
|
1037
|
+
* @returns The registered handler
|
|
1038
|
+
*/
|
|
1039
|
+
registerClientVisual(name, handler) {
|
|
1040
|
+
return this.clientVisuals.register(name, handler);
|
|
1041
|
+
}
|
|
1042
|
+
/**
|
|
1043
|
+
* Register several named client visual macros.
|
|
1044
|
+
*
|
|
1045
|
+
* @param visuals - Map of visual names to client-side handlers
|
|
1046
|
+
*/
|
|
1047
|
+
registerClientVisuals(visuals) {
|
|
1048
|
+
this.clientVisuals.registerMany(visuals);
|
|
1049
|
+
}
|
|
1050
|
+
/**
|
|
1051
|
+
* Play a registered client visual locally.
|
|
1052
|
+
*
|
|
1053
|
+
* This is also used by the websocket listener when the server calls
|
|
1054
|
+
* `player.clientVisual()` or `map.clientVisual()`.
|
|
1055
|
+
*
|
|
1056
|
+
* @param packet - Visual name and serializable payload
|
|
1057
|
+
*/
|
|
1058
|
+
playClientVisual(packet) {
|
|
1059
|
+
return this.clientVisuals.play(packet, this);
|
|
1060
|
+
}
|
|
1061
|
+
/**
|
|
970
1062
|
* Add a component animation to the engine
|
|
971
1063
|
*
|
|
972
1064
|
* Component animations are temporary visual effects that can be displayed
|
|
@@ -1123,6 +1215,9 @@ var RpgClientEngine = class {
|
|
|
1123
1215
|
get scene() {
|
|
1124
1216
|
return this.sceneMap;
|
|
1125
1217
|
}
|
|
1218
|
+
getObjectById(id) {
|
|
1219
|
+
return this.sceneMap?.getObjectById(id);
|
|
1220
|
+
}
|
|
1126
1221
|
getPhysicsTick() {
|
|
1127
1222
|
return this.sceneMap?.getTick?.() ?? 0;
|
|
1128
1223
|
}
|
|
@@ -1565,6 +1660,7 @@ var RpgClientEngine = class {
|
|
|
1565
1660
|
this.cameraFollowTargetId.set(null);
|
|
1566
1661
|
this.spriteComponentsBehind.set([]);
|
|
1567
1662
|
this.spriteComponentsInFront.set([]);
|
|
1663
|
+
this.eventComponentResolvers.clear();
|
|
1568
1664
|
this.spritesheets.clear();
|
|
1569
1665
|
this.sounds.clear();
|
|
1570
1666
|
this.componentAnimations = [];
|