incanto 0.51.0 → 0.52.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/2d.d.ts +37 -2
- package/dist/2d.js +3 -3
- package/dist/3d.d.ts +3 -3
- package/dist/3d.js +4 -4
- package/dist/{behavior-rZNfzVbH.d.ts → behavior-uPEuZrUB.d.ts} +10 -0
- package/dist/{create-game-CkzKZ4v5.js → create-game-B_e9hJf7.js} +92 -10
- package/dist/{create-game-BNaOC3Px.js → create-game-CGnoypjL.js} +6 -6
- package/dist/debug.d.ts +1 -1
- package/dist/debug.js +1 -1
- package/dist/{duplicate-EybyYeyL.js → duplicate-B-OtSRFL.js} +1 -1
- package/dist/editor.js +1917 -1579
- package/dist/{environment-presets-C08pOC6H.js → environment-presets-DSZwsKPs.js} +3 -3
- package/dist/{gameplay-bStgtZBV.js → gameplay-B6jqvYeM.js} +6 -4
- package/dist/gameplay.d.ts +1 -1
- package/dist/gameplay.js +1 -1
- package/dist/index.d.ts +65 -5
- package/dist/index.js +7 -7
- package/dist/{loader-B2asghWa.js → loader-B-Gft32x.js} +32 -32
- package/dist/{loader-Dkbn56KC.d.ts → loader-B9iTqs27.d.ts} +1 -1
- package/dist/net.d.ts +15 -410
- package/dist/net.js +1 -822
- package/dist/{pathfinding-Bz34pvQD.d.ts → pathfinding-CAR9DjQQ.d.ts} +1 -1
- package/dist/{physics-2d-Ccq2L9R0.js → physics-2d-Dns-oZlE.js} +2 -2
- package/dist/{physics-3d-B2c5KNYh.js → physics-3d-BhI0ehpe.js} +3 -3
- package/dist/react.d.ts +1 -1
- package/dist/react.js +1 -1
- package/dist/{register-CGq-Hee8.js → register-DVwlnZAZ.js} +2 -2
- package/dist/{register-B_BaaGx-.js → register-Trx7WHnD.js} +3 -3
- package/dist/{registry-IyWCGe4q.js → registry-C7u42TID.js} +23 -1
- package/dist/{replay-DIP2_as4.d.ts → replay-BU1CCM15.d.ts} +1 -1
- package/dist/{replay-BgKxGcXH.js → replay-BicPOMX0.js} +195 -2
- package/dist/split-screen-CZ9ccBBQ.js +1267 -0
- package/dist/split-screen-paxkQs_q.d.ts +441 -0
- package/dist/{src-C3UwzYXl.js → src-5gbZO47I.js} +1 -1
- package/dist/{teardown-BKTCzLek.js → teardown-ks3d5W9n.js} +2 -1
- package/dist/{test-D2gRpk5V.js → test-DAojuFdb.js} +119 -22
- package/dist/test.d.ts +60 -5
- package/dist/test.js +3 -3
- package/dist/vite.js +2 -2
- package/editor/assets/{agent8-DbX_msaO.js → agent8-CCvckvbw.js} +1 -1
- package/editor/assets/{debug-C-kMxdl1.js → debug-CLNCOnbc.js} +1 -1
- package/editor/assets/{index-CUc1U7wm.js → index-Cb5Brupb.js} +99 -92
- package/editor/index.html +1 -1
- package/package.json +1 -1
- package/skills/incanto-assets.md +4 -1
- package/skills/incanto-editor.md +48 -11
- package/skills/incanto-gameplay-behaviors.md +14 -5
- package/skills/incanto-multiplayer.md +39 -3
- package/skills/incanto-verifying-your-game.md +56 -0
- package/templates/agent8-server.ts +79 -2
- package/templates-app/beacon-isle-3d/package.json +1 -1
- package/templates-app/tps-3d/package.json +1 -1
- package/templates-app/village-quest-3d/package.json +1 -1
- package/dist/register-CLVhzWcI.js +0 -374
|
@@ -1,374 +0,0 @@
|
|
|
1
|
-
import { M as Signal, f as Node, t as buildNodeJson } from "./loader-B2asghWa.js";
|
|
2
|
-
import { t as registerCoreNodes } from "./register-CGq-Hee8.js";
|
|
3
|
-
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
4
|
-
import { n as jsonEquals, t as jsonClone } from "./json-BLk7H2Qa.js";
|
|
5
|
-
import { l as registerNode } from "./registry-IyWCGe4q.js";
|
|
6
|
-
//#region src/net/network-manager.ts
|
|
7
|
-
const managers = /* @__PURE__ */ new WeakMap();
|
|
8
|
-
/**
|
|
9
|
-
* Per-engine multiplayer hub: joins a room, exposes the room channels as core
|
|
10
|
-
* Signals, replicates `network: {mode:'owner'}` node props on a throttle
|
|
11
|
-
* window, and resolves registered scenes for NetworkSpawner.
|
|
12
|
-
*/
|
|
13
|
-
var NetworkManager = class NetworkManager {
|
|
14
|
-
account;
|
|
15
|
-
roomId;
|
|
16
|
-
roomState = new Signal();
|
|
17
|
-
allUserStates = new Signal();
|
|
18
|
-
userJoined = new Signal();
|
|
19
|
-
userLeft = new Signal();
|
|
20
|
-
/**
|
|
21
|
-
* GLOBAL (cross-room, persistent) channels — populated only when the transport
|
|
22
|
-
* supports them (`LocalGameServer`, the agent8 adapter). On a transport without a
|
|
23
|
-
* global tier they stay empty / never fire.
|
|
24
|
-
*/
|
|
25
|
-
globalState = new Signal();
|
|
26
|
-
globalMyState = new Signal();
|
|
27
|
-
/** The local account's `$asset` ledger. */
|
|
28
|
-
asset = new Signal();
|
|
29
|
-
/** Latest snapshots for polling consumers (NetworkSpawner). */
|
|
30
|
-
latestUserStates = {};
|
|
31
|
-
latestRoomState = {};
|
|
32
|
-
latestGlobalState = {};
|
|
33
|
-
latestGlobalMyState = {};
|
|
34
|
-
latestAsset = {};
|
|
35
|
-
server;
|
|
36
|
-
engine;
|
|
37
|
-
throttleMs;
|
|
38
|
-
subs = [];
|
|
39
|
-
messageSignals = /* @__PURE__ */ new Map();
|
|
40
|
-
collectionSignals = /* @__PURE__ */ new Map();
|
|
41
|
-
latestCollections = /* @__PURE__ */ new Map();
|
|
42
|
-
globalMessageSignals = /* @__PURE__ */ new Map();
|
|
43
|
-
globalCollectionSignals = /* @__PURE__ */ new Map();
|
|
44
|
-
latestGlobalCollections = /* @__PURE__ */ new Map();
|
|
45
|
-
scenes = /* @__PURE__ */ new Map();
|
|
46
|
-
lastSent = /* @__PURE__ */ new Map();
|
|
47
|
-
sendAccumulator = 0;
|
|
48
|
-
detachReplication = null;
|
|
49
|
-
lastOwner = null;
|
|
50
|
-
boundScene = null;
|
|
51
|
-
static get(engine) {
|
|
52
|
-
return managers.get(engine) ?? null;
|
|
53
|
-
}
|
|
54
|
-
static async create(engine, opts = {}) {
|
|
55
|
-
await managers.get(engine)?.dispose();
|
|
56
|
-
const server = opts.transport ?? await createDefaultTransport(opts.config);
|
|
57
|
-
await server.connect();
|
|
58
|
-
const requested = opts.room ?? engine.scene?.multiplayer?.room ?? "auto";
|
|
59
|
-
const manager = new NetworkManager(engine, server, await server.remoteFunction("joinRoom", [requested === "auto" ? void 0 : requested], { needResponse: true }), opts.throttleMs ?? 50);
|
|
60
|
-
managers.set(engine, manager);
|
|
61
|
-
return manager;
|
|
62
|
-
}
|
|
63
|
-
constructor(engine, server, roomId, throttleMs) {
|
|
64
|
-
this.engine = engine;
|
|
65
|
-
this.server = server;
|
|
66
|
-
this.roomId = roomId;
|
|
67
|
-
this.account = server.account;
|
|
68
|
-
this.throttleMs = Math.max(30, throttleMs);
|
|
69
|
-
this.boundScene = engine.scene;
|
|
70
|
-
this.subs.push(server.subscribeRoomState(roomId, (state) => {
|
|
71
|
-
this.latestRoomState = state;
|
|
72
|
-
this.roomState.emit(state);
|
|
73
|
-
}), server.subscribeRoomAllUserStates(roomId, (states) => {
|
|
74
|
-
this.latestUserStates = states;
|
|
75
|
-
this.allUserStates.emit(states);
|
|
76
|
-
}), server.onRoomUserJoin(roomId, (account) => this.userJoined.emit(account)), server.onRoomUserLeave(roomId, (account) => this.userLeft.emit(account)));
|
|
77
|
-
if (server.subscribeGlobalState) this.subs.push(server.subscribeGlobalState((state) => {
|
|
78
|
-
this.latestGlobalState = state;
|
|
79
|
-
this.globalState.emit(state);
|
|
80
|
-
}));
|
|
81
|
-
if (server.subscribeGlobalMyState) this.subs.push(server.subscribeGlobalMyState((state) => {
|
|
82
|
-
this.latestGlobalMyState = state;
|
|
83
|
-
this.globalMyState.emit(state);
|
|
84
|
-
}));
|
|
85
|
-
if (server.subscribeAsset) this.subs.push(server.subscribeAsset(this.account, (assets) => {
|
|
86
|
-
this.latestAsset = assets;
|
|
87
|
-
this.asset.emit(assets);
|
|
88
|
-
}));
|
|
89
|
-
this.detachReplication = engine.fixedUpdated.connect((dt) => this.replicate(dt));
|
|
90
|
-
}
|
|
91
|
-
/** Signal for a typed room message (`sendEvent` on any client). */
|
|
92
|
-
message(type) {
|
|
93
|
-
let sig = this.messageSignals.get(type);
|
|
94
|
-
if (!sig) {
|
|
95
|
-
sig = new Signal();
|
|
96
|
-
this.messageSignals.set(type, sig);
|
|
97
|
-
this.subs.push(this.server.onRoomMessage(this.roomId, type, (m) => sig?.emit(m)));
|
|
98
|
-
}
|
|
99
|
-
return sig;
|
|
100
|
-
}
|
|
101
|
-
/** Signal + snapshot for a room collection (spawned entities). */
|
|
102
|
-
collection(id) {
|
|
103
|
-
let sig = this.collectionSignals.get(id);
|
|
104
|
-
if (!sig) {
|
|
105
|
-
sig = new Signal();
|
|
106
|
-
this.collectionSignals.set(id, sig);
|
|
107
|
-
this.subs.push(this.server.subscribeRoomCollection(this.roomId, id, (entities) => {
|
|
108
|
-
this.latestCollections.set(id, entities);
|
|
109
|
-
sig?.emit(entities);
|
|
110
|
-
}));
|
|
111
|
-
}
|
|
112
|
-
return sig;
|
|
113
|
-
}
|
|
114
|
-
latestCollection(id) {
|
|
115
|
-
this.collection(id);
|
|
116
|
-
return this.latestCollections.get(id) ?? {};
|
|
117
|
-
}
|
|
118
|
-
/** Signal for a typed GLOBAL message (`$global.broadcastToAll`/`sendMessageToUser`). */
|
|
119
|
-
globalMessage(type) {
|
|
120
|
-
let sig = this.globalMessageSignals.get(type);
|
|
121
|
-
if (!sig) {
|
|
122
|
-
sig = new Signal();
|
|
123
|
-
this.globalMessageSignals.set(type, sig);
|
|
124
|
-
const sub = this.server.onGlobalMessage?.(type, (m) => sig?.emit(m));
|
|
125
|
-
if (sub) this.subs.push(sub);
|
|
126
|
-
}
|
|
127
|
-
return sig;
|
|
128
|
-
}
|
|
129
|
-
/** Signal + snapshot for a GLOBAL collection (persistent, cross-room). */
|
|
130
|
-
globalCollection(id) {
|
|
131
|
-
let sig = this.globalCollectionSignals.get(id);
|
|
132
|
-
if (!sig) {
|
|
133
|
-
sig = new Signal();
|
|
134
|
-
this.globalCollectionSignals.set(id, sig);
|
|
135
|
-
const sub = this.server.subscribeGlobalCollection?.(id, (entities) => {
|
|
136
|
-
this.latestGlobalCollections.set(id, entities);
|
|
137
|
-
sig?.emit(entities);
|
|
138
|
-
});
|
|
139
|
-
if (sub) this.subs.push(sub);
|
|
140
|
-
}
|
|
141
|
-
return sig;
|
|
142
|
-
}
|
|
143
|
-
latestGlobalCollection(id) {
|
|
144
|
-
this.globalCollection(id);
|
|
145
|
-
return this.latestGlobalCollections.get(id) ?? {};
|
|
146
|
-
}
|
|
147
|
-
setMyState(patch) {
|
|
148
|
-
return this.server.remoteFunction("setMyState", [this.roomId, patch], {
|
|
149
|
-
throttle: this.throttleMs,
|
|
150
|
-
throttleKey: "incanto:myState"
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
patchRoomState(patch) {
|
|
154
|
-
return this.server.remoteFunction("patchRoomState", [this.roomId, patch]);
|
|
155
|
-
}
|
|
156
|
-
addEntity(collectionId, entity) {
|
|
157
|
-
return this.server.remoteFunction("addEntity", [
|
|
158
|
-
this.roomId,
|
|
159
|
-
collectionId,
|
|
160
|
-
entity
|
|
161
|
-
]);
|
|
162
|
-
}
|
|
163
|
-
updateEntity(collectionId, id, patch) {
|
|
164
|
-
return this.server.remoteFunction("updateEntity", [
|
|
165
|
-
this.roomId,
|
|
166
|
-
collectionId,
|
|
167
|
-
id,
|
|
168
|
-
patch
|
|
169
|
-
]);
|
|
170
|
-
}
|
|
171
|
-
removeEntity(collectionId, id) {
|
|
172
|
-
return this.server.remoteFunction("removeEntity", [
|
|
173
|
-
this.roomId,
|
|
174
|
-
collectionId,
|
|
175
|
-
id
|
|
176
|
-
]);
|
|
177
|
-
}
|
|
178
|
-
sendEvent(type, payload) {
|
|
179
|
-
return this.server.remoteFunction("sendEvent", [
|
|
180
|
-
this.roomId,
|
|
181
|
-
type,
|
|
182
|
-
payload
|
|
183
|
-
]);
|
|
184
|
-
}
|
|
185
|
-
/**
|
|
186
|
-
* Invoke a CUSTOM server-authoritative function — a method you added to your
|
|
187
|
-
* `server/src/server.ts` `Server` class (run live on the Agent8 platform, or
|
|
188
|
-
* locally via `createLocalGameServer`). The room id is prepended automatically,
|
|
189
|
-
* matching the `(roomId, …)` shape every server method takes:
|
|
190
|
-
*
|
|
191
|
-
* `manager.call('claimCoin', coinId)` → server `claimCoin(roomId, coinId)`
|
|
192
|
-
*
|
|
193
|
-
* Returns the function's result (use it for server-validated outcomes — a
|
|
194
|
-
* rejected claim, a rolled value). This is THE entry point for game rules the
|
|
195
|
-
* client must not be trusted to compute.
|
|
196
|
-
*/
|
|
197
|
-
call(fn, ...args) {
|
|
198
|
-
return this.server.remoteFunction(fn, [this.roomId, ...args], { needResponse: true });
|
|
199
|
-
}
|
|
200
|
-
/** Register a scene for NetworkSpawner (`"scene": "<key>"`). */
|
|
201
|
-
registerScene(key, json) {
|
|
202
|
-
this.scenes.set(key, json);
|
|
203
|
-
}
|
|
204
|
-
resolveScene(key) {
|
|
205
|
-
const json = this.scenes.get(key);
|
|
206
|
-
if (!json) throw new IncantoError("UNRESOLVED_INSTANCE", `No scene registered for '${key}'. Registered: [${[...this.scenes.keys()].join(", ")}]. Call manager.registerScene('${key}', sceneJson).`);
|
|
207
|
-
return json;
|
|
208
|
-
}
|
|
209
|
-
async dispose() {
|
|
210
|
-
this.detachReplication?.();
|
|
211
|
-
for (const off of this.subs) off();
|
|
212
|
-
await this.server.remoteFunction("leaveRoom", [this.roomId]);
|
|
213
|
-
managers.delete(this.engine);
|
|
214
|
-
}
|
|
215
|
-
replicate(dt) {
|
|
216
|
-
const scene = this.engine.scene;
|
|
217
|
-
if (!scene || scene !== this.boundScene) return;
|
|
218
|
-
this.sendAccumulator += dt * 1e3;
|
|
219
|
-
const owner = findOwnerNode(scene.root, true);
|
|
220
|
-
if (!owner) return;
|
|
221
|
-
if (owner !== this.lastOwner) {
|
|
222
|
-
this.lastOwner = owner;
|
|
223
|
-
this.lastSent.clear();
|
|
224
|
-
}
|
|
225
|
-
const net = owner.network;
|
|
226
|
-
const window = Math.max(30, typeof net.throttleMs === "number" ? net.throttleMs : this.throttleMs);
|
|
227
|
-
const syncKeys = Array.isArray(net.sync) ? net.sync : [];
|
|
228
|
-
const patch = {};
|
|
229
|
-
for (const key of syncKeys) {
|
|
230
|
-
const value = readSyncKey(owner, key);
|
|
231
|
-
if (value === void 0) continue;
|
|
232
|
-
if (!jsonEquals(this.lastSent.get(key) ?? null, value)) patch[key] = jsonClone(value);
|
|
233
|
-
}
|
|
234
|
-
if (this.sendAccumulator < window) return;
|
|
235
|
-
if (Object.keys(patch).length === 0) return;
|
|
236
|
-
for (const [key, value] of Object.entries(patch)) this.lastSent.set(key, jsonClone(value));
|
|
237
|
-
this.sendAccumulator = 0;
|
|
238
|
-
this.setMyState({ sync: patch });
|
|
239
|
-
}
|
|
240
|
-
};
|
|
241
|
-
function findOwnerNode(node, enforceSingle = false) {
|
|
242
|
-
const owners = [];
|
|
243
|
-
collectOwners(node, owners);
|
|
244
|
-
if (enforceSingle && owners.length > 1) throw new IncantoError("BAD_FORMAT", `Multiple network owner nodes found (${owners.map((o) => o.getPath()).join(", ")}). Exactly ONE node per player may declare network.mode 'owner' — replicate spawned entities through collections instead.`);
|
|
245
|
-
return owners[0] ?? null;
|
|
246
|
-
}
|
|
247
|
-
function collectOwners(node, out) {
|
|
248
|
-
if (node.network?.mode === "owner") out.push(node);
|
|
249
|
-
for (const c of node.children) collectOwners(c, out);
|
|
250
|
-
}
|
|
251
|
-
/** `'position'` → own prop; `'Sprite.animation'` → child path + prop (last dot splits). */
|
|
252
|
-
function readSyncKey(node, key) {
|
|
253
|
-
const lastDot = key.lastIndexOf(".");
|
|
254
|
-
const target = lastDot === -1 ? node : node.getNodeOrNull(key.slice(0, lastDot)) ?? void 0;
|
|
255
|
-
const prop = lastDot === -1 ? key : key.slice(lastDot + 1);
|
|
256
|
-
if (!target) return void 0;
|
|
257
|
-
return target[prop];
|
|
258
|
-
}
|
|
259
|
-
/**
|
|
260
|
-
* @internal Applies a replicated flat sync patch (`{'position': …,
|
|
261
|
-
* 'Sprite.animation': …}`) onto a spawned subtree (NetworkSpawner).
|
|
262
|
-
*/
|
|
263
|
-
function applySyncPatch(root, patch, setProp) {
|
|
264
|
-
for (const [key, value] of Object.entries(patch)) {
|
|
265
|
-
const lastDot = key.lastIndexOf(".");
|
|
266
|
-
const target = lastDot === -1 ? root : root.getNodeOrNull(key.slice(0, lastDot));
|
|
267
|
-
const prop = lastDot === -1 ? key : key.slice(lastDot + 1);
|
|
268
|
-
if (target) setProp(target, prop, value);
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
async function createDefaultTransport(config) {
|
|
272
|
-
const { createAgent8Server } = await import("./agent8-CvsfVskX.js").then((n) => n.t);
|
|
273
|
-
return createAgent8Server(config);
|
|
274
|
-
}
|
|
275
|
-
//#endregion
|
|
276
|
-
//#region src/net/nodes/network-spawner.ts
|
|
277
|
-
/**
|
|
278
|
-
* Materializes a registered scene per remote player or collection entity:
|
|
279
|
-
*
|
|
280
|
-
* - `source: 'users'` — one instance per OTHER account in the room
|
|
281
|
-
* (self is skipped; the local player is your own owned node)
|
|
282
|
-
* - `source: 'collection:<id>'` — one instance per entity (bullets, pickups…)
|
|
283
|
-
*
|
|
284
|
-
* Replicated flat `{sync: {...}}` patches apply onto each instance's root;
|
|
285
|
-
* `position` lerps toward its target when `interpolate` is on. Emits
|
|
286
|
-
* `spawned(node, key)` / `despawned(node, key)`.
|
|
287
|
-
*/
|
|
288
|
-
var NetworkSpawner = class extends Node {
|
|
289
|
-
static typeName = "NetworkSpawner";
|
|
290
|
-
static signals = ["spawned", "despawned"];
|
|
291
|
-
static props = {
|
|
292
|
-
source: { default: "users" },
|
|
293
|
-
scene: { default: "" },
|
|
294
|
-
interpolate: { default: true }
|
|
295
|
-
};
|
|
296
|
-
source = "users";
|
|
297
|
-
/** Key registered via `manager.registerScene(key, json)`. */
|
|
298
|
-
scene = "";
|
|
299
|
-
interpolate = true;
|
|
300
|
-
spawned = /* @__PURE__ */ new Map();
|
|
301
|
-
positionTargets = /* @__PURE__ */ new Map();
|
|
302
|
-
failedKeys = /* @__PURE__ */ new Set();
|
|
303
|
-
update(dt) {
|
|
304
|
-
const engine = this.tree?.engine;
|
|
305
|
-
if (!engine) return;
|
|
306
|
-
const manager = NetworkManager.get(engine);
|
|
307
|
-
if (!manager || this.scene === "") return;
|
|
308
|
-
const entries = this.currentEntries(manager);
|
|
309
|
-
for (const [key, state] of Object.entries(entries)) {
|
|
310
|
-
let instance = this.spawned.get(key);
|
|
311
|
-
if (!instance) {
|
|
312
|
-
if (this.failedKeys.has(key)) continue;
|
|
313
|
-
try {
|
|
314
|
-
instance = buildNodeJson(manager.resolveScene(this.scene).root);
|
|
315
|
-
} catch (error) {
|
|
316
|
-
this.failedKeys.add(key);
|
|
317
|
-
throw error;
|
|
318
|
-
}
|
|
319
|
-
instance.name = sanitizeName(key);
|
|
320
|
-
this.addChild(instance);
|
|
321
|
-
this.spawned.set(key, instance);
|
|
322
|
-
this.emit("spawned", instance, key);
|
|
323
|
-
}
|
|
324
|
-
const patch = state.sync;
|
|
325
|
-
if (patch) applySyncPatch(instance, patch, (target, prop, value) => this.setProp(target, prop, value));
|
|
326
|
-
}
|
|
327
|
-
for (const [key, instance] of [...this.spawned.entries()]) if (!(key in entries)) {
|
|
328
|
-
this.spawned.delete(key);
|
|
329
|
-
this.positionTargets.delete(instance);
|
|
330
|
-
this.emit("despawned", instance, key);
|
|
331
|
-
instance.free();
|
|
332
|
-
}
|
|
333
|
-
if (this.interpolate) this.stepInterpolation(dt);
|
|
334
|
-
}
|
|
335
|
-
currentEntries(manager) {
|
|
336
|
-
if (this.source === "users") {
|
|
337
|
-
const out = {};
|
|
338
|
-
for (const [account, state] of Object.entries(manager.latestUserStates)) if (account !== manager.account) out[account] = state;
|
|
339
|
-
return out;
|
|
340
|
-
}
|
|
341
|
-
if (this.source.startsWith("collection:")) return manager.latestCollection(this.source.slice(11));
|
|
342
|
-
return {};
|
|
343
|
-
}
|
|
344
|
-
setProp(target, prop, value) {
|
|
345
|
-
if (this.interpolate && prop === "position" && Array.isArray(value)) {
|
|
346
|
-
this.positionTargets.set(target, value);
|
|
347
|
-
return;
|
|
348
|
-
}
|
|
349
|
-
target[prop] = value;
|
|
350
|
-
}
|
|
351
|
-
stepInterpolation(dt) {
|
|
352
|
-
const f = Math.min(1, dt * 8);
|
|
353
|
-
for (const [target, goal] of this.positionTargets) {
|
|
354
|
-
const pos = target.position;
|
|
355
|
-
if (!Array.isArray(pos)) continue;
|
|
356
|
-
target.position = pos.map((v, i) => v + ((goal[i] ?? v) - v) * f);
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
};
|
|
360
|
-
function sanitizeName(key) {
|
|
361
|
-
return key.replace(/[/%]/g, "_") || "remote";
|
|
362
|
-
}
|
|
363
|
-
//#endregion
|
|
364
|
-
//#region src/net/register.ts
|
|
365
|
-
/**
|
|
366
|
-
* Register the networking node types (and the core nodes). Call once in your
|
|
367
|
-
* game entry before loading a multiplayer scene. Explicit — never a side effect.
|
|
368
|
-
*/
|
|
369
|
-
function registerNodesNet() {
|
|
370
|
-
registerCoreNodes();
|
|
371
|
-
registerNode(NetworkSpawner);
|
|
372
|
-
}
|
|
373
|
-
//#endregion
|
|
374
|
-
export { applySyncPatch as i, NetworkSpawner as n, NetworkManager as r, registerNodesNet as t };
|