@rpgjs/client 5.0.0-beta.1 → 5.0.0-beta.11
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 +49 -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/Game/ProjectileManager.d.ts +89 -0
- package/dist/Game/ProjectileManager.js +179 -0
- package/dist/Game/ProjectileManager.js.map +1 -0
- package/dist/Game/ProjectileManager.spec.d.ts +1 -0
- 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 +110 -15
- package/dist/RpgClientEngine.d.ts +86 -10
- package/dist/RpgClientEngine.js +306 -49
- 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 +422 -240
- package/dist/components/character.ce.js.map +1 -1
- package/dist/components/dynamics/bar.ce.js +97 -0
- package/dist/components/dynamics/bar.ce.js.map +1 -0
- package/dist/components/dynamics/image.ce.js +24 -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 +84 -0
- package/dist/components/dynamics/shape.ce.js.map +1 -0
- package/dist/components/dynamics/text.ce.js +34 -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 +56 -62
- package/dist/components/gui/dialogbox/index.ce.js.map +1 -1
- package/dist/components/gui/gameover.ce.js +42 -65
- 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 +112 -165
- package/dist/components/gui/menu/equip-menu.ce.js.map +1 -1
- package/dist/components/gui/menu/exit-menu.ce.js +8 -6
- package/dist/components/gui/menu/exit-menu.ce.js.map +1 -1
- package/dist/components/gui/menu/items-menu.ce.js +52 -69
- package/dist/components/gui/menu/items-menu.ce.js.map +1 -1
- package/dist/components/gui/menu/main-menu.ce.js +75 -92
- 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 +72 -249
- package/dist/components/gui/save-load.ce.js.map +1 -1
- package/dist/components/gui/shop/shop.ce.js +90 -127
- package/dist/components/gui/shop/shop.ce.js.map +1 -1
- package/dist/components/gui/title-screen.ce.js +45 -70
- package/dist/components/gui/title-screen.ce.js.map +1 -1
- package/dist/components/index.d.ts +2 -1
- package/dist/components/index.js +1 -0
- 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 +189 -0
- package/dist/components/player-components.ce.js.map +1 -0
- package/dist/components/prebuilt/hp-bar.ce.js +42 -44
- package/dist/components/prebuilt/hp-bar.ce.js.map +1 -1
- package/dist/components/prebuilt/light-halo.ce.js +36 -59
- package/dist/components/prebuilt/light-halo.ce.js.map +1 -1
- package/dist/components/scenes/canvas.ce.js +165 -21
- package/dist/components/scenes/canvas.ce.js.map +1 -1
- package/dist/components/scenes/draw-map.ce.js +25 -32
- 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 +4 -0
- package/dist/index.js +26 -21
- package/dist/module.js +15 -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/actionInput.d.ts +12 -0
- package/dist/services/actionInput.js +27 -0
- package/dist/services/actionInput.js.map +1 -0
- package/dist/services/actionInput.spec.d.ts +1 -0
- 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-connection.d.ts +5 -0
- package/dist/services/mmorpg-connection.js +50 -0
- package/dist/services/mmorpg-connection.js.map +1 -0
- package/dist/services/mmorpg-connection.spec.d.ts +1 -0
- package/dist/services/mmorpg.d.ts +10 -4
- package/dist/services/mmorpg.js +56 -33
- package/dist/services/mmorpg.js.map +1 -1
- package/dist/services/pointerContext.d.ts +11 -0
- package/dist/services/pointerContext.js +48 -0
- package/dist/services/pointerContext.js.map +1 -0
- package/dist/services/pointerContext.spec.d.ts +1 -0
- package/dist/services/save.js.map +1 -1
- package/dist/services/save.spec.d.ts +1 -0
- package/dist/services/standalone-message.d.ts +1 -0
- package/dist/services/standalone-message.js +9 -0
- package/dist/services/standalone-message.js.map +1 -0
- package/dist/services/standalone.js +4 -3
- package/dist/services/standalone.js.map +1 -1
- package/dist/services/standalone.spec.d.ts +1 -0
- 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/Game/ProjectileManager.spec.ts +338 -0
- package/src/Game/ProjectileManager.ts +324 -0
- 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 +125 -17
- package/src/RpgClientEngine.ts +457 -87
- package/src/components/character.ce +441 -32
- package/src/components/dynamics/bar.ce +88 -0
- package/src/components/dynamics/image.ce +21 -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 +90 -0
- package/src/components/dynamics/text.ce +35 -149
- package/src/components/gui/dialogbox/index.ce +18 -8
- package/src/components/gui/gameover.ce +2 -1
- package/src/components/gui/menu/equip-menu.ce +2 -1
- package/src/components/gui/menu/exit-menu.ce +2 -1
- package/src/components/gui/menu/items-menu.ce +3 -2
- package/src/components/gui/menu/main-menu.ce +2 -1
- package/src/components/gui/save-load.ce +2 -1
- package/src/components/gui/shop/shop.ce +3 -2
- package/src/components/gui/title-screen.ce +2 -1
- package/src/components/index.ts +2 -1
- 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 +222 -0
- package/src/components/prebuilt/hp-bar.ce +4 -3
- package/src/components/prebuilt/light-halo.ce +2 -2
- package/src/components/scenes/canvas.ce +175 -8
- package/src/components/scenes/draw-map.ce +18 -17
- 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 +4 -0
- package/src/module.ts +18 -1
- package/src/services/actionInput.spec.ts +101 -0
- package/src/services/actionInput.ts +53 -0
- package/src/services/loadMap.ts +2 -0
- package/src/services/mmorpg-connection.spec.ts +99 -0
- package/src/services/mmorpg-connection.ts +69 -0
- package/src/services/mmorpg.ts +68 -36
- package/src/services/pointerContext.spec.ts +36 -0
- package/src/services/pointerContext.ts +84 -0
- package/src/services/save.spec.ts +127 -0
- package/src/services/standalone-message.ts +7 -0
- package/src/services/standalone.spec.ts +34 -0
- package/src/services/standalone.ts +3 -2
- 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/dist/RpgClientEngine.js
CHANGED
|
@@ -1,35 +1,47 @@
|
|
|
1
1
|
import { inject } from "./core/inject.js";
|
|
2
2
|
import { WebSocketToken } from "./services/AbstractSocket.js";
|
|
3
|
+
import { normalizeActionInput } from "./services/actionInput.js";
|
|
4
|
+
import { getCanMoveValue } from "./utils/readPropValue.js";
|
|
3
5
|
import { SaveClientService } from "./services/save.js";
|
|
4
6
|
import { RpgGui } from "./Gui/Gui.js";
|
|
5
|
-
import
|
|
7
|
+
import __ce_component from "./components/scenes/canvas.ce.js";
|
|
8
|
+
import __ce_component$1 from "./components/scenes/draw-map.ce.js";
|
|
6
9
|
import { LoadMapToken } from "./services/loadMap.js";
|
|
7
10
|
import { RpgSound } from "./Sound.js";
|
|
8
11
|
import { RpgResource } from "./Resource.js";
|
|
9
|
-
import { load } from "./node_modules/.pnpm/@signe_sync@
|
|
12
|
+
import { load } from "./node_modules/.pnpm/@signe_sync@3.0.1/node_modules/@signe/sync/dist/index.js";
|
|
10
13
|
import { RpgClientMap } from "./Game/Map.js";
|
|
11
14
|
import { AnimationManager } from "./Game/AnimationManager.js";
|
|
12
15
|
import { GlobalConfigToken } from "./module.js";
|
|
13
16
|
import { PrebuiltComponentAnimations } from "./components/animations/index.js";
|
|
17
|
+
import __ce_component$2 from "./components/dynamics/text.ce.js";
|
|
18
|
+
import __ce_component$3 from "./components/dynamics/bar.ce.js";
|
|
19
|
+
import __ce_component$4 from "./components/dynamics/shape.ce.js";
|
|
20
|
+
import __ce_component$5 from "./components/dynamics/image.ce.js";
|
|
14
21
|
import { NotificationManager } from "./Gui/NotificationManager.js";
|
|
22
|
+
import { ProjectileManager } from "./Game/ProjectileManager.js";
|
|
23
|
+
import { createClientPointerContext } from "./services/pointerContext.js";
|
|
15
24
|
import { Howl, bootstrapCanvas, signal, trigger } from "canvasengine";
|
|
16
|
-
import { Direction, ModulesToken, PredictionController } from "@rpgjs/common";
|
|
25
|
+
import { Direction, ModulesToken, PredictionController, Vector2, normalizeLightingState } from "@rpgjs/common";
|
|
17
26
|
import { BehaviorSubject, combineLatest, filter, lastValueFrom, switchMap, take } from "rxjs";
|
|
18
27
|
import * as PIXI from "pixi.js";
|
|
19
28
|
//#region src/RpgClientEngine.ts
|
|
20
29
|
var RpgClientEngine = class {
|
|
21
30
|
constructor(context) {
|
|
22
31
|
this.context = context;
|
|
32
|
+
this.sceneMapComponent = __ce_component$1;
|
|
23
33
|
this.stopProcessingInput = false;
|
|
24
34
|
this.width = signal("100%");
|
|
25
35
|
this.height = signal("100%");
|
|
26
36
|
this.spritesheets = /* @__PURE__ */ new Map();
|
|
27
37
|
this.sounds = /* @__PURE__ */ new Map();
|
|
28
38
|
this.componentAnimations = [];
|
|
39
|
+
this.pointer = createClientPointerContext();
|
|
29
40
|
this.particleSettings = { emitters: [] };
|
|
30
41
|
this.playerIdSignal = signal(null);
|
|
31
42
|
this.spriteComponentsBehind = signal([]);
|
|
32
43
|
this.spriteComponentsInFront = signal([]);
|
|
44
|
+
this.spriteComponents = /* @__PURE__ */ new Map();
|
|
33
45
|
this.cameraFollowTargetId = signal(null);
|
|
34
46
|
this.mapShakeTrigger = trigger();
|
|
35
47
|
this.controlsReady = signal(void 0);
|
|
@@ -40,6 +52,7 @@ var RpgClientEngine = class {
|
|
|
40
52
|
this.pendingPredictionFrames = [];
|
|
41
53
|
this.lastClientPhysicsStepAt = 0;
|
|
42
54
|
this.frameOffset = 0;
|
|
55
|
+
this.latestServerTickAt = 0;
|
|
43
56
|
this.rtt = 0;
|
|
44
57
|
this.pingInterval = null;
|
|
45
58
|
this.PING_INTERVAL_MS = 5e3;
|
|
@@ -54,11 +67,13 @@ var RpgClientEngine = class {
|
|
|
54
67
|
this.eventsReceived$ = new BehaviorSubject(false);
|
|
55
68
|
this.sceneResetQueued = false;
|
|
56
69
|
this.tickSubscriptions = [];
|
|
70
|
+
this.pendingSyncPackets = [];
|
|
57
71
|
this.notificationManager = new NotificationManager();
|
|
58
72
|
this.webSocket = inject(WebSocketToken);
|
|
59
73
|
this.guiService = inject(RpgGui);
|
|
60
74
|
this.loadMapService = inject(LoadMapToken);
|
|
61
75
|
this.hooks = inject(ModulesToken);
|
|
76
|
+
this.projectiles = new ProjectileManager(this.hooks, (projectile) => this.predictProjectileImpact(projectile));
|
|
62
77
|
this.globalConfig = inject(GlobalConfigToken);
|
|
63
78
|
if (!this.globalConfig) this.globalConfig = {};
|
|
64
79
|
if (!this.globalConfig.box) this.globalConfig.box = {
|
|
@@ -72,6 +87,12 @@ var RpgClientEngine = class {
|
|
|
72
87
|
id: "animation",
|
|
73
88
|
component: PrebuiltComponentAnimations.Animation
|
|
74
89
|
});
|
|
90
|
+
this.registerSpriteComponent("rpg:text", __ce_component$2);
|
|
91
|
+
this.registerSpriteComponent("rpg:hpBar", __ce_component$3);
|
|
92
|
+
this.registerSpriteComponent("rpg:spBar", __ce_component$3);
|
|
93
|
+
this.registerSpriteComponent("rpg:bar", __ce_component$3);
|
|
94
|
+
this.registerSpriteComponent("rpg:shape", __ce_component$4);
|
|
95
|
+
this.registerSpriteComponent("rpg:image", __ce_component$5);
|
|
75
96
|
this.predictionEnabled = this.globalConfig?.prediction?.enabled !== false;
|
|
76
97
|
this.initializePredictionController();
|
|
77
98
|
}
|
|
@@ -120,13 +141,26 @@ var RpgClientEngine = class {
|
|
|
120
141
|
this.sceneMap = new RpgClientMap();
|
|
121
142
|
this.sceneMap.configureClientPrediction(this.predictionEnabled);
|
|
122
143
|
this.sceneMap.loadPhysic();
|
|
144
|
+
this.resolveSceneMapComponent();
|
|
145
|
+
inject(SaveClientService).initialize();
|
|
146
|
+
this.initListeners();
|
|
147
|
+
this.guiService._initialize();
|
|
148
|
+
try {
|
|
149
|
+
await this.webSocket.connection();
|
|
150
|
+
} catch (error) {
|
|
151
|
+
this.stopPingPong();
|
|
152
|
+
await this.callConnectError(error);
|
|
153
|
+
throw error;
|
|
154
|
+
}
|
|
123
155
|
this.selector = document.body.querySelector("#rpg");
|
|
124
156
|
const bootstrapOptions = this.globalConfig?.bootstrapCanvasOptions;
|
|
125
|
-
const { app, canvasElement } = await bootstrapCanvas(this.selector,
|
|
157
|
+
const { app, canvasElement } = await bootstrapCanvas(this.selector, __ce_component, bootstrapOptions);
|
|
126
158
|
this.canvasApp = app;
|
|
127
159
|
this.canvasElement = canvasElement;
|
|
128
160
|
this.renderer = app.renderer;
|
|
161
|
+
this.setupPointerTracking();
|
|
129
162
|
this.tick = canvasElement?.propObservables?.context["tick"].observable;
|
|
163
|
+
this.flushPendingSyncPackets();
|
|
130
164
|
const inputCheckSubscription = this.tick.subscribe(() => {
|
|
131
165
|
if (Date.now() - this.lastInputTime > 100) {
|
|
132
166
|
const player = this.getCurrentPlayer();
|
|
@@ -144,6 +178,7 @@ var RpgClientEngine = class {
|
|
|
144
178
|
this.hooks.callHooks("client-gui-load", this).subscribe();
|
|
145
179
|
this.hooks.callHooks("client-particles-load", this).subscribe();
|
|
146
180
|
this.hooks.callHooks("client-componentAnimations-load", this).subscribe();
|
|
181
|
+
this.hooks.callHooks("client-projectiles-load", this).subscribe();
|
|
147
182
|
this.hooks.callHooks("client-sprite-load", this).subscribe();
|
|
148
183
|
await lastValueFrom(this.hooks.callHooks("client-engine-onStart", this));
|
|
149
184
|
this.resizeHandler = () => {
|
|
@@ -152,6 +187,7 @@ var RpgClientEngine = class {
|
|
|
152
187
|
window.addEventListener("resize", this.resizeHandler);
|
|
153
188
|
const tickSubscription = this.tick.subscribe((tick) => {
|
|
154
189
|
this.stepClientPhysicsTick();
|
|
190
|
+
this.projectiles.step();
|
|
155
191
|
this.flushPendingPredictedStates();
|
|
156
192
|
this.flushPendingMovePath();
|
|
157
193
|
this.hooks.callHooks("client-engine-onStep", this, tick).subscribe();
|
|
@@ -162,12 +198,46 @@ var RpgClientEngine = class {
|
|
|
162
198
|
}
|
|
163
199
|
});
|
|
164
200
|
this.tickSubscriptions.push(tickSubscription);
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
201
|
+
this.startPingPong();
|
|
202
|
+
}
|
|
203
|
+
resolveSceneMapComponent() {
|
|
204
|
+
const components = this.hooks.getHookFunctions("client-sceneMap-component");
|
|
205
|
+
const component = components[components.length - 1];
|
|
206
|
+
if (component) this.sceneMapComponent = component;
|
|
207
|
+
}
|
|
208
|
+
setupPointerTracking() {
|
|
209
|
+
const renderer = this.renderer;
|
|
210
|
+
const canvas = renderer?.canvas ?? renderer?.view ?? this.canvasApp?.canvas;
|
|
211
|
+
if (!canvas || typeof canvas.addEventListener !== "function") return;
|
|
212
|
+
this.pointerCanvas = canvas;
|
|
213
|
+
this.pointerMoveHandler = (event) => {
|
|
214
|
+
const rect = canvas.getBoundingClientRect();
|
|
215
|
+
const screen = {
|
|
216
|
+
x: event.clientX - rect.left,
|
|
217
|
+
y: event.clientY - rect.top
|
|
218
|
+
};
|
|
219
|
+
const viewport = this.findViewportInstance();
|
|
220
|
+
let world = screen;
|
|
221
|
+
if (viewport && typeof viewport.toWorld === "function") {
|
|
222
|
+
const point = viewport.toWorld(screen.x, screen.y);
|
|
223
|
+
world = {
|
|
224
|
+
x: Number(point.x),
|
|
225
|
+
y: Number(point.y)
|
|
226
|
+
};
|
|
227
|
+
} else if (viewport && typeof viewport.toLocal === "function") {
|
|
228
|
+
const point = viewport.toLocal(screen);
|
|
229
|
+
world = {
|
|
230
|
+
x: Number(point.x),
|
|
231
|
+
y: Number(point.y)
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
this.pointer.update(screen, world);
|
|
235
|
+
};
|
|
236
|
+
canvas.addEventListener("pointermove", this.pointerMoveHandler);
|
|
237
|
+
canvas.addEventListener("pointerdown", this.pointerMoveHandler);
|
|
238
|
+
}
|
|
239
|
+
findViewportInstance() {
|
|
240
|
+
return (this.canvasApp?.stage?.children ?? []).find((child) => typeof child?.toWorld === "function" || child?.constructor?.name === "Viewport");
|
|
171
241
|
}
|
|
172
242
|
prepareSyncPayload(data) {
|
|
173
243
|
const payload = { ...data ?? {} };
|
|
@@ -202,39 +272,27 @@ var RpgClientEngine = class {
|
|
|
202
272
|
}
|
|
203
273
|
initListeners() {
|
|
204
274
|
this.webSocket.on("sync", (data) => {
|
|
205
|
-
if (
|
|
206
|
-
this.
|
|
207
|
-
|
|
208
|
-
}
|
|
209
|
-
if (this.sceneResetQueued) {
|
|
210
|
-
this.sceneMap.reset();
|
|
211
|
-
this.sceneMap.loadPhysic();
|
|
212
|
-
this.sceneResetQueued = false;
|
|
213
|
-
}
|
|
214
|
-
this.hooks.callHooks("client-sceneMap-onChanges", this.sceneMap, { partial: data }).subscribe();
|
|
215
|
-
const ack = data?.ack;
|
|
216
|
-
const normalizedAck = ack && typeof ack.frame === "number" ? this.normalizeAckWithSyncState(ack, data) : void 0;
|
|
217
|
-
const payload = this.prepareSyncPayload(data);
|
|
218
|
-
load(this.sceneMap, payload, true);
|
|
219
|
-
if (normalizedAck) this.applyServerAck(normalizedAck);
|
|
220
|
-
for (const playerId in payload.players ?? {}) {
|
|
221
|
-
const player = payload.players[playerId];
|
|
222
|
-
if (!player._param) continue;
|
|
223
|
-
for (const param in player._param) this.sceneMap.players()[playerId]._param()[param] = player._param[param];
|
|
275
|
+
if (!this.tick) {
|
|
276
|
+
this.pendingSyncPackets.push(data);
|
|
277
|
+
return;
|
|
224
278
|
}
|
|
225
|
-
|
|
226
|
-
if (players && Object.keys(players).length > 0) this.playersReceived$.next(true);
|
|
227
|
-
if ((payload.events || this.sceneMap.events()) !== void 0) this.eventsReceived$.next(true);
|
|
279
|
+
this.applySyncPacket(data);
|
|
228
280
|
});
|
|
229
281
|
this.webSocket.on("pong", (data) => {
|
|
230
|
-
|
|
282
|
+
const now = Date.now();
|
|
283
|
+
this.rtt = now - data.clientTime;
|
|
231
284
|
const estimatedTicksInFlight = Math.floor(this.rtt / 2 / (1e3 / 60));
|
|
232
285
|
const estimatedServerTickNow = data.serverTick + estimatedTicksInFlight;
|
|
286
|
+
this.updateServerTickEstimate(estimatedServerTickNow, now);
|
|
233
287
|
if (this.inputFrameCounter > 0) this.frameOffset = estimatedServerTickNow - data.clientFrame;
|
|
234
288
|
console.debug(`[Ping/Pong] RTT: ${this.rtt}ms, ServerTick: ${data.serverTick}, FrameOffset: ${this.frameOffset}`);
|
|
235
289
|
});
|
|
236
290
|
this.webSocket.on("changeMap", (data) => {
|
|
237
291
|
this.sceneResetQueued = true;
|
|
292
|
+
this.sceneMap.weatherState.set(null);
|
|
293
|
+
this.sceneMap.lightingState.set(null);
|
|
294
|
+
this.sceneMap.clearLightSpots();
|
|
295
|
+
this.projectiles.clear();
|
|
238
296
|
this.cameraFollowTargetId.set(null);
|
|
239
297
|
const transferToken = typeof data?.transferToken === "string" ? data.transferToken : void 0;
|
|
240
298
|
this.loadScene(data.mapId, transferToken);
|
|
@@ -245,14 +303,34 @@ var RpgClientEngine = class {
|
|
|
245
303
|
const player = object ? this.sceneMap.getObjectById(object) : void 0;
|
|
246
304
|
this.getComponentAnimation(id).displayEffect(params, player || position);
|
|
247
305
|
});
|
|
306
|
+
this.webSocket.on("projectile:spawnBatch", (data) => {
|
|
307
|
+
this.projectiles.spawnBatch(data?.projectiles ?? [], {
|
|
308
|
+
currentServerTick: this.estimateServerTick(),
|
|
309
|
+
tickDurationMs: this.getPhysicsTickDurationMs()
|
|
310
|
+
});
|
|
311
|
+
});
|
|
312
|
+
this.webSocket.on("projectile:impactBatch", (data) => {
|
|
313
|
+
this.projectiles.impactBatch(data?.impacts ?? []);
|
|
314
|
+
});
|
|
315
|
+
this.webSocket.on("projectile:destroyBatch", (data) => {
|
|
316
|
+
this.projectiles.destroyBatch(data?.projectiles ?? []);
|
|
317
|
+
});
|
|
318
|
+
this.webSocket.on("projectile:clear", () => {
|
|
319
|
+
this.projectiles.clear();
|
|
320
|
+
});
|
|
248
321
|
this.webSocket.on("notification", (data) => {
|
|
249
322
|
this.notificationManager.add(data);
|
|
250
323
|
});
|
|
251
324
|
this.webSocket.on("setAnimation", (data) => {
|
|
252
|
-
const { animationName, nbTimes, object, graphic } = data;
|
|
253
|
-
const player = this.sceneMap.getObjectById(object);
|
|
254
|
-
if (
|
|
255
|
-
|
|
325
|
+
const { animationName, nbTimes, object, graphic, restoreAnimationName, restoreGraphics } = data;
|
|
326
|
+
const player = object ? this.sceneMap.getObjectById(object) : void 0;
|
|
327
|
+
if (!player) return;
|
|
328
|
+
const restoreOptions = {
|
|
329
|
+
restoreAnimationName,
|
|
330
|
+
restoreGraphics
|
|
331
|
+
};
|
|
332
|
+
if (graphic !== void 0) player.setAnimation(animationName, graphic, nbTimes, restoreOptions);
|
|
333
|
+
else player.setAnimation(animationName, nbTimes, restoreOptions);
|
|
256
334
|
});
|
|
257
335
|
this.webSocket.on("playSound", (data) => {
|
|
258
336
|
const { soundId, volume, loop } = data;
|
|
@@ -314,6 +392,10 @@ var RpgClientEngine = class {
|
|
|
314
392
|
seed: raw.seed
|
|
315
393
|
});
|
|
316
394
|
});
|
|
395
|
+
this.webSocket.on("lightingState", (data) => {
|
|
396
|
+
const raw = data && typeof data === "object" && "value" in data ? data.value : data;
|
|
397
|
+
this.sceneMap.lightingState.set(normalizeLightingState(raw));
|
|
398
|
+
});
|
|
317
399
|
this.webSocket.on("open", () => {
|
|
318
400
|
this.hooks.callHooks("client-engine-onConnected", this, this.socket).subscribe();
|
|
319
401
|
this.startPingPong();
|
|
@@ -323,9 +405,46 @@ var RpgClientEngine = class {
|
|
|
323
405
|
this.stopPingPong();
|
|
324
406
|
});
|
|
325
407
|
this.webSocket.on("error", (error) => {
|
|
326
|
-
this.
|
|
408
|
+
this.callConnectError(error);
|
|
327
409
|
});
|
|
328
410
|
}
|
|
411
|
+
async callConnectError(error) {
|
|
412
|
+
await lastValueFrom(this.hooks.callHooks("client-engine-onConnectError", this, error, this.socket));
|
|
413
|
+
}
|
|
414
|
+
flushPendingSyncPackets() {
|
|
415
|
+
const packets = this.pendingSyncPackets;
|
|
416
|
+
this.pendingSyncPackets = [];
|
|
417
|
+
packets.forEach((packet) => this.applySyncPacket(packet));
|
|
418
|
+
}
|
|
419
|
+
applySyncPacket(data) {
|
|
420
|
+
if (data.pId) {
|
|
421
|
+
this.playerIdSignal.set(data.pId);
|
|
422
|
+
this.playerIdReceived$.next(true);
|
|
423
|
+
}
|
|
424
|
+
if (this.sceneResetQueued) {
|
|
425
|
+
const weatherState = this.sceneMap.weatherState();
|
|
426
|
+
const lightingState = this.sceneMap.lightingState();
|
|
427
|
+
this.sceneMap.reset();
|
|
428
|
+
this.sceneMap.weatherState.set(weatherState);
|
|
429
|
+
this.sceneMap.lightingState.set(lightingState);
|
|
430
|
+
this.sceneMap.loadPhysic();
|
|
431
|
+
this.sceneResetQueued = false;
|
|
432
|
+
}
|
|
433
|
+
this.hooks.callHooks("client-sceneMap-onChanges", this.sceneMap, { partial: data }).subscribe();
|
|
434
|
+
const ack = data?.ack;
|
|
435
|
+
const normalizedAck = ack && typeof ack.frame === "number" ? this.normalizeAckWithSyncState(ack, data) : void 0;
|
|
436
|
+
const payload = this.prepareSyncPayload(data);
|
|
437
|
+
load(this.sceneMap, payload, true);
|
|
438
|
+
if (normalizedAck) this.applyServerAck(normalizedAck);
|
|
439
|
+
for (const playerId in payload.players ?? {}) {
|
|
440
|
+
const player = payload.players[playerId];
|
|
441
|
+
if (!player._param) continue;
|
|
442
|
+
for (const param in player._param) this.sceneMap.players()[playerId]._param()[param] = player._param[param];
|
|
443
|
+
}
|
|
444
|
+
const players = payload.players || this.sceneMap.players();
|
|
445
|
+
if (players && Object.keys(players).length > 0) this.playersReceived$.next(true);
|
|
446
|
+
if ((payload.events || this.sceneMap.events()) !== void 0) this.eventsReceived$.next(true);
|
|
447
|
+
}
|
|
329
448
|
/**
|
|
330
449
|
* Start periodic ping/pong for client-server synchronization
|
|
331
450
|
*
|
|
@@ -402,11 +521,17 @@ var RpgClientEngine = class {
|
|
|
402
521
|
room: mapId,
|
|
403
522
|
query: transferToken ? { transferToken } : void 0
|
|
404
523
|
});
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
524
|
+
try {
|
|
525
|
+
await this.webSocket.reconnect(() => {
|
|
526
|
+
inject(SaveClientService).initialize();
|
|
527
|
+
this.initListeners();
|
|
528
|
+
this.guiService._initialize();
|
|
529
|
+
});
|
|
530
|
+
} catch (error) {
|
|
531
|
+
this.stopPingPong();
|
|
532
|
+
await this.callConnectError(error);
|
|
533
|
+
throw error;
|
|
534
|
+
}
|
|
410
535
|
const res = await this.loadMapService.load(mapId);
|
|
411
536
|
this.sceneMap.data.set(res);
|
|
412
537
|
if (this.playerIdSignal()) this.playerIdReceived$.next(true);
|
|
@@ -458,7 +583,7 @@ var RpgClientEngine = class {
|
|
|
458
583
|
* If not found and a resolver is set, it calls the resolver to create the spritesheet.
|
|
459
584
|
* The resolved spritesheet is automatically cached for future use.
|
|
460
585
|
*
|
|
461
|
-
* @param id - The spritesheet ID to retrieve
|
|
586
|
+
* @param id - The spritesheet ID or legacy tile ID to retrieve
|
|
462
587
|
* @returns The spritesheet if found or created, or undefined if not found and no resolver
|
|
463
588
|
* @returns Promise<any> if the resolver is asynchronous
|
|
464
589
|
*
|
|
@@ -807,6 +932,41 @@ var RpgClientEngine = class {
|
|
|
807
932
|
return component;
|
|
808
933
|
}
|
|
809
934
|
/**
|
|
935
|
+
* Register a reusable sprite component that can be addressed by the server.
|
|
936
|
+
*
|
|
937
|
+
* Server-side component definitions only carry the component id and
|
|
938
|
+
* serializable props. The client registry maps that id to the CanvasEngine
|
|
939
|
+
* component that performs the actual rendering.
|
|
940
|
+
*
|
|
941
|
+
* @param id - Stable component id used by server component definitions
|
|
942
|
+
* @param component - CanvasEngine component to render for this id
|
|
943
|
+
* @returns The registered component
|
|
944
|
+
*
|
|
945
|
+
* @example
|
|
946
|
+
* ```ts
|
|
947
|
+
* engine.registerSpriteComponent('guildBadge', GuildBadgeComponent);
|
|
948
|
+
* ```
|
|
949
|
+
*/
|
|
950
|
+
registerSpriteComponent(id, component) {
|
|
951
|
+
this.spriteComponents.set(id, component);
|
|
952
|
+
return component;
|
|
953
|
+
}
|
|
954
|
+
/**
|
|
955
|
+
* Get a reusable sprite component by id.
|
|
956
|
+
*
|
|
957
|
+
* @param id - Component id registered on the client
|
|
958
|
+
* @returns The CanvasEngine component, or undefined when missing
|
|
959
|
+
*/
|
|
960
|
+
getSpriteComponent(id) {
|
|
961
|
+
return this.spriteComponents.get(id);
|
|
962
|
+
}
|
|
963
|
+
registerProjectileComponent(type, component) {
|
|
964
|
+
return this.projectiles.register(type, component);
|
|
965
|
+
}
|
|
966
|
+
getProjectileComponent(type) {
|
|
967
|
+
return this.projectiles.get(type);
|
|
968
|
+
}
|
|
969
|
+
/**
|
|
810
970
|
* Add a component animation to the engine
|
|
811
971
|
*
|
|
812
972
|
* Component animations are temporary visual effects that can be displayed
|
|
@@ -882,13 +1042,34 @@ var RpgClientEngine = class {
|
|
|
882
1042
|
* duration: 1000,
|
|
883
1043
|
* onFinish: () => console.log('Fade complete')
|
|
884
1044
|
* });
|
|
1045
|
+
*
|
|
1046
|
+
* // Wait until the transition component calls onFinish
|
|
1047
|
+
* await engine.startTransition('fade', { duration: 1000 });
|
|
885
1048
|
* ```
|
|
886
1049
|
*/
|
|
887
1050
|
startTransition(id, props = {}) {
|
|
888
1051
|
if (!this.guiService.exists(id)) throw new Error(`Transition with id ${id} not found. Make sure to add it using engine.addTransition() or in your module's transitions property.`);
|
|
889
|
-
|
|
1052
|
+
return new Promise((resolve) => {
|
|
1053
|
+
let finished = false;
|
|
1054
|
+
const finish = (data) => {
|
|
1055
|
+
if (finished) return;
|
|
1056
|
+
finished = true;
|
|
1057
|
+
props?.onFinish?.(data);
|
|
1058
|
+
resolve();
|
|
1059
|
+
};
|
|
1060
|
+
this.guiService.display(id, {
|
|
1061
|
+
...props,
|
|
1062
|
+
onFinish: finish
|
|
1063
|
+
});
|
|
1064
|
+
});
|
|
890
1065
|
}
|
|
891
1066
|
async processInput({ input }) {
|
|
1067
|
+
if (this.stopProcessingInput) return;
|
|
1068
|
+
const currentPlayer = this.sceneMap.getCurrentPlayer();
|
|
1069
|
+
if (!(!currentPlayer || getCanMoveValue(currentPlayer))) {
|
|
1070
|
+
this.interruptCurrentPlayerMovement(currentPlayer);
|
|
1071
|
+
return;
|
|
1072
|
+
}
|
|
892
1073
|
const timestamp = Date.now();
|
|
893
1074
|
let frame;
|
|
894
1075
|
let tick;
|
|
@@ -905,7 +1086,6 @@ var RpgClientEngine = class {
|
|
|
905
1086
|
input,
|
|
906
1087
|
playerId: this.playerId
|
|
907
1088
|
}).subscribe();
|
|
908
|
-
const currentPlayer = this.sceneMap.getCurrentPlayer();
|
|
909
1089
|
const bodyReady = this.ensureCurrentPlayerBody();
|
|
910
1090
|
if (currentPlayer && bodyReady) {
|
|
911
1091
|
currentPlayer.changeDirection(input);
|
|
@@ -918,13 +1098,18 @@ var RpgClientEngine = class {
|
|
|
918
1098
|
this.emitMovePacket(input, frame, tick, timestamp, true);
|
|
919
1099
|
this.lastInputTime = Date.now();
|
|
920
1100
|
}
|
|
921
|
-
processAction(
|
|
1101
|
+
processAction(action, data) {
|
|
922
1102
|
if (this.stopProcessingInput) return;
|
|
1103
|
+
const currentPlayer = this.sceneMap.getCurrentPlayer();
|
|
1104
|
+
if (!(!currentPlayer || getCanMoveValue(currentPlayer))) return;
|
|
1105
|
+
const payload = normalizeActionInput(action, data);
|
|
923
1106
|
this.hooks.callHooks("client-engine-onInput", this, {
|
|
924
|
-
input:
|
|
1107
|
+
input: payload.action,
|
|
1108
|
+
action: payload.action,
|
|
1109
|
+
data: payload.data,
|
|
925
1110
|
playerId: this.playerId
|
|
926
1111
|
}).subscribe();
|
|
927
|
-
this.webSocket.emit("action",
|
|
1112
|
+
this.webSocket.emit("action", payload);
|
|
928
1113
|
}
|
|
929
1114
|
get PIXI() {
|
|
930
1115
|
return PIXI;
|
|
@@ -941,6 +1126,37 @@ var RpgClientEngine = class {
|
|
|
941
1126
|
getPhysicsTick() {
|
|
942
1127
|
return this.sceneMap?.getTick?.() ?? 0;
|
|
943
1128
|
}
|
|
1129
|
+
getPhysicsTickDurationMs() {
|
|
1130
|
+
const timeStep = this.sceneMap?.physic?.getWorld?.()?.getTimeStep?.();
|
|
1131
|
+
return typeof timeStep === "number" && Number.isFinite(timeStep) && timeStep > 0 ? timeStep * 1e3 : 1e3 / 60;
|
|
1132
|
+
}
|
|
1133
|
+
updateServerTickEstimate(serverTick, now = Date.now()) {
|
|
1134
|
+
if (typeof serverTick !== "number" || !Number.isFinite(serverTick)) return;
|
|
1135
|
+
this.latestServerTick = serverTick;
|
|
1136
|
+
this.latestServerTickAt = now;
|
|
1137
|
+
}
|
|
1138
|
+
estimateServerTick(now = Date.now()) {
|
|
1139
|
+
if (typeof this.latestServerTick !== "number" || this.latestServerTickAt <= 0) return;
|
|
1140
|
+
const elapsedTicks = Math.max(0, (now - this.latestServerTickAt) / this.getPhysicsTickDurationMs());
|
|
1141
|
+
return this.latestServerTick + elapsedTicks;
|
|
1142
|
+
}
|
|
1143
|
+
predictProjectileImpact(projectile) {
|
|
1144
|
+
if (projectile.predictImpact === false) return null;
|
|
1145
|
+
const sceneMap = this.sceneMap;
|
|
1146
|
+
if (!sceneMap?.physic || !Number.isFinite(projectile.range) || projectile.range <= 0) return null;
|
|
1147
|
+
const origin = projectile.origin;
|
|
1148
|
+
const direction = projectile.direction;
|
|
1149
|
+
if (!origin || !direction || !Number.isFinite(origin.x) || !Number.isFinite(origin.y) || !Number.isFinite(direction.x) || !Number.isFinite(direction.y) || direction.x === 0 && direction.y === 0) return null;
|
|
1150
|
+
const hit = sceneMap.physic.raycast(new Vector2(origin.x, origin.y), new Vector2(direction.x, direction.y), projectile.range, projectile.collisionMask, (entity) => projectile.ignoreOwner === false || !projectile.ownerId || entity.uuid !== projectile.ownerId);
|
|
1151
|
+
if (!hit) return null;
|
|
1152
|
+
return {
|
|
1153
|
+
id: projectile.id,
|
|
1154
|
+
targetId: hit.entity.uuid,
|
|
1155
|
+
x: hit.point.x,
|
|
1156
|
+
y: hit.point.y,
|
|
1157
|
+
distance: hit.distance
|
|
1158
|
+
};
|
|
1159
|
+
}
|
|
944
1160
|
ensureCurrentPlayerBody() {
|
|
945
1161
|
const player = this.sceneMap?.getCurrentPlayer();
|
|
946
1162
|
const myId = this.playerIdSignal();
|
|
@@ -1008,6 +1224,11 @@ var RpgClientEngine = class {
|
|
|
1008
1224
|
}
|
|
1009
1225
|
flushPendingMovePath() {
|
|
1010
1226
|
if (!this.predictionEnabled || !this.prediction) return;
|
|
1227
|
+
const player = this.sceneMap?.getCurrentPlayer?.();
|
|
1228
|
+
if (player && !getCanMoveValue(player)) {
|
|
1229
|
+
this.interruptCurrentPlayerMovement(player);
|
|
1230
|
+
return;
|
|
1231
|
+
}
|
|
1011
1232
|
const pendingInputs = this.prediction.getPendingInputs();
|
|
1012
1233
|
if (pendingInputs.length === 0) return;
|
|
1013
1234
|
const latest = pendingInputs[pendingInputs.length - 1];
|
|
@@ -1124,6 +1345,31 @@ var RpgClientEngine = class {
|
|
|
1124
1345
|
this.lastMovePathSentFrame = 0;
|
|
1125
1346
|
}
|
|
1126
1347
|
/**
|
|
1348
|
+
* Stop local movement immediately and discard pending predicted movement.
|
|
1349
|
+
*
|
|
1350
|
+
* Use this before a blocking action such as an A-RPG attack, dialog, dash
|
|
1351
|
+
* startup, or any client-side state where already buffered movement inputs
|
|
1352
|
+
* must not be replayed after server reconciliation.
|
|
1353
|
+
*
|
|
1354
|
+
* @param player - Player object to stop. Defaults to the current player.
|
|
1355
|
+
* @returns `true` when a player was found and interrupted.
|
|
1356
|
+
*
|
|
1357
|
+
* @example
|
|
1358
|
+
* ```ts
|
|
1359
|
+
* engine.interruptCurrentPlayerMovement();
|
|
1360
|
+
* ```
|
|
1361
|
+
*/
|
|
1362
|
+
interruptCurrentPlayerMovement(player = this.sceneMap?.getCurrentPlayer?.()) {
|
|
1363
|
+
if (!player) return false;
|
|
1364
|
+
this.sceneMap?.stopMovement?.(player);
|
|
1365
|
+
this.prediction?.clearPendingInputs();
|
|
1366
|
+
this.pendingPredictionFrames = [];
|
|
1367
|
+
this.lastInputTime = 0;
|
|
1368
|
+
this.lastMovePathSentAt = Date.now();
|
|
1369
|
+
this.lastMovePathSentFrame = this.inputFrameCounter;
|
|
1370
|
+
return true;
|
|
1371
|
+
}
|
|
1372
|
+
/**
|
|
1127
1373
|
* Trigger a flash animation on a sprite
|
|
1128
1374
|
*
|
|
1129
1375
|
* This method allows you to trigger a flash effect on any sprite from client-side code.
|
|
@@ -1177,6 +1423,7 @@ var RpgClientEngine = class {
|
|
|
1177
1423
|
if (sprite && typeof sprite.flash === "function") sprite.flash(options);
|
|
1178
1424
|
}
|
|
1179
1425
|
applyServerAck(ack) {
|
|
1426
|
+
this.updateServerTickEstimate(ack.serverTick);
|
|
1180
1427
|
if (this.predictionEnabled && this.prediction) {
|
|
1181
1428
|
const result = this.prediction.applyServerAck({
|
|
1182
1429
|
frame: ack.frame,
|
|
@@ -1205,6 +1452,10 @@ var RpgClientEngine = class {
|
|
|
1205
1452
|
reconcilePrediction(authoritativeState, pendingInputs) {
|
|
1206
1453
|
const player = this.getCurrentPlayer();
|
|
1207
1454
|
if (!player) return;
|
|
1455
|
+
if (!getCanMoveValue(player)) {
|
|
1456
|
+
this.interruptCurrentPlayerMovement(player);
|
|
1457
|
+
return;
|
|
1458
|
+
}
|
|
1208
1459
|
this.sceneMap.stopMovement(player);
|
|
1209
1460
|
this.applyAuthoritativeState(authoritativeState);
|
|
1210
1461
|
if (!pendingInputs.length) return;
|
|
@@ -1277,6 +1528,12 @@ var RpgClientEngine = class {
|
|
|
1277
1528
|
window.removeEventListener("resize", this.resizeHandler);
|
|
1278
1529
|
this.resizeHandler = void 0;
|
|
1279
1530
|
}
|
|
1531
|
+
if (this.pointerMoveHandler && this.pointerCanvas) {
|
|
1532
|
+
this.pointerCanvas.removeEventListener("pointermove", this.pointerMoveHandler);
|
|
1533
|
+
this.pointerCanvas.removeEventListener("pointerdown", this.pointerMoveHandler);
|
|
1534
|
+
this.pointerMoveHandler = void 0;
|
|
1535
|
+
this.pointerCanvas = void 0;
|
|
1536
|
+
}
|
|
1280
1537
|
const rendererStillExists = this.renderer && typeof this.renderer.destroy === "function";
|
|
1281
1538
|
if (this.canvasApp && typeof this.canvasApp.destroy === "function") {
|
|
1282
1539
|
try {
|