@rpgjs/client 5.0.0-beta.1 → 5.0.0-beta.10
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 +37 -0
- package/LICENSE +19 -0
- package/dist/Game/AnimationManager.d.ts +1 -1
- package/dist/Game/AnimationManager.js +18 -9
- package/dist/Game/AnimationManager.js.map +1 -1
- package/dist/Game/AnimationManager.spec.d.ts +1 -0
- package/dist/Game/Event.js.map +1 -1
- package/dist/Game/Map.d.ts +9 -1
- package/dist/Game/Map.js +63 -5
- package/dist/Game/Map.js.map +1 -1
- package/dist/Game/Object.d.ts +47 -15
- package/dist/Game/Object.js +82 -38
- package/dist/Game/Object.js.map +1 -1
- package/dist/Game/Player.js.map +1 -1
- package/dist/Gui/Gui.d.ts +17 -4
- package/dist/Gui/Gui.js +78 -48
- package/dist/Gui/Gui.js.map +1 -1
- package/dist/Gui/Gui.spec.d.ts +1 -0
- package/dist/Gui/NotificationManager.js.map +1 -1
- package/dist/Resource.js +1 -1
- package/dist/Resource.js.map +1 -1
- package/dist/RpgClient.d.ts +57 -2
- package/dist/RpgClientEngine.d.ts +61 -6
- package/dist/RpgClientEngine.js +122 -14
- package/dist/RpgClientEngine.js.map +1 -1
- package/dist/Sound.js.map +1 -1
- package/dist/_virtual/{_@oxc-project_runtime@0.122.0 → _@oxc-project_runtime@0.130.0}/helpers/decorate.js +1 -1
- package/dist/_virtual/{_@oxc-project_runtime@0.122.0 → _@oxc-project_runtime@0.130.0}/helpers/decorateMetadata.js +1 -1
- package/dist/components/animations/animation.ce.js +4 -5
- package/dist/components/animations/animation.ce.js.map +1 -1
- package/dist/components/animations/hit.ce.js +19 -25
- package/dist/components/animations/hit.ce.js.map +1 -1
- package/dist/components/animations/index.js +4 -4
- package/dist/components/animations/index.js.map +1 -1
- package/dist/components/character.ce.js +406 -226
- package/dist/components/character.ce.js.map +1 -1
- package/dist/components/dynamics/bar.ce.js +96 -0
- package/dist/components/dynamics/bar.ce.js.map +1 -0
- package/dist/components/dynamics/image.ce.js +23 -0
- package/dist/components/dynamics/image.ce.js.map +1 -0
- package/dist/components/dynamics/parse-value.d.ts +3 -0
- package/dist/components/dynamics/parse-value.js +54 -35
- package/dist/components/dynamics/parse-value.js.map +1 -1
- package/dist/components/dynamics/parse-value.spec.d.ts +1 -0
- package/dist/components/dynamics/shape-utils.d.ts +16 -0
- package/dist/components/dynamics/shape-utils.js +73 -0
- package/dist/components/dynamics/shape-utils.js.map +1 -0
- package/dist/components/dynamics/shape-utils.spec.d.ts +1 -0
- package/dist/components/dynamics/shape.ce.js +83 -0
- package/dist/components/dynamics/shape.ce.js.map +1 -0
- package/dist/components/dynamics/text.ce.js +33 -56
- package/dist/components/dynamics/text.ce.js.map +1 -1
- package/dist/components/gui/box.ce.js +6 -8
- package/dist/components/gui/box.ce.js.map +1 -1
- package/dist/components/gui/dialogbox/index.ce.js +53 -60
- package/dist/components/gui/dialogbox/index.ce.js.map +1 -1
- package/dist/components/gui/gameover.ce.js +39 -63
- package/dist/components/gui/gameover.ce.js.map +1 -1
- package/dist/components/gui/hud/hud.ce.js +21 -30
- package/dist/components/gui/hud/hud.ce.js.map +1 -1
- package/dist/components/gui/menu/equip-menu.ce.js +110 -164
- package/dist/components/gui/menu/equip-menu.ce.js.map +1 -1
- package/dist/components/gui/menu/exit-menu.ce.js +6 -5
- package/dist/components/gui/menu/exit-menu.ce.js.map +1 -1
- package/dist/components/gui/menu/items-menu.ce.js +49 -67
- package/dist/components/gui/menu/items-menu.ce.js.map +1 -1
- package/dist/components/gui/menu/main-menu.ce.js +72 -90
- package/dist/components/gui/menu/main-menu.ce.js.map +1 -1
- package/dist/components/gui/menu/options-menu.ce.js +5 -4
- package/dist/components/gui/menu/options-menu.ce.js.map +1 -1
- package/dist/components/gui/menu/skills-menu.ce.js +12 -17
- package/dist/components/gui/menu/skills-menu.ce.js.map +1 -1
- package/dist/components/gui/mobile/index.js +2 -2
- package/dist/components/gui/mobile/index.js.map +1 -1
- package/dist/components/gui/mobile/mobile.ce.js +5 -4
- package/dist/components/gui/mobile/mobile.ce.js.map +1 -1
- package/dist/components/gui/notification/notification.ce.js +22 -24
- package/dist/components/gui/notification/notification.ce.js.map +1 -1
- package/dist/components/gui/save-load.ce.js +70 -248
- package/dist/components/gui/save-load.ce.js.map +1 -1
- package/dist/components/gui/shop/shop.ce.js +87 -125
- package/dist/components/gui/shop/shop.ce.js.map +1 -1
- package/dist/components/gui/title-screen.ce.js +42 -68
- package/dist/components/gui/title-screen.ce.js.map +1 -1
- package/dist/components/player-components-utils.d.ts +67 -0
- package/dist/components/player-components-utils.js +162 -0
- package/dist/components/player-components-utils.js.map +1 -0
- package/dist/components/player-components-utils.spec.d.ts +1 -0
- package/dist/components/player-components.ce.js +188 -0
- package/dist/components/player-components.ce.js.map +1 -0
- package/dist/components/prebuilt/hp-bar.ce.js +41 -44
- package/dist/components/prebuilt/hp-bar.ce.js.map +1 -1
- package/dist/components/prebuilt/light-halo.ce.js +35 -59
- package/dist/components/prebuilt/light-halo.ce.js.map +1 -1
- package/dist/components/scenes/canvas.ce.js +157 -21
- package/dist/components/scenes/canvas.ce.js.map +1 -1
- package/dist/components/scenes/draw-map.ce.js +19 -29
- package/dist/components/scenes/draw-map.ce.js.map +1 -1
- package/dist/components/scenes/event-layer.ce.js +9 -8
- package/dist/components/scenes/event-layer.ce.js.map +1 -1
- package/dist/core/inject.js +1 -1
- package/dist/core/inject.js.map +1 -1
- package/dist/core/setup.js +1 -1
- package/dist/core/setup.js.map +1 -1
- package/dist/decorators/spritesheet.d.ts +1 -0
- package/dist/decorators/spritesheet.js +11 -0
- package/dist/decorators/spritesheet.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +21 -20
- package/dist/module.js +4 -1
- package/dist/module.js.map +1 -1
- package/dist/node_modules/.pnpm/{@signe_di@2.9.0 → @signe_di@3.0.1}/node_modules/@signe/di/dist/index.js +7 -117
- package/dist/node_modules/.pnpm/@signe_di@3.0.1/node_modules/@signe/di/dist/index.js.map +1 -0
- package/dist/node_modules/.pnpm/@signe_reactive@3.0.1/node_modules/@signe/reactive/dist/index.js +239 -0
- package/dist/node_modules/.pnpm/@signe_reactive@3.0.1/node_modules/@signe/reactive/dist/index.js.map +1 -0
- package/dist/node_modules/.pnpm/@signe_room@3.0.1/node_modules/@signe/room/dist/chunk-EUXUH3YW.js +13 -0
- package/dist/node_modules/.pnpm/@signe_room@3.0.1/node_modules/@signe/room/dist/chunk-EUXUH3YW.js.map +1 -0
- package/dist/node_modules/.pnpm/@signe_room@3.0.1/node_modules/@signe/room/dist/index.js +696 -0
- package/dist/node_modules/.pnpm/@signe_room@3.0.1/node_modules/@signe/room/dist/index.js.map +1 -0
- package/dist/node_modules/.pnpm/@signe_sync@3.0.1/node_modules/@signe/sync/dist/client/index.js +44 -0
- package/dist/node_modules/.pnpm/@signe_sync@3.0.1/node_modules/@signe/sync/dist/client/index.js.map +1 -0
- package/dist/node_modules/.pnpm/{@signe_sync@2.9.0 → @signe_sync@3.0.1}/node_modules/@signe/sync/dist/index.js +57 -141
- package/dist/node_modules/.pnpm/@signe_sync@3.0.1/node_modules/@signe/sync/dist/index.js.map +1 -0
- package/dist/node_modules/.pnpm/partysocket@1.1.3/node_modules/partysocket/dist/chunk-HAC622V3.js.map +1 -1
- package/dist/node_modules/.pnpm/partysocket@1.1.3/node_modules/partysocket/dist/chunk-S74YV6PU.js.map +1 -1
- package/dist/node_modules/.pnpm/zod@3.24.2/node_modules/zod/lib/index.js +27 -27
- package/dist/node_modules/.pnpm/zod@3.24.2/node_modules/zod/lib/index.js.map +1 -1
- package/dist/presets/animation.js.map +1 -1
- package/dist/presets/faceset.js.map +1 -1
- package/dist/presets/icon.js.map +1 -1
- package/dist/presets/index.js.map +1 -1
- package/dist/presets/lpc.js.map +1 -1
- package/dist/presets/rmspritesheet.js.map +1 -1
- package/dist/services/AbstractSocket.js.map +1 -1
- package/dist/services/keyboardControls.js.map +1 -1
- package/dist/services/loadMap.d.ts +6 -0
- package/dist/services/loadMap.js +1 -1
- package/dist/services/loadMap.js.map +1 -1
- package/dist/services/mmorpg.js +9 -4
- package/dist/services/mmorpg.js.map +1 -1
- package/dist/services/save.js.map +1 -1
- package/dist/services/save.spec.d.ts +1 -0
- package/dist/services/standalone.js +1 -1
- package/dist/services/standalone.js.map +1 -1
- package/dist/utils/getEntityProp.js +4 -3
- package/dist/utils/getEntityProp.js.map +1 -1
- package/dist/utils/getEntityProp.spec.d.ts +1 -0
- package/dist/utils/readPropValue.d.ts +2 -0
- package/dist/utils/readPropValue.js +13 -0
- package/dist/utils/readPropValue.js.map +1 -0
- package/package.json +13 -14
- package/src/Game/AnimationManager.spec.ts +30 -0
- package/src/Game/AnimationManager.ts +22 -10
- package/src/Game/Map.ts +91 -2
- package/src/Game/Object.ts +148 -69
- package/src/Gui/Gui.spec.ts +273 -0
- package/src/Gui/Gui.ts +105 -50
- package/src/Resource.ts +1 -2
- package/src/RpgClient.ts +63 -2
- package/src/RpgClientEngine.ts +173 -25
- package/src/components/character.ce +422 -15
- package/src/components/dynamics/bar.ce +87 -0
- package/src/components/dynamics/image.ce +20 -0
- package/src/components/dynamics/parse-value.spec.ts +83 -0
- package/src/components/dynamics/parse-value.ts +111 -37
- package/src/components/dynamics/shape-utils.spec.ts +46 -0
- package/src/components/dynamics/shape-utils.ts +61 -0
- package/src/components/dynamics/shape.ce +89 -0
- package/src/components/dynamics/text.ce +34 -149
- package/src/components/gui/dialogbox/index.ce +15 -6
- package/src/components/player-components-utils.spec.ts +109 -0
- package/src/components/player-components-utils.ts +205 -0
- package/src/components/player-components.ce +221 -0
- package/src/components/scenes/canvas.ce +165 -6
- package/src/components/scenes/draw-map.ce +2 -15
- package/src/components/scenes/event-layer.ce +1 -2
- package/src/core/setup.ts +2 -2
- package/src/decorators/spritesheet.ts +8 -0
- package/src/index.ts +1 -0
- package/src/module.ts +5 -1
- package/src/services/loadMap.ts +2 -0
- package/src/services/mmorpg.ts +8 -2
- package/src/services/save.spec.ts +127 -0
- package/src/utils/getEntityProp.spec.ts +96 -0
- package/src/utils/getEntityProp.ts +4 -3
- package/src/utils/readPropValue.ts +16 -0
- package/dist/node_modules/.pnpm/@signe_di@2.9.0/node_modules/@signe/di/dist/index.js.map +0 -1
- package/dist/node_modules/.pnpm/@signe_reactive@2.8.3/node_modules/@signe/reactive/dist/index.js +0 -457
- package/dist/node_modules/.pnpm/@signe_reactive@2.8.3/node_modules/@signe/reactive/dist/index.js.map +0 -1
- package/dist/node_modules/.pnpm/@signe_reactive@2.9.0/node_modules/@signe/reactive/dist/index.js +0 -463
- package/dist/node_modules/.pnpm/@signe_reactive@2.9.0/node_modules/@signe/reactive/dist/index.js.map +0 -1
- package/dist/node_modules/.pnpm/@signe_room@2.9.0/node_modules/@signe/room/dist/index.js +0 -2191
- package/dist/node_modules/.pnpm/@signe_room@2.9.0/node_modules/@signe/room/dist/index.js.map +0 -1
- package/dist/node_modules/.pnpm/@signe_sync@2.9.0/node_modules/@signe/sync/dist/chunk-7QVYU63E.js +0 -10
- package/dist/node_modules/.pnpm/@signe_sync@2.9.0/node_modules/@signe/sync/dist/chunk-7QVYU63E.js.map +0 -1
- package/dist/node_modules/.pnpm/@signe_sync@2.9.0/node_modules/@signe/sync/dist/client/index.js +0 -91
- package/dist/node_modules/.pnpm/@signe_sync@2.9.0/node_modules/@signe/sync/dist/client/index.js.map +0 -1
- package/dist/node_modules/.pnpm/@signe_sync@2.9.0/node_modules/@signe/sync/dist/index.js.map +0 -1
- package/dist/node_modules/.pnpm/dset@3.1.4/node_modules/dset/dist/index.js +0 -14
- package/dist/node_modules/.pnpm/dset@3.1.4/node_modules/dset/dist/index.js.map +0 -1
package/src/RpgClientEngine.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import Canvas from "./components/scenes/canvas.ce";
|
|
2
2
|
import { inject } from './core/inject'
|
|
3
|
-
import { signal, bootstrapCanvas, Howl, trigger } from "canvasengine";
|
|
3
|
+
import { signal, bootstrapCanvas, Howl, trigger, type Trigger } from "canvasengine";
|
|
4
4
|
import { AbstractWebsocket, WebSocketToken } from "./services/AbstractSocket";
|
|
5
5
|
import { LoadMapService, LoadMapToken } from "./services/loadMap";
|
|
6
6
|
import { RpgSound } from "./Sound";
|
|
7
7
|
import { RpgResource } from "./Resource";
|
|
8
|
-
import { Hooks, ModulesToken, Direction } from "@rpgjs/common";
|
|
8
|
+
import { Hooks, ModulesToken, Direction, normalizeLightingState } from "@rpgjs/common";
|
|
9
9
|
import { load } from "@signe/sync";
|
|
10
10
|
import { RpgClientMap } from "./Game/Map"
|
|
11
11
|
import { RpgGui } from "./Gui/Gui";
|
|
@@ -14,6 +14,10 @@ import { lastValueFrom, Observable, combineLatest, BehaviorSubject, filter, swit
|
|
|
14
14
|
import { GlobalConfigToken } from "./module";
|
|
15
15
|
import * as PIXI from "pixi.js";
|
|
16
16
|
import { PrebuiltComponentAnimations } from "./components/animations";
|
|
17
|
+
import TextComponent from "./components/dynamics/text.ce";
|
|
18
|
+
import BarComponent from "./components/dynamics/bar.ce";
|
|
19
|
+
import ShapeComponent from "./components/dynamics/shape.ce";
|
|
20
|
+
import ImageComponent from "./components/dynamics/image.ce";
|
|
17
21
|
import {
|
|
18
22
|
PredictionController,
|
|
19
23
|
type PredictionHistoryEntry,
|
|
@@ -21,6 +25,7 @@ import {
|
|
|
21
25
|
} from "@rpgjs/common";
|
|
22
26
|
import { NotificationManager } from "./Gui/NotificationManager";
|
|
23
27
|
import { SaveClientService } from "./services/save";
|
|
28
|
+
import { getCanMoveValue } from "./utils/readPropValue";
|
|
24
29
|
|
|
25
30
|
interface MovementTrajectoryPoint {
|
|
26
31
|
frame: number;
|
|
@@ -32,6 +37,17 @@ interface MovementTrajectoryPoint {
|
|
|
32
37
|
direction?: Direction;
|
|
33
38
|
}
|
|
34
39
|
|
|
40
|
+
type ConfigurableTrigger<T> = Omit<Trigger<T>, "start"> & {
|
|
41
|
+
start(config?: T): Promise<void>;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
type MapShakeOptions = {
|
|
45
|
+
intensity?: number;
|
|
46
|
+
duration?: number;
|
|
47
|
+
frequency?: number;
|
|
48
|
+
direction?: string;
|
|
49
|
+
};
|
|
50
|
+
|
|
35
51
|
export class RpgClientEngine<T = any> {
|
|
36
52
|
private guiService: RpgGui;
|
|
37
53
|
private webSocket: AbstractWebsocket;
|
|
@@ -44,10 +60,10 @@ export class RpgClientEngine<T = any> {
|
|
|
44
60
|
stopProcessingInput = false;
|
|
45
61
|
width = signal("100%");
|
|
46
62
|
height = signal("100%");
|
|
47
|
-
spritesheets: Map<string, any> = new Map();
|
|
63
|
+
spritesheets: Map<string | number, any> = new Map();
|
|
48
64
|
sounds: Map<string, any> = new Map();
|
|
49
65
|
componentAnimations: any[] = [];
|
|
50
|
-
private spritesheetResolver?: (id: string) => any | Promise<any>;
|
|
66
|
+
private spritesheetResolver?: (id: string | number) => any | Promise<any>;
|
|
51
67
|
private soundResolver?: (id: string) => any | Promise<any>;
|
|
52
68
|
particleSettings: {
|
|
53
69
|
emitters: any[]
|
|
@@ -61,10 +77,11 @@ export class RpgClientEngine<T = any> {
|
|
|
61
77
|
playerIdSignal = signal<string | null>(null);
|
|
62
78
|
spriteComponentsBehind = signal<any[]>([]);
|
|
63
79
|
spriteComponentsInFront = signal<any[]>([]);
|
|
80
|
+
spriteComponents: Map<string, any> = new Map();
|
|
64
81
|
/** ID of the sprite that the camera should follow. null means follow the current player */
|
|
65
82
|
cameraFollowTargetId = signal<string | null>(null);
|
|
66
83
|
/** Trigger for map shake animation */
|
|
67
|
-
mapShakeTrigger = trigger();
|
|
84
|
+
mapShakeTrigger: ConfigurableTrigger<MapShakeOptions> = trigger<MapShakeOptions>();
|
|
68
85
|
|
|
69
86
|
controlsReady = signal(undefined);
|
|
70
87
|
gamePause = signal(false);
|
|
@@ -123,6 +140,13 @@ export class RpgClientEngine<T = any> {
|
|
|
123
140
|
component: PrebuiltComponentAnimations.Animation
|
|
124
141
|
})
|
|
125
142
|
|
|
143
|
+
this.registerSpriteComponent("rpg:text", TextComponent);
|
|
144
|
+
this.registerSpriteComponent("rpg:hpBar", BarComponent);
|
|
145
|
+
this.registerSpriteComponent("rpg:spBar", BarComponent);
|
|
146
|
+
this.registerSpriteComponent("rpg:bar", BarComponent);
|
|
147
|
+
this.registerSpriteComponent("rpg:shape", ShapeComponent);
|
|
148
|
+
this.registerSpriteComponent("rpg:image", ImageComponent);
|
|
149
|
+
|
|
126
150
|
this.predictionEnabled = (this.globalConfig as any)?.prediction?.enabled !== false;
|
|
127
151
|
this.initializePredictionController();
|
|
128
152
|
}
|
|
@@ -233,7 +257,7 @@ export class RpgClientEngine<T = any> {
|
|
|
233
257
|
|
|
234
258
|
await this.webSocket.connection(() => {
|
|
235
259
|
const saveClient = inject(SaveClientService);
|
|
236
|
-
saveClient.initialize(
|
|
260
|
+
saveClient.initialize();
|
|
237
261
|
this.initListeners()
|
|
238
262
|
this.guiService._initialize()
|
|
239
263
|
this.startPingPong();
|
|
@@ -355,6 +379,7 @@ export class RpgClientEngine<T = any> {
|
|
|
355
379
|
|
|
356
380
|
this.webSocket.on("changeMap", (data) => {
|
|
357
381
|
this.sceneResetQueued = true;
|
|
382
|
+
this.sceneMap.clearLightSpots();
|
|
358
383
|
// Reset camera follow to default (follow current player) when changing maps
|
|
359
384
|
this.cameraFollowTargetId.set(null);
|
|
360
385
|
const transferToken = typeof data?.transferToken === "string" ? data.transferToken : undefined;
|
|
@@ -374,15 +399,27 @@ export class RpgClientEngine<T = any> {
|
|
|
374
399
|
this.notificationManager.add(data);
|
|
375
400
|
});
|
|
376
401
|
|
|
377
|
-
|
|
378
|
-
const {
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
402
|
+
this.webSocket.on("setAnimation", (data) => {
|
|
403
|
+
const {
|
|
404
|
+
animationName,
|
|
405
|
+
nbTimes,
|
|
406
|
+
object,
|
|
407
|
+
graphic,
|
|
408
|
+
restoreAnimationName,
|
|
409
|
+
restoreGraphics,
|
|
410
|
+
} = data;
|
|
411
|
+
const player = object ? this.sceneMap.getObjectById(object) : undefined;
|
|
412
|
+
if (!player) return;
|
|
413
|
+
const restoreOptions = {
|
|
414
|
+
restoreAnimationName,
|
|
415
|
+
restoreGraphics,
|
|
416
|
+
};
|
|
417
|
+
if (graphic !== undefined) {
|
|
418
|
+
player.setAnimation(animationName, graphic, nbTimes, restoreOptions);
|
|
419
|
+
} else {
|
|
420
|
+
player.setAnimation(animationName, nbTimes, restoreOptions);
|
|
421
|
+
}
|
|
422
|
+
})
|
|
386
423
|
|
|
387
424
|
this.webSocket.on("playSound", (data) => {
|
|
388
425
|
const { soundId, volume, loop } = data;
|
|
@@ -413,7 +450,7 @@ export class RpgClientEngine<T = any> {
|
|
|
413
450
|
|
|
414
451
|
this.webSocket.on("shakeMap", (data) => {
|
|
415
452
|
const { intensity, duration, frequency, direction } = data || {};
|
|
416
|
-
|
|
453
|
+
this.mapShakeTrigger.start({
|
|
417
454
|
intensity,
|
|
418
455
|
duration,
|
|
419
456
|
frequency,
|
|
@@ -447,6 +484,14 @@ export class RpgClientEngine<T = any> {
|
|
|
447
484
|
});
|
|
448
485
|
});
|
|
449
486
|
|
|
487
|
+
this.webSocket.on("lightingState", (data) => {
|
|
488
|
+
const raw = (data && typeof data === "object" && "value" in data)
|
|
489
|
+
? (data as any).value
|
|
490
|
+
: data;
|
|
491
|
+
|
|
492
|
+
this.sceneMap.lightingState.set(normalizeLightingState(raw));
|
|
493
|
+
});
|
|
494
|
+
|
|
450
495
|
this.webSocket.on('open', () => {
|
|
451
496
|
this.hooks.callHooks("client-engine-onConnected", this, this.socket).subscribe();
|
|
452
497
|
// Start ping/pong for synchronization
|
|
@@ -562,7 +607,7 @@ export class RpgClientEngine<T = any> {
|
|
|
562
607
|
})
|
|
563
608
|
await this.webSocket.reconnect(() => {
|
|
564
609
|
const saveClient = inject(SaveClientService);
|
|
565
|
-
saveClient.initialize(
|
|
610
|
+
saveClient.initialize();
|
|
566
611
|
this.initListeners()
|
|
567
612
|
this.guiService._initialize()
|
|
568
613
|
})
|
|
@@ -623,7 +668,7 @@ export class RpgClientEngine<T = any> {
|
|
|
623
668
|
* });
|
|
624
669
|
* ```
|
|
625
670
|
*/
|
|
626
|
-
setSpritesheetResolver(resolver: (id: string) => any | Promise<any>): void {
|
|
671
|
+
setSpritesheetResolver(resolver: (id: string | number) => any | Promise<any>): void {
|
|
627
672
|
this.spritesheetResolver = resolver;
|
|
628
673
|
}
|
|
629
674
|
|
|
@@ -634,7 +679,7 @@ export class RpgClientEngine<T = any> {
|
|
|
634
679
|
* If not found and a resolver is set, it calls the resolver to create the spritesheet.
|
|
635
680
|
* The resolved spritesheet is automatically cached for future use.
|
|
636
681
|
*
|
|
637
|
-
* @param id - The spritesheet ID to retrieve
|
|
682
|
+
* @param id - The spritesheet ID or legacy tile ID to retrieve
|
|
638
683
|
* @returns The spritesheet if found or created, or undefined if not found and no resolver
|
|
639
684
|
* @returns Promise<any> if the resolver is asynchronous
|
|
640
685
|
*
|
|
@@ -647,7 +692,7 @@ export class RpgClientEngine<T = any> {
|
|
|
647
692
|
* const spritesheet = await engine.getSpriteSheet('dynamic-sprite');
|
|
648
693
|
* ```
|
|
649
694
|
*/
|
|
650
|
-
getSpriteSheet(id: string): any | Promise<any> {
|
|
695
|
+
getSpriteSheet(id: string | number): any | Promise<any> {
|
|
651
696
|
// Check cache first
|
|
652
697
|
if (this.spritesheets.has(id)) {
|
|
653
698
|
return this.spritesheets.get(id);
|
|
@@ -1081,6 +1126,37 @@ export class RpgClientEngine<T = any> {
|
|
|
1081
1126
|
return component
|
|
1082
1127
|
}
|
|
1083
1128
|
|
|
1129
|
+
/**
|
|
1130
|
+
* Register a reusable sprite component that can be addressed by the server.
|
|
1131
|
+
*
|
|
1132
|
+
* Server-side component definitions only carry the component id and
|
|
1133
|
+
* serializable props. The client registry maps that id to the CanvasEngine
|
|
1134
|
+
* component that performs the actual rendering.
|
|
1135
|
+
*
|
|
1136
|
+
* @param id - Stable component id used by server component definitions
|
|
1137
|
+
* @param component - CanvasEngine component to render for this id
|
|
1138
|
+
* @returns The registered component
|
|
1139
|
+
*
|
|
1140
|
+
* @example
|
|
1141
|
+
* ```ts
|
|
1142
|
+
* engine.registerSpriteComponent('guildBadge', GuildBadgeComponent);
|
|
1143
|
+
* ```
|
|
1144
|
+
*/
|
|
1145
|
+
registerSpriteComponent(id: string, component: any) {
|
|
1146
|
+
this.spriteComponents.set(id, component);
|
|
1147
|
+
return component;
|
|
1148
|
+
}
|
|
1149
|
+
|
|
1150
|
+
/**
|
|
1151
|
+
* Get a reusable sprite component by id.
|
|
1152
|
+
*
|
|
1153
|
+
* @param id - Component id registered on the client
|
|
1154
|
+
* @returns The CanvasEngine component, or undefined when missing
|
|
1155
|
+
*/
|
|
1156
|
+
getSpriteComponent(id: string) {
|
|
1157
|
+
return this.spriteComponents.get(id);
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1084
1160
|
/**
|
|
1085
1161
|
* Add a component animation to the engine
|
|
1086
1162
|
*
|
|
@@ -1164,16 +1240,43 @@ export class RpgClientEngine<T = any> {
|
|
|
1164
1240
|
* duration: 1000,
|
|
1165
1241
|
* onFinish: () => console.log('Fade complete')
|
|
1166
1242
|
* });
|
|
1243
|
+
*
|
|
1244
|
+
* // Wait until the transition component calls onFinish
|
|
1245
|
+
* await engine.startTransition('fade', { duration: 1000 });
|
|
1167
1246
|
* ```
|
|
1168
1247
|
*/
|
|
1169
|
-
startTransition(id: string, props: any = {}) {
|
|
1248
|
+
startTransition(id: string, props: any = {}): Promise<void> {
|
|
1170
1249
|
if (!this.guiService.exists(id)) {
|
|
1171
1250
|
throw new Error(`Transition with id ${id} not found. Make sure to add it using engine.addTransition() or in your module's transitions property.`);
|
|
1172
1251
|
}
|
|
1173
|
-
|
|
1252
|
+
return new Promise<void>((resolve) => {
|
|
1253
|
+
let finished = false;
|
|
1254
|
+
const finish = (data?: any) => {
|
|
1255
|
+
if (finished) return;
|
|
1256
|
+
finished = true;
|
|
1257
|
+
props?.onFinish?.(data);
|
|
1258
|
+
resolve();
|
|
1259
|
+
};
|
|
1260
|
+
|
|
1261
|
+
this.guiService.display(id, {
|
|
1262
|
+
...props,
|
|
1263
|
+
onFinish: finish,
|
|
1264
|
+
});
|
|
1265
|
+
});
|
|
1174
1266
|
}
|
|
1175
1267
|
|
|
1176
1268
|
async processInput({ input }: { input: Direction }) {
|
|
1269
|
+
if (this.stopProcessingInput) return;
|
|
1270
|
+
|
|
1271
|
+
const currentPlayer = this.sceneMap.getCurrentPlayer() as any;
|
|
1272
|
+
const canMove =
|
|
1273
|
+
!currentPlayer ||
|
|
1274
|
+
getCanMoveValue(currentPlayer);
|
|
1275
|
+
if (!canMove) {
|
|
1276
|
+
this.interruptCurrentPlayerMovement(currentPlayer);
|
|
1277
|
+
return;
|
|
1278
|
+
}
|
|
1279
|
+
|
|
1177
1280
|
const timestamp = Date.now();
|
|
1178
1281
|
let frame: number;
|
|
1179
1282
|
let tick: number;
|
|
@@ -1188,7 +1291,6 @@ export class RpgClientEngine<T = any> {
|
|
|
1188
1291
|
this.inputFrameCounter = frame;
|
|
1189
1292
|
this.hooks.callHooks("client-engine-onInput", this, { input, playerId: this.playerId }).subscribe();
|
|
1190
1293
|
|
|
1191
|
-
const currentPlayer = this.sceneMap.getCurrentPlayer();
|
|
1192
1294
|
const bodyReady = this.ensureCurrentPlayerBody();
|
|
1193
1295
|
if (currentPlayer && bodyReady) {
|
|
1194
1296
|
currentPlayer.changeDirection(input);
|
|
@@ -1207,6 +1309,12 @@ export class RpgClientEngine<T = any> {
|
|
|
1207
1309
|
|
|
1208
1310
|
processAction({ action }: { action: number }) {
|
|
1209
1311
|
if (this.stopProcessingInput) return;
|
|
1312
|
+
const currentPlayer = this.sceneMap.getCurrentPlayer() as any;
|
|
1313
|
+
const canMove =
|
|
1314
|
+
!currentPlayer ||
|
|
1315
|
+
getCanMoveValue(currentPlayer);
|
|
1316
|
+
if (!canMove) return;
|
|
1317
|
+
|
|
1210
1318
|
this.hooks.callHooks("client-engine-onInput", this, { input: 'action', playerId: this.playerId }).subscribe();
|
|
1211
1319
|
this.webSocket.emit('action', { action })
|
|
1212
1320
|
}
|
|
@@ -1337,6 +1445,14 @@ export class RpgClientEngine<T = any> {
|
|
|
1337
1445
|
if (!this.predictionEnabled || !this.prediction) {
|
|
1338
1446
|
return;
|
|
1339
1447
|
}
|
|
1448
|
+
const player = this.sceneMap?.getCurrentPlayer?.() as any;
|
|
1449
|
+
if (
|
|
1450
|
+
player &&
|
|
1451
|
+
!getCanMoveValue(player)
|
|
1452
|
+
) {
|
|
1453
|
+
this.interruptCurrentPlayerMovement(player);
|
|
1454
|
+
return;
|
|
1455
|
+
}
|
|
1340
1456
|
const pendingInputs = this.prediction.getPendingInputs();
|
|
1341
1457
|
if (pendingInputs.length === 0) {
|
|
1342
1458
|
return;
|
|
@@ -1475,6 +1591,34 @@ export class RpgClientEngine<T = any> {
|
|
|
1475
1591
|
this.lastMovePathSentFrame = 0;
|
|
1476
1592
|
}
|
|
1477
1593
|
|
|
1594
|
+
/**
|
|
1595
|
+
* Stop local movement immediately and discard pending predicted movement.
|
|
1596
|
+
*
|
|
1597
|
+
* Use this before a blocking action such as an A-RPG attack, dialog, dash
|
|
1598
|
+
* startup, or any client-side state where already buffered movement inputs
|
|
1599
|
+
* must not be replayed after server reconciliation.
|
|
1600
|
+
*
|
|
1601
|
+
* @param player - Player object to stop. Defaults to the current player.
|
|
1602
|
+
* @returns `true` when a player was found and interrupted.
|
|
1603
|
+
*
|
|
1604
|
+
* @example
|
|
1605
|
+
* ```ts
|
|
1606
|
+
* engine.interruptCurrentPlayerMovement();
|
|
1607
|
+
* ```
|
|
1608
|
+
*/
|
|
1609
|
+
interruptCurrentPlayerMovement(player: any = this.sceneMap?.getCurrentPlayer?.()): boolean {
|
|
1610
|
+
if (!player) {
|
|
1611
|
+
return false;
|
|
1612
|
+
}
|
|
1613
|
+
(this.sceneMap as any)?.stopMovement?.(player);
|
|
1614
|
+
this.prediction?.clearPendingInputs();
|
|
1615
|
+
this.pendingPredictionFrames = [];
|
|
1616
|
+
this.lastInputTime = 0;
|
|
1617
|
+
this.lastMovePathSentAt = Date.now();
|
|
1618
|
+
this.lastMovePathSentFrame = this.inputFrameCounter;
|
|
1619
|
+
return true;
|
|
1620
|
+
}
|
|
1621
|
+
|
|
1478
1622
|
/**
|
|
1479
1623
|
* Trigger a flash animation on a sprite
|
|
1480
1624
|
*
|
|
@@ -1560,7 +1704,7 @@ export class RpgClientEngine<T = any> {
|
|
|
1560
1704
|
if (typeof ack.x !== "number" || typeof ack.y !== "number") {
|
|
1561
1705
|
return;
|
|
1562
1706
|
}
|
|
1563
|
-
const player = this.getCurrentPlayer();
|
|
1707
|
+
const player = this.getCurrentPlayer() as any;
|
|
1564
1708
|
const myId = this.playerIdSignal();
|
|
1565
1709
|
if (!player || !myId) {
|
|
1566
1710
|
return;
|
|
@@ -1583,10 +1727,14 @@ export class RpgClientEngine<T = any> {
|
|
|
1583
1727
|
authoritativeState: PredictionState<Direction>,
|
|
1584
1728
|
pendingInputs: PredictionHistoryEntry<Direction>[],
|
|
1585
1729
|
): void {
|
|
1586
|
-
const player = this.getCurrentPlayer();
|
|
1730
|
+
const player = this.getCurrentPlayer() as any;
|
|
1587
1731
|
if (!player) {
|
|
1588
1732
|
return;
|
|
1589
1733
|
}
|
|
1734
|
+
if (!getCanMoveValue(player)) {
|
|
1735
|
+
this.interruptCurrentPlayerMovement(player);
|
|
1736
|
+
return;
|
|
1737
|
+
}
|
|
1590
1738
|
|
|
1591
1739
|
(this.sceneMap as any).stopMovement(player);
|
|
1592
1740
|
this.applyAuthoritativeState(authoritativeState);
|