@esengine/network 1.0.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.
Files changed (38) hide show
  1. package/LICENSE +21 -0
  2. package/dist/NetworkPlugin.d.ts +100 -0
  3. package/dist/NetworkPlugin.d.ts.map +1 -0
  4. package/dist/components/NetworkIdentity.d.ts +51 -0
  5. package/dist/components/NetworkIdentity.d.ts.map +1 -0
  6. package/dist/components/NetworkTransform.d.ts +71 -0
  7. package/dist/components/NetworkTransform.d.ts.map +1 -0
  8. package/dist/index.d.ts +23 -0
  9. package/dist/index.d.ts.map +1 -0
  10. package/dist/index.js +1348 -0
  11. package/dist/index.js.map +1 -0
  12. package/dist/nodes/NetworkNodes.d.ts +77 -0
  13. package/dist/nodes/NetworkNodes.d.ts.map +1 -0
  14. package/dist/nodes/index.d.ts +9 -0
  15. package/dist/nodes/index.d.ts.map +1 -0
  16. package/dist/services/NetworkService.d.ts +62 -0
  17. package/dist/services/NetworkService.d.ts.map +1 -0
  18. package/dist/sync/ClientPrediction.d.ts +158 -0
  19. package/dist/sync/ClientPrediction.d.ts.map +1 -0
  20. package/dist/sync/IInterpolator.d.ts +62 -0
  21. package/dist/sync/IInterpolator.d.ts.map +1 -0
  22. package/dist/sync/IStateSnapshot.d.ts +116 -0
  23. package/dist/sync/IStateSnapshot.d.ts.map +1 -0
  24. package/dist/sync/SnapshotBuffer.d.ts +58 -0
  25. package/dist/sync/SnapshotBuffer.d.ts.map +1 -0
  26. package/dist/sync/TransformInterpolator.d.ts +47 -0
  27. package/dist/sync/TransformInterpolator.d.ts.map +1 -0
  28. package/dist/sync/index.d.ts +15 -0
  29. package/dist/sync/index.d.ts.map +1 -0
  30. package/dist/systems/NetworkInputSystem.d.ts +32 -0
  31. package/dist/systems/NetworkInputSystem.d.ts.map +1 -0
  32. package/dist/systems/NetworkSpawnSystem.d.ts +37 -0
  33. package/dist/systems/NetworkSpawnSystem.d.ts.map +1 -0
  34. package/dist/systems/NetworkSyncSystem.d.ts +39 -0
  35. package/dist/systems/NetworkSyncSystem.d.ts.map +1 -0
  36. package/dist/tokens.d.ts +29 -0
  37. package/dist/tokens.d.ts.map +1 -0
  38. package/package.json +51 -0
package/dist/index.js ADDED
@@ -0,0 +1,1348 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
4
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
5
+
6
+ // src/index.ts
7
+ import { serviceProto as serviceProto2 } from "@esengine/network-protocols";
8
+
9
+ // src/tokens.ts
10
+ import { createServiceToken } from "@esengine/ecs-framework";
11
+ var NetworkServiceToken = createServiceToken("networkService");
12
+ var NetworkSyncSystemToken = createServiceToken("networkSyncSystem");
13
+ var NetworkSpawnSystemToken = createServiceToken("networkSpawnSystem");
14
+ var NetworkInputSystemToken = createServiceToken("networkInputSystem");
15
+
16
+ // src/NetworkPlugin.ts
17
+ import { Core } from "@esengine/ecs-framework";
18
+
19
+ // src/services/NetworkService.ts
20
+ import { WsClient } from "tsrpc-browser";
21
+ import { serviceProto } from "@esengine/network-protocols";
22
+ var ENetworkState = /* @__PURE__ */ (function(ENetworkState2) {
23
+ ENetworkState2[ENetworkState2["Disconnected"] = 0] = "Disconnected";
24
+ ENetworkState2[ENetworkState2["Connecting"] = 1] = "Connecting";
25
+ ENetworkState2[ENetworkState2["Connected"] = 2] = "Connected";
26
+ return ENetworkState2;
27
+ })({});
28
+ function createClient(serverUrl) {
29
+ return new WsClient(serviceProto, {
30
+ server: serverUrl,
31
+ json: true,
32
+ logLevel: "warn"
33
+ });
34
+ }
35
+ __name(createClient, "createClient");
36
+ var _NetworkService = class _NetworkService {
37
+ constructor() {
38
+ __publicField(this, "_client", null);
39
+ __publicField(this, "_state", 0);
40
+ __publicField(this, "_clientId", 0);
41
+ __publicField(this, "_roomId", "");
42
+ __publicField(this, "_callbacks", {});
43
+ }
44
+ get state() {
45
+ return this._state;
46
+ }
47
+ get clientId() {
48
+ return this._clientId;
49
+ }
50
+ get roomId() {
51
+ return this._roomId;
52
+ }
53
+ get isConnected() {
54
+ return this._state === 2;
55
+ }
56
+ /**
57
+ * 设置回调
58
+ * Set callbacks
59
+ */
60
+ setCallbacks(callbacks) {
61
+ this._callbacks = {
62
+ ...this._callbacks,
63
+ ...callbacks
64
+ };
65
+ }
66
+ /**
67
+ * 连接到服务器
68
+ * Connect to server
69
+ */
70
+ async connect(serverUrl, playerName, roomId) {
71
+ if (this._state !== 0) {
72
+ return false;
73
+ }
74
+ this._state = 1;
75
+ this._client = createClient(serverUrl);
76
+ this._setupListeners();
77
+ const connectResult = await this._client.connect();
78
+ if (!connectResult.isSucc) {
79
+ this._state = 0;
80
+ this._callbacks.onError?.(new Error(connectResult.errMsg));
81
+ return false;
82
+ }
83
+ const joinResult = await this._client.callApi("Join", {
84
+ playerName,
85
+ roomId
86
+ });
87
+ if (!joinResult.isSucc) {
88
+ await this._client.disconnect();
89
+ this._state = 0;
90
+ this._callbacks.onError?.(new Error(joinResult.err.message));
91
+ return false;
92
+ }
93
+ this._clientId = joinResult.res.clientId;
94
+ this._roomId = joinResult.res.roomId;
95
+ this._state = 2;
96
+ this._callbacks.onConnected?.(this._clientId, this._roomId);
97
+ return true;
98
+ }
99
+ /**
100
+ * 断开连接
101
+ * Disconnect
102
+ */
103
+ async disconnect() {
104
+ if (this._client) {
105
+ await this._client.disconnect();
106
+ }
107
+ this._state = 0;
108
+ this._clientId = 0;
109
+ this._roomId = "";
110
+ this._client = null;
111
+ }
112
+ /**
113
+ * 发送输入
114
+ * Send input
115
+ */
116
+ sendInput(input) {
117
+ if (!this.isConnected || !this._client) return;
118
+ this._client.sendMsg("Input", {
119
+ input
120
+ });
121
+ }
122
+ _setupListeners() {
123
+ if (!this._client) return;
124
+ this._client.listenMsg("Sync", (msg) => {
125
+ this._callbacks.onSync?.(msg);
126
+ });
127
+ this._client.listenMsg("Spawn", (msg) => {
128
+ this._callbacks.onSpawn?.(msg);
129
+ });
130
+ this._client.listenMsg("Despawn", (msg) => {
131
+ this._callbacks.onDespawn?.(msg);
132
+ });
133
+ this._client.flows.postDisconnectFlow.push((v) => {
134
+ this._state = 0;
135
+ this._callbacks.onDisconnected?.();
136
+ return v;
137
+ });
138
+ }
139
+ };
140
+ __name(_NetworkService, "NetworkService");
141
+ var NetworkService = _NetworkService;
142
+
143
+ // src/systems/NetworkSyncSystem.ts
144
+ import { EntitySystem, Matcher, Time } from "@esengine/ecs-framework";
145
+
146
+ // src/components/NetworkIdentity.ts
147
+ import { Component, ECSComponent, Serialize, Serializable, Property } from "@esengine/ecs-framework";
148
+ function _ts_decorate(decorators, target, key, desc) {
149
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
150
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
151
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
152
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
153
+ }
154
+ __name(_ts_decorate, "_ts_decorate");
155
+ function _ts_metadata(k, v) {
156
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
157
+ }
158
+ __name(_ts_metadata, "_ts_metadata");
159
+ var _NetworkIdentity = class _NetworkIdentity extends Component {
160
+ constructor() {
161
+ super(...arguments);
162
+ /**
163
+ * 网络实体 ID
164
+ * Network entity ID
165
+ */
166
+ __publicField(this, "netId", 0);
167
+ /**
168
+ * 所有者客户端 ID
169
+ * Owner client ID
170
+ */
171
+ __publicField(this, "ownerId", 0);
172
+ /**
173
+ * 是否为本地玩家拥有
174
+ * Is owned by local player
175
+ */
176
+ __publicField(this, "bIsLocalPlayer", false);
177
+ /**
178
+ * 是否有权限控制
179
+ * Has authority
180
+ */
181
+ __publicField(this, "bHasAuthority", false);
182
+ /**
183
+ * 预制体类型
184
+ * Prefab type
185
+ */
186
+ __publicField(this, "prefabType", "");
187
+ /**
188
+ * 同步间隔 (ms)
189
+ * Sync interval in milliseconds
190
+ */
191
+ __publicField(this, "syncInterval", 100);
192
+ /**
193
+ * 上次同步时间
194
+ * Last sync time
195
+ */
196
+ __publicField(this, "lastSyncTime", 0);
197
+ }
198
+ /**
199
+ * 检查是否需要同步
200
+ * Check if sync is needed
201
+ */
202
+ needsSync(now) {
203
+ return now - this.lastSyncTime >= this.syncInterval;
204
+ }
205
+ };
206
+ __name(_NetworkIdentity, "NetworkIdentity");
207
+ var NetworkIdentity = _NetworkIdentity;
208
+ _ts_decorate([
209
+ Serialize(),
210
+ Property({
211
+ type: "integer",
212
+ label: "Net ID",
213
+ readOnly: true
214
+ }),
215
+ _ts_metadata("design:type", Number)
216
+ ], NetworkIdentity.prototype, "netId", void 0);
217
+ _ts_decorate([
218
+ Serialize(),
219
+ Property({
220
+ type: "integer",
221
+ label: "Owner ID",
222
+ readOnly: true
223
+ }),
224
+ _ts_metadata("design:type", Number)
225
+ ], NetworkIdentity.prototype, "ownerId", void 0);
226
+ _ts_decorate([
227
+ Serialize(),
228
+ Property({
229
+ type: "string",
230
+ label: "Prefab Type"
231
+ }),
232
+ _ts_metadata("design:type", String)
233
+ ], NetworkIdentity.prototype, "prefabType", void 0);
234
+ _ts_decorate([
235
+ Serialize(),
236
+ Property({
237
+ type: "number",
238
+ label: "Sync Interval",
239
+ min: 16
240
+ }),
241
+ _ts_metadata("design:type", Number)
242
+ ], NetworkIdentity.prototype, "syncInterval", void 0);
243
+ NetworkIdentity = _ts_decorate([
244
+ ECSComponent("NetworkIdentity"),
245
+ Serializable({
246
+ version: 1,
247
+ typeId: "NetworkIdentity"
248
+ })
249
+ ], NetworkIdentity);
250
+
251
+ // src/components/NetworkTransform.ts
252
+ import { Component as Component2, ECSComponent as ECSComponent2, Serialize as Serialize2, Serializable as Serializable2, Property as Property2 } from "@esengine/ecs-framework";
253
+ function _ts_decorate2(decorators, target, key, desc) {
254
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
255
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
256
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
257
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
258
+ }
259
+ __name(_ts_decorate2, "_ts_decorate");
260
+ function _ts_metadata2(k, v) {
261
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
262
+ }
263
+ __name(_ts_metadata2, "_ts_metadata");
264
+ var _NetworkTransform = class _NetworkTransform extends Component2 {
265
+ constructor() {
266
+ super(...arguments);
267
+ /**
268
+ * 目标位置 X
269
+ * Target position X
270
+ */
271
+ __publicField(this, "targetX", 0);
272
+ /**
273
+ * 目标位置 Y
274
+ * Target position Y
275
+ */
276
+ __publicField(this, "targetY", 0);
277
+ /**
278
+ * 目标旋转
279
+ * Target rotation
280
+ */
281
+ __publicField(this, "targetRotation", 0);
282
+ /**
283
+ * 当前位置 X
284
+ * Current position X
285
+ */
286
+ __publicField(this, "currentX", 0);
287
+ /**
288
+ * 当前位置 Y
289
+ * Current position Y
290
+ */
291
+ __publicField(this, "currentY", 0);
292
+ /**
293
+ * 当前旋转
294
+ * Current rotation
295
+ */
296
+ __publicField(this, "currentRotation", 0);
297
+ /**
298
+ * 插值速度
299
+ * Interpolation speed
300
+ */
301
+ __publicField(this, "lerpSpeed", 10);
302
+ /**
303
+ * 是否启用插值
304
+ * Enable interpolation
305
+ */
306
+ __publicField(this, "bInterpolate", true);
307
+ /**
308
+ * 同步间隔 (ms)
309
+ * Sync interval in milliseconds
310
+ */
311
+ __publicField(this, "syncInterval", 50);
312
+ /**
313
+ * 上次同步时间
314
+ * Last sync time
315
+ */
316
+ __publicField(this, "lastSyncTime", 0);
317
+ }
318
+ /**
319
+ * 设置目标位置
320
+ * Set target position
321
+ */
322
+ setTarget(x, y, rotation) {
323
+ this.targetX = x;
324
+ this.targetY = y;
325
+ if (rotation !== void 0) {
326
+ this.targetRotation = rotation;
327
+ }
328
+ }
329
+ /**
330
+ * 立即跳转到目标位置
331
+ * Snap to target position immediately
332
+ */
333
+ snap() {
334
+ this.currentX = this.targetX;
335
+ this.currentY = this.targetY;
336
+ this.currentRotation = this.targetRotation;
337
+ }
338
+ };
339
+ __name(_NetworkTransform, "NetworkTransform");
340
+ var NetworkTransform = _NetworkTransform;
341
+ _ts_decorate2([
342
+ Serialize2(),
343
+ Property2({
344
+ type: "number",
345
+ label: "Lerp Speed",
346
+ min: 0.1,
347
+ max: 50
348
+ }),
349
+ _ts_metadata2("design:type", Number)
350
+ ], NetworkTransform.prototype, "lerpSpeed", void 0);
351
+ _ts_decorate2([
352
+ Serialize2(),
353
+ Property2({
354
+ type: "boolean",
355
+ label: "Interpolate"
356
+ }),
357
+ _ts_metadata2("design:type", Boolean)
358
+ ], NetworkTransform.prototype, "bInterpolate", void 0);
359
+ _ts_decorate2([
360
+ Serialize2(),
361
+ Property2({
362
+ type: "number",
363
+ label: "Sync Interval",
364
+ min: 16
365
+ }),
366
+ _ts_metadata2("design:type", Number)
367
+ ], NetworkTransform.prototype, "syncInterval", void 0);
368
+ NetworkTransform = _ts_decorate2([
369
+ ECSComponent2("NetworkTransform", {
370
+ requires: [
371
+ "NetworkIdentity"
372
+ ]
373
+ }),
374
+ Serializable2({
375
+ version: 1,
376
+ typeId: "NetworkTransform"
377
+ })
378
+ ], NetworkTransform);
379
+
380
+ // src/systems/NetworkSyncSystem.ts
381
+ var _NetworkSyncSystem = class _NetworkSyncSystem extends EntitySystem {
382
+ constructor(networkService) {
383
+ super(Matcher.all(NetworkIdentity, NetworkTransform));
384
+ __publicField(this, "_networkService");
385
+ __publicField(this, "_netIdToEntity", /* @__PURE__ */ new Map());
386
+ this._networkService = networkService;
387
+ }
388
+ onInitialize() {
389
+ this._networkService.setCallbacks({
390
+ onSync: this._handleSync.bind(this)
391
+ });
392
+ }
393
+ /**
394
+ * 处理实体列表
395
+ * Process entities
396
+ */
397
+ process(entities) {
398
+ const deltaTime = Time.deltaTime;
399
+ for (const entity of entities) {
400
+ const transform = this.requireComponent(entity, NetworkTransform);
401
+ const identity = this.requireComponent(entity, NetworkIdentity);
402
+ if (!identity.bHasAuthority && transform.bInterpolate) {
403
+ this._interpolate(transform, deltaTime);
404
+ }
405
+ }
406
+ }
407
+ /**
408
+ * 注册网络实体
409
+ * Register network entity
410
+ */
411
+ registerEntity(netId, entityId) {
412
+ this._netIdToEntity.set(netId, entityId);
413
+ }
414
+ /**
415
+ * 注销网络实体
416
+ * Unregister network entity
417
+ */
418
+ unregisterEntity(netId) {
419
+ this._netIdToEntity.delete(netId);
420
+ }
421
+ /**
422
+ * 根据网络 ID 获取实体 ID
423
+ * Get entity ID by network ID
424
+ */
425
+ getEntityId(netId) {
426
+ return this._netIdToEntity.get(netId);
427
+ }
428
+ _handleSync(msg) {
429
+ for (const state of msg.entities) {
430
+ const entityId = this._netIdToEntity.get(state.netId);
431
+ if (entityId === void 0) continue;
432
+ const entity = this.scene?.findEntityById(entityId);
433
+ if (!entity) continue;
434
+ const transform = entity.getComponent(NetworkTransform);
435
+ if (transform && state.pos) {
436
+ transform.setTarget(state.pos.x, state.pos.y, state.rot);
437
+ }
438
+ }
439
+ }
440
+ _interpolate(transform, deltaTime) {
441
+ const t = Math.min(1, transform.lerpSpeed * deltaTime);
442
+ transform.currentX += (transform.targetX - transform.currentX) * t;
443
+ transform.currentY += (transform.targetY - transform.currentY) * t;
444
+ let angleDiff = transform.targetRotation - transform.currentRotation;
445
+ while (angleDiff > Math.PI) angleDiff -= Math.PI * 2;
446
+ while (angleDiff < -Math.PI) angleDiff += Math.PI * 2;
447
+ transform.currentRotation += angleDiff * t;
448
+ }
449
+ onDestroy() {
450
+ this._netIdToEntity.clear();
451
+ }
452
+ };
453
+ __name(_NetworkSyncSystem, "NetworkSyncSystem");
454
+ var NetworkSyncSystem = _NetworkSyncSystem;
455
+
456
+ // src/systems/NetworkSpawnSystem.ts
457
+ import { EntitySystem as EntitySystem2, Matcher as Matcher2 } from "@esengine/ecs-framework";
458
+ var _NetworkSpawnSystem = class _NetworkSpawnSystem extends EntitySystem2 {
459
+ constructor(networkService, syncSystem) {
460
+ super(Matcher2.nothing());
461
+ __publicField(this, "_networkService");
462
+ __publicField(this, "_syncSystem");
463
+ __publicField(this, "_prefabFactories", /* @__PURE__ */ new Map());
464
+ this._networkService = networkService;
465
+ this._syncSystem = syncSystem;
466
+ }
467
+ onInitialize() {
468
+ this._networkService.setCallbacks({
469
+ onSpawn: this._handleSpawn.bind(this),
470
+ onDespawn: this._handleDespawn.bind(this)
471
+ });
472
+ }
473
+ /**
474
+ * 注册预制体工厂
475
+ * Register prefab factory
476
+ */
477
+ registerPrefab(prefabType, factory) {
478
+ this._prefabFactories.set(prefabType, factory);
479
+ }
480
+ /**
481
+ * 注销预制体工厂
482
+ * Unregister prefab factory
483
+ */
484
+ unregisterPrefab(prefabType) {
485
+ this._prefabFactories.delete(prefabType);
486
+ }
487
+ _handleSpawn(msg) {
488
+ if (!this.scene) return;
489
+ const factory = this._prefabFactories.get(msg.prefab);
490
+ if (!factory) {
491
+ this.logger.warn(`Unknown prefab: ${msg.prefab}`);
492
+ return;
493
+ }
494
+ const entity = factory(this.scene, msg);
495
+ const identity = entity.addComponent(new NetworkIdentity());
496
+ identity.netId = msg.netId;
497
+ identity.ownerId = msg.ownerId;
498
+ identity.prefabType = msg.prefab;
499
+ identity.bHasAuthority = msg.ownerId === this._networkService.clientId;
500
+ identity.bIsLocalPlayer = identity.bHasAuthority;
501
+ const transform = entity.addComponent(new NetworkTransform());
502
+ transform.setTarget(msg.pos.x, msg.pos.y, msg.rot);
503
+ transform.snap();
504
+ this._syncSystem.registerEntity(msg.netId, entity.id);
505
+ }
506
+ _handleDespawn(msg) {
507
+ const entityId = this._syncSystem.getEntityId(msg.netId);
508
+ if (entityId === void 0) return;
509
+ const entity = this.scene?.findEntityById(entityId);
510
+ if (entity) {
511
+ entity.destroy();
512
+ }
513
+ this._syncSystem.unregisterEntity(msg.netId);
514
+ }
515
+ onDestroy() {
516
+ this._prefabFactories.clear();
517
+ }
518
+ };
519
+ __name(_NetworkSpawnSystem, "NetworkSpawnSystem");
520
+ var NetworkSpawnSystem = _NetworkSpawnSystem;
521
+
522
+ // src/systems/NetworkInputSystem.ts
523
+ import { EntitySystem as EntitySystem3, Matcher as Matcher3 } from "@esengine/ecs-framework";
524
+ var _NetworkInputSystem = class _NetworkInputSystem extends EntitySystem3 {
525
+ constructor(networkService) {
526
+ super(Matcher3.nothing());
527
+ __publicField(this, "_networkService");
528
+ __publicField(this, "_frame", 0);
529
+ __publicField(this, "_inputQueue", []);
530
+ this._networkService = networkService;
531
+ }
532
+ /**
533
+ * 处理输入队列
534
+ * Process input queue
535
+ */
536
+ process() {
537
+ if (!this._networkService.isConnected) return;
538
+ this._frame++;
539
+ while (this._inputQueue.length > 0) {
540
+ const input = this._inputQueue.shift();
541
+ input.frame = this._frame;
542
+ this._networkService.sendInput(input);
543
+ }
544
+ }
545
+ /**
546
+ * 添加移动输入
547
+ * Add move input
548
+ */
549
+ addMoveInput(x, y) {
550
+ this._inputQueue.push({
551
+ frame: 0,
552
+ moveDir: {
553
+ x,
554
+ y
555
+ }
556
+ });
557
+ }
558
+ /**
559
+ * 添加动作输入
560
+ * Add action input
561
+ */
562
+ addActionInput(action) {
563
+ const lastInput = this._inputQueue[this._inputQueue.length - 1];
564
+ if (lastInput) {
565
+ lastInput.actions = lastInput.actions || [];
566
+ lastInput.actions.push(action);
567
+ } else {
568
+ this._inputQueue.push({
569
+ frame: 0,
570
+ actions: [
571
+ action
572
+ ]
573
+ });
574
+ }
575
+ }
576
+ onDestroy() {
577
+ this._inputQueue.length = 0;
578
+ }
579
+ };
580
+ __name(_NetworkInputSystem, "NetworkInputSystem");
581
+ var NetworkInputSystem = _NetworkInputSystem;
582
+
583
+ // src/NetworkPlugin.ts
584
+ var _NetworkPlugin = class _NetworkPlugin {
585
+ constructor() {
586
+ __publicField(this, "name", "@esengine/network");
587
+ __publicField(this, "version", "1.0.0");
588
+ __publicField(this, "_networkService");
589
+ __publicField(this, "_syncSystem");
590
+ __publicField(this, "_spawnSystem");
591
+ __publicField(this, "_inputSystem");
592
+ }
593
+ /**
594
+ * 网络服务
595
+ * Network service
596
+ */
597
+ get networkService() {
598
+ return this._networkService;
599
+ }
600
+ /**
601
+ * 同步系统
602
+ * Sync system
603
+ */
604
+ get syncSystem() {
605
+ return this._syncSystem;
606
+ }
607
+ /**
608
+ * 生成系统
609
+ * Spawn system
610
+ */
611
+ get spawnSystem() {
612
+ return this._spawnSystem;
613
+ }
614
+ /**
615
+ * 输入系统
616
+ * Input system
617
+ */
618
+ get inputSystem() {
619
+ return this._inputSystem;
620
+ }
621
+ /**
622
+ * 是否已连接
623
+ * Is connected
624
+ */
625
+ get isConnected() {
626
+ return this._networkService?.isConnected ?? false;
627
+ }
628
+ /**
629
+ * 安装插件
630
+ * Install plugin
631
+ */
632
+ install(_core, _services) {
633
+ this._networkService = new NetworkService();
634
+ const scene = Core.scene;
635
+ if (scene) {
636
+ this._setupSystems(scene);
637
+ }
638
+ }
639
+ /**
640
+ * 卸载插件
641
+ * Uninstall plugin
642
+ */
643
+ uninstall() {
644
+ this._networkService?.disconnect();
645
+ }
646
+ _setupSystems(scene) {
647
+ this._syncSystem = new NetworkSyncSystem(this._networkService);
648
+ this._spawnSystem = new NetworkSpawnSystem(this._networkService, this._syncSystem);
649
+ this._inputSystem = new NetworkInputSystem(this._networkService);
650
+ scene.addSystem(this._syncSystem);
651
+ scene.addSystem(this._spawnSystem);
652
+ scene.addSystem(this._inputSystem);
653
+ }
654
+ /**
655
+ * 连接到服务器
656
+ * Connect to server
657
+ */
658
+ async connect(serverUrl, playerName, roomId) {
659
+ return this._networkService.connect(serverUrl, playerName, roomId);
660
+ }
661
+ /**
662
+ * 断开连接
663
+ * Disconnect
664
+ */
665
+ async disconnect() {
666
+ await this._networkService.disconnect();
667
+ }
668
+ /**
669
+ * 注册预制体工厂
670
+ * Register prefab factory
671
+ */
672
+ registerPrefab(prefabType, factory) {
673
+ this._spawnSystem?.registerPrefab(prefabType, factory);
674
+ }
675
+ /**
676
+ * 发送移动输入
677
+ * Send move input
678
+ */
679
+ sendMoveInput(x, y) {
680
+ this._inputSystem?.addMoveInput(x, y);
681
+ }
682
+ /**
683
+ * 发送动作输入
684
+ * Send action input
685
+ */
686
+ sendActionInput(action) {
687
+ this._inputSystem?.addActionInput(action);
688
+ }
689
+ };
690
+ __name(_NetworkPlugin, "NetworkPlugin");
691
+ var NetworkPlugin = _NetworkPlugin;
692
+
693
+ // src/sync/SnapshotBuffer.ts
694
+ var _SnapshotBuffer = class _SnapshotBuffer {
695
+ constructor(config) {
696
+ __publicField(this, "_buffer", []);
697
+ __publicField(this, "_maxSize");
698
+ __publicField(this, "_interpolationDelay");
699
+ this._maxSize = config.maxSize;
700
+ this._interpolationDelay = config.interpolationDelay;
701
+ }
702
+ get size() {
703
+ return this._buffer.length;
704
+ }
705
+ /**
706
+ * @zh 获取插值延迟
707
+ * @en Get interpolation delay
708
+ */
709
+ get interpolationDelay() {
710
+ return this._interpolationDelay;
711
+ }
712
+ /**
713
+ * @zh 添加快照
714
+ * @en Add snapshot
715
+ */
716
+ push(snapshot) {
717
+ let insertIndex = this._buffer.length;
718
+ for (let i = this._buffer.length - 1; i >= 0; i--) {
719
+ if (this._buffer[i].timestamp <= snapshot.timestamp) {
720
+ insertIndex = i + 1;
721
+ break;
722
+ }
723
+ if (i === 0) {
724
+ insertIndex = 0;
725
+ }
726
+ }
727
+ this._buffer.splice(insertIndex, 0, snapshot);
728
+ while (this._buffer.length > this._maxSize) {
729
+ this._buffer.shift();
730
+ }
731
+ }
732
+ /**
733
+ * @zh 获取用于插值的两个快照
734
+ * @en Get two snapshots for interpolation
735
+ */
736
+ getInterpolationSnapshots(renderTime) {
737
+ if (this._buffer.length < 2) {
738
+ return null;
739
+ }
740
+ const targetTime = renderTime - this._interpolationDelay;
741
+ for (let i = 0; i < this._buffer.length - 1; i++) {
742
+ const prev = this._buffer[i];
743
+ const next = this._buffer[i + 1];
744
+ if (prev.timestamp <= targetTime && next.timestamp >= targetTime) {
745
+ const duration = next.timestamp - prev.timestamp;
746
+ const t = duration > 0 ? (targetTime - prev.timestamp) / duration : 0;
747
+ return [
748
+ prev,
749
+ next,
750
+ Math.max(0, Math.min(1, t))
751
+ ];
752
+ }
753
+ }
754
+ if (targetTime > this._buffer[this._buffer.length - 1].timestamp) {
755
+ const prev = this._buffer[this._buffer.length - 2];
756
+ const next = this._buffer[this._buffer.length - 1];
757
+ const duration = next.timestamp - prev.timestamp;
758
+ const t = duration > 0 ? (targetTime - prev.timestamp) / duration : 1;
759
+ return [
760
+ prev,
761
+ next,
762
+ Math.min(t, 2)
763
+ ];
764
+ }
765
+ return null;
766
+ }
767
+ /**
768
+ * @zh 获取最新快照
769
+ * @en Get latest snapshot
770
+ */
771
+ getLatest() {
772
+ return this._buffer.length > 0 ? this._buffer[this._buffer.length - 1] : null;
773
+ }
774
+ /**
775
+ * @zh 获取特定时间之后的所有快照
776
+ * @en Get all snapshots after a specific time
777
+ */
778
+ getSnapshotsAfter(timestamp) {
779
+ return this._buffer.filter((s) => s.timestamp > timestamp);
780
+ }
781
+ /**
782
+ * @zh 清空缓冲区
783
+ * @en Clear buffer
784
+ */
785
+ clear() {
786
+ this._buffer.length = 0;
787
+ }
788
+ };
789
+ __name(_SnapshotBuffer, "SnapshotBuffer");
790
+ var SnapshotBuffer = _SnapshotBuffer;
791
+ function createSnapshotBuffer(maxSize = 30, interpolationDelay = 100) {
792
+ return new SnapshotBuffer({
793
+ maxSize,
794
+ interpolationDelay
795
+ });
796
+ }
797
+ __name(createSnapshotBuffer, "createSnapshotBuffer");
798
+
799
+ // src/sync/IInterpolator.ts
800
+ function lerp(a, b, t) {
801
+ return a + (b - a) * t;
802
+ }
803
+ __name(lerp, "lerp");
804
+ function lerpAngle(a, b, t) {
805
+ let diff = b - a;
806
+ while (diff > Math.PI) diff -= Math.PI * 2;
807
+ while (diff < -Math.PI) diff += Math.PI * 2;
808
+ return a + diff * t;
809
+ }
810
+ __name(lerpAngle, "lerpAngle");
811
+ function smoothDamp(current, target, velocity, smoothTime, deltaTime, maxSpeed = Infinity) {
812
+ smoothTime = Math.max(1e-4, smoothTime);
813
+ const omega = 2 / smoothTime;
814
+ const x = omega * deltaTime;
815
+ const exp = 1 / (1 + x + 0.48 * x * x + 0.235 * x * x * x);
816
+ let change = current - target;
817
+ const maxChange = maxSpeed * smoothTime;
818
+ change = Math.max(-maxChange, Math.min(maxChange, change));
819
+ const temp = (velocity + omega * change) * deltaTime;
820
+ let newVelocity = (velocity - omega * temp) * exp;
821
+ let newValue = target + (change + temp) * exp;
822
+ if (target - current > 0 === newValue > target) {
823
+ newValue = target;
824
+ newVelocity = (newValue - target) / deltaTime;
825
+ }
826
+ return [
827
+ newValue,
828
+ newVelocity
829
+ ];
830
+ }
831
+ __name(smoothDamp, "smoothDamp");
832
+
833
+ // src/sync/TransformInterpolator.ts
834
+ var _TransformInterpolator = class _TransformInterpolator {
835
+ /**
836
+ * @zh 在两个变换状态之间插值
837
+ * @en Interpolate between two transform states
838
+ */
839
+ interpolate(from, to, t) {
840
+ return {
841
+ x: lerp(from.x, to.x, t),
842
+ y: lerp(from.y, to.y, t),
843
+ rotation: lerpAngle(from.rotation, to.rotation, t)
844
+ };
845
+ }
846
+ /**
847
+ * @zh 基于速度外推变换状态
848
+ * @en Extrapolate transform state based on velocity
849
+ */
850
+ extrapolate(state, deltaTime) {
851
+ return {
852
+ x: state.x + state.velocityX * deltaTime,
853
+ y: state.y + state.velocityY * deltaTime,
854
+ rotation: state.rotation + state.angularVelocity * deltaTime,
855
+ velocityX: state.velocityX,
856
+ velocityY: state.velocityY,
857
+ angularVelocity: state.angularVelocity
858
+ };
859
+ }
860
+ };
861
+ __name(_TransformInterpolator, "TransformInterpolator");
862
+ var TransformInterpolator = _TransformInterpolator;
863
+ var _HermiteTransformInterpolator = class _HermiteTransformInterpolator {
864
+ /**
865
+ * @zh 使用赫尔米特插值
866
+ * @en Use Hermite interpolation
867
+ */
868
+ interpolate(from, to, t) {
869
+ const t2 = t * t;
870
+ const t3 = t2 * t;
871
+ const h00 = 2 * t3 - 3 * t2 + 1;
872
+ const h10 = t3 - 2 * t2 + t;
873
+ const h01 = -2 * t3 + 3 * t2;
874
+ const h11 = t3 - t2;
875
+ const dt = 0.1;
876
+ const x = h00 * from.x + h10 * from.velocityX * dt + h01 * to.x + h11 * to.velocityX * dt;
877
+ const y = h00 * from.y + h10 * from.velocityY * dt + h01 * to.y + h11 * to.velocityY * dt;
878
+ const dh00 = 6 * t2 - 6 * t;
879
+ const dh10 = 3 * t2 - 4 * t + 1;
880
+ const dh01 = -6 * t2 + 6 * t;
881
+ const dh11 = 3 * t2 - 2 * t;
882
+ const velocityX = (dh00 * from.x + dh10 * from.velocityX * dt + dh01 * to.x + dh11 * to.velocityX * dt) / dt;
883
+ const velocityY = (dh00 * from.y + dh10 * from.velocityY * dt + dh01 * to.y + dh11 * to.velocityY * dt) / dt;
884
+ return {
885
+ x,
886
+ y,
887
+ rotation: lerpAngle(from.rotation, to.rotation, t),
888
+ velocityX,
889
+ velocityY,
890
+ angularVelocity: lerp(from.angularVelocity, to.angularVelocity, t)
891
+ };
892
+ }
893
+ };
894
+ __name(_HermiteTransformInterpolator, "HermiteTransformInterpolator");
895
+ var HermiteTransformInterpolator = _HermiteTransformInterpolator;
896
+ function createTransformInterpolator() {
897
+ return new TransformInterpolator();
898
+ }
899
+ __name(createTransformInterpolator, "createTransformInterpolator");
900
+ function createHermiteTransformInterpolator() {
901
+ return new HermiteTransformInterpolator();
902
+ }
903
+ __name(createHermiteTransformInterpolator, "createHermiteTransformInterpolator");
904
+
905
+ // src/sync/ClientPrediction.ts
906
+ var _ClientPrediction = class _ClientPrediction {
907
+ constructor(predictor, config) {
908
+ __publicField(this, "_predictor");
909
+ __publicField(this, "_config");
910
+ __publicField(this, "_pendingInputs", []);
911
+ __publicField(this, "_lastAcknowledgedSequence", 0);
912
+ __publicField(this, "_currentSequence", 0);
913
+ __publicField(this, "_lastServerState", null);
914
+ __publicField(this, "_predictedState", null);
915
+ __publicField(this, "_correctionOffset", {
916
+ x: 0,
917
+ y: 0
918
+ });
919
+ this._predictor = predictor;
920
+ this._config = {
921
+ maxUnacknowledgedInputs: 60,
922
+ reconciliationThreshold: 0.1,
923
+ reconciliationSpeed: 10,
924
+ ...config
925
+ };
926
+ }
927
+ /**
928
+ * @zh 获取当前预测状态
929
+ * @en Get current predicted state
930
+ */
931
+ get predictedState() {
932
+ return this._predictedState;
933
+ }
934
+ /**
935
+ * @zh 获取校正偏移
936
+ * @en Get correction offset
937
+ */
938
+ get correctionOffset() {
939
+ return this._correctionOffset;
940
+ }
941
+ /**
942
+ * @zh 获取待确认输入数量
943
+ * @en Get pending input count
944
+ */
945
+ get pendingInputCount() {
946
+ return this._pendingInputs.length;
947
+ }
948
+ /**
949
+ * @zh 记录并预测输入
950
+ * @en Record and predict input
951
+ *
952
+ * @param input - @zh 输入数据 @en Input data
953
+ * @param currentState - @zh 当前状态 @en Current state
954
+ * @param deltaTime - @zh 时间间隔 @en Delta time
955
+ * @returns @zh 预测的状态 @en Predicted state
956
+ */
957
+ recordInput(input, currentState, deltaTime) {
958
+ this._currentSequence++;
959
+ const inputSnapshot = {
960
+ sequence: this._currentSequence,
961
+ input,
962
+ timestamp: Date.now()
963
+ };
964
+ this._pendingInputs.push(inputSnapshot);
965
+ while (this._pendingInputs.length > this._config.maxUnacknowledgedInputs) {
966
+ this._pendingInputs.shift();
967
+ }
968
+ this._predictedState = this._predictor.predict(currentState, input, deltaTime);
969
+ return this._predictedState;
970
+ }
971
+ /**
972
+ * @zh 获取下一个要发送的输入
973
+ * @en Get next input to send
974
+ */
975
+ getInputToSend() {
976
+ return this._pendingInputs.length > 0 ? this._pendingInputs[this._pendingInputs.length - 1] : null;
977
+ }
978
+ /**
979
+ * @zh 获取当前序列号
980
+ * @en Get current sequence number
981
+ */
982
+ get currentSequence() {
983
+ return this._currentSequence;
984
+ }
985
+ /**
986
+ * @zh 处理服务器状态并进行校正
987
+ * @en Process server state and reconcile
988
+ *
989
+ * @param serverState - @zh 服务器状态 @en Server state
990
+ * @param acknowledgedSequence - @zh 已确认的输入序列号 @en Acknowledged input sequence
991
+ * @param stateGetter - @zh 获取状态位置的函数 @en Function to get state position
992
+ * @param deltaTime - @zh 帧时间 @en Frame delta time
993
+ */
994
+ reconcile(serverState, acknowledgedSequence, stateGetter, deltaTime) {
995
+ this._lastServerState = serverState;
996
+ this._lastAcknowledgedSequence = acknowledgedSequence;
997
+ while (this._pendingInputs.length > 0 && this._pendingInputs[0].sequence <= acknowledgedSequence) {
998
+ this._pendingInputs.shift();
999
+ }
1000
+ let state = serverState;
1001
+ for (const inputSnapshot of this._pendingInputs) {
1002
+ state = this._predictor.predict(state, inputSnapshot.input, deltaTime);
1003
+ }
1004
+ const serverPos = stateGetter(serverState);
1005
+ const predictedPos = stateGetter(state);
1006
+ const errorX = serverPos.x - predictedPos.x;
1007
+ const errorY = serverPos.y - predictedPos.y;
1008
+ const errorMagnitude = Math.sqrt(errorX * errorX + errorY * errorY);
1009
+ if (errorMagnitude > this._config.reconciliationThreshold) {
1010
+ const t = Math.min(1, this._config.reconciliationSpeed * deltaTime);
1011
+ this._correctionOffset.x += errorX * t;
1012
+ this._correctionOffset.y += errorY * t;
1013
+ }
1014
+ const decayRate = 0.9;
1015
+ this._correctionOffset.x *= decayRate;
1016
+ this._correctionOffset.y *= decayRate;
1017
+ this._predictedState = state;
1018
+ return state;
1019
+ }
1020
+ /**
1021
+ * @zh 清空预测状态
1022
+ * @en Clear prediction state
1023
+ */
1024
+ clear() {
1025
+ this._pendingInputs.length = 0;
1026
+ this._lastAcknowledgedSequence = 0;
1027
+ this._currentSequence = 0;
1028
+ this._lastServerState = null;
1029
+ this._predictedState = null;
1030
+ this._correctionOffset = {
1031
+ x: 0,
1032
+ y: 0
1033
+ };
1034
+ }
1035
+ };
1036
+ __name(_ClientPrediction, "ClientPrediction");
1037
+ var ClientPrediction = _ClientPrediction;
1038
+ function createClientPrediction(predictor, config) {
1039
+ return new ClientPrediction(predictor, config);
1040
+ }
1041
+ __name(createClientPrediction, "createClientPrediction");
1042
+
1043
+ // src/nodes/NetworkNodes.ts
1044
+ var IsLocalPlayerTemplate = {
1045
+ type: "IsLocalPlayer",
1046
+ title: "Is Local Player",
1047
+ category: "entity",
1048
+ description: "Check if this entity is the local player / \u68C0\u67E5\u6B64\u5B9E\u4F53\u662F\u5426\u662F\u672C\u5730\u73A9\u5BB6",
1049
+ keywords: [
1050
+ "network",
1051
+ "local",
1052
+ "player",
1053
+ "authority",
1054
+ "owner"
1055
+ ],
1056
+ menuPath: [
1057
+ "Network",
1058
+ "Is Local Player"
1059
+ ],
1060
+ isPure: true,
1061
+ inputs: [],
1062
+ outputs: [
1063
+ {
1064
+ name: "isLocal",
1065
+ displayName: "Is Local",
1066
+ type: "bool"
1067
+ }
1068
+ ],
1069
+ color: "#ff9800"
1070
+ };
1071
+ var _IsLocalPlayerExecutor = class _IsLocalPlayerExecutor {
1072
+ execute(node, context) {
1073
+ var _a;
1074
+ const ctx = context;
1075
+ let isLocal = false;
1076
+ if (ctx.entity) {
1077
+ const identity = ctx.entity.getComponent((_a = class {
1078
+ constructor() {
1079
+ __publicField(this, "bIsLocalPlayer", false);
1080
+ }
1081
+ }, __name(_a, "NetworkIdentity"), _a));
1082
+ if (identity) {
1083
+ isLocal = identity.bIsLocalPlayer;
1084
+ }
1085
+ }
1086
+ return {
1087
+ outputs: {
1088
+ isLocal
1089
+ }
1090
+ };
1091
+ }
1092
+ };
1093
+ __name(_IsLocalPlayerExecutor, "IsLocalPlayerExecutor");
1094
+ var IsLocalPlayerExecutor = _IsLocalPlayerExecutor;
1095
+ var IsServerTemplate = {
1096
+ type: "IsServer",
1097
+ title: "Is Server",
1098
+ category: "entity",
1099
+ description: "Check if running on server / \u68C0\u67E5\u662F\u5426\u5728\u670D\u52A1\u5668\u4E0A\u8FD0\u884C",
1100
+ keywords: [
1101
+ "network",
1102
+ "server",
1103
+ "authority",
1104
+ "host"
1105
+ ],
1106
+ menuPath: [
1107
+ "Network",
1108
+ "Is Server"
1109
+ ],
1110
+ isPure: true,
1111
+ inputs: [],
1112
+ outputs: [
1113
+ {
1114
+ name: "isServer",
1115
+ displayName: "Is Server",
1116
+ type: "bool"
1117
+ }
1118
+ ],
1119
+ color: "#ff9800"
1120
+ };
1121
+ var _IsServerExecutor = class _IsServerExecutor {
1122
+ execute(_node, context) {
1123
+ const ctx = context;
1124
+ return {
1125
+ outputs: {
1126
+ isServer: ctx.isServer ?? false
1127
+ }
1128
+ };
1129
+ }
1130
+ };
1131
+ __name(_IsServerExecutor, "IsServerExecutor");
1132
+ var IsServerExecutor = _IsServerExecutor;
1133
+ var HasAuthorityTemplate = {
1134
+ type: "HasAuthority",
1135
+ title: "Has Authority",
1136
+ category: "entity",
1137
+ description: "Check if this entity has authority / \u68C0\u67E5\u6B64\u5B9E\u4F53\u662F\u5426\u6709\u6743\u9650\u63A7\u5236",
1138
+ keywords: [
1139
+ "network",
1140
+ "authority",
1141
+ "control",
1142
+ "owner"
1143
+ ],
1144
+ menuPath: [
1145
+ "Network",
1146
+ "Has Authority"
1147
+ ],
1148
+ isPure: true,
1149
+ inputs: [],
1150
+ outputs: [
1151
+ {
1152
+ name: "hasAuthority",
1153
+ displayName: "Has Authority",
1154
+ type: "bool"
1155
+ }
1156
+ ],
1157
+ color: "#ff9800"
1158
+ };
1159
+ var _HasAuthorityExecutor = class _HasAuthorityExecutor {
1160
+ execute(node, context) {
1161
+ var _a;
1162
+ const ctx = context;
1163
+ let hasAuthority = false;
1164
+ if (ctx.entity) {
1165
+ const identity = ctx.entity.getComponent((_a = class {
1166
+ constructor() {
1167
+ __publicField(this, "bHasAuthority", false);
1168
+ }
1169
+ }, __name(_a, "NetworkIdentity"), _a));
1170
+ if (identity) {
1171
+ hasAuthority = identity.bHasAuthority;
1172
+ }
1173
+ }
1174
+ return {
1175
+ outputs: {
1176
+ hasAuthority
1177
+ }
1178
+ };
1179
+ }
1180
+ };
1181
+ __name(_HasAuthorityExecutor, "HasAuthorityExecutor");
1182
+ var HasAuthorityExecutor = _HasAuthorityExecutor;
1183
+ var GetNetworkIdTemplate = {
1184
+ type: "GetNetworkId",
1185
+ title: "Get Network ID",
1186
+ category: "entity",
1187
+ description: "Get the network ID of this entity / \u83B7\u53D6\u6B64\u5B9E\u4F53\u7684\u7F51\u7EDC ID",
1188
+ keywords: [
1189
+ "network",
1190
+ "id",
1191
+ "netid",
1192
+ "identity"
1193
+ ],
1194
+ menuPath: [
1195
+ "Network",
1196
+ "Get Network ID"
1197
+ ],
1198
+ isPure: true,
1199
+ inputs: [],
1200
+ outputs: [
1201
+ {
1202
+ name: "netId",
1203
+ displayName: "Net ID",
1204
+ type: "int"
1205
+ },
1206
+ {
1207
+ name: "ownerId",
1208
+ displayName: "Owner ID",
1209
+ type: "int"
1210
+ }
1211
+ ],
1212
+ color: "#ff9800"
1213
+ };
1214
+ var _GetNetworkIdExecutor = class _GetNetworkIdExecutor {
1215
+ execute(node, context) {
1216
+ var _a;
1217
+ const ctx = context;
1218
+ let netId = 0;
1219
+ let ownerId = 0;
1220
+ if (ctx.entity) {
1221
+ const identity = ctx.entity.getComponent((_a = class {
1222
+ constructor() {
1223
+ __publicField(this, "netId", 0);
1224
+ __publicField(this, "ownerId", 0);
1225
+ }
1226
+ }, __name(_a, "NetworkIdentity"), _a));
1227
+ if (identity) {
1228
+ netId = identity.netId;
1229
+ ownerId = identity.ownerId;
1230
+ }
1231
+ }
1232
+ return {
1233
+ outputs: {
1234
+ netId,
1235
+ ownerId
1236
+ }
1237
+ };
1238
+ }
1239
+ };
1240
+ __name(_GetNetworkIdExecutor, "GetNetworkIdExecutor");
1241
+ var GetNetworkIdExecutor = _GetNetworkIdExecutor;
1242
+ var GetLocalPlayerIdTemplate = {
1243
+ type: "GetLocalPlayerId",
1244
+ title: "Get Local Player ID",
1245
+ category: "entity",
1246
+ description: "Get the local player ID / \u83B7\u53D6\u672C\u5730\u73A9\u5BB6 ID",
1247
+ keywords: [
1248
+ "network",
1249
+ "local",
1250
+ "player",
1251
+ "id"
1252
+ ],
1253
+ menuPath: [
1254
+ "Network",
1255
+ "Get Local Player ID"
1256
+ ],
1257
+ isPure: true,
1258
+ inputs: [],
1259
+ outputs: [
1260
+ {
1261
+ name: "playerId",
1262
+ displayName: "Player ID",
1263
+ type: "int"
1264
+ }
1265
+ ],
1266
+ color: "#ff9800"
1267
+ };
1268
+ var _GetLocalPlayerIdExecutor = class _GetLocalPlayerIdExecutor {
1269
+ execute(_node, context) {
1270
+ const ctx = context;
1271
+ return {
1272
+ outputs: {
1273
+ playerId: ctx.localPlayerId ?? 0
1274
+ }
1275
+ };
1276
+ }
1277
+ };
1278
+ __name(_GetLocalPlayerIdExecutor, "GetLocalPlayerIdExecutor");
1279
+ var GetLocalPlayerIdExecutor = _GetLocalPlayerIdExecutor;
1280
+ var NetworkNodeDefinitions = {
1281
+ templates: [
1282
+ IsLocalPlayerTemplate,
1283
+ IsServerTemplate,
1284
+ HasAuthorityTemplate,
1285
+ GetNetworkIdTemplate,
1286
+ GetLocalPlayerIdTemplate
1287
+ ],
1288
+ executors: /* @__PURE__ */ new Map([
1289
+ [
1290
+ "IsLocalPlayer",
1291
+ new IsLocalPlayerExecutor()
1292
+ ],
1293
+ [
1294
+ "IsServer",
1295
+ new IsServerExecutor()
1296
+ ],
1297
+ [
1298
+ "HasAuthority",
1299
+ new HasAuthorityExecutor()
1300
+ ],
1301
+ [
1302
+ "GetNetworkId",
1303
+ new GetNetworkIdExecutor()
1304
+ ],
1305
+ [
1306
+ "GetLocalPlayerId",
1307
+ new GetLocalPlayerIdExecutor()
1308
+ ]
1309
+ ])
1310
+ };
1311
+ export {
1312
+ ClientPrediction,
1313
+ ENetworkState,
1314
+ GetLocalPlayerIdExecutor,
1315
+ GetLocalPlayerIdTemplate,
1316
+ GetNetworkIdExecutor,
1317
+ GetNetworkIdTemplate,
1318
+ HasAuthorityExecutor,
1319
+ HasAuthorityTemplate,
1320
+ HermiteTransformInterpolator,
1321
+ IsLocalPlayerExecutor,
1322
+ IsLocalPlayerTemplate,
1323
+ IsServerExecutor,
1324
+ IsServerTemplate,
1325
+ NetworkIdentity,
1326
+ NetworkInputSystem,
1327
+ NetworkInputSystemToken,
1328
+ NetworkNodeDefinitions,
1329
+ NetworkPlugin,
1330
+ NetworkService,
1331
+ NetworkServiceToken,
1332
+ NetworkSpawnSystem,
1333
+ NetworkSpawnSystemToken,
1334
+ NetworkSyncSystem,
1335
+ NetworkSyncSystemToken,
1336
+ NetworkTransform,
1337
+ SnapshotBuffer,
1338
+ TransformInterpolator,
1339
+ createClientPrediction,
1340
+ createHermiteTransformInterpolator,
1341
+ createSnapshotBuffer,
1342
+ createTransformInterpolator,
1343
+ lerp,
1344
+ lerpAngle,
1345
+ serviceProto2 as serviceProto,
1346
+ smoothDamp
1347
+ };
1348
+ //# sourceMappingURL=index.js.map