@esengine/network 2.1.1 → 3.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.
- package/dist/NetworkPlugin.d.ts +150 -8
- package/dist/NetworkPlugin.d.ts.map +1 -1
- package/dist/index.d.ts +11 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2055 -508
- package/dist/index.js.map +1 -1
- package/dist/protocol.d.ts +125 -0
- package/dist/protocol.d.ts.map +1 -1
- package/dist/sync/ComponentSync.d.ts +173 -0
- package/dist/sync/ComponentSync.d.ts.map +1 -0
- package/dist/sync/StateDelta.d.ts +177 -0
- package/dist/sync/StateDelta.d.ts.map +1 -0
- package/dist/sync/index.d.ts +4 -0
- package/dist/sync/index.d.ts.map +1 -1
- package/dist/systems/NetworkAOISystem.d.ts +172 -0
- package/dist/systems/NetworkAOISystem.d.ts.map +1 -0
- package/dist/systems/NetworkInputSystem.d.ts +69 -2
- package/dist/systems/NetworkInputSystem.d.ts.map +1 -1
- package/dist/systems/NetworkPredictionSystem.d.ts +113 -0
- package/dist/systems/NetworkPredictionSystem.d.ts.map +1 -0
- package/dist/systems/NetworkSyncSystem.d.ts +88 -9
- package/dist/systems/NetworkSyncSystem.d.ts.map +1 -1
- package/dist/tokens.d.ts +12 -0
- package/dist/tokens.d.ts.map +1 -1
- package/package.json +12 -3
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/protocol.ts","../src/tokens.ts","../src/NetworkPlugin.ts","../src/services/NetworkService.ts","../src/systems/NetworkSyncSystem.ts","../src/components/NetworkIdentity.ts","../src/components/NetworkTransform.ts","../src/systems/NetworkSpawnSystem.ts","../src/systems/NetworkInputSystem.ts","../src/sync/SnapshotBuffer.ts","../src/sync/IInterpolator.ts","../src/sync/TransformInterpolator.ts","../src/sync/ClientPrediction.ts","../src/nodes/NetworkNodes.ts"],"sourcesContent":["/**\n * @zh @esengine/network 网络同步模块\n * @en @esengine/network Network synchronization module\n *\n * @zh 基于 @esengine/rpc 的网络同步模块,提供类型安全的多人游戏网络通信\n * @en Network synchronization module based on @esengine/rpc for type-safe multiplayer game communication\n */\n\n// ============================================================================\n// Re-export from RPC | 从 RPC 包重新导出\n// ============================================================================\n\nexport { rpc } from '@esengine/rpc'\nexport type {\n ProtocolDef,\n ApiDef,\n MsgDef,\n ApiInput,\n ApiOutput,\n MsgData,\n ApiNames,\n MsgNames,\n RpcError,\n} from '@esengine/rpc'\n\n// ============================================================================\n// Protocol | 协议\n// ============================================================================\n\nexport {\n gameProtocol,\n type GameProtocol,\n type PlayerInput,\n type EntitySyncState,\n type SyncData,\n type SpawnData,\n type DespawnData,\n type JoinRequest,\n type JoinResponse,\n} from './protocol'\n\n// ============================================================================\n// Tokens | 服务令牌\n// ============================================================================\n\nexport {\n NetworkServiceToken,\n NetworkSyncSystemToken,\n NetworkSpawnSystemToken,\n NetworkInputSystemToken,\n} from './tokens'\n\n// ============================================================================\n// Plugin | 插件\n// ============================================================================\n\nexport { NetworkPlugin } from './NetworkPlugin'\n\n// ============================================================================\n// Services | 服务\n// ============================================================================\n\nexport {\n RpcService,\n GameNetworkService,\n NetworkService,\n NetworkState,\n createNetworkService,\n} from './services/NetworkService'\nexport type { NetworkServiceOptions } from './services/NetworkService'\n\n// ============================================================================\n// Components | 组件\n// ============================================================================\n\nexport { NetworkIdentity } from './components/NetworkIdentity'\nexport { NetworkTransform } from './components/NetworkTransform'\n\n// ============================================================================\n// Systems | 系统\n// ============================================================================\n\nexport { NetworkSyncSystem } from './systems/NetworkSyncSystem'\nexport type { SyncMessage } from './systems/NetworkSyncSystem'\nexport { NetworkSpawnSystem } from './systems/NetworkSpawnSystem'\nexport type { PrefabFactory, SpawnMessage, DespawnMessage } from './systems/NetworkSpawnSystem'\nexport { NetworkInputSystem } from './systems/NetworkInputSystem'\n\n// ============================================================================\n// State Sync | 状态同步\n// ============================================================================\n\nexport type {\n IStateSnapshot,\n ITransformState,\n ITransformStateWithVelocity,\n ISnapshotBufferConfig,\n ISnapshotBuffer,\n} from './sync'\n\nexport type {\n IInterpolator,\n IExtrapolator,\n IInputSnapshot,\n IPredictedState,\n IPredictor,\n ClientPredictionConfig,\n} from './sync'\n\nexport {\n lerp,\n lerpAngle,\n smoothDamp,\n SnapshotBuffer,\n createSnapshotBuffer,\n TransformInterpolator,\n HermiteTransformInterpolator,\n createTransformInterpolator,\n createHermiteTransformInterpolator,\n ClientPrediction,\n createClientPrediction,\n} from './sync'\n\n// ============================================================================\n// Blueprint Nodes | 蓝图节点\n// ============================================================================\n\nexport {\n IsLocalPlayerTemplate,\n IsServerTemplate,\n HasAuthorityTemplate,\n GetNetworkIdTemplate,\n GetLocalPlayerIdTemplate,\n IsLocalPlayerExecutor,\n IsServerExecutor,\n HasAuthorityExecutor,\n GetNetworkIdExecutor,\n GetLocalPlayerIdExecutor,\n NetworkNodeDefinitions,\n} from './nodes'\n","/**\n * @zh 游戏网络协议定义\n * @en Game Network Protocol Definition\n *\n * @zh 定义客户端与服务器之间的通信协议\n * @en Defines the communication protocol between client and server\n */\n\nimport { rpc } from '@esengine/rpc'\n\n// ============================================================================\n// Message Types | 消息类型\n// ============================================================================\n\n/**\n * @zh 玩家输入\n * @en Player input\n */\nexport interface PlayerInput {\n /**\n * @zh 帧序号\n * @en Frame number\n */\n frame: number\n\n /**\n * @zh 移动方向\n * @en Move direction\n */\n moveDir?: { x: number; y: number }\n\n /**\n * @zh 动作列表\n * @en Action list\n */\n actions?: string[]\n}\n\n/**\n * @zh 实体同步状态\n * @en Entity sync state\n */\nexport interface EntitySyncState {\n netId: number\n pos?: { x: number; y: number }\n rot?: number\n}\n\n/**\n * @zh 同步消息\n * @en Sync message\n */\nexport interface SyncData {\n /**\n * @zh 服务器帧号\n * @en Server frame number\n */\n frame: number\n\n /**\n * @zh 实体状态列表\n * @en Entity state list\n */\n entities: EntitySyncState[]\n}\n\n/**\n * @zh 生成消息\n * @en Spawn message\n */\nexport interface SpawnData {\n netId: number\n ownerId: number\n prefab: string\n pos: { x: number; y: number }\n rot?: number\n}\n\n/**\n * @zh 销毁消息\n * @en Despawn message\n */\nexport interface DespawnData {\n netId: number\n}\n\n// ============================================================================\n// API Types | API 类型\n// ============================================================================\n\n/**\n * @zh 加入房间请求\n * @en Join room request\n */\nexport interface JoinRequest {\n playerName: string\n roomId?: string\n}\n\n/**\n * @zh 加入房间响应\n * @en Join room response\n */\nexport interface JoinResponse {\n playerId: number\n roomId: string\n}\n\n// ============================================================================\n// Protocol Definition | 协议定义\n// ============================================================================\n\n/**\n * @zh 默认游戏网络协议\n * @en Default game network protocol\n *\n * @example\n * ```typescript\n * // 使用默认协议\n * const service = new NetworkService(gameProtocol)\n *\n * // 或者扩展协议\n * const customProtocol = rpc.define({\n * api: {\n * ...gameProtocol.api,\n * customApi: rpc.api<CustomInput, CustomOutput>(),\n * },\n * msg: {\n * ...gameProtocol.msg,\n * customMsg: rpc.msg<CustomData>(),\n * },\n * })\n * ```\n */\nexport const gameProtocol = rpc.define({\n api: {\n /**\n * @zh 加入房间\n * @en Join room\n */\n join: rpc.api<JoinRequest, JoinResponse>(),\n\n /**\n * @zh 离开房间\n * @en Leave room\n */\n leave: rpc.api<void, void>(),\n },\n msg: {\n /**\n * @zh 玩家输入\n * @en Player input\n */\n input: rpc.msg<PlayerInput>(),\n\n /**\n * @zh 状态同步\n * @en State sync\n */\n sync: rpc.msg<SyncData>(),\n\n /**\n * @zh 实体生成\n * @en Entity spawn\n */\n spawn: rpc.msg<SpawnData>(),\n\n /**\n * @zh 实体销毁\n * @en Entity despawn\n */\n despawn: rpc.msg<DespawnData>(),\n },\n})\n\n/**\n * @zh 游戏协议类型\n * @en Game protocol type\n */\nexport type GameProtocol = typeof gameProtocol\n","/**\n * Network 模块服务令牌\n * Network module service tokens\n */\n\nimport { createServiceToken } from '@esengine/ecs-framework';\nimport type { NetworkService } from './services/NetworkService';\nimport type { NetworkSyncSystem } from './systems/NetworkSyncSystem';\nimport type { NetworkSpawnSystem } from './systems/NetworkSpawnSystem';\nimport type { NetworkInputSystem } from './systems/NetworkInputSystem';\n\n// ============================================================================\n// Network 模块导出的令牌 | Tokens exported by Network module\n// ============================================================================\n\n/**\n * 网络服务令牌\n * Network service token\n */\nexport const NetworkServiceToken = createServiceToken<NetworkService>('networkService');\n\n/**\n * 网络同步系统令牌\n * Network sync system token\n */\nexport const NetworkSyncSystemToken = createServiceToken<NetworkSyncSystem>('networkSyncSystem');\n\n/**\n * 网络生成系统令牌\n * Network spawn system token\n */\nexport const NetworkSpawnSystemToken = createServiceToken<NetworkSpawnSystem>('networkSpawnSystem');\n\n/**\n * 网络输入系统令牌\n * Network input system token\n */\nexport const NetworkInputSystemToken = createServiceToken<NetworkInputSystem>('networkInputSystem');\n","/**\n * @zh 网络插件\n * @en Network Plugin\n */\n\nimport { type IPlugin, Core, type ServiceContainer, type Scene } from '@esengine/ecs-framework'\nimport { GameNetworkService, type NetworkServiceOptions } from './services/NetworkService'\nimport { NetworkSyncSystem } from './systems/NetworkSyncSystem'\nimport { NetworkSpawnSystem, type PrefabFactory } from './systems/NetworkSpawnSystem'\nimport { NetworkInputSystem } from './systems/NetworkInputSystem'\n\n/**\n * @zh 网络插件\n * @en Network plugin\n *\n * @zh 提供基于 @esengine/rpc 的网络同步功能\n * @en Provides @esengine/rpc based network synchronization\n *\n * @example\n * ```typescript\n * import { Core } from '@esengine/ecs-framework'\n * import { NetworkPlugin } from '@esengine/network'\n *\n * const networkPlugin = new NetworkPlugin()\n * await Core.installPlugin(networkPlugin)\n *\n * // 连接到服务器\n * await networkPlugin.connect({ url: 'ws://localhost:3000', playerName: 'Player1' })\n *\n * // 注册预制体\n * networkPlugin.registerPrefab('player', (scene, spawn) => {\n * const entity = scene.createEntity('Player')\n * return entity\n * })\n * ```\n */\nexport class NetworkPlugin implements IPlugin {\n public readonly name = '@esengine/network'\n public readonly version = '2.0.0'\n\n private _networkService!: GameNetworkService\n private _syncSystem!: NetworkSyncSystem\n private _spawnSystem!: NetworkSpawnSystem\n private _inputSystem!: NetworkInputSystem\n private _localPlayerId: number = 0\n\n /**\n * @zh 网络服务\n * @en Network service\n */\n get networkService(): GameNetworkService {\n return this._networkService\n }\n\n /**\n * @zh 同步系统\n * @en Sync system\n */\n get syncSystem(): NetworkSyncSystem {\n return this._syncSystem\n }\n\n /**\n * @zh 生成系统\n * @en Spawn system\n */\n get spawnSystem(): NetworkSpawnSystem {\n return this._spawnSystem\n }\n\n /**\n * @zh 输入系统\n * @en Input system\n */\n get inputSystem(): NetworkInputSystem {\n return this._inputSystem\n }\n\n /**\n * @zh 本地玩家 ID\n * @en Local player ID\n */\n get localPlayerId(): number {\n return this._localPlayerId\n }\n\n /**\n * @zh 是否已连接\n * @en Is connected\n */\n get isConnected(): boolean {\n return this._networkService?.isConnected ?? false\n }\n\n /**\n * @zh 安装插件\n * @en Install plugin\n */\n install(_core: Core, _services: ServiceContainer): void {\n this._networkService = new GameNetworkService()\n\n const scene = Core.scene\n if (scene) {\n this._setupSystems(scene as Scene)\n }\n }\n\n /**\n * @zh 卸载插件\n * @en Uninstall plugin\n */\n uninstall(): void {\n this._networkService?.disconnect()\n }\n\n private _setupSystems(scene: Scene): void {\n this._syncSystem = new NetworkSyncSystem()\n this._spawnSystem = new NetworkSpawnSystem(this._syncSystem)\n this._inputSystem = new NetworkInputSystem(this._networkService)\n\n scene.addSystem(this._syncSystem)\n scene.addSystem(this._spawnSystem)\n scene.addSystem(this._inputSystem)\n\n this._setupMessageHandlers()\n }\n\n private _setupMessageHandlers(): void {\n this._networkService\n .onSync((data) => {\n this._syncSystem.handleSync({ entities: data.entities })\n })\n .onSpawn((data) => {\n this._spawnSystem.handleSpawn(data)\n })\n .onDespawn((data) => {\n this._spawnSystem.handleDespawn(data)\n })\n }\n\n /**\n * @zh 连接到服务器\n * @en Connect to server\n */\n public async connect(options: NetworkServiceOptions & { playerName: string; roomId?: string }): Promise<boolean> {\n try {\n await this._networkService.connect(options)\n\n const result = await this._networkService.call('join', {\n playerName: options.playerName,\n roomId: options.roomId,\n })\n\n this._localPlayerId = result.playerId\n this._spawnSystem.setLocalPlayerId(this._localPlayerId)\n\n return true\n } catch (err) {\n return false\n }\n }\n\n /**\n * @zh 断开连接\n * @en Disconnect\n */\n public async disconnect(): Promise<void> {\n try {\n await this._networkService.call('leave', undefined)\n } catch {\n // ignore\n }\n this._networkService.disconnect()\n }\n\n /**\n * @zh 注册预制体工厂\n * @en Register prefab factory\n */\n public registerPrefab(prefabType: string, factory: PrefabFactory): void {\n this._spawnSystem?.registerPrefab(prefabType, factory)\n }\n\n /**\n * @zh 发送移动输入\n * @en Send move input\n */\n public sendMoveInput(x: number, y: number): void {\n this._inputSystem?.addMoveInput(x, y)\n }\n\n /**\n * @zh 发送动作输入\n * @en Send action input\n */\n public sendActionInput(action: string): void {\n this._inputSystem?.addActionInput(action)\n }\n}\n","/**\n * @zh 网络服务模块\n * @en Network Service Module\n */\n\nimport {\n RpcClient,\n type ProtocolDef,\n type ApiNames,\n type MsgNames,\n type ApiInput,\n type ApiOutput,\n type MsgData,\n type RpcClientOptions,\n} from '@esengine/rpc/client'\nimport { gameProtocol, type GameProtocol, type PlayerInput } from '../protocol'\n\n// ============================================================================\n// Types | 类型定义\n// ============================================================================\n\n/**\n * @zh 连接状态\n * @en Connection state\n */\nexport const enum NetworkState {\n Disconnected = 0,\n Connecting = 1,\n Connected = 2,\n}\n\n/**\n * @zh 网络服务配置\n * @en Network service options\n */\nexport interface NetworkServiceOptions extends RpcClientOptions {\n /**\n * @zh 服务器地址\n * @en Server URL\n */\n url: string\n}\n\n// ============================================================================\n// RpcService - Base Class | RPC 服务基类\n// ============================================================================\n\n/**\n * @zh RPC 服务基类\n * @en RPC Service base class\n *\n * @zh 纯粹的 RPC 客户端封装,不包含任何游戏特定逻辑\n * @en Pure RPC client wrapper without any game-specific logic\n *\n * @typeParam P - @zh 协议定义类型 @en Protocol definition type\n */\nexport class RpcService<P extends ProtocolDef> {\n protected _client: RpcClient<P> | null = null\n protected _state: NetworkState = NetworkState.Disconnected\n\n constructor(protected readonly _protocol: P) {}\n\n /**\n * @zh 获取连接状态\n * @en Get connection state\n */\n get state(): NetworkState {\n return this._state\n }\n\n /**\n * @zh 是否已连接\n * @en Whether connected\n */\n get isConnected(): boolean {\n return this._state === NetworkState.Connected\n }\n\n /**\n * @zh 获取底层 RPC 客户端\n * @en Get underlying RPC client\n */\n get client(): RpcClient<P> | null {\n return this._client\n }\n\n /**\n * @zh 连接到服务器\n * @en Connect to server\n */\n async connect(options: NetworkServiceOptions): Promise<void> {\n if (this._state !== NetworkState.Disconnected) {\n throw new Error('Already connected or connecting')\n }\n\n this._state = NetworkState.Connecting\n\n try {\n this._client = new RpcClient(this._protocol, options.url, {\n ...options,\n onConnect: () => {\n this._state = NetworkState.Connected\n options.onConnect?.()\n },\n onDisconnect: (reason) => {\n this._state = NetworkState.Disconnected\n options.onDisconnect?.(reason)\n },\n onError: options.onError,\n })\n await this._client.connect()\n this._state = NetworkState.Connected\n } catch (err) {\n this._state = NetworkState.Disconnected\n this._client = null\n throw err\n }\n }\n\n /**\n * @zh 断开连接\n * @en Disconnect\n */\n disconnect(): void {\n this._client?.disconnect()\n this._client = null\n this._state = NetworkState.Disconnected\n }\n\n /**\n * @zh 调用 API\n * @en Call API\n */\n call<K extends ApiNames<P>>(\n name: K,\n input: ApiInput<P['api'][K]>\n ): Promise<ApiOutput<P['api'][K]>> {\n if (!this._client) {\n return Promise.reject(new Error('Not connected'))\n }\n return this._client.call(name, input)\n }\n\n /**\n * @zh 发送消息\n * @en Send message\n */\n send<K extends MsgNames<P>>(name: K, data: MsgData<P['msg'][K]>): void {\n this._client?.send(name, data)\n }\n\n /**\n * @zh 监听消息\n * @en Listen to message\n */\n on<K extends MsgNames<P>>(\n name: K,\n handler: (data: MsgData<P['msg'][K]>) => void\n ): this {\n this._client?.on(name, handler)\n return this\n }\n\n /**\n * @zh 取消监听消息\n * @en Remove message listener\n */\n off<K extends MsgNames<P>>(\n name: K,\n handler?: (data: MsgData<P['msg'][K]>) => void\n ): this {\n this._client?.off(name, handler)\n return this\n }\n\n /**\n * @zh 监听消息(只触发一次)\n * @en Listen to message (once)\n */\n once<K extends MsgNames<P>>(\n name: K,\n handler: (data: MsgData<P['msg'][K]>) => void\n ): this {\n this._client?.once(name, handler)\n return this\n }\n}\n\n// ============================================================================\n// GameNetworkService - Game-specific Class | 游戏网络服务\n// ============================================================================\n\n/**\n * @zh 游戏网络服务\n * @en Game network service\n *\n * @zh 基于默认游戏协议的网络服务,提供游戏特定的便捷方法\n * @en Network service based on default game protocol with game-specific convenience methods\n *\n * @example\n * ```typescript\n * const network = new GameNetworkService()\n * await network.connect({ url: 'ws://localhost:3000' })\n *\n * // 游戏特定的便捷方法\n * network.sendInput({ frame: 1, moveDir: { x: 1, y: 0 } })\n *\n * network.onSync((data) => {\n * for (const entity of data.entities) {\n * // 更新实体状态\n * }\n * })\n * ```\n */\nexport class GameNetworkService extends RpcService<GameProtocol> {\n constructor() {\n super(gameProtocol)\n }\n\n /**\n * @zh 发送玩家输入\n * @en Send player input\n */\n sendInput(input: PlayerInput): void {\n this.send('input', input)\n }\n\n /**\n * @zh 监听状态同步\n * @en Listen to state sync\n */\n onSync(handler: (data: MsgData<GameProtocol['msg']['sync']>) => void): this {\n return this.on('sync', handler)\n }\n\n /**\n * @zh 监听实体生成\n * @en Listen to entity spawn\n */\n onSpawn(handler: (data: MsgData<GameProtocol['msg']['spawn']>) => void): this {\n return this.on('spawn', handler)\n }\n\n /**\n * @zh 监听实体销毁\n * @en Listen to entity despawn\n */\n onDespawn(handler: (data: MsgData<GameProtocol['msg']['despawn']>) => void): this {\n return this.on('despawn', handler)\n }\n}\n\n// ============================================================================\n// Exports & Factories | 导出与工厂函数\n// ============================================================================\n\n/**\n * @zh 网络服务(GameNetworkService 的别名)\n * @en Network service (alias for GameNetworkService)\n */\nexport { GameNetworkService as NetworkService }\n\n/**\n * @zh 创建网络服务\n * @en Create network service\n */\nexport function createNetworkService(): GameNetworkService\nexport function createNetworkService<P extends ProtocolDef>(protocol: P): RpcService<P>\nexport function createNetworkService<P extends ProtocolDef>(protocol?: P): RpcService<P> | GameNetworkService {\n if (protocol) {\n return new RpcService(protocol)\n }\n return new GameNetworkService()\n}\n","import { EntitySystem, Matcher, Time, type Entity } from '@esengine/ecs-framework'\nimport { NetworkIdentity } from '../components/NetworkIdentity'\nimport { NetworkTransform } from '../components/NetworkTransform'\n\n/**\n * @zh 同步消息接口\n * @en Sync message interface\n */\nexport interface SyncMessage {\n entities: Array<{\n netId: number\n pos?: { x: number; y: number }\n rot?: number\n }>\n}\n\n/**\n * @zh 网络同步系统\n * @en Network sync system\n *\n * @zh 处理网络实体的状态同步和插值\n * @en Handles state synchronization and interpolation for networked entities\n */\nexport class NetworkSyncSystem extends EntitySystem {\n private _netIdToEntity: Map<number, number> = new Map()\n\n constructor() {\n super(Matcher.all(NetworkIdentity, NetworkTransform))\n }\n\n /**\n * @zh 处理同步消息\n * @en Handle sync message\n */\n handleSync(msg: SyncMessage): void {\n for (const state of msg.entities) {\n const entityId = this._netIdToEntity.get(state.netId)\n if (entityId === undefined) continue\n\n const entity = this.scene?.findEntityById(entityId)\n if (!entity) continue\n\n const transform = entity.getComponent(NetworkTransform)\n if (transform && state.pos) {\n transform.setTarget(state.pos.x, state.pos.y, state.rot ?? 0)\n }\n }\n }\n\n protected override process(entities: readonly Entity[]): void {\n const deltaTime = Time.deltaTime\n\n for (const entity of entities) {\n const transform = this.requireComponent(entity, NetworkTransform)\n const identity = this.requireComponent(entity, NetworkIdentity)\n\n if (!identity.bHasAuthority && transform.bInterpolate) {\n this._interpolate(transform, deltaTime)\n }\n }\n }\n\n /**\n * @zh 注册网络实体\n * @en Register network entity\n */\n registerEntity(netId: number, entityId: number): void {\n this._netIdToEntity.set(netId, entityId)\n }\n\n /**\n * @zh 注销网络实体\n * @en Unregister network entity\n */\n unregisterEntity(netId: number): void {\n this._netIdToEntity.delete(netId)\n }\n\n /**\n * @zh 根据网络 ID 获取实体 ID\n * @en Get entity ID by network ID\n */\n getEntityId(netId: number): number | undefined {\n return this._netIdToEntity.get(netId)\n }\n\n private _interpolate(transform: NetworkTransform, deltaTime: number): void {\n const t = Math.min(1, transform.lerpSpeed * deltaTime)\n\n transform.currentX += (transform.targetX - transform.currentX) * t\n transform.currentY += (transform.targetY - transform.currentY) * t\n\n let angleDiff = transform.targetRotation - transform.currentRotation\n while (angleDiff > Math.PI) angleDiff -= Math.PI * 2\n while (angleDiff < -Math.PI) angleDiff += Math.PI * 2\n transform.currentRotation += angleDiff * t\n }\n\n protected override onDestroy(): void {\n this._netIdToEntity.clear()\n }\n}\n","import { Component, ECSComponent, Serialize, Serializable, Property } from '@esengine/ecs-framework';\n\n/**\n * 网络身份组件\n * Network identity component\n *\n * 标识一个实体在网络上的唯一身份。\n * Identifies an entity's unique identity on the network.\n */\n@ECSComponent('NetworkIdentity')\n@Serializable({ version: 1, typeId: 'NetworkIdentity' })\nexport class NetworkIdentity extends Component {\n /**\n * 网络实体 ID\n * Network entity ID\n */\n @Serialize()\n @Property({ type: 'integer', label: 'Net ID', readOnly: true })\n public netId: number = 0;\n\n /**\n * 所有者客户端 ID\n * Owner client ID\n */\n @Serialize()\n @Property({ type: 'integer', label: 'Owner ID', readOnly: true })\n public ownerId: number = 0;\n\n /**\n * 是否为本地玩家拥有\n * Is owned by local player\n */\n public bIsLocalPlayer: boolean = false;\n\n /**\n * 是否有权限控制\n * Has authority\n */\n public bHasAuthority: boolean = false;\n\n /**\n * 预制体类型\n * Prefab type\n */\n @Serialize()\n @Property({ type: 'string', label: 'Prefab Type' })\n public prefabType: string = '';\n\n /**\n * 同步间隔 (ms)\n * Sync interval in milliseconds\n */\n @Serialize()\n @Property({ type: 'number', label: 'Sync Interval', min: 16 })\n public syncInterval: number = 100;\n\n /**\n * 上次同步时间\n * Last sync time\n */\n public lastSyncTime: number = 0;\n\n /**\n * 检查是否需要同步\n * Check if sync is needed\n */\n public needsSync(now: number): boolean {\n return now - this.lastSyncTime >= this.syncInterval;\n }\n}\n","import { Component, ECSComponent, Serialize, Serializable, Property } from '@esengine/ecs-framework';\n\n/**\n * 网络变换组件\n * Network transform component\n *\n * 同步实体的位置和旋转。支持插值平滑。\n * Syncs entity position and rotation with interpolation smoothing.\n */\n@ECSComponent('NetworkTransform', { requires: ['NetworkIdentity'] })\n@Serializable({ version: 1, typeId: 'NetworkTransform' })\nexport class NetworkTransform extends Component {\n /**\n * 目标位置 X\n * Target position X\n */\n public targetX: number = 0;\n\n /**\n * 目标位置 Y\n * Target position Y\n */\n public targetY: number = 0;\n\n /**\n * 目标旋转\n * Target rotation\n */\n public targetRotation: number = 0;\n\n /**\n * 当前位置 X\n * Current position X\n */\n public currentX: number = 0;\n\n /**\n * 当前位置 Y\n * Current position Y\n */\n public currentY: number = 0;\n\n /**\n * 当前旋转\n * Current rotation\n */\n public currentRotation: number = 0;\n\n /**\n * 插值速度\n * Interpolation speed\n */\n @Serialize()\n @Property({ type: 'number', label: 'Lerp Speed', min: 0.1, max: 50 })\n public lerpSpeed: number = 10;\n\n /**\n * 是否启用插值\n * Enable interpolation\n */\n @Serialize()\n @Property({ type: 'boolean', label: 'Interpolate' })\n public bInterpolate: boolean = true;\n\n /**\n * 同步间隔 (ms)\n * Sync interval in milliseconds\n */\n @Serialize()\n @Property({ type: 'number', label: 'Sync Interval', min: 16 })\n public syncInterval: number = 50;\n\n /**\n * 上次同步时间\n * Last sync time\n */\n public lastSyncTime: number = 0;\n\n /**\n * 设置目标位置\n * Set target position\n */\n public setTarget(x: number, y: number, rotation?: number): void {\n this.targetX = x;\n this.targetY = y;\n if (rotation !== undefined) {\n this.targetRotation = rotation;\n }\n }\n\n /**\n * 立即跳转到目标位置\n * Snap to target position immediately\n */\n public snap(): void {\n this.currentX = this.targetX;\n this.currentY = this.targetY;\n this.currentRotation = this.targetRotation;\n }\n}\n","import { EntitySystem, Entity, type Scene, Matcher } from '@esengine/ecs-framework'\nimport { NetworkIdentity } from '../components/NetworkIdentity'\nimport { NetworkTransform } from '../components/NetworkTransform'\nimport type { NetworkSyncSystem } from './NetworkSyncSystem'\n\n/**\n * @zh 生成消息接口\n * @en Spawn message interface\n */\nexport interface SpawnMessage {\n netId: number\n ownerId: number\n prefab: string\n pos: { x: number; y: number }\n rot?: number\n}\n\n/**\n * @zh 销毁消息接口\n * @en Despawn message interface\n */\nexport interface DespawnMessage {\n netId: number\n}\n\n/**\n * @zh 预制体工厂函数类型\n * @en Prefab factory function type\n */\nexport type PrefabFactory = (scene: Scene, spawn: SpawnMessage) => Entity\n\n/**\n * @zh 网络生成系统\n * @en Network spawn system\n *\n * @zh 处理网络实体的生成和销毁\n * @en Handles spawning and despawning of networked entities\n */\nexport class NetworkSpawnSystem extends EntitySystem {\n private _syncSystem: NetworkSyncSystem\n private _prefabFactories: Map<string, PrefabFactory> = new Map()\n private _localPlayerId: number = 0\n\n constructor(syncSystem: NetworkSyncSystem) {\n super(Matcher.nothing())\n this._syncSystem = syncSystem\n }\n\n /**\n * @zh 设置本地玩家 ID\n * @en Set local player ID\n */\n setLocalPlayerId(id: number): void {\n this._localPlayerId = id\n }\n\n /**\n * @zh 处理生成消息\n * @en Handle spawn message\n */\n handleSpawn(msg: SpawnMessage): Entity | null {\n if (!this.scene) return null\n\n const factory = this._prefabFactories.get(msg.prefab)\n if (!factory) {\n this.logger.warn(`Unknown prefab: ${msg.prefab}`)\n return null\n }\n\n const entity = factory(this.scene, msg)\n\n const identity = entity.addComponent(new NetworkIdentity())\n identity.netId = msg.netId\n identity.ownerId = msg.ownerId\n identity.prefabType = msg.prefab\n identity.bHasAuthority = msg.ownerId === this._localPlayerId\n identity.bIsLocalPlayer = identity.bHasAuthority\n\n const transform = entity.addComponent(new NetworkTransform())\n transform.setTarget(msg.pos.x, msg.pos.y, msg.rot ?? 0)\n transform.snap()\n\n this._syncSystem.registerEntity(msg.netId, entity.id)\n\n return entity\n }\n\n /**\n * @zh 处理销毁消息\n * @en Handle despawn message\n */\n handleDespawn(msg: DespawnMessage): void {\n const entityId = this._syncSystem.getEntityId(msg.netId)\n if (entityId === undefined) return\n\n const entity = this.scene?.findEntityById(entityId)\n if (entity) {\n entity.destroy()\n }\n\n this._syncSystem.unregisterEntity(msg.netId)\n }\n\n /**\n * @zh 注册预制体工厂\n * @en Register prefab factory\n */\n registerPrefab(prefabType: string, factory: PrefabFactory): void {\n this._prefabFactories.set(prefabType, factory)\n }\n\n /**\n * @zh 注销预制体工厂\n * @en Unregister prefab factory\n */\n unregisterPrefab(prefabType: string): void {\n this._prefabFactories.delete(prefabType)\n }\n\n protected override onDestroy(): void {\n this._prefabFactories.clear()\n }\n}\n","/**\n * @zh 网络输入系统\n * @en Network Input System\n */\n\nimport { EntitySystem, Matcher } from '@esengine/ecs-framework'\nimport type { PlayerInput } from '../protocol'\nimport type { NetworkService } from '../services/NetworkService'\n\n/**\n * @zh 网络输入系统\n * @en Network input system\n *\n * @zh 收集本地玩家输入并发送到服务器\n * @en Collects local player input and sends to server\n */\nexport class NetworkInputSystem extends EntitySystem {\n private _networkService: NetworkService\n private _frame: number = 0\n private _inputQueue: PlayerInput[] = []\n\n constructor(networkService: NetworkService) {\n super(Matcher.nothing())\n this._networkService = networkService\n }\n\n /**\n * @zh 处理输入队列\n * @en Process input queue\n */\n protected override process(): void {\n if (!this._networkService.isConnected) return\n\n this._frame++\n\n while (this._inputQueue.length > 0) {\n const input = this._inputQueue.shift()!\n input.frame = this._frame\n this._networkService.sendInput(input)\n }\n }\n\n /**\n * @zh 添加移动输入\n * @en Add move input\n */\n public addMoveInput(x: number, y: number): void {\n this._inputQueue.push({\n frame: 0,\n moveDir: { x, y },\n })\n }\n\n /**\n * @zh 添加动作输入\n * @en Add action input\n */\n public addActionInput(action: string): void {\n const lastInput = this._inputQueue[this._inputQueue.length - 1]\n if (lastInput) {\n lastInput.actions = lastInput.actions || []\n lastInput.actions.push(action)\n } else {\n this._inputQueue.push({\n frame: 0,\n actions: [action],\n })\n }\n }\n\n protected override onDestroy(): void {\n this._inputQueue.length = 0\n }\n}\n","/**\n * @zh 快照缓冲区实现\n * @en Snapshot Buffer Implementation\n *\n * @zh 用于存储和插值网络状态快照\n * @en Stores and interpolates network state snapshots\n */\n\nimport type { IStateSnapshot, ISnapshotBuffer, ISnapshotBufferConfig } from './IStateSnapshot';\n\n// =============================================================================\n// 快照缓冲区实现 | Snapshot Buffer Implementation\n// =============================================================================\n\n/**\n * @zh 快照缓冲区\n * @en Snapshot buffer\n */\nexport class SnapshotBuffer<T> implements ISnapshotBuffer<T> {\n private readonly _buffer: IStateSnapshot<T>[] = [];\n private readonly _maxSize: number;\n private readonly _interpolationDelay: number;\n\n constructor(config: ISnapshotBufferConfig) {\n this._maxSize = config.maxSize;\n this._interpolationDelay = config.interpolationDelay;\n }\n\n get size(): number {\n return this._buffer.length;\n }\n\n /**\n * @zh 获取插值延迟\n * @en Get interpolation delay\n */\n get interpolationDelay(): number {\n return this._interpolationDelay;\n }\n\n /**\n * @zh 添加快照\n * @en Add snapshot\n */\n push(snapshot: IStateSnapshot<T>): void {\n // Insert in sorted order by timestamp\n let insertIndex = this._buffer.length;\n for (let i = this._buffer.length - 1; i >= 0; i--) {\n if (this._buffer[i].timestamp <= snapshot.timestamp) {\n insertIndex = i + 1;\n break;\n }\n if (i === 0) {\n insertIndex = 0;\n }\n }\n\n this._buffer.splice(insertIndex, 0, snapshot);\n\n // Remove old snapshots if buffer is full\n while (this._buffer.length > this._maxSize) {\n this._buffer.shift();\n }\n }\n\n /**\n * @zh 获取用于插值的两个快照\n * @en Get two snapshots for interpolation\n */\n getInterpolationSnapshots(renderTime: number): [IStateSnapshot<T>, IStateSnapshot<T>, number] | null {\n if (this._buffer.length < 2) {\n return null;\n }\n\n // Apply interpolation delay\n const targetTime = renderTime - this._interpolationDelay;\n\n // Find the two snapshots that bracket the target time\n for (let i = 0; i < this._buffer.length - 1; i++) {\n const prev = this._buffer[i];\n const next = this._buffer[i + 1];\n\n if (prev.timestamp <= targetTime && next.timestamp >= targetTime) {\n const duration = next.timestamp - prev.timestamp;\n const t = duration > 0 ? (targetTime - prev.timestamp) / duration : 0;\n return [prev, next, Math.max(0, Math.min(1, t))];\n }\n }\n\n // If target time is beyond buffer, extrapolate from last two snapshots\n if (targetTime > this._buffer[this._buffer.length - 1].timestamp) {\n const prev = this._buffer[this._buffer.length - 2];\n const next = this._buffer[this._buffer.length - 1];\n const duration = next.timestamp - prev.timestamp;\n const t = duration > 0 ? (targetTime - prev.timestamp) / duration : 1;\n // Clamp extrapolation to prevent wild values\n return [prev, next, Math.min(t, 2)];\n }\n\n // Target time is before buffer start\n return null;\n }\n\n /**\n * @zh 获取最新快照\n * @en Get latest snapshot\n */\n getLatest(): IStateSnapshot<T> | null {\n return this._buffer.length > 0 ? this._buffer[this._buffer.length - 1] : null;\n }\n\n /**\n * @zh 获取特定时间之后的所有快照\n * @en Get all snapshots after a specific time\n */\n getSnapshotsAfter(timestamp: number): IStateSnapshot<T>[] {\n return this._buffer.filter(s => s.timestamp > timestamp);\n }\n\n /**\n * @zh 清空缓冲区\n * @en Clear buffer\n */\n clear(): void {\n this._buffer.length = 0;\n }\n}\n\n// =============================================================================\n// 工厂函数 | Factory Functions\n// =============================================================================\n\n/**\n * @zh 创建快照缓冲区\n * @en Create snapshot buffer\n *\n * @param maxSize - @zh 最大快照数量(默认 30)@en Maximum snapshot count (default 30)\n * @param interpolationDelay - @zh 插值延迟毫秒(默认 100)@en Interpolation delay in ms (default 100)\n */\nexport function createSnapshotBuffer<T>(\n maxSize: number = 30,\n interpolationDelay: number = 100\n): SnapshotBuffer<T> {\n return new SnapshotBuffer<T>({ maxSize, interpolationDelay });\n}\n","/**\n * @zh 插值器接口\n * @en Interpolator Interface\n *\n * @zh 提供状态插值的抽象\n * @en Provides abstraction for state interpolation\n */\n\n// =============================================================================\n// 插值器接口 | Interpolator Interface\n// =============================================================================\n\n/**\n * @zh 插值器接口\n * @en Interpolator interface\n */\nexport interface IInterpolator<T> {\n /**\n * @zh 在两个状态之间插值\n * @en Interpolate between two states\n *\n * @param from - @zh 起始状态 @en Start state\n * @param to - @zh 目标状态 @en Target state\n * @param t - @zh 插值因子 (0-1) @en Interpolation factor (0-1)\n * @returns @zh 插值后的状态 @en Interpolated state\n */\n interpolate(from: T, to: T, t: number): T;\n}\n\n/**\n * @zh 外推器接口\n * @en Extrapolator interface\n */\nexport interface IExtrapolator<T> {\n /**\n * @zh 基于当前状态外推\n * @en Extrapolate based on current state\n *\n * @param state - @zh 当前状态 @en Current state\n * @param deltaTime - @zh 外推时间(秒)@en Extrapolation time in seconds\n * @returns @zh 外推后的状态 @en Extrapolated state\n */\n extrapolate(state: T, deltaTime: number): T;\n}\n\n// =============================================================================\n// 内置插值器 | Built-in Interpolators\n// =============================================================================\n\n/**\n * @zh 线性插值函数\n * @en Linear interpolation function\n */\nexport function lerp(a: number, b: number, t: number): number {\n return a + (b - a) * t;\n}\n\n/**\n * @zh 角度插值函数(处理环绕)\n * @en Angle interpolation function (handles wrap-around)\n */\nexport function lerpAngle(a: number, b: number, t: number): number {\n let diff = b - a;\n while (diff > Math.PI) diff -= Math.PI * 2;\n while (diff < -Math.PI) diff += Math.PI * 2;\n return a + diff * t;\n}\n\n/**\n * @zh 平滑阻尼插值\n * @en Smooth damp interpolation\n *\n * @param current - @zh 当前值 @en Current value\n * @param target - @zh 目标值 @en Target value\n * @param velocity - @zh 当前速度(将被修改)@en Current velocity (will be modified)\n * @param smoothTime - @zh 平滑时间 @en Smooth time\n * @param deltaTime - @zh 帧时间 @en Delta time\n * @param maxSpeed - @zh 最大速度 @en Maximum speed\n * @returns @zh [新值, 新速度] @en [new value, new velocity]\n */\nexport function smoothDamp(\n current: number,\n target: number,\n velocity: number,\n smoothTime: number,\n deltaTime: number,\n maxSpeed: number = Infinity\n): [number, number] {\n smoothTime = Math.max(0.0001, smoothTime);\n const omega = 2 / smoothTime;\n const x = omega * deltaTime;\n const exp = 1 / (1 + x + 0.48 * x * x + 0.235 * x * x * x);\n\n let change = current - target;\n const maxChange = maxSpeed * smoothTime;\n change = Math.max(-maxChange, Math.min(maxChange, change));\n\n const temp = (velocity + omega * change) * deltaTime;\n let newVelocity = (velocity - omega * temp) * exp;\n let newValue = target + (change + temp) * exp;\n\n // Prevent overshoot\n if ((target - current > 0) === (newValue > target)) {\n newValue = target;\n newVelocity = (newValue - target) / deltaTime;\n }\n\n return [newValue, newVelocity];\n}\n","/**\n * @zh 变换插值器\n * @en Transform Interpolator\n *\n * @zh 用于网络变换状态的插值\n * @en Interpolates network transform states\n */\n\nimport type { ITransformState, ITransformStateWithVelocity } from './IStateSnapshot';\nimport type { IInterpolator, IExtrapolator } from './IInterpolator';\nimport { lerp, lerpAngle } from './IInterpolator';\n\n// =============================================================================\n// 变换插值器 | Transform Interpolator\n// =============================================================================\n\n/**\n * @zh 变换状态插值器\n * @en Transform state interpolator\n */\nexport class TransformInterpolator implements IInterpolator<ITransformState>, IExtrapolator<ITransformStateWithVelocity> {\n /**\n * @zh 在两个变换状态之间插值\n * @en Interpolate between two transform states\n */\n interpolate(from: ITransformState, to: ITransformState, t: number): ITransformState {\n return {\n x: lerp(from.x, to.x, t),\n y: lerp(from.y, to.y, t),\n rotation: lerpAngle(from.rotation, to.rotation, t)\n };\n }\n\n /**\n * @zh 基于速度外推变换状态\n * @en Extrapolate transform state based on velocity\n */\n extrapolate(state: ITransformStateWithVelocity, deltaTime: number): ITransformStateWithVelocity {\n return {\n x: state.x + state.velocityX * deltaTime,\n y: state.y + state.velocityY * deltaTime,\n rotation: state.rotation + state.angularVelocity * deltaTime,\n velocityX: state.velocityX,\n velocityY: state.velocityY,\n angularVelocity: state.angularVelocity\n };\n }\n}\n\n// =============================================================================\n// 赫尔米特插值器 | Hermite Interpolator\n// =============================================================================\n\n/**\n * @zh 赫尔米特变换插值器(更平滑的曲线)\n * @en Hermite transform interpolator (smoother curves)\n */\nexport class HermiteTransformInterpolator implements IInterpolator<ITransformStateWithVelocity> {\n /**\n * @zh 使用赫尔米特插值\n * @en Use Hermite interpolation\n */\n interpolate(\n from: ITransformStateWithVelocity,\n to: ITransformStateWithVelocity,\n t: number\n ): ITransformStateWithVelocity {\n const t2 = t * t;\n const t3 = t2 * t;\n\n // Hermite basis functions\n const h00 = 2 * t3 - 3 * t2 + 1;\n const h10 = t3 - 2 * t2 + t;\n const h01 = -2 * t3 + 3 * t2;\n const h11 = t3 - t2;\n\n // Estimate time interval (assume 100ms between snapshots)\n const dt = 0.1;\n\n const x = h00 * from.x + h10 * from.velocityX * dt + h01 * to.x + h11 * to.velocityX * dt;\n const y = h00 * from.y + h10 * from.velocityY * dt + h01 * to.y + h11 * to.velocityY * dt;\n\n // Derive velocity from position derivatives\n const dh00 = 6 * t2 - 6 * t;\n const dh10 = 3 * t2 - 4 * t + 1;\n const dh01 = -6 * t2 + 6 * t;\n const dh11 = 3 * t2 - 2 * t;\n\n const velocityX = (dh00 * from.x + dh10 * from.velocityX * dt + dh01 * to.x + dh11 * to.velocityX * dt) / dt;\n const velocityY = (dh00 * from.y + dh10 * from.velocityY * dt + dh01 * to.y + dh11 * to.velocityY * dt) / dt;\n\n return {\n x,\n y,\n rotation: lerpAngle(from.rotation, to.rotation, t),\n velocityX,\n velocityY,\n angularVelocity: lerp(from.angularVelocity, to.angularVelocity, t)\n };\n }\n}\n\n// =============================================================================\n// 工厂函数 | Factory Functions\n// =============================================================================\n\n/**\n * @zh 创建变换插值器\n * @en Create transform interpolator\n */\nexport function createTransformInterpolator(): TransformInterpolator {\n return new TransformInterpolator();\n}\n\n/**\n * @zh 创建赫尔米特变换插值器\n * @en Create Hermite transform interpolator\n */\nexport function createHermiteTransformInterpolator(): HermiteTransformInterpolator {\n return new HermiteTransformInterpolator();\n}\n","/**\n * @zh 客户端预测\n * @en Client Prediction\n *\n * @zh 提供客户端输入预测和服务器校正\n * @en Provides client-side input prediction and server reconciliation\n */\n\n// =============================================================================\n// 输入快照接口 | Input Snapshot Interface\n// =============================================================================\n\n/**\n * @zh 输入快照\n * @en Input snapshot\n */\nexport interface IInputSnapshot<TInput> {\n /**\n * @zh 输入序列号\n * @en Input sequence number\n */\n readonly sequence: number;\n\n /**\n * @zh 输入数据\n * @en Input data\n */\n readonly input: TInput;\n\n /**\n * @zh 输入时间戳\n * @en Input timestamp\n */\n readonly timestamp: number;\n}\n\n/**\n * @zh 预测状态\n * @en Predicted state\n */\nexport interface IPredictedState<TState> {\n /**\n * @zh 状态数据\n * @en State data\n */\n readonly state: TState;\n\n /**\n * @zh 对应的输入序列号\n * @en Corresponding input sequence number\n */\n readonly sequence: number;\n}\n\n// =============================================================================\n// 预测器接口 | Predictor Interface\n// =============================================================================\n\n/**\n * @zh 状态预测器接口\n * @en State predictor interface\n */\nexport interface IPredictor<TState, TInput> {\n /**\n * @zh 根据当前状态和输入预测下一状态\n * @en Predict next state based on current state and input\n *\n * @param state - @zh 当前状态 @en Current state\n * @param input - @zh 输入 @en Input\n * @param deltaTime - @zh 时间间隔 @en Delta time\n * @returns @zh 预测的状态 @en Predicted state\n */\n predict(state: TState, input: TInput, deltaTime: number): TState;\n}\n\n// =============================================================================\n// 客户端预测管理器 | Client Prediction Manager\n// =============================================================================\n\n/**\n * @zh 客户端预测配置\n * @en Client prediction configuration\n */\nexport interface ClientPredictionConfig {\n /**\n * @zh 最大未确认输入数量\n * @en Maximum unacknowledged inputs\n */\n maxUnacknowledgedInputs: number;\n\n /**\n * @zh 校正阈值(超过此值才进行平滑校正)\n * @en Reconciliation threshold (smooth correction only above this value)\n */\n reconciliationThreshold: number;\n\n /**\n * @zh 校正平滑速度\n * @en Reconciliation smoothing speed\n */\n reconciliationSpeed: number;\n}\n\n/**\n * @zh 客户端预测管理器\n * @en Client prediction manager\n */\nexport class ClientPrediction<TState, TInput> {\n private readonly _predictor: IPredictor<TState, TInput>;\n private readonly _config: ClientPredictionConfig;\n private readonly _pendingInputs: IInputSnapshot<TInput>[] = [];\n private _lastAcknowledgedSequence: number = 0;\n private _currentSequence: number = 0;\n private _lastServerState: TState | null = null;\n private _predictedState: TState | null = null;\n private _correctionOffset: { x: number; y: number } = { x: 0, y: 0 };\n\n constructor(predictor: IPredictor<TState, TInput>, config?: Partial<ClientPredictionConfig>) {\n this._predictor = predictor;\n this._config = {\n maxUnacknowledgedInputs: 60,\n reconciliationThreshold: 0.1,\n reconciliationSpeed: 10,\n ...config\n };\n }\n\n /**\n * @zh 获取当前预测状态\n * @en Get current predicted state\n */\n get predictedState(): TState | null {\n return this._predictedState;\n }\n\n /**\n * @zh 获取校正偏移\n * @en Get correction offset\n */\n get correctionOffset(): { x: number; y: number } {\n return this._correctionOffset;\n }\n\n /**\n * @zh 获取待确认输入数量\n * @en Get pending input count\n */\n get pendingInputCount(): number {\n return this._pendingInputs.length;\n }\n\n /**\n * @zh 记录并预测输入\n * @en Record and predict input\n *\n * @param input - @zh 输入数据 @en Input data\n * @param currentState - @zh 当前状态 @en Current state\n * @param deltaTime - @zh 时间间隔 @en Delta time\n * @returns @zh 预测的状态 @en Predicted state\n */\n recordInput(input: TInput, currentState: TState, deltaTime: number): TState {\n this._currentSequence++;\n\n const inputSnapshot: IInputSnapshot<TInput> = {\n sequence: this._currentSequence,\n input,\n timestamp: Date.now()\n };\n\n this._pendingInputs.push(inputSnapshot);\n\n // Remove old inputs if buffer is full\n while (this._pendingInputs.length > this._config.maxUnacknowledgedInputs) {\n this._pendingInputs.shift();\n }\n\n // Predict new state\n this._predictedState = this._predictor.predict(currentState, input, deltaTime);\n\n return this._predictedState;\n }\n\n /**\n * @zh 获取下一个要发送的输入\n * @en Get next input to send\n */\n getInputToSend(): IInputSnapshot<TInput> | null {\n return this._pendingInputs.length > 0 ? this._pendingInputs[this._pendingInputs.length - 1] : null;\n }\n\n /**\n * @zh 获取当前序列号\n * @en Get current sequence number\n */\n get currentSequence(): number {\n return this._currentSequence;\n }\n\n /**\n * @zh 处理服务器状态并进行校正\n * @en Process server state and reconcile\n *\n * @param serverState - @zh 服务器状态 @en Server state\n * @param acknowledgedSequence - @zh 已确认的输入序列号 @en Acknowledged input sequence\n * @param stateGetter - @zh 获取状态位置的函数 @en Function to get state position\n * @param deltaTime - @zh 帧时间 @en Frame delta time\n */\n reconcile(\n serverState: TState,\n acknowledgedSequence: number,\n stateGetter: (state: TState) => { x: number; y: number },\n deltaTime: number\n ): TState {\n this._lastServerState = serverState;\n this._lastAcknowledgedSequence = acknowledgedSequence;\n\n // Remove acknowledged inputs\n while (this._pendingInputs.length > 0 && this._pendingInputs[0].sequence <= acknowledgedSequence) {\n this._pendingInputs.shift();\n }\n\n // Re-predict from server state using unacknowledged inputs\n let state = serverState;\n for (const inputSnapshot of this._pendingInputs) {\n state = this._predictor.predict(state, inputSnapshot.input, deltaTime);\n }\n\n // Calculate error\n const serverPos = stateGetter(serverState);\n const predictedPos = stateGetter(state);\n const errorX = serverPos.x - predictedPos.x;\n const errorY = serverPos.y - predictedPos.y;\n const errorMagnitude = Math.sqrt(errorX * errorX + errorY * errorY);\n\n // Apply correction\n if (errorMagnitude > this._config.reconciliationThreshold) {\n // Smooth correction over time\n const t = Math.min(1, this._config.reconciliationSpeed * deltaTime);\n this._correctionOffset.x += errorX * t;\n this._correctionOffset.y += errorY * t;\n }\n\n // Decay correction offset\n const decayRate = 0.9;\n this._correctionOffset.x *= decayRate;\n this._correctionOffset.y *= decayRate;\n\n this._predictedState = state;\n return state;\n }\n\n /**\n * @zh 清空预测状态\n * @en Clear prediction state\n */\n clear(): void {\n this._pendingInputs.length = 0;\n this._lastAcknowledgedSequence = 0;\n this._currentSequence = 0;\n this._lastServerState = null;\n this._predictedState = null;\n this._correctionOffset = { x: 0, y: 0 };\n }\n}\n\n// =============================================================================\n// 工厂函数 | Factory Functions\n// =============================================================================\n\n/**\n * @zh 创建客户端预测管理器\n * @en Create client prediction manager\n */\nexport function createClientPrediction<TState, TInput>(\n predictor: IPredictor<TState, TInput>,\n config?: Partial<ClientPredictionConfig>\n): ClientPrediction<TState, TInput> {\n return new ClientPrediction(predictor, config);\n}\n","/**\n * @zh 网络蓝图节点\n * @en Network Blueprint Nodes\n *\n * @zh 提供网络功能的蓝图节点\n * @en Provides blueprint nodes for network functionality\n */\n\nimport type { BlueprintNodeTemplate, BlueprintNode, INodeExecutor, ExecutionResult } from '@esengine/blueprint';\n\n// =============================================================================\n// 执行上下文接口 | Execution Context Interface\n// =============================================================================\n\n/**\n * @zh 网络上下文\n * @en Network context\n */\ninterface NetworkContext {\n entity: {\n getComponent<T>(type: new (...args: unknown[]) => T): T | null;\n };\n isServer: boolean;\n localPlayerId: number;\n evaluateInput(nodeId: string, pinName: string, defaultValue?: unknown): unknown;\n setOutputs(nodeId: string, outputs: Record<string, unknown>): void;\n}\n\n// =============================================================================\n// IsLocalPlayer 节点 | IsLocalPlayer Node\n// =============================================================================\n\n/**\n * @zh IsLocalPlayer 节点模板\n * @en IsLocalPlayer node template\n */\nexport const IsLocalPlayerTemplate: BlueprintNodeTemplate = {\n type: 'IsLocalPlayer',\n title: 'Is Local Player',\n category: 'entity',\n description: 'Check if this entity is the local player / 检查此实体是否是本地玩家',\n keywords: ['network', 'local', 'player', 'authority', 'owner'],\n menuPath: ['Network', 'Is Local Player'],\n isPure: true,\n inputs: [],\n outputs: [\n {\n name: 'isLocal',\n displayName: 'Is Local',\n type: 'bool'\n }\n ],\n color: '#ff9800'\n};\n\n/**\n * @zh IsLocalPlayer 节点执行器\n * @en IsLocalPlayer node executor\n */\nexport class IsLocalPlayerExecutor implements INodeExecutor {\n execute(node: BlueprintNode, context: unknown): ExecutionResult {\n const ctx = context as NetworkContext;\n\n // Try to get NetworkIdentity component\n let isLocal = false;\n if (ctx.entity) {\n const identity = ctx.entity.getComponent(class NetworkIdentity {\n bIsLocalPlayer: boolean = false;\n });\n if (identity) {\n isLocal = identity.bIsLocalPlayer;\n }\n }\n\n return {\n outputs: {\n isLocal\n }\n };\n }\n}\n\n// =============================================================================\n// IsServer 节点 | IsServer Node\n// =============================================================================\n\n/**\n * @zh IsServer 节点模板\n * @en IsServer node template\n */\nexport const IsServerTemplate: BlueprintNodeTemplate = {\n type: 'IsServer',\n title: 'Is Server',\n category: 'entity',\n description: 'Check if running on server / 检查是否在服务器上运行',\n keywords: ['network', 'server', 'authority', 'host'],\n menuPath: ['Network', 'Is Server'],\n isPure: true,\n inputs: [],\n outputs: [\n {\n name: 'isServer',\n displayName: 'Is Server',\n type: 'bool'\n }\n ],\n color: '#ff9800'\n};\n\n/**\n * @zh IsServer 节点执行器\n * @en IsServer node executor\n */\nexport class IsServerExecutor implements INodeExecutor {\n execute(_node: BlueprintNode, context: unknown): ExecutionResult {\n const ctx = context as NetworkContext;\n\n return {\n outputs: {\n isServer: ctx.isServer ?? false\n }\n };\n }\n}\n\n// =============================================================================\n// HasAuthority 节点 | HasAuthority Node\n// =============================================================================\n\n/**\n * @zh HasAuthority 节点模板\n * @en HasAuthority node template\n */\nexport const HasAuthorityTemplate: BlueprintNodeTemplate = {\n type: 'HasAuthority',\n title: 'Has Authority',\n category: 'entity',\n description: 'Check if this entity has authority / 检查此实体是否有权限控制',\n keywords: ['network', 'authority', 'control', 'owner'],\n menuPath: ['Network', 'Has Authority'],\n isPure: true,\n inputs: [],\n outputs: [\n {\n name: 'hasAuthority',\n displayName: 'Has Authority',\n type: 'bool'\n }\n ],\n color: '#ff9800'\n};\n\n/**\n * @zh HasAuthority 节点执行器\n * @en HasAuthority node executor\n */\nexport class HasAuthorityExecutor implements INodeExecutor {\n execute(node: BlueprintNode, context: unknown): ExecutionResult {\n const ctx = context as NetworkContext;\n\n let hasAuthority = false;\n if (ctx.entity) {\n const identity = ctx.entity.getComponent(class NetworkIdentity {\n bHasAuthority: boolean = false;\n });\n if (identity) {\n hasAuthority = identity.bHasAuthority;\n }\n }\n\n return {\n outputs: {\n hasAuthority\n }\n };\n }\n}\n\n// =============================================================================\n// GetNetworkId 节点 | GetNetworkId Node\n// =============================================================================\n\n/**\n * @zh GetNetworkId 节点模板\n * @en GetNetworkId node template\n */\nexport const GetNetworkIdTemplate: BlueprintNodeTemplate = {\n type: 'GetNetworkId',\n title: 'Get Network ID',\n category: 'entity',\n description: 'Get the network ID of this entity / 获取此实体的网络 ID',\n keywords: ['network', 'id', 'netid', 'identity'],\n menuPath: ['Network', 'Get Network ID'],\n isPure: true,\n inputs: [],\n outputs: [\n {\n name: 'netId',\n displayName: 'Net ID',\n type: 'int'\n },\n {\n name: 'ownerId',\n displayName: 'Owner ID',\n type: 'int'\n }\n ],\n color: '#ff9800'\n};\n\n/**\n * @zh GetNetworkId 节点执行器\n * @en GetNetworkId node executor\n */\nexport class GetNetworkIdExecutor implements INodeExecutor {\n execute(node: BlueprintNode, context: unknown): ExecutionResult {\n const ctx = context as NetworkContext;\n\n let netId = 0;\n let ownerId = 0;\n\n if (ctx.entity) {\n const identity = ctx.entity.getComponent(class NetworkIdentity {\n netId: number = 0;\n ownerId: number = 0;\n });\n if (identity) {\n netId = identity.netId;\n ownerId = identity.ownerId;\n }\n }\n\n return {\n outputs: {\n netId,\n ownerId\n }\n };\n }\n}\n\n// =============================================================================\n// GetLocalPlayerId 节点 | GetLocalPlayerId Node\n// =============================================================================\n\n/**\n * @zh GetLocalPlayerId 节点模板\n * @en GetLocalPlayerId node template\n */\nexport const GetLocalPlayerIdTemplate: BlueprintNodeTemplate = {\n type: 'GetLocalPlayerId',\n title: 'Get Local Player ID',\n category: 'entity',\n description: 'Get the local player ID / 获取本地玩家 ID',\n keywords: ['network', 'local', 'player', 'id'],\n menuPath: ['Network', 'Get Local Player ID'],\n isPure: true,\n inputs: [],\n outputs: [\n {\n name: 'playerId',\n displayName: 'Player ID',\n type: 'int'\n }\n ],\n color: '#ff9800'\n};\n\n/**\n * @zh GetLocalPlayerId 节点执行器\n * @en GetLocalPlayerId node executor\n */\nexport class GetLocalPlayerIdExecutor implements INodeExecutor {\n execute(_node: BlueprintNode, context: unknown): ExecutionResult {\n const ctx = context as NetworkContext;\n\n return {\n outputs: {\n playerId: ctx.localPlayerId ?? 0\n }\n };\n }\n}\n\n// =============================================================================\n// 节点定义集合 | Node Definition Collection\n// =============================================================================\n\n/**\n * @zh 网络节点定义集合\n * @en Network node definition collection\n */\nexport const NetworkNodeDefinitions = {\n templates: [\n IsLocalPlayerTemplate,\n IsServerTemplate,\n HasAuthorityTemplate,\n GetNetworkIdTemplate,\n GetLocalPlayerIdTemplate\n ],\n executors: new Map<string, INodeExecutor>([\n ['IsLocalPlayer', new IsLocalPlayerExecutor()],\n ['IsServer', new IsServerExecutor()],\n ['HasAuthority', new HasAuthorityExecutor()],\n ['GetNetworkId', new GetNetworkIdExecutor()],\n ['GetLocalPlayerId', new GetLocalPlayerIdExecutor()]\n ])\n};\n"],"mappings":"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","names":["rpc","rpc","gameProtocol","define","api","join","leave","msg","input","sync","spawn","despawn","createServiceToken","NetworkServiceToken","NetworkSyncSystemToken","NetworkSpawnSystemToken","NetworkInputSystemToken","Core","RpcClient","NetworkState","RpcService","_protocol","_client","_state","state","isConnected","client","connect","options","Error","RpcClient","url","onConnect","onDisconnect","reason","onError","err","disconnect","call","name","input","Promise","reject","send","data","on","handler","off","once","GameNetworkService","gameProtocol","sendInput","onSync","onSpawn","onDespawn","createNetworkService","protocol","RpcService","GameNetworkService","EntitySystem","Matcher","Time","Component","ECSComponent","Serialize","Serializable","Property","NetworkIdentity","Component","netId","ownerId","bIsLocalPlayer","bHasAuthority","prefabType","syncInterval","lastSyncTime","needsSync","now","type","label","readOnly","min","version","typeId","Component","ECSComponent","Serialize","Serializable","Property","NetworkTransform","Component","targetX","targetY","targetRotation","currentX","currentY","currentRotation","lerpSpeed","bInterpolate","syncInterval","lastSyncTime","setTarget","x","y","rotation","undefined","snap","type","label","min","max","requires","version","typeId","NetworkSyncSystem","EntitySystem","Matcher","all","NetworkIdentity","NetworkTransform","_netIdToEntity","Map","handleSync","msg","state","entities","entityId","get","netId","undefined","entity","scene","findEntityById","transform","getComponent","pos","setTarget","x","y","rot","process","deltaTime","Time","requireComponent","identity","bHasAuthority","bInterpolate","_interpolate","registerEntity","set","unregisterEntity","delete","getEntityId","t","Math","min","lerpSpeed","currentX","targetX","currentY","targetY","angleDiff","targetRotation","currentRotation","PI","onDestroy","clear","EntitySystem","Matcher","NetworkSpawnSystem","EntitySystem","syncSystem","Matcher","nothing","_syncSystem","_prefabFactories","Map","_localPlayerId","setLocalPlayerId","id","handleSpawn","msg","scene","factory","get","prefab","logger","warn","entity","identity","addComponent","NetworkIdentity","netId","ownerId","prefabType","bHasAuthority","bIsLocalPlayer","transform","NetworkTransform","setTarget","pos","x","y","rot","snap","registerEntity","handleDespawn","entityId","getEntityId","undefined","findEntityById","destroy","unregisterEntity","registerPrefab","set","unregisterPrefab","delete","onDestroy","clear","EntitySystem","Matcher","NetworkInputSystem","EntitySystem","networkService","Matcher","nothing","_networkService","_frame","_inputQueue","process","isConnected","length","input","shift","frame","sendInput","addMoveInput","x","y","push","moveDir","addActionInput","action","lastInput","actions","onDestroy","NetworkPlugin","name","version","_networkService","_syncSystem","_spawnSystem","_inputSystem","_localPlayerId","networkService","syncSystem","spawnSystem","inputSystem","localPlayerId","isConnected","install","_core","_services","GameNetworkService","scene","Core","_setupSystems","uninstall","disconnect","NetworkSyncSystem","NetworkSpawnSystem","NetworkInputSystem","addSystem","_setupMessageHandlers","onSync","data","handleSync","entities","onSpawn","handleSpawn","onDespawn","handleDespawn","connect","options","result","call","playerName","roomId","playerId","setLocalPlayerId","err","undefined","registerPrefab","prefabType","factory","sendMoveInput","x","y","addMoveInput","sendActionInput","action","addActionInput","SnapshotBuffer","config","_buffer","_maxSize","_interpolationDelay","maxSize","interpolationDelay","size","length","push","snapshot","insertIndex","i","timestamp","splice","shift","getInterpolationSnapshots","renderTime","targetTime","prev","next","duration","t","Math","max","min","getLatest","getSnapshotsAfter","filter","s","clear","createSnapshotBuffer","lerp","a","b","t","lerpAngle","diff","Math","PI","smoothDamp","current","target","velocity","smoothTime","deltaTime","maxSpeed","Infinity","max","omega","x","exp","change","maxChange","min","temp","newVelocity","newValue","TransformInterpolator","interpolate","from","to","t","x","lerp","y","rotation","lerpAngle","extrapolate","state","deltaTime","velocityX","velocityY","angularVelocity","HermiteTransformInterpolator","t2","t3","h00","h10","h01","h11","dt","dh00","dh10","dh01","dh11","createTransformInterpolator","createHermiteTransformInterpolator","ClientPrediction","predictor","config","_predictor","_config","_pendingInputs","_lastAcknowledgedSequence","_currentSequence","_lastServerState","_predictedState","_correctionOffset","x","y","maxUnacknowledgedInputs","reconciliationThreshold","reconciliationSpeed","predictedState","correctionOffset","pendingInputCount","length","recordInput","input","currentState","deltaTime","inputSnapshot","sequence","timestamp","Date","now","push","shift","predict","getInputToSend","currentSequence","reconcile","serverState","acknowledgedSequence","stateGetter","state","serverPos","predictedPos","errorX","errorY","errorMagnitude","Math","sqrt","t","min","decayRate","clear","createClientPrediction","IsLocalPlayerTemplate","type","title","category","description","keywords","menuPath","isPure","inputs","outputs","name","displayName","color","IsLocalPlayerExecutor","execute","node","context","ctx","isLocal","entity","identity","getComponent","NetworkIdentity","bIsLocalPlayer","IsServerTemplate","IsServerExecutor","_node","isServer","HasAuthorityTemplate","HasAuthorityExecutor","hasAuthority","bHasAuthority","GetNetworkIdTemplate","GetNetworkIdExecutor","netId","ownerId","GetLocalPlayerIdTemplate","GetLocalPlayerIdExecutor","playerId","localPlayerId","NetworkNodeDefinitions","templates","executors","Map"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/protocol.ts","../src/tokens.ts","../src/NetworkPlugin.ts","../src/services/NetworkService.ts","../src/systems/NetworkSyncSystem.ts","../src/components/NetworkIdentity.ts","../src/components/NetworkTransform.ts","../src/sync/SnapshotBuffer.ts","../src/sync/IInterpolator.ts","../src/sync/TransformInterpolator.ts","../src/sync/ClientPrediction.ts","../src/sync/StateDelta.ts","../src/sync/ComponentSync.ts","../src/systems/NetworkSpawnSystem.ts","../src/systems/NetworkInputSystem.ts","../src/systems/NetworkPredictionSystem.ts","../src/systems/NetworkAOISystem.ts","../src/nodes/NetworkNodes.ts"],"sourcesContent":["/**\n * @zh @esengine/network 网络同步模块\n * @en @esengine/network Network synchronization module\n *\n * @zh 基于 @esengine/rpc 的网络同步模块,提供类型安全的多人游戏网络通信\n * @en Network synchronization module based on @esengine/rpc for type-safe multiplayer game communication\n */\n\n// ============================================================================\n// Re-export from RPC | 从 RPC 包重新导出\n// ============================================================================\n\nexport { rpc } from '@esengine/rpc'\nexport type {\n ProtocolDef,\n ApiDef,\n MsgDef,\n ApiInput,\n ApiOutput,\n MsgData,\n ApiNames,\n MsgNames,\n RpcError,\n} from '@esengine/rpc'\n\n// ============================================================================\n// Protocol | 协议\n// ============================================================================\n\nexport {\n gameProtocol,\n type GameProtocol,\n type PlayerInput,\n type EntitySyncState,\n type SyncData,\n type SpawnData,\n type DespawnData,\n type FullStateData,\n type JoinRequest,\n type JoinResponse,\n type ReconnectRequest,\n type ReconnectResponse,\n} from './protocol'\n\n// ============================================================================\n// Tokens | 服务令牌\n// ============================================================================\n\nexport {\n NetworkServiceToken,\n NetworkSyncSystemToken,\n NetworkSpawnSystemToken,\n NetworkInputSystemToken,\n NetworkPredictionSystemToken,\n NetworkAOISystemToken,\n} from './tokens'\n\n// ============================================================================\n// Plugin | 插件\n// ============================================================================\n\nexport { NetworkPlugin } from './NetworkPlugin'\n\n// ============================================================================\n// Services | 服务\n// ============================================================================\n\nexport {\n RpcService,\n GameNetworkService,\n NetworkService,\n NetworkState,\n createNetworkService,\n} from './services/NetworkService'\nexport type { NetworkServiceOptions } from './services/NetworkService'\n\n// ============================================================================\n// Components | 组件\n// ============================================================================\n\nexport { NetworkIdentity } from './components/NetworkIdentity'\nexport { NetworkTransform } from './components/NetworkTransform'\n\n// ============================================================================\n// Systems | 系统\n// ============================================================================\n\nexport { NetworkSyncSystem } from './systems/NetworkSyncSystem'\nexport type { SyncMessage, NetworkSyncConfig } from './systems/NetworkSyncSystem'\nexport { NetworkSpawnSystem } from './systems/NetworkSpawnSystem'\nexport type { PrefabFactory, SpawnMessage, DespawnMessage } from './systems/NetworkSpawnSystem'\nexport { NetworkInputSystem, createNetworkInputSystem } from './systems/NetworkInputSystem'\nexport type { NetworkInputConfig } from './systems/NetworkInputSystem'\nexport {\n NetworkPredictionSystem,\n createNetworkPredictionSystem,\n} from './systems/NetworkPredictionSystem'\nexport type {\n NetworkPredictionConfig,\n MovementInput,\n PredictedTransform,\n} from './systems/NetworkPredictionSystem'\nexport {\n NetworkAOISystem,\n createNetworkAOISystem,\n} from './systems/NetworkAOISystem'\nexport type {\n NetworkAOIConfig,\n NetworkAOIEvent,\n NetworkAOIEventType,\n NetworkAOIEventListener,\n} from './systems/NetworkAOISystem'\n\n// ============================================================================\n// State Sync | 状态同步\n// ============================================================================\n\nexport type {\n IStateSnapshot,\n ITransformState,\n ITransformStateWithVelocity,\n ISnapshotBufferConfig,\n ISnapshotBuffer,\n} from './sync'\n\nexport type {\n IInterpolator,\n IExtrapolator,\n IInputSnapshot,\n IPredictedState,\n IPredictor,\n ClientPredictionConfig,\n EntityDeltaState,\n DeltaSyncData,\n DeltaCompressionConfig,\n // Component sync types\n ComponentSyncEventType,\n ComponentSyncEvent,\n ComponentSyncEventListener,\n ComponentSyncConfig,\n} from './sync'\n\nexport {\n lerp,\n lerpAngle,\n smoothDamp,\n SnapshotBuffer,\n createSnapshotBuffer,\n TransformInterpolator,\n HermiteTransformInterpolator,\n createTransformInterpolator,\n createHermiteTransformInterpolator,\n ClientPrediction,\n createClientPrediction,\n DeltaFlags,\n StateDeltaCompressor,\n createStateDeltaCompressor,\n // Component sync\n ComponentSyncSystem,\n createComponentSyncSystem,\n} from './sync'\n\n// ============================================================================\n// Blueprint Nodes | 蓝图节点\n// ============================================================================\n\nexport {\n IsLocalPlayerTemplate,\n IsServerTemplate,\n HasAuthorityTemplate,\n GetNetworkIdTemplate,\n GetLocalPlayerIdTemplate,\n IsLocalPlayerExecutor,\n IsServerExecutor,\n HasAuthorityExecutor,\n GetNetworkIdExecutor,\n GetLocalPlayerIdExecutor,\n NetworkNodeDefinitions,\n} from './nodes'\n","/**\n * @zh 游戏网络协议定义\n * @en Game Network Protocol Definition\n *\n * @zh 定义客户端与服务器之间的通信协议\n * @en Defines the communication protocol between client and server\n */\n\nimport { rpc } from '@esengine/rpc'\n\n// ============================================================================\n// Message Types | 消息类型\n// ============================================================================\n\n/**\n * @zh 玩家输入\n * @en Player input\n */\nexport interface PlayerInput {\n /**\n * @zh 输入序列号(用于客户端预测)\n * @en Input sequence number (for client prediction)\n */\n seq: number\n\n /**\n * @zh 帧序号\n * @en Frame number\n */\n frame: number\n\n /**\n * @zh 客户端时间戳\n * @en Client timestamp\n */\n timestamp: number\n\n /**\n * @zh 移动方向\n * @en Move direction\n */\n moveDir?: { x: number; y: number }\n\n /**\n * @zh 动作列表\n * @en Action list\n */\n actions?: string[]\n}\n\n/**\n * @zh 实体同步状态\n * @en Entity sync state\n */\nexport interface EntitySyncState {\n /**\n * @zh 网络实体 ID\n * @en Network entity ID\n */\n netId: number\n\n /**\n * @zh 位置\n * @en Position\n */\n pos?: { x: number; y: number }\n\n /**\n * @zh 旋转角度\n * @en Rotation angle\n */\n rot?: number\n\n /**\n * @zh 速度(用于外推)\n * @en Velocity (for extrapolation)\n */\n vel?: { x: number; y: number }\n\n /**\n * @zh 角速度\n * @en Angular velocity\n */\n angVel?: number\n\n /**\n * @zh 自定义数据\n * @en Custom data\n */\n custom?: Record<string, unknown>\n}\n\n/**\n * @zh 同步消息\n * @en Sync message\n */\nexport interface SyncData {\n /**\n * @zh 服务器帧号\n * @en Server frame number\n */\n frame: number\n\n /**\n * @zh 服务器时间戳(用于插值)\n * @en Server timestamp (for interpolation)\n */\n timestamp: number\n\n /**\n * @zh 已确认的输入序列号(用于客户端预测校正)\n * @en Acknowledged input sequence (for client prediction reconciliation)\n */\n ackSeq?: number\n\n /**\n * @zh 实体状态列表\n * @en Entity state list\n */\n entities: EntitySyncState[]\n}\n\n/**\n * @zh 生成消息\n * @en Spawn message\n */\nexport interface SpawnData {\n netId: number\n ownerId: number\n prefab: string\n pos: { x: number; y: number }\n rot?: number\n}\n\n/**\n * @zh 销毁消息\n * @en Despawn message\n */\nexport interface DespawnData {\n netId: number\n}\n\n/**\n * @zh 完整状态快照(用于重连)\n * @en Full state snapshot (for reconnection)\n */\nexport interface FullStateData {\n /**\n * @zh 服务器帧号\n * @en Server frame number\n */\n frame: number\n\n /**\n * @zh 服务器时间戳\n * @en Server timestamp\n */\n timestamp: number\n\n /**\n * @zh 所有实体状态\n * @en All entity states\n */\n entities: Array<SpawnData & { state?: EntitySyncState }>\n}\n\n// ============================================================================\n// API Types | API 类型\n// ============================================================================\n\n/**\n * @zh 加入房间请求\n * @en Join room request\n */\nexport interface JoinRequest {\n playerName: string\n roomId?: string\n}\n\n/**\n * @zh 加入房间响应\n * @en Join room response\n */\nexport interface JoinResponse {\n playerId: number\n roomId: string\n}\n\n/**\n * @zh 重连请求\n * @en Reconnect request\n */\nexport interface ReconnectRequest {\n /**\n * @zh 之前的玩家 ID\n * @en Previous player ID\n */\n playerId: number\n\n /**\n * @zh 房间 ID\n * @en Room ID\n */\n roomId: string\n\n /**\n * @zh 重连令牌\n * @en Reconnection token\n */\n token: string\n}\n\n/**\n * @zh 重连响应\n * @en Reconnect response\n */\nexport interface ReconnectResponse {\n /**\n * @zh 是否成功\n * @en Whether successful\n */\n success: boolean\n\n /**\n * @zh 完整状态(成功时)\n * @en Full state (when successful)\n */\n state?: FullStateData\n\n /**\n * @zh 错误信息(失败时)\n * @en Error message (when failed)\n */\n error?: string\n}\n\n// ============================================================================\n// Protocol Definition | 协议定义\n// ============================================================================\n\n/**\n * @zh 默认游戏网络协议\n * @en Default game network protocol\n *\n * @example\n * ```typescript\n * // 使用默认协议\n * const service = new NetworkService(gameProtocol)\n *\n * // 或者扩展协议\n * const customProtocol = rpc.define({\n * api: {\n * ...gameProtocol.api,\n * customApi: rpc.api<CustomInput, CustomOutput>(),\n * },\n * msg: {\n * ...gameProtocol.msg,\n * customMsg: rpc.msg<CustomData>(),\n * },\n * })\n * ```\n */\nexport const gameProtocol = rpc.define({\n api: {\n /**\n * @zh 加入房间\n * @en Join room\n */\n join: rpc.api<JoinRequest, JoinResponse>(),\n\n /**\n * @zh 离开房间\n * @en Leave room\n */\n leave: rpc.api<void, void>(),\n\n /**\n * @zh 重连\n * @en Reconnect\n */\n reconnect: rpc.api<ReconnectRequest, ReconnectResponse>(),\n },\n msg: {\n /**\n * @zh 玩家输入\n * @en Player input\n */\n input: rpc.msg<PlayerInput>(),\n\n /**\n * @zh 状态同步\n * @en State sync\n */\n sync: rpc.msg<SyncData>(),\n\n /**\n * @zh 实体生成\n * @en Entity spawn\n */\n spawn: rpc.msg<SpawnData>(),\n\n /**\n * @zh 实体销毁\n * @en Entity despawn\n */\n despawn: rpc.msg<DespawnData>(),\n\n /**\n * @zh 完整状态快照\n * @en Full state snapshot\n */\n fullState: rpc.msg<FullStateData>(),\n },\n})\n\n/**\n * @zh 游戏协议类型\n * @en Game protocol type\n */\nexport type GameProtocol = typeof gameProtocol\n","/**\n * Network 模块服务令牌\n * Network module service tokens\n */\n\nimport { createServiceToken } from '@esengine/ecs-framework';\nimport type { NetworkService } from './services/NetworkService';\nimport type { NetworkSyncSystem } from './systems/NetworkSyncSystem';\nimport type { NetworkSpawnSystem } from './systems/NetworkSpawnSystem';\nimport type { NetworkInputSystem } from './systems/NetworkInputSystem';\nimport type { NetworkPredictionSystem } from './systems/NetworkPredictionSystem';\nimport type { NetworkAOISystem } from './systems/NetworkAOISystem';\n\n// ============================================================================\n// Network 模块导出的令牌 | Tokens exported by Network module\n// ============================================================================\n\n/**\n * 网络服务令牌\n * Network service token\n */\nexport const NetworkServiceToken = createServiceToken<NetworkService>('networkService');\n\n/**\n * 网络同步系统令牌\n * Network sync system token\n */\nexport const NetworkSyncSystemToken = createServiceToken<NetworkSyncSystem>('networkSyncSystem');\n\n/**\n * 网络生成系统令牌\n * Network spawn system token\n */\nexport const NetworkSpawnSystemToken = createServiceToken<NetworkSpawnSystem>('networkSpawnSystem');\n\n/**\n * 网络输入系统令牌\n * Network input system token\n */\nexport const NetworkInputSystemToken = createServiceToken<NetworkInputSystem>('networkInputSystem');\n\n/**\n * 网络预测系统令牌\n * Network prediction system token\n */\nexport const NetworkPredictionSystemToken = createServiceToken<NetworkPredictionSystem>('networkPredictionSystem');\n\n/**\n * 网络 AOI 系统令牌\n * Network AOI system token\n */\nexport const NetworkAOISystemToken = createServiceToken<NetworkAOISystem>('networkAOISystem');\n","/**\n * @zh 网络插件\n * @en Network Plugin\n *\n * @zh 提供基于 @esengine/rpc 的网络同步功能,支持客户端预测和断线重连\n * @en Provides @esengine/rpc based network synchronization with client prediction and reconnection\n */\n\nimport { type IPlugin, Core, type ServiceContainer, type Scene } from '@esengine/ecs-framework'\nimport {\n GameNetworkService,\n type NetworkServiceOptions,\n NetworkState,\n} from './services/NetworkService'\nimport { NetworkSyncSystem, type NetworkSyncConfig } from './systems/NetworkSyncSystem'\nimport { NetworkSpawnSystem, type PrefabFactory } from './systems/NetworkSpawnSystem'\nimport { NetworkInputSystem, type NetworkInputConfig } from './systems/NetworkInputSystem'\nimport {\n NetworkPredictionSystem,\n type NetworkPredictionConfig,\n} from './systems/NetworkPredictionSystem'\nimport {\n NetworkAOISystem,\n type NetworkAOIConfig,\n} from './systems/NetworkAOISystem'\nimport type { FullStateData, SyncData } from './protocol'\n\n// =============================================================================\n// Types | 类型定义\n// =============================================================================\n\n/**\n * @zh 网络插件配置\n * @en Network plugin configuration\n */\nexport interface NetworkPluginConfig {\n /**\n * @zh 是否启用客户端预测\n * @en Whether to enable client prediction\n */\n enablePrediction: boolean\n\n /**\n * @zh 是否启用自动重连\n * @en Whether to enable auto reconnection\n */\n enableAutoReconnect: boolean\n\n /**\n * @zh 重连最大尝试次数\n * @en Maximum reconnection attempts\n */\n maxReconnectAttempts: number\n\n /**\n * @zh 重连间隔(毫秒)\n * @en Reconnection interval in milliseconds\n */\n reconnectInterval: number\n\n /**\n * @zh 同步系统配置\n * @en Sync system configuration\n */\n syncConfig?: Partial<NetworkSyncConfig>\n\n /**\n * @zh 输入系统配置\n * @en Input system configuration\n */\n inputConfig?: Partial<NetworkInputConfig>\n\n /**\n * @zh 预测系统配置\n * @en Prediction system configuration\n */\n predictionConfig?: Partial<NetworkPredictionConfig>\n\n /**\n * @zh 是否启用 AOI 兴趣管理\n * @en Whether to enable AOI interest management\n */\n enableAOI: boolean\n\n /**\n * @zh AOI 系统配置\n * @en AOI system configuration\n */\n aoiConfig?: Partial<NetworkAOIConfig>\n}\n\nconst DEFAULT_CONFIG: NetworkPluginConfig = {\n enablePrediction: true,\n enableAutoReconnect: true,\n maxReconnectAttempts: 5,\n reconnectInterval: 2000,\n enableAOI: false,\n}\n\n/**\n * @zh 连接选项\n * @en Connection options\n */\nexport interface ConnectOptions extends NetworkServiceOptions {\n playerName: string\n roomId?: string\n}\n\n/**\n * @zh 重连状态\n * @en Reconnection state\n */\ninterface ReconnectState {\n token: string\n playerId: number\n roomId: string\n attempts: number\n isReconnecting: boolean\n}\n\n// =============================================================================\n// NetworkPlugin | 网络插件\n// =============================================================================\n\n/**\n * @zh 网络插件\n * @en Network plugin\n *\n * @zh 提供基于 @esengine/rpc 的网络同步功能\n * @en Provides @esengine/rpc based network synchronization\n *\n * @example\n * ```typescript\n * import { Core } from '@esengine/ecs-framework'\n * import { NetworkPlugin } from '@esengine/network'\n *\n * const networkPlugin = new NetworkPlugin({\n * enablePrediction: true,\n * enableAutoReconnect: true\n * })\n * await Core.installPlugin(networkPlugin)\n *\n * // 连接到服务器\n * await networkPlugin.connect({ url: 'ws://localhost:3000', playerName: 'Player1' })\n *\n * // 注册预制体\n * networkPlugin.registerPrefab('player', (scene, spawn) => {\n * const entity = scene.createEntity('Player')\n * return entity\n * })\n * ```\n */\nexport class NetworkPlugin implements IPlugin {\n public readonly name = '@esengine/network'\n public readonly version = '2.1.0'\n\n private readonly _config: NetworkPluginConfig\n private _networkService!: GameNetworkService\n private _syncSystem!: NetworkSyncSystem\n private _spawnSystem!: NetworkSpawnSystem\n private _inputSystem!: NetworkInputSystem\n private _predictionSystem: NetworkPredictionSystem | null = null\n private _aoiSystem: NetworkAOISystem | null = null\n\n private _localPlayerId: number = 0\n private _reconnectState: ReconnectState | null = null\n private _reconnectTimer: ReturnType<typeof setTimeout> | null = null\n private _lastConnectOptions: ConnectOptions | null = null\n\n constructor(config?: Partial<NetworkPluginConfig>) {\n this._config = { ...DEFAULT_CONFIG, ...config }\n }\n\n // =========================================================================\n // Getters | 属性访问器\n // =========================================================================\n\n /**\n * @zh 网络服务\n * @en Network service\n */\n get networkService(): GameNetworkService {\n return this._networkService\n }\n\n /**\n * @zh 同步系统\n * @en Sync system\n */\n get syncSystem(): NetworkSyncSystem {\n return this._syncSystem\n }\n\n /**\n * @zh 生成系统\n * @en Spawn system\n */\n get spawnSystem(): NetworkSpawnSystem {\n return this._spawnSystem\n }\n\n /**\n * @zh 输入系统\n * @en Input system\n */\n get inputSystem(): NetworkInputSystem {\n return this._inputSystem\n }\n\n /**\n * @zh 预测系统\n * @en Prediction system\n */\n get predictionSystem(): NetworkPredictionSystem | null {\n return this._predictionSystem\n }\n\n /**\n * @zh AOI 系统\n * @en AOI system\n */\n get aoiSystem(): NetworkAOISystem | null {\n return this._aoiSystem\n }\n\n /**\n * @zh 本地玩家 ID\n * @en Local player ID\n */\n get localPlayerId(): number {\n return this._localPlayerId\n }\n\n /**\n * @zh 是否已连接\n * @en Is connected\n */\n get isConnected(): boolean {\n return this._networkService?.isConnected ?? false\n }\n\n /**\n * @zh 是否正在重连\n * @en Is reconnecting\n */\n get isReconnecting(): boolean {\n return this._reconnectState?.isReconnecting ?? false\n }\n\n /**\n * @zh 是否启用预测\n * @en Is prediction enabled\n */\n get isPredictionEnabled(): boolean {\n return this._config.enablePrediction && this._predictionSystem !== null\n }\n\n /**\n * @zh 是否启用 AOI\n * @en Is AOI enabled\n */\n get isAOIEnabled(): boolean {\n return this._config.enableAOI && this._aoiSystem !== null\n }\n\n // =========================================================================\n // Plugin Lifecycle | 插件生命周期\n // =========================================================================\n\n /**\n * @zh 安装插件\n * @en Install plugin\n */\n install(_core: Core, _services: ServiceContainer): void {\n this._networkService = new GameNetworkService()\n\n const scene = Core.scene\n if (scene) {\n this._setupSystems(scene as Scene)\n }\n }\n\n /**\n * @zh 卸载插件\n * @en Uninstall plugin\n */\n uninstall(): void {\n this._clearReconnectTimer()\n this._networkService?.disconnect()\n }\n\n private _setupSystems(scene: Scene): void {\n // Create systems\n this._syncSystem = new NetworkSyncSystem(this._config.syncConfig)\n this._spawnSystem = new NetworkSpawnSystem(this._syncSystem)\n this._inputSystem = new NetworkInputSystem(this._networkService, this._config.inputConfig)\n\n // Create prediction system if enabled\n if (this._config.enablePrediction) {\n this._predictionSystem = new NetworkPredictionSystem(this._config.predictionConfig)\n this._inputSystem.setPredictionSystem(this._predictionSystem)\n scene.addSystem(this._predictionSystem)\n }\n\n // Create AOI system if enabled\n if (this._config.enableAOI) {\n this._aoiSystem = new NetworkAOISystem(this._config.aoiConfig)\n scene.addSystem(this._aoiSystem)\n }\n\n scene.addSystem(this._syncSystem)\n scene.addSystem(this._spawnSystem)\n scene.addSystem(this._inputSystem)\n\n this._setupMessageHandlers()\n }\n\n private _setupMessageHandlers(): void {\n this._networkService\n .onSync((data: SyncData) => {\n // Use new sync handler with timestamps\n this._syncSystem.handleSyncData(data)\n\n // Reconcile prediction if enabled\n if (this._predictionSystem) {\n this._predictionSystem.reconcileWithServer(data)\n }\n })\n .onSpawn((data) => {\n this._spawnSystem.handleSpawn(data)\n })\n .onDespawn((data) => {\n this._spawnSystem.handleDespawn(data)\n })\n\n // Handle full state for reconnection\n this._networkService.on('fullState', (data: FullStateData) => {\n this._handleFullState(data)\n })\n }\n\n // =========================================================================\n // Connection | 连接管理\n // =========================================================================\n\n /**\n * @zh 连接到服务器\n * @en Connect to server\n */\n public async connect(options: ConnectOptions): Promise<boolean> {\n this._lastConnectOptions = options\n\n try {\n // Setup disconnect handler for auto-reconnect\n const originalOnDisconnect = options.onDisconnect\n options.onDisconnect = (reason) => {\n originalOnDisconnect?.(reason)\n this._handleDisconnect(reason)\n }\n\n await this._networkService.connect(options)\n\n const result = await this._networkService.call('join', {\n playerName: options.playerName,\n roomId: options.roomId,\n })\n\n this._localPlayerId = result.playerId\n this._spawnSystem.setLocalPlayerId(this._localPlayerId)\n\n // Setup prediction for local player\n if (this._predictionSystem) {\n // Will be set when local player entity is spawned\n }\n\n // Save reconnect state\n if (this._config.enableAutoReconnect) {\n this._reconnectState = {\n token: this._generateReconnectToken(),\n playerId: result.playerId,\n roomId: result.roomId,\n attempts: 0,\n isReconnecting: false,\n }\n }\n\n return true\n } catch (err) {\n console.error('[NetworkPlugin] Connection failed:', err)\n return false\n }\n }\n\n /**\n * @zh 断开连接\n * @en Disconnect\n */\n public async disconnect(): Promise<void> {\n this._clearReconnectTimer()\n this._reconnectState = null\n\n try {\n await this._networkService.call('leave', undefined)\n } catch {\n // ignore\n }\n this._networkService.disconnect()\n this._cleanup()\n }\n\n private _handleDisconnect(reason?: string): void {\n console.log('[NetworkPlugin] Disconnected:', reason)\n\n if (this._config.enableAutoReconnect && this._reconnectState && !this._reconnectState.isReconnecting) {\n this._attemptReconnect()\n }\n }\n\n private _attemptReconnect(): void {\n if (!this._reconnectState || !this._lastConnectOptions) return\n\n if (this._reconnectState.attempts >= this._config.maxReconnectAttempts) {\n console.error('[NetworkPlugin] Max reconnection attempts reached')\n this._reconnectState = null\n return\n }\n\n this._reconnectState.isReconnecting = true\n this._reconnectState.attempts++\n\n console.log(`[NetworkPlugin] Attempting reconnection (${this._reconnectState.attempts}/${this._config.maxReconnectAttempts})`)\n\n this._reconnectTimer = setTimeout(async () => {\n try {\n await this._networkService.connect(this._lastConnectOptions!)\n\n const result = await this._networkService.call('reconnect', {\n playerId: this._reconnectState!.playerId,\n roomId: this._reconnectState!.roomId,\n token: this._reconnectState!.token,\n })\n\n if (result.success) {\n console.log('[NetworkPlugin] Reconnection successful')\n this._reconnectState!.isReconnecting = false\n this._reconnectState!.attempts = 0\n\n // Restore state\n if (result.state) {\n this._handleFullState(result.state)\n }\n } else {\n console.error('[NetworkPlugin] Reconnection rejected:', result.error)\n this._attemptReconnect()\n }\n } catch (err) {\n console.error('[NetworkPlugin] Reconnection failed:', err)\n if (this._reconnectState) {\n this._reconnectState.isReconnecting = false\n }\n this._attemptReconnect()\n }\n }, this._config.reconnectInterval)\n }\n\n private _handleFullState(data: FullStateData): void {\n // Clear existing entities\n this._syncSystem.clearSnapshots()\n\n // Spawn all entities from full state\n for (const entityData of data.entities) {\n this._spawnSystem.handleSpawn(entityData)\n\n // Apply initial state if available\n if (entityData.state) {\n this._syncSystem.handleSyncData({\n frame: data.frame,\n timestamp: data.timestamp,\n entities: [entityData.state],\n })\n }\n }\n }\n\n private _clearReconnectTimer(): void {\n if (this._reconnectTimer) {\n clearTimeout(this._reconnectTimer)\n this._reconnectTimer = null\n }\n }\n\n private _generateReconnectToken(): string {\n return `${Date.now()}-${Math.random().toString(36).substring(2, 15)}`\n }\n\n private _cleanup(): void {\n this._localPlayerId = 0\n this._syncSystem?.clearSnapshots()\n this._predictionSystem?.reset()\n this._inputSystem?.reset()\n }\n\n // =========================================================================\n // Game API | 游戏接口\n // =========================================================================\n\n /**\n * @zh 注册预制体工厂\n * @en Register prefab factory\n */\n public registerPrefab(prefabType: string, factory: PrefabFactory): void {\n this._spawnSystem?.registerPrefab(prefabType, factory)\n }\n\n /**\n * @zh 发送移动输入\n * @en Send move input\n */\n public sendMoveInput(x: number, y: number): void {\n this._inputSystem?.addMoveInput(x, y)\n }\n\n /**\n * @zh 发送动作输入\n * @en Send action input\n */\n public sendActionInput(action: string): void {\n this._inputSystem?.addActionInput(action)\n }\n\n /**\n * @zh 设置本地玩家网络 ID(用于预测)\n * @en Set local player network ID (for prediction)\n */\n public setLocalPlayerNetId(netId: number): void {\n if (this._predictionSystem) {\n this._predictionSystem.setLocalPlayerNetId(netId)\n }\n }\n\n /**\n * @zh 启用/禁用预测\n * @en Enable/disable prediction\n */\n public setPredictionEnabled(enabled: boolean): void {\n if (this._predictionSystem) {\n this._predictionSystem.enabled = enabled\n }\n }\n\n // =========================================================================\n // AOI API | AOI 接口\n // =========================================================================\n\n /**\n * @zh 添加 AOI 观察者(玩家)\n * @en Add AOI observer (player)\n */\n public addAOIObserver(netId: number, x: number, y: number, viewRange?: number): void {\n this._aoiSystem?.addObserver(netId, x, y, viewRange)\n }\n\n /**\n * @zh 移除 AOI 观察者\n * @en Remove AOI observer\n */\n public removeAOIObserver(netId: number): void {\n this._aoiSystem?.removeObserver(netId)\n }\n\n /**\n * @zh 更新 AOI 观察者位置\n * @en Update AOI observer position\n */\n public updateAOIObserverPosition(netId: number, x: number, y: number): void {\n this._aoiSystem?.updateObserverPosition(netId, x, y)\n }\n\n /**\n * @zh 获取观察者可见的实体\n * @en Get entities visible to observer\n */\n public getVisibleEntities(observerNetId: number): number[] {\n return this._aoiSystem?.getVisibleEntities(observerNetId) ?? []\n }\n\n /**\n * @zh 检查是否可见\n * @en Check if visible\n */\n public canSee(observerNetId: number, targetNetId: number): boolean {\n return this._aoiSystem?.canSee(observerNetId, targetNetId) ?? true\n }\n\n /**\n * @zh 启用/禁用 AOI\n * @en Enable/disable AOI\n */\n public setAOIEnabled(enabled: boolean): void {\n if (this._aoiSystem) {\n this._aoiSystem.enabled = enabled\n }\n }\n}\n","/**\n * @zh 网络服务模块\n * @en Network Service Module\n */\n\nimport {\n RpcClient,\n type ProtocolDef,\n type ApiNames,\n type MsgNames,\n type ApiInput,\n type ApiOutput,\n type MsgData,\n type RpcClientOptions,\n} from '@esengine/rpc/client'\nimport { gameProtocol, type GameProtocol, type PlayerInput } from '../protocol'\n\n// ============================================================================\n// Types | 类型定义\n// ============================================================================\n\n/**\n * @zh 连接状态\n * @en Connection state\n */\nexport const enum NetworkState {\n Disconnected = 0,\n Connecting = 1,\n Connected = 2,\n}\n\n/**\n * @zh 网络服务配置\n * @en Network service options\n */\nexport interface NetworkServiceOptions extends RpcClientOptions {\n /**\n * @zh 服务器地址\n * @en Server URL\n */\n url: string\n}\n\n// ============================================================================\n// RpcService - Base Class | RPC 服务基类\n// ============================================================================\n\n/**\n * @zh RPC 服务基类\n * @en RPC Service base class\n *\n * @zh 纯粹的 RPC 客户端封装,不包含任何游戏特定逻辑\n * @en Pure RPC client wrapper without any game-specific logic\n *\n * @typeParam P - @zh 协议定义类型 @en Protocol definition type\n */\nexport class RpcService<P extends ProtocolDef> {\n protected _client: RpcClient<P> | null = null\n protected _state: NetworkState = NetworkState.Disconnected\n\n constructor(protected readonly _protocol: P) {}\n\n /**\n * @zh 获取连接状态\n * @en Get connection state\n */\n get state(): NetworkState {\n return this._state\n }\n\n /**\n * @zh 是否已连接\n * @en Whether connected\n */\n get isConnected(): boolean {\n return this._state === NetworkState.Connected\n }\n\n /**\n * @zh 获取底层 RPC 客户端\n * @en Get underlying RPC client\n */\n get client(): RpcClient<P> | null {\n return this._client\n }\n\n /**\n * @zh 连接到服务器\n * @en Connect to server\n */\n async connect(options: NetworkServiceOptions): Promise<void> {\n if (this._state !== NetworkState.Disconnected) {\n throw new Error('Already connected or connecting')\n }\n\n this._state = NetworkState.Connecting\n\n try {\n this._client = new RpcClient(this._protocol, options.url, {\n ...options,\n onConnect: () => {\n this._state = NetworkState.Connected\n options.onConnect?.()\n },\n onDisconnect: (reason) => {\n this._state = NetworkState.Disconnected\n options.onDisconnect?.(reason)\n },\n onError: options.onError,\n })\n await this._client.connect()\n this._state = NetworkState.Connected\n } catch (err) {\n this._state = NetworkState.Disconnected\n this._client = null\n throw err\n }\n }\n\n /**\n * @zh 断开连接\n * @en Disconnect\n */\n disconnect(): void {\n this._client?.disconnect()\n this._client = null\n this._state = NetworkState.Disconnected\n }\n\n /**\n * @zh 调用 API\n * @en Call API\n */\n call<K extends ApiNames<P>>(\n name: K,\n input: ApiInput<P['api'][K]>\n ): Promise<ApiOutput<P['api'][K]>> {\n if (!this._client) {\n return Promise.reject(new Error('Not connected'))\n }\n return this._client.call(name, input)\n }\n\n /**\n * @zh 发送消息\n * @en Send message\n */\n send<K extends MsgNames<P>>(name: K, data: MsgData<P['msg'][K]>): void {\n this._client?.send(name, data)\n }\n\n /**\n * @zh 监听消息\n * @en Listen to message\n */\n on<K extends MsgNames<P>>(\n name: K,\n handler: (data: MsgData<P['msg'][K]>) => void\n ): this {\n this._client?.on(name, handler)\n return this\n }\n\n /**\n * @zh 取消监听消息\n * @en Remove message listener\n */\n off<K extends MsgNames<P>>(\n name: K,\n handler?: (data: MsgData<P['msg'][K]>) => void\n ): this {\n this._client?.off(name, handler)\n return this\n }\n\n /**\n * @zh 监听消息(只触发一次)\n * @en Listen to message (once)\n */\n once<K extends MsgNames<P>>(\n name: K,\n handler: (data: MsgData<P['msg'][K]>) => void\n ): this {\n this._client?.once(name, handler)\n return this\n }\n}\n\n// ============================================================================\n// GameNetworkService - Game-specific Class | 游戏网络服务\n// ============================================================================\n\n/**\n * @zh 游戏网络服务\n * @en Game network service\n *\n * @zh 基于默认游戏协议的网络服务,提供游戏特定的便捷方法\n * @en Network service based on default game protocol with game-specific convenience methods\n *\n * @example\n * ```typescript\n * const network = new GameNetworkService()\n * await network.connect({ url: 'ws://localhost:3000' })\n *\n * // 游戏特定的便捷方法\n * network.sendInput({ frame: 1, moveDir: { x: 1, y: 0 } })\n *\n * network.onSync((data) => {\n * for (const entity of data.entities) {\n * // 更新实体状态\n * }\n * })\n * ```\n */\nexport class GameNetworkService extends RpcService<GameProtocol> {\n constructor() {\n super(gameProtocol)\n }\n\n /**\n * @zh 发送玩家输入\n * @en Send player input\n */\n sendInput(input: PlayerInput): void {\n this.send('input', input)\n }\n\n /**\n * @zh 监听状态同步\n * @en Listen to state sync\n */\n onSync(handler: (data: MsgData<GameProtocol['msg']['sync']>) => void): this {\n return this.on('sync', handler)\n }\n\n /**\n * @zh 监听实体生成\n * @en Listen to entity spawn\n */\n onSpawn(handler: (data: MsgData<GameProtocol['msg']['spawn']>) => void): this {\n return this.on('spawn', handler)\n }\n\n /**\n * @zh 监听实体销毁\n * @en Listen to entity despawn\n */\n onDespawn(handler: (data: MsgData<GameProtocol['msg']['despawn']>) => void): this {\n return this.on('despawn', handler)\n }\n}\n\n// ============================================================================\n// Exports & Factories | 导出与工厂函数\n// ============================================================================\n\n/**\n * @zh 网络服务(GameNetworkService 的别名)\n * @en Network service (alias for GameNetworkService)\n */\nexport { GameNetworkService as NetworkService }\n\n/**\n * @zh 创建网络服务\n * @en Create network service\n */\nexport function createNetworkService(): GameNetworkService\nexport function createNetworkService<P extends ProtocolDef>(protocol: P): RpcService<P>\nexport function createNetworkService<P extends ProtocolDef>(protocol?: P): RpcService<P> | GameNetworkService {\n if (protocol) {\n return new RpcService(protocol)\n }\n return new GameNetworkService()\n}\n","/**\n * @zh 网络同步系统\n * @en Network Sync System\n *\n * @zh 处理网络实体的状态同步、快照缓冲和插值\n * @en Handles state synchronization, snapshot buffering, and interpolation for networked entities\n */\n\nimport { EntitySystem, Matcher, Time, type Entity } from '@esengine/ecs-framework'\nimport { NetworkIdentity } from '../components/NetworkIdentity'\nimport { NetworkTransform } from '../components/NetworkTransform'\nimport type { SyncData, EntitySyncState } from '../protocol'\nimport {\n SnapshotBuffer,\n createSnapshotBuffer,\n TransformInterpolator,\n createTransformInterpolator,\n type ITransformState,\n type ITransformStateWithVelocity,\n type IStateSnapshot,\n} from '../sync'\n\n// =============================================================================\n// Types | 类型定义\n// =============================================================================\n\n/**\n * @zh 同步消息接口(兼容旧版)\n * @en Sync message interface (for backwards compatibility)\n */\nexport interface SyncMessage {\n entities: Array<{\n netId: number\n pos?: { x: number; y: number }\n rot?: number\n }>\n}\n\n/**\n * @zh 实体快照数据\n * @en Entity snapshot data\n */\ninterface EntitySnapshotData {\n buffer: SnapshotBuffer<ITransformStateWithVelocity>\n lastServerTime: number\n}\n\n/**\n * @zh 同步系统配置\n * @en Sync system configuration\n */\nexport interface NetworkSyncConfig {\n /**\n * @zh 快照缓冲区大小\n * @en Snapshot buffer size\n */\n bufferSize: number\n\n /**\n * @zh 插值延迟(毫秒)\n * @en Interpolation delay in milliseconds\n */\n interpolationDelay: number\n\n /**\n * @zh 是否启用外推\n * @en Whether to enable extrapolation\n */\n enableExtrapolation: boolean\n\n /**\n * @zh 最大外推时间(毫秒)\n * @en Maximum extrapolation time in milliseconds\n */\n maxExtrapolationTime: number\n\n /**\n * @zh 使用赫尔米特插值(更平滑)\n * @en Use Hermite interpolation (smoother)\n */\n useHermiteInterpolation: boolean\n}\n\nconst DEFAULT_CONFIG: NetworkSyncConfig = {\n bufferSize: 30,\n interpolationDelay: 100,\n enableExtrapolation: true,\n maxExtrapolationTime: 200,\n useHermiteInterpolation: false,\n}\n\n// =============================================================================\n// NetworkSyncSystem | 网络同步系统\n// =============================================================================\n\n/**\n * @zh 网络同步系统\n * @en Network sync system\n *\n * @zh 处理网络实体的状态同步和插值,支持快照缓冲、平滑插值和外推\n * @en Handles state synchronization and interpolation for networked entities,\n * supports snapshot buffering, smooth interpolation, and extrapolation\n */\nexport class NetworkSyncSystem extends EntitySystem {\n private readonly _netIdToEntity: Map<number, number> = new Map()\n private readonly _entitySnapshots: Map<number, EntitySnapshotData> = new Map()\n private readonly _interpolator: TransformInterpolator\n private readonly _config: NetworkSyncConfig\n\n private _serverTimeOffset: number = 0\n private _lastSyncTime: number = 0\n private _renderTime: number = 0\n\n constructor(config?: Partial<NetworkSyncConfig>) {\n super(Matcher.all(NetworkIdentity, NetworkTransform))\n this._config = { ...DEFAULT_CONFIG, ...config }\n this._interpolator = createTransformInterpolator()\n }\n\n /**\n * @zh 获取配置\n * @en Get configuration\n */\n get config(): Readonly<NetworkSyncConfig> {\n return this._config\n }\n\n /**\n * @zh 获取服务器时间偏移\n * @en Get server time offset\n */\n get serverTimeOffset(): number {\n return this._serverTimeOffset\n }\n\n /**\n * @zh 获取当前渲染时间\n * @en Get current render time\n */\n get renderTime(): number {\n return this._renderTime\n }\n\n /**\n * @zh 处理同步消息(新版,带时间戳)\n * @en Handle sync message (new version with timestamp)\n */\n handleSyncData(data: SyncData): void {\n const serverTime = data.timestamp\n\n // Update server time offset\n const clientTime = Date.now()\n this._serverTimeOffset = serverTime - clientTime\n this._lastSyncTime = clientTime\n\n for (const state of data.entities) {\n this._processEntityState(state, serverTime)\n }\n }\n\n /**\n * @zh 处理同步消息(兼容旧版)\n * @en Handle sync message (backwards compatible)\n */\n handleSync(msg: SyncMessage): void {\n const now = Date.now()\n for (const state of msg.entities) {\n const entityId = this._netIdToEntity.get(state.netId)\n if (entityId === undefined) continue\n\n const entity = this.scene?.findEntityById(entityId)\n if (!entity) continue\n\n const transform = entity.getComponent(NetworkTransform)\n if (transform && state.pos) {\n transform.setTarget(state.pos.x, state.pos.y, state.rot ?? 0)\n }\n\n // Also add to snapshot buffer for interpolation\n this._processEntityState({\n netId: state.netId,\n pos: state.pos,\n rot: state.rot,\n }, now)\n }\n }\n\n private _processEntityState(state: EntitySyncState, serverTime: number): void {\n const entityId = this._netIdToEntity.get(state.netId)\n if (entityId === undefined) return\n\n // Get or create snapshot buffer\n let snapshotData = this._entitySnapshots.get(state.netId)\n if (!snapshotData) {\n snapshotData = {\n buffer: createSnapshotBuffer<ITransformStateWithVelocity>(\n this._config.bufferSize,\n this._config.interpolationDelay\n ),\n lastServerTime: 0,\n }\n this._entitySnapshots.set(state.netId, snapshotData)\n }\n\n // Create snapshot\n const transformState: ITransformStateWithVelocity = {\n x: state.pos?.x ?? 0,\n y: state.pos?.y ?? 0,\n rotation: state.rot ?? 0,\n velocityX: state.vel?.x ?? 0,\n velocityY: state.vel?.y ?? 0,\n angularVelocity: state.angVel ?? 0,\n }\n\n const snapshot: IStateSnapshot<ITransformStateWithVelocity> = {\n timestamp: serverTime,\n state: transformState,\n }\n\n snapshotData.buffer.push(snapshot)\n snapshotData.lastServerTime = serverTime\n }\n\n protected override process(entities: readonly Entity[]): void {\n const deltaTime = Time.deltaTime\n const clientTime = Date.now()\n\n // Calculate render time (current time adjusted for server offset)\n this._renderTime = clientTime + this._serverTimeOffset\n\n for (const entity of entities) {\n const transform = this.requireComponent(entity, NetworkTransform)\n const identity = this.requireComponent(entity, NetworkIdentity)\n\n // Skip entities with authority (local player handles their own movement)\n if (identity.bHasAuthority) continue\n\n if (transform.bInterpolate) {\n this._interpolateEntity(identity.netId, transform, deltaTime)\n }\n }\n }\n\n private _interpolateEntity(\n netId: number,\n transform: NetworkTransform,\n deltaTime: number\n ): void {\n const snapshotData = this._entitySnapshots.get(netId)\n\n if (snapshotData && snapshotData.buffer.size >= 2) {\n // Use snapshot buffer for interpolation\n const result = snapshotData.buffer.getInterpolationSnapshots(this._renderTime)\n\n if (result) {\n const [prev, next, t] = result\n const interpolated = this._interpolator.interpolate(prev.state, next.state, t)\n\n transform.currentX = interpolated.x\n transform.currentY = interpolated.y\n transform.currentRotation = interpolated.rotation\n\n // Update target for compatibility\n transform.targetX = next.state.x\n transform.targetY = next.state.y\n transform.targetRotation = next.state.rotation\n return\n }\n\n // Extrapolation if enabled and we have velocity data\n if (this._config.enableExtrapolation) {\n const latest = snapshotData.buffer.getLatest()\n if (latest) {\n const timeSinceLastSnapshot = this._renderTime - latest.timestamp\n if (timeSinceLastSnapshot > 0 && timeSinceLastSnapshot < this._config.maxExtrapolationTime) {\n const extrapolated = this._interpolator.extrapolate(\n latest.state,\n timeSinceLastSnapshot / 1000\n )\n transform.currentX = extrapolated.x\n transform.currentY = extrapolated.y\n transform.currentRotation = extrapolated.rotation\n return\n }\n }\n }\n }\n\n // Fallback: simple lerp towards target\n this._simpleLerp(transform, deltaTime)\n }\n\n private _simpleLerp(transform: NetworkTransform, deltaTime: number): void {\n const t = Math.min(1, transform.lerpSpeed * deltaTime)\n\n transform.currentX += (transform.targetX - transform.currentX) * t\n transform.currentY += (transform.targetY - transform.currentY) * t\n\n let angleDiff = transform.targetRotation - transform.currentRotation\n while (angleDiff > Math.PI) angleDiff -= Math.PI * 2\n while (angleDiff < -Math.PI) angleDiff += Math.PI * 2\n transform.currentRotation += angleDiff * t\n }\n\n /**\n * @zh 注册网络实体\n * @en Register network entity\n */\n registerEntity(netId: number, entityId: number): void {\n this._netIdToEntity.set(netId, entityId)\n }\n\n /**\n * @zh 注销网络实体\n * @en Unregister network entity\n */\n unregisterEntity(netId: number): void {\n this._netIdToEntity.delete(netId)\n this._entitySnapshots.delete(netId)\n }\n\n /**\n * @zh 根据网络 ID 获取实体 ID\n * @en Get entity ID by network ID\n */\n getEntityId(netId: number): number | undefined {\n return this._netIdToEntity.get(netId)\n }\n\n /**\n * @zh 获取实体的快照缓冲区\n * @en Get entity's snapshot buffer\n */\n getSnapshotBuffer(netId: number): SnapshotBuffer<ITransformStateWithVelocity> | undefined {\n return this._entitySnapshots.get(netId)?.buffer\n }\n\n /**\n * @zh 清空所有快照缓冲\n * @en Clear all snapshot buffers\n */\n clearSnapshots(): void {\n for (const data of this._entitySnapshots.values()) {\n data.buffer.clear()\n }\n }\n\n protected override onDestroy(): void {\n this._netIdToEntity.clear()\n this._entitySnapshots.clear()\n }\n}\n","import { Component, ECSComponent, Serialize, Serializable, Property } from '@esengine/ecs-framework';\n\n/**\n * 网络身份组件\n * Network identity component\n *\n * 标识一个实体在网络上的唯一身份。\n * Identifies an entity's unique identity on the network.\n */\n@ECSComponent('NetworkIdentity')\n@Serializable({ version: 1, typeId: 'NetworkIdentity' })\nexport class NetworkIdentity extends Component {\n /**\n * 网络实体 ID\n * Network entity ID\n */\n @Serialize()\n @Property({ type: 'integer', label: 'Net ID', readOnly: true })\n public netId: number = 0;\n\n /**\n * 所有者客户端 ID\n * Owner client ID\n */\n @Serialize()\n @Property({ type: 'integer', label: 'Owner ID', readOnly: true })\n public ownerId: number = 0;\n\n /**\n * 是否为本地玩家拥有\n * Is owned by local player\n */\n public bIsLocalPlayer: boolean = false;\n\n /**\n * 是否有权限控制\n * Has authority\n */\n public bHasAuthority: boolean = false;\n\n /**\n * 预制体类型\n * Prefab type\n */\n @Serialize()\n @Property({ type: 'string', label: 'Prefab Type' })\n public prefabType: string = '';\n\n /**\n * 同步间隔 (ms)\n * Sync interval in milliseconds\n */\n @Serialize()\n @Property({ type: 'number', label: 'Sync Interval', min: 16 })\n public syncInterval: number = 100;\n\n /**\n * 上次同步时间\n * Last sync time\n */\n public lastSyncTime: number = 0;\n\n /**\n * 检查是否需要同步\n * Check if sync is needed\n */\n public needsSync(now: number): boolean {\n return now - this.lastSyncTime >= this.syncInterval;\n }\n}\n","import { Component, ECSComponent, Serialize, Serializable, Property } from '@esengine/ecs-framework';\n\n/**\n * 网络变换组件\n * Network transform component\n *\n * 同步实体的位置和旋转。支持插值平滑。\n * Syncs entity position and rotation with interpolation smoothing.\n */\n@ECSComponent('NetworkTransform', { requires: ['NetworkIdentity'] })\n@Serializable({ version: 1, typeId: 'NetworkTransform' })\nexport class NetworkTransform extends Component {\n /**\n * 目标位置 X\n * Target position X\n */\n public targetX: number = 0;\n\n /**\n * 目标位置 Y\n * Target position Y\n */\n public targetY: number = 0;\n\n /**\n * 目标旋转\n * Target rotation\n */\n public targetRotation: number = 0;\n\n /**\n * 当前位置 X\n * Current position X\n */\n public currentX: number = 0;\n\n /**\n * 当前位置 Y\n * Current position Y\n */\n public currentY: number = 0;\n\n /**\n * 当前旋转\n * Current rotation\n */\n public currentRotation: number = 0;\n\n /**\n * 插值速度\n * Interpolation speed\n */\n @Serialize()\n @Property({ type: 'number', label: 'Lerp Speed', min: 0.1, max: 50 })\n public lerpSpeed: number = 10;\n\n /**\n * 是否启用插值\n * Enable interpolation\n */\n @Serialize()\n @Property({ type: 'boolean', label: 'Interpolate' })\n public bInterpolate: boolean = true;\n\n /**\n * 同步间隔 (ms)\n * Sync interval in milliseconds\n */\n @Serialize()\n @Property({ type: 'number', label: 'Sync Interval', min: 16 })\n public syncInterval: number = 50;\n\n /**\n * 上次同步时间\n * Last sync time\n */\n public lastSyncTime: number = 0;\n\n /**\n * 设置目标位置\n * Set target position\n */\n public setTarget(x: number, y: number, rotation?: number): void {\n this.targetX = x;\n this.targetY = y;\n if (rotation !== undefined) {\n this.targetRotation = rotation;\n }\n }\n\n /**\n * 立即跳转到目标位置\n * Snap to target position immediately\n */\n public snap(): void {\n this.currentX = this.targetX;\n this.currentY = this.targetY;\n this.currentRotation = this.targetRotation;\n }\n}\n","/**\n * @zh 快照缓冲区实现\n * @en Snapshot Buffer Implementation\n *\n * @zh 用于存储和插值网络状态快照\n * @en Stores and interpolates network state snapshots\n */\n\nimport type { IStateSnapshot, ISnapshotBuffer, ISnapshotBufferConfig } from './IStateSnapshot';\n\n// =============================================================================\n// 快照缓冲区实现 | Snapshot Buffer Implementation\n// =============================================================================\n\n/**\n * @zh 快照缓冲区\n * @en Snapshot buffer\n */\nexport class SnapshotBuffer<T> implements ISnapshotBuffer<T> {\n private readonly _buffer: IStateSnapshot<T>[] = [];\n private readonly _maxSize: number;\n private readonly _interpolationDelay: number;\n\n constructor(config: ISnapshotBufferConfig) {\n this._maxSize = config.maxSize;\n this._interpolationDelay = config.interpolationDelay;\n }\n\n get size(): number {\n return this._buffer.length;\n }\n\n /**\n * @zh 获取插值延迟\n * @en Get interpolation delay\n */\n get interpolationDelay(): number {\n return this._interpolationDelay;\n }\n\n /**\n * @zh 添加快照\n * @en Add snapshot\n */\n push(snapshot: IStateSnapshot<T>): void {\n // Insert in sorted order by timestamp\n let insertIndex = this._buffer.length;\n for (let i = this._buffer.length - 1; i >= 0; i--) {\n if (this._buffer[i].timestamp <= snapshot.timestamp) {\n insertIndex = i + 1;\n break;\n }\n if (i === 0) {\n insertIndex = 0;\n }\n }\n\n this._buffer.splice(insertIndex, 0, snapshot);\n\n // Remove old snapshots if buffer is full\n while (this._buffer.length > this._maxSize) {\n this._buffer.shift();\n }\n }\n\n /**\n * @zh 获取用于插值的两个快照\n * @en Get two snapshots for interpolation\n */\n getInterpolationSnapshots(renderTime: number): [IStateSnapshot<T>, IStateSnapshot<T>, number] | null {\n if (this._buffer.length < 2) {\n return null;\n }\n\n // Apply interpolation delay\n const targetTime = renderTime - this._interpolationDelay;\n\n // Find the two snapshots that bracket the target time\n for (let i = 0; i < this._buffer.length - 1; i++) {\n const prev = this._buffer[i];\n const next = this._buffer[i + 1];\n\n if (prev.timestamp <= targetTime && next.timestamp >= targetTime) {\n const duration = next.timestamp - prev.timestamp;\n const t = duration > 0 ? (targetTime - prev.timestamp) / duration : 0;\n return [prev, next, Math.max(0, Math.min(1, t))];\n }\n }\n\n // If target time is beyond buffer, extrapolate from last two snapshots\n if (targetTime > this._buffer[this._buffer.length - 1].timestamp) {\n const prev = this._buffer[this._buffer.length - 2];\n const next = this._buffer[this._buffer.length - 1];\n const duration = next.timestamp - prev.timestamp;\n const t = duration > 0 ? (targetTime - prev.timestamp) / duration : 1;\n // Clamp extrapolation to prevent wild values\n return [prev, next, Math.min(t, 2)];\n }\n\n // Target time is before buffer start\n return null;\n }\n\n /**\n * @zh 获取最新快照\n * @en Get latest snapshot\n */\n getLatest(): IStateSnapshot<T> | null {\n return this._buffer.length > 0 ? this._buffer[this._buffer.length - 1] : null;\n }\n\n /**\n * @zh 获取特定时间之后的所有快照\n * @en Get all snapshots after a specific time\n */\n getSnapshotsAfter(timestamp: number): IStateSnapshot<T>[] {\n return this._buffer.filter(s => s.timestamp > timestamp);\n }\n\n /**\n * @zh 清空缓冲区\n * @en Clear buffer\n */\n clear(): void {\n this._buffer.length = 0;\n }\n}\n\n// =============================================================================\n// 工厂函数 | Factory Functions\n// =============================================================================\n\n/**\n * @zh 创建快照缓冲区\n * @en Create snapshot buffer\n *\n * @param maxSize - @zh 最大快照数量(默认 30)@en Maximum snapshot count (default 30)\n * @param interpolationDelay - @zh 插值延迟毫秒(默认 100)@en Interpolation delay in ms (default 100)\n */\nexport function createSnapshotBuffer<T>(\n maxSize: number = 30,\n interpolationDelay: number = 100\n): SnapshotBuffer<T> {\n return new SnapshotBuffer<T>({ maxSize, interpolationDelay });\n}\n","/**\n * @zh 插值器接口\n * @en Interpolator Interface\n *\n * @zh 提供状态插值的抽象\n * @en Provides abstraction for state interpolation\n */\n\n// =============================================================================\n// 插值器接口 | Interpolator Interface\n// =============================================================================\n\n/**\n * @zh 插值器接口\n * @en Interpolator interface\n */\nexport interface IInterpolator<T> {\n /**\n * @zh 在两个状态之间插值\n * @en Interpolate between two states\n *\n * @param from - @zh 起始状态 @en Start state\n * @param to - @zh 目标状态 @en Target state\n * @param t - @zh 插值因子 (0-1) @en Interpolation factor (0-1)\n * @returns @zh 插值后的状态 @en Interpolated state\n */\n interpolate(from: T, to: T, t: number): T;\n}\n\n/**\n * @zh 外推器接口\n * @en Extrapolator interface\n */\nexport interface IExtrapolator<T> {\n /**\n * @zh 基于当前状态外推\n * @en Extrapolate based on current state\n *\n * @param state - @zh 当前状态 @en Current state\n * @param deltaTime - @zh 外推时间(秒)@en Extrapolation time in seconds\n * @returns @zh 外推后的状态 @en Extrapolated state\n */\n extrapolate(state: T, deltaTime: number): T;\n}\n\n// =============================================================================\n// 内置插值器 | Built-in Interpolators\n// =============================================================================\n\n/**\n * @zh 线性插值函数\n * @en Linear interpolation function\n */\nexport function lerp(a: number, b: number, t: number): number {\n return a + (b - a) * t;\n}\n\n/**\n * @zh 角度插值函数(处理环绕)\n * @en Angle interpolation function (handles wrap-around)\n */\nexport function lerpAngle(a: number, b: number, t: number): number {\n let diff = b - a;\n while (diff > Math.PI) diff -= Math.PI * 2;\n while (diff < -Math.PI) diff += Math.PI * 2;\n return a + diff * t;\n}\n\n/**\n * @zh 平滑阻尼插值\n * @en Smooth damp interpolation\n *\n * @param current - @zh 当前值 @en Current value\n * @param target - @zh 目标值 @en Target value\n * @param velocity - @zh 当前速度(将被修改)@en Current velocity (will be modified)\n * @param smoothTime - @zh 平滑时间 @en Smooth time\n * @param deltaTime - @zh 帧时间 @en Delta time\n * @param maxSpeed - @zh 最大速度 @en Maximum speed\n * @returns @zh [新值, 新速度] @en [new value, new velocity]\n */\nexport function smoothDamp(\n current: number,\n target: number,\n velocity: number,\n smoothTime: number,\n deltaTime: number,\n maxSpeed: number = Infinity\n): [number, number] {\n smoothTime = Math.max(0.0001, smoothTime);\n const omega = 2 / smoothTime;\n const x = omega * deltaTime;\n const exp = 1 / (1 + x + 0.48 * x * x + 0.235 * x * x * x);\n\n let change = current - target;\n const maxChange = maxSpeed * smoothTime;\n change = Math.max(-maxChange, Math.min(maxChange, change));\n\n const temp = (velocity + omega * change) * deltaTime;\n let newVelocity = (velocity - omega * temp) * exp;\n let newValue = target + (change + temp) * exp;\n\n // Prevent overshoot\n if ((target - current > 0) === (newValue > target)) {\n newValue = target;\n newVelocity = (newValue - target) / deltaTime;\n }\n\n return [newValue, newVelocity];\n}\n","/**\n * @zh 变换插值器\n * @en Transform Interpolator\n *\n * @zh 用于网络变换状态的插值\n * @en Interpolates network transform states\n */\n\nimport type { ITransformState, ITransformStateWithVelocity } from './IStateSnapshot';\nimport type { IInterpolator, IExtrapolator } from './IInterpolator';\nimport { lerp, lerpAngle } from './IInterpolator';\n\n// =============================================================================\n// 变换插值器 | Transform Interpolator\n// =============================================================================\n\n/**\n * @zh 变换状态插值器\n * @en Transform state interpolator\n */\nexport class TransformInterpolator implements IInterpolator<ITransformState>, IExtrapolator<ITransformStateWithVelocity> {\n /**\n * @zh 在两个变换状态之间插值\n * @en Interpolate between two transform states\n */\n interpolate(from: ITransformState, to: ITransformState, t: number): ITransformState {\n return {\n x: lerp(from.x, to.x, t),\n y: lerp(from.y, to.y, t),\n rotation: lerpAngle(from.rotation, to.rotation, t)\n };\n }\n\n /**\n * @zh 基于速度外推变换状态\n * @en Extrapolate transform state based on velocity\n */\n extrapolate(state: ITransformStateWithVelocity, deltaTime: number): ITransformStateWithVelocity {\n return {\n x: state.x + state.velocityX * deltaTime,\n y: state.y + state.velocityY * deltaTime,\n rotation: state.rotation + state.angularVelocity * deltaTime,\n velocityX: state.velocityX,\n velocityY: state.velocityY,\n angularVelocity: state.angularVelocity\n };\n }\n}\n\n// =============================================================================\n// 赫尔米特插值器 | Hermite Interpolator\n// =============================================================================\n\n/**\n * @zh 赫尔米特变换插值器(更平滑的曲线)\n * @en Hermite transform interpolator (smoother curves)\n */\nexport class HermiteTransformInterpolator implements IInterpolator<ITransformStateWithVelocity> {\n /**\n * @zh 使用赫尔米特插值\n * @en Use Hermite interpolation\n */\n interpolate(\n from: ITransformStateWithVelocity,\n to: ITransformStateWithVelocity,\n t: number\n ): ITransformStateWithVelocity {\n const t2 = t * t;\n const t3 = t2 * t;\n\n // Hermite basis functions\n const h00 = 2 * t3 - 3 * t2 + 1;\n const h10 = t3 - 2 * t2 + t;\n const h01 = -2 * t3 + 3 * t2;\n const h11 = t3 - t2;\n\n // Estimate time interval (assume 100ms between snapshots)\n const dt = 0.1;\n\n const x = h00 * from.x + h10 * from.velocityX * dt + h01 * to.x + h11 * to.velocityX * dt;\n const y = h00 * from.y + h10 * from.velocityY * dt + h01 * to.y + h11 * to.velocityY * dt;\n\n // Derive velocity from position derivatives\n const dh00 = 6 * t2 - 6 * t;\n const dh10 = 3 * t2 - 4 * t + 1;\n const dh01 = -6 * t2 + 6 * t;\n const dh11 = 3 * t2 - 2 * t;\n\n const velocityX = (dh00 * from.x + dh10 * from.velocityX * dt + dh01 * to.x + dh11 * to.velocityX * dt) / dt;\n const velocityY = (dh00 * from.y + dh10 * from.velocityY * dt + dh01 * to.y + dh11 * to.velocityY * dt) / dt;\n\n return {\n x,\n y,\n rotation: lerpAngle(from.rotation, to.rotation, t),\n velocityX,\n velocityY,\n angularVelocity: lerp(from.angularVelocity, to.angularVelocity, t)\n };\n }\n}\n\n// =============================================================================\n// 工厂函数 | Factory Functions\n// =============================================================================\n\n/**\n * @zh 创建变换插值器\n * @en Create transform interpolator\n */\nexport function createTransformInterpolator(): TransformInterpolator {\n return new TransformInterpolator();\n}\n\n/**\n * @zh 创建赫尔米特变换插值器\n * @en Create Hermite transform interpolator\n */\nexport function createHermiteTransformInterpolator(): HermiteTransformInterpolator {\n return new HermiteTransformInterpolator();\n}\n","/**\n * @zh 客户端预测\n * @en Client Prediction\n *\n * @zh 提供客户端输入预测和服务器校正\n * @en Provides client-side input prediction and server reconciliation\n */\n\n// =============================================================================\n// 输入快照接口 | Input Snapshot Interface\n// =============================================================================\n\n/**\n * @zh 输入快照\n * @en Input snapshot\n */\nexport interface IInputSnapshot<TInput> {\n /**\n * @zh 输入序列号\n * @en Input sequence number\n */\n readonly sequence: number;\n\n /**\n * @zh 输入数据\n * @en Input data\n */\n readonly input: TInput;\n\n /**\n * @zh 输入时间戳\n * @en Input timestamp\n */\n readonly timestamp: number;\n}\n\n/**\n * @zh 预测状态\n * @en Predicted state\n */\nexport interface IPredictedState<TState> {\n /**\n * @zh 状态数据\n * @en State data\n */\n readonly state: TState;\n\n /**\n * @zh 对应的输入序列号\n * @en Corresponding input sequence number\n */\n readonly sequence: number;\n}\n\n// =============================================================================\n// 预测器接口 | Predictor Interface\n// =============================================================================\n\n/**\n * @zh 状态预测器接口\n * @en State predictor interface\n */\nexport interface IPredictor<TState, TInput> {\n /**\n * @zh 根据当前状态和输入预测下一状态\n * @en Predict next state based on current state and input\n *\n * @param state - @zh 当前状态 @en Current state\n * @param input - @zh 输入 @en Input\n * @param deltaTime - @zh 时间间隔 @en Delta time\n * @returns @zh 预测的状态 @en Predicted state\n */\n predict(state: TState, input: TInput, deltaTime: number): TState;\n}\n\n// =============================================================================\n// 客户端预测管理器 | Client Prediction Manager\n// =============================================================================\n\n/**\n * @zh 客户端预测配置\n * @en Client prediction configuration\n */\nexport interface ClientPredictionConfig {\n /**\n * @zh 最大未确认输入数量\n * @en Maximum unacknowledged inputs\n */\n maxUnacknowledgedInputs: number;\n\n /**\n * @zh 校正阈值(超过此值才进行平滑校正)\n * @en Reconciliation threshold (smooth correction only above this value)\n */\n reconciliationThreshold: number;\n\n /**\n * @zh 校正平滑速度\n * @en Reconciliation smoothing speed\n */\n reconciliationSpeed: number;\n}\n\n/**\n * @zh 客户端预测管理器\n * @en Client prediction manager\n */\nexport class ClientPrediction<TState, TInput> {\n private readonly _predictor: IPredictor<TState, TInput>;\n private readonly _config: ClientPredictionConfig;\n private readonly _pendingInputs: IInputSnapshot<TInput>[] = [];\n private _lastAcknowledgedSequence: number = 0;\n private _currentSequence: number = 0;\n private _lastServerState: TState | null = null;\n private _predictedState: TState | null = null;\n private _correctionOffset: { x: number; y: number } = { x: 0, y: 0 };\n\n constructor(predictor: IPredictor<TState, TInput>, config?: Partial<ClientPredictionConfig>) {\n this._predictor = predictor;\n this._config = {\n maxUnacknowledgedInputs: 60,\n reconciliationThreshold: 0.1,\n reconciliationSpeed: 10,\n ...config\n };\n }\n\n /**\n * @zh 获取当前预测状态\n * @en Get current predicted state\n */\n get predictedState(): TState | null {\n return this._predictedState;\n }\n\n /**\n * @zh 获取校正偏移\n * @en Get correction offset\n */\n get correctionOffset(): { x: number; y: number } {\n return this._correctionOffset;\n }\n\n /**\n * @zh 获取待确认输入数量\n * @en Get pending input count\n */\n get pendingInputCount(): number {\n return this._pendingInputs.length;\n }\n\n /**\n * @zh 记录并预测输入\n * @en Record and predict input\n *\n * @param input - @zh 输入数据 @en Input data\n * @param currentState - @zh 当前状态 @en Current state\n * @param deltaTime - @zh 时间间隔 @en Delta time\n * @returns @zh 预测的状态 @en Predicted state\n */\n recordInput(input: TInput, currentState: TState, deltaTime: number): TState {\n this._currentSequence++;\n\n const inputSnapshot: IInputSnapshot<TInput> = {\n sequence: this._currentSequence,\n input,\n timestamp: Date.now()\n };\n\n this._pendingInputs.push(inputSnapshot);\n\n // Remove old inputs if buffer is full\n while (this._pendingInputs.length > this._config.maxUnacknowledgedInputs) {\n this._pendingInputs.shift();\n }\n\n // Predict new state\n this._predictedState = this._predictor.predict(currentState, input, deltaTime);\n\n return this._predictedState;\n }\n\n /**\n * @zh 获取下一个要发送的输入\n * @en Get next input to send\n */\n getInputToSend(): IInputSnapshot<TInput> | null {\n return this._pendingInputs.length > 0 ? this._pendingInputs[this._pendingInputs.length - 1] : null;\n }\n\n /**\n * @zh 获取当前序列号\n * @en Get current sequence number\n */\n get currentSequence(): number {\n return this._currentSequence;\n }\n\n /**\n * @zh 处理服务器状态并进行校正\n * @en Process server state and reconcile\n *\n * @param serverState - @zh 服务器状态 @en Server state\n * @param acknowledgedSequence - @zh 已确认的输入序列号 @en Acknowledged input sequence\n * @param stateGetter - @zh 获取状态位置的函数 @en Function to get state position\n * @param deltaTime - @zh 帧时间 @en Frame delta time\n */\n reconcile(\n serverState: TState,\n acknowledgedSequence: number,\n stateGetter: (state: TState) => { x: number; y: number },\n deltaTime: number\n ): TState {\n this._lastServerState = serverState;\n this._lastAcknowledgedSequence = acknowledgedSequence;\n\n // Remove acknowledged inputs\n while (this._pendingInputs.length > 0 && this._pendingInputs[0].sequence <= acknowledgedSequence) {\n this._pendingInputs.shift();\n }\n\n // Re-predict from server state using unacknowledged inputs\n let state = serverState;\n for (const inputSnapshot of this._pendingInputs) {\n state = this._predictor.predict(state, inputSnapshot.input, deltaTime);\n }\n\n // Calculate error\n const serverPos = stateGetter(serverState);\n const predictedPos = stateGetter(state);\n const errorX = serverPos.x - predictedPos.x;\n const errorY = serverPos.y - predictedPos.y;\n const errorMagnitude = Math.sqrt(errorX * errorX + errorY * errorY);\n\n // Apply correction\n if (errorMagnitude > this._config.reconciliationThreshold) {\n // Smooth correction over time\n const t = Math.min(1, this._config.reconciliationSpeed * deltaTime);\n this._correctionOffset.x += errorX * t;\n this._correctionOffset.y += errorY * t;\n }\n\n // Decay correction offset\n const decayRate = 0.9;\n this._correctionOffset.x *= decayRate;\n this._correctionOffset.y *= decayRate;\n\n this._predictedState = state;\n return state;\n }\n\n /**\n * @zh 清空预测状态\n * @en Clear prediction state\n */\n clear(): void {\n this._pendingInputs.length = 0;\n this._lastAcknowledgedSequence = 0;\n this._currentSequence = 0;\n this._lastServerState = null;\n this._predictedState = null;\n this._correctionOffset = { x: 0, y: 0 };\n }\n}\n\n// =============================================================================\n// 工厂函数 | Factory Functions\n// =============================================================================\n\n/**\n * @zh 创建客户端预测管理器\n * @en Create client prediction manager\n */\nexport function createClientPrediction<TState, TInput>(\n predictor: IPredictor<TState, TInput>,\n config?: Partial<ClientPredictionConfig>\n): ClientPrediction<TState, TInput> {\n return new ClientPrediction(predictor, config);\n}\n","/**\n * @zh 状态增量压缩\n * @en State Delta Compression\n *\n * @zh 通过只发送变化的字段来减少网络带宽\n * @en Reduces network bandwidth by only sending changed fields\n */\n\nimport type { EntitySyncState, SyncData } from '../protocol'\n\n// =============================================================================\n// Types | 类型定义\n// =============================================================================\n\n/**\n * @zh 增量类型标志\n * @en Delta type flags\n */\nexport const DeltaFlags = {\n NONE: 0,\n POSITION: 1 << 0,\n ROTATION: 1 << 1,\n VELOCITY: 1 << 2,\n ANGULAR_VELOCITY: 1 << 3,\n CUSTOM: 1 << 4,\n} as const\n\n/**\n * @zh 增量状态(只包含变化的字段)\n * @en Delta state (only contains changed fields)\n */\nexport interface EntityDeltaState {\n /**\n * @zh 网络标识\n * @en Network identity\n */\n netId: number\n\n /**\n * @zh 变化标志\n * @en Change flags\n */\n flags: number\n\n /**\n * @zh 位置(如果变化)\n * @en Position (if changed)\n */\n pos?: { x: number; y: number }\n\n /**\n * @zh 旋转(如果变化)\n * @en Rotation (if changed)\n */\n rot?: number\n\n /**\n * @zh 速度(如果变化)\n * @en Velocity (if changed)\n */\n vel?: { x: number; y: number }\n\n /**\n * @zh 角速度(如果变化)\n * @en Angular velocity (if changed)\n */\n angVel?: number\n\n /**\n * @zh 自定义数据(如果变化)\n * @en Custom data (if changed)\n */\n custom?: Record<string, unknown>\n}\n\n/**\n * @zh 增量同步数据\n * @en Delta sync data\n */\nexport interface DeltaSyncData {\n /**\n * @zh 帧号\n * @en Frame number\n */\n frame: number\n\n /**\n * @zh 时间戳\n * @en Timestamp\n */\n timestamp: number\n\n /**\n * @zh 已确认的输入序列号\n * @en Acknowledged input sequence\n */\n ackSeq?: number\n\n /**\n * @zh 增量实体状态\n * @en Delta entity states\n */\n entities: EntityDeltaState[]\n\n /**\n * @zh 是否为完整快照\n * @en Whether this is a full snapshot\n */\n isFullSnapshot?: boolean\n}\n\n/**\n * @zh 增量压缩配置\n * @en Delta compression configuration\n */\nexport interface DeltaCompressionConfig {\n /**\n * @zh 位置变化阈值\n * @en Position change threshold\n */\n positionThreshold: number\n\n /**\n * @zh 旋转变化阈值(弧度)\n * @en Rotation change threshold (radians)\n */\n rotationThreshold: number\n\n /**\n * @zh 速度变化阈值\n * @en Velocity change threshold\n */\n velocityThreshold: number\n\n /**\n * @zh 强制完整快照间隔(帧数)\n * @en Forced full snapshot interval (frames)\n */\n fullSnapshotInterval: number\n}\n\nconst DEFAULT_CONFIG: DeltaCompressionConfig = {\n positionThreshold: 0.01,\n rotationThreshold: 0.001,\n velocityThreshold: 0.1,\n fullSnapshotInterval: 60,\n}\n\n// =============================================================================\n// StateDeltaCompressor | 状态增量压缩器\n// =============================================================================\n\n/**\n * @zh 状态增量压缩器\n * @en State delta compressor\n *\n * @zh 追踪实体状态变化,生成增量更新\n * @en Tracks entity state changes and generates delta updates\n */\nexport class StateDeltaCompressor {\n private readonly _config: DeltaCompressionConfig\n private readonly _lastStates: Map<number, EntitySyncState> = new Map()\n private _frameCounter: number = 0\n\n constructor(config?: Partial<DeltaCompressionConfig>) {\n this._config = { ...DEFAULT_CONFIG, ...config }\n }\n\n /**\n * @zh 获取配置\n * @en Get configuration\n */\n get config(): Readonly<DeltaCompressionConfig> {\n return this._config\n }\n\n /**\n * @zh 压缩同步数据为增量格式\n * @en Compress sync data to delta format\n */\n compress(data: SyncData): DeltaSyncData {\n this._frameCounter++\n\n const isFullSnapshot = this._frameCounter % this._config.fullSnapshotInterval === 0\n const deltaEntities: EntityDeltaState[] = []\n\n for (const entity of data.entities) {\n const lastState = this._lastStates.get(entity.netId)\n\n if (isFullSnapshot || !lastState) {\n // Send full state\n deltaEntities.push(this._createFullDelta(entity))\n } else {\n // Calculate delta\n const delta = this._calculateDelta(lastState, entity)\n if (delta) {\n deltaEntities.push(delta)\n }\n }\n\n // Update last state\n this._lastStates.set(entity.netId, { ...entity })\n }\n\n return {\n frame: data.frame,\n timestamp: data.timestamp,\n ackSeq: data.ackSeq,\n entities: deltaEntities,\n isFullSnapshot,\n }\n }\n\n /**\n * @zh 解压增量数据为完整同步数据\n * @en Decompress delta data to full sync data\n */\n decompress(data: DeltaSyncData): SyncData {\n const entities: EntitySyncState[] = []\n\n for (const delta of data.entities) {\n const lastState = this._lastStates.get(delta.netId)\n const fullState = this._applyDelta(lastState, delta)\n entities.push(fullState)\n\n // Update last state\n this._lastStates.set(delta.netId, fullState)\n }\n\n return {\n frame: data.frame,\n timestamp: data.timestamp,\n ackSeq: data.ackSeq,\n entities,\n }\n }\n\n /**\n * @zh 移除实体状态\n * @en Remove entity state\n */\n removeEntity(netId: number): void {\n this._lastStates.delete(netId)\n }\n\n /**\n * @zh 清除所有状态\n * @en Clear all states\n */\n clear(): void {\n this._lastStates.clear()\n this._frameCounter = 0\n }\n\n /**\n * @zh 强制下一次发送完整快照\n * @en Force next send to be a full snapshot\n */\n forceFullSnapshot(): void {\n this._frameCounter = this._config.fullSnapshotInterval - 1\n }\n\n // =========================================================================\n // 私有方法 | Private Methods\n // =========================================================================\n\n private _createFullDelta(entity: EntitySyncState): EntityDeltaState {\n let flags = 0\n\n if (entity.pos) flags |= DeltaFlags.POSITION\n if (entity.rot !== undefined) flags |= DeltaFlags.ROTATION\n if (entity.vel) flags |= DeltaFlags.VELOCITY\n if (entity.angVel !== undefined) flags |= DeltaFlags.ANGULAR_VELOCITY\n if (entity.custom) flags |= DeltaFlags.CUSTOM\n\n return {\n netId: entity.netId,\n flags,\n pos: entity.pos,\n rot: entity.rot,\n vel: entity.vel,\n angVel: entity.angVel,\n custom: entity.custom,\n }\n }\n\n private _calculateDelta(\n lastState: EntitySyncState,\n currentState: EntitySyncState\n ): EntityDeltaState | null {\n let flags = 0\n const delta: EntityDeltaState = {\n netId: currentState.netId,\n flags: 0,\n }\n\n // Check position change\n if (currentState.pos) {\n const posChanged = !lastState.pos ||\n Math.abs(currentState.pos.x - lastState.pos.x) > this._config.positionThreshold ||\n Math.abs(currentState.pos.y - lastState.pos.y) > this._config.positionThreshold\n\n if (posChanged) {\n flags |= DeltaFlags.POSITION\n delta.pos = currentState.pos\n }\n }\n\n // Check rotation change\n if (currentState.rot !== undefined) {\n const rotChanged = lastState.rot === undefined ||\n Math.abs(currentState.rot - lastState.rot) > this._config.rotationThreshold\n\n if (rotChanged) {\n flags |= DeltaFlags.ROTATION\n delta.rot = currentState.rot\n }\n }\n\n // Check velocity change\n if (currentState.vel) {\n const velChanged = !lastState.vel ||\n Math.abs(currentState.vel.x - lastState.vel.x) > this._config.velocityThreshold ||\n Math.abs(currentState.vel.y - lastState.vel.y) > this._config.velocityThreshold\n\n if (velChanged) {\n flags |= DeltaFlags.VELOCITY\n delta.vel = currentState.vel\n }\n }\n\n // Check angular velocity change\n if (currentState.angVel !== undefined) {\n const angVelChanged = lastState.angVel === undefined ||\n Math.abs(currentState.angVel - lastState.angVel) > this._config.velocityThreshold\n\n if (angVelChanged) {\n flags |= DeltaFlags.ANGULAR_VELOCITY\n delta.angVel = currentState.angVel\n }\n }\n\n // Check custom data change (simple reference comparison)\n if (currentState.custom) {\n const customChanged = !this._customDataEqual(lastState.custom, currentState.custom)\n\n if (customChanged) {\n flags |= DeltaFlags.CUSTOM\n delta.custom = currentState.custom\n }\n }\n\n // Return null if no changes\n if (flags === 0) {\n return null\n }\n\n delta.flags = flags\n return delta\n }\n\n private _applyDelta(\n lastState: EntitySyncState | undefined,\n delta: EntityDeltaState\n ): EntitySyncState {\n const state: EntitySyncState = {\n netId: delta.netId,\n }\n\n // Apply position\n if (delta.flags & DeltaFlags.POSITION) {\n state.pos = delta.pos\n } else if (lastState?.pos) {\n state.pos = lastState.pos\n }\n\n // Apply rotation\n if (delta.flags & DeltaFlags.ROTATION) {\n state.rot = delta.rot\n } else if (lastState?.rot !== undefined) {\n state.rot = lastState.rot\n }\n\n // Apply velocity\n if (delta.flags & DeltaFlags.VELOCITY) {\n state.vel = delta.vel\n } else if (lastState?.vel) {\n state.vel = lastState.vel\n }\n\n // Apply angular velocity\n if (delta.flags & DeltaFlags.ANGULAR_VELOCITY) {\n state.angVel = delta.angVel\n } else if (lastState?.angVel !== undefined) {\n state.angVel = lastState.angVel\n }\n\n // Apply custom data\n if (delta.flags & DeltaFlags.CUSTOM) {\n state.custom = delta.custom\n } else if (lastState?.custom) {\n state.custom = lastState.custom\n }\n\n return state\n }\n\n private _customDataEqual(\n a: Record<string, unknown> | undefined,\n b: Record<string, unknown> | undefined\n ): boolean {\n if (a === b) return true\n if (!a || !b) return false\n\n const keysA = Object.keys(a)\n const keysB = Object.keys(b)\n\n if (keysA.length !== keysB.length) return false\n\n for (const key of keysA) {\n if (a[key] !== b[key]) return false\n }\n\n return true\n }\n}\n\n// =============================================================================\n// 工厂函数 | Factory Functions\n// =============================================================================\n\n/**\n * @zh 创建状态增量压缩器\n * @en Create state delta compressor\n */\nexport function createStateDeltaCompressor(\n config?: Partial<DeltaCompressionConfig>\n): StateDeltaCompressor {\n return new StateDeltaCompressor(config)\n}\n","/**\n * @zh 组件同步系统\n * @en Component Sync System\n *\n * @zh 基于 @sync 装饰器的组件状态同步,与 ecs-framework 的 Sync 模块集成\n * @en Component state synchronization based on @sync decorator, integrated with ecs-framework Sync module\n */\n\nimport {\n EntitySystem,\n Matcher,\n type Entity,\n // Sync types\n SyncOperation,\n SYNC_METADATA,\n CHANGE_TRACKER,\n type SyncMetadata,\n type ChangeTracker,\n // Encoding\n encodeSnapshot,\n encodeSpawn,\n encodeDespawn,\n decodeSnapshot,\n decodeSpawn,\n processDespawn,\n registerSyncComponent,\n type DecodeSnapshotResult,\n type DecodeSpawnResult,\n} from '@esengine/ecs-framework';\n\nimport { NetworkIdentity } from '../components/NetworkIdentity';\n\n// =============================================================================\n// Types | 类型定义\n// =============================================================================\n\n/**\n * @zh 组件同步事件类型\n * @en Component sync event type\n */\nexport type ComponentSyncEventType =\n | 'entitySpawned'\n | 'entityDespawned'\n | 'stateUpdated';\n\n/**\n * @zh 组件同步事件\n * @en Component sync event\n */\nexport interface ComponentSyncEvent {\n type: ComponentSyncEventType;\n entityId: number;\n prefabType?: string;\n}\n\n/**\n * @zh 组件同步事件监听器\n * @en Component sync event listener\n */\nexport type ComponentSyncEventListener = (event: ComponentSyncEvent) => void;\n\n/**\n * @zh 组件同步配置\n * @en Component sync configuration\n */\nexport interface ComponentSyncConfig {\n /**\n * @zh 是否启用增量同步\n * @en Whether to enable delta sync\n */\n enableDeltaSync: boolean;\n\n /**\n * @zh 同步间隔(毫秒)\n * @en Sync interval in milliseconds\n */\n syncInterval: number;\n}\n\nconst DEFAULT_CONFIG: ComponentSyncConfig = {\n enableDeltaSync: true,\n syncInterval: 50, // 20 Hz\n};\n\n// =============================================================================\n// ComponentSyncSystem | 组件同步系统\n// =============================================================================\n\n/**\n * @zh 组件同步系统\n * @en Component sync system\n *\n * @zh 基于 @sync 装饰器自动同步组件状态\n * @en Automatically syncs component state based on @sync decorator\n *\n * @example\n * ```typescript\n * // Server-side: broadcast state\n * const syncSystem = scene.getSystem(ComponentSyncSystem);\n * const data = syncSystem.encodeAllEntities(false); // delta\n * broadcast(data);\n *\n * // Client-side: receive state\n * const syncSystem = scene.getSystem(ComponentSyncSystem);\n * syncSystem.applySnapshot(data);\n * ```\n */\nexport class ComponentSyncSystem extends EntitySystem {\n private readonly _config: ComponentSyncConfig;\n private readonly _syncEntityMap: Map<number, Entity> = new Map();\n private readonly _syncListeners: Set<ComponentSyncEventListener> = new Set();\n private _lastSyncTime: number = 0;\n private _isServer: boolean = false;\n\n constructor(config?: Partial<ComponentSyncConfig>, isServer: boolean = false) {\n super(Matcher.all(NetworkIdentity));\n this._config = { ...DEFAULT_CONFIG, ...config };\n this._isServer = isServer;\n }\n\n /**\n * @zh 设置是否为服务端模式\n * @en Set whether in server mode\n */\n public set isServer(value: boolean) {\n this._isServer = value;\n }\n\n /**\n * @zh 获取是否为服务端模式\n * @en Get whether in server mode\n */\n public get isServer(): boolean {\n return this._isServer;\n }\n\n /**\n * @zh 获取配置\n * @en Get configuration\n */\n public get config(): Readonly<ComponentSyncConfig> {\n return this._config;\n }\n\n /**\n * @zh 添加同步事件监听器\n * @en Add sync event listener\n */\n public addSyncListener(listener: ComponentSyncEventListener): void {\n this._syncListeners.add(listener);\n }\n\n /**\n * @zh 移除同步事件监听器\n * @en Remove sync event listener\n */\n public removeSyncListener(listener: ComponentSyncEventListener): void {\n this._syncListeners.delete(listener);\n }\n\n /**\n * @zh 注册同步组件类型\n * @en Register sync component type\n *\n * @zh 客户端需要调用此方法注册所有需要同步的组件类型\n * @en Client needs to call this to register all component types to be synced\n */\n public registerComponent<T extends new () => any>(componentClass: T): void {\n const metadata: SyncMetadata | undefined = (componentClass as any)[SYNC_METADATA];\n if (metadata) {\n registerSyncComponent(metadata.typeId, componentClass as any);\n }\n }\n\n // =========================================================================\n // Server-side: Encoding | 服务端:编码\n // =========================================================================\n\n /**\n * @zh 编码所有实体状态\n * @en Encode all entities state\n *\n * @param fullSync - @zh 是否完整同步(首次连接时使用)@en Whether to do full sync (for initial connection)\n * @returns @zh 编码后的二进制数据 @en Encoded binary data\n */\n public encodeAllEntities(fullSync: boolean = false): Uint8Array {\n const entities = this.getMatchingEntities();\n const operation = fullSync ? SyncOperation.FULL : SyncOperation.DELTA;\n\n const data = encodeSnapshot(entities, operation);\n\n // Clear change trackers after encoding delta\n if (!fullSync) {\n this._clearChangeTrackers(entities);\n }\n\n return data;\n }\n\n /**\n * @zh 编码有变更的实体\n * @en Encode entities with changes\n *\n * @returns @zh 编码后的二进制数据,如果没有变更返回 null @en Encoded binary data, or null if no changes\n */\n public encodeDelta(): Uint8Array | null {\n const entities = this.getMatchingEntities();\n const changedEntities = entities.filter(entity => this._hasChanges(entity));\n\n if (changedEntities.length === 0) {\n return null;\n }\n\n const data = encodeSnapshot(changedEntities, SyncOperation.DELTA);\n this._clearChangeTrackers(changedEntities);\n\n return data;\n }\n\n /**\n * @zh 编码实体生成消息\n * @en Encode entity spawn message\n */\n public encodeSpawn(entity: Entity, prefabType?: string): Uint8Array {\n return encodeSpawn(entity, prefabType);\n }\n\n /**\n * @zh 编码实体销毁消息\n * @en Encode entity despawn message\n */\n public encodeDespawn(entityId: number): Uint8Array {\n return encodeDespawn(entityId);\n }\n\n // =========================================================================\n // Client-side: Decoding | 客户端:解码\n // =========================================================================\n\n /**\n * @zh 应用状态快照\n * @en Apply state snapshot\n *\n * @param data - @zh 二进制数据 @en Binary data\n * @returns @zh 解码结果 @en Decode result\n */\n public applySnapshot(data: Uint8Array): DecodeSnapshotResult {\n if (!this.scene) {\n throw new Error('ComponentSyncSystem not attached to a scene');\n }\n\n const result = decodeSnapshot(this.scene, data, this._syncEntityMap);\n\n // Emit events\n for (const entityResult of result.entities) {\n if (entityResult.isNew) {\n this._emitEvent({\n type: 'entitySpawned',\n entityId: entityResult.entityId,\n });\n } else {\n this._emitEvent({\n type: 'stateUpdated',\n entityId: entityResult.entityId,\n });\n }\n }\n\n return result;\n }\n\n /**\n * @zh 应用实体生成消息\n * @en Apply entity spawn message\n *\n * @param data - @zh 二进制数据 @en Binary data\n * @returns @zh 解码结果,如果不是 SPAWN 消息返回 null @en Decode result, or null if not a SPAWN message\n */\n public applySpawn(data: Uint8Array): DecodeSpawnResult | null {\n if (!this.scene) {\n throw new Error('ComponentSyncSystem not attached to a scene');\n }\n\n const result = decodeSpawn(this.scene, data, this._syncEntityMap);\n\n if (result) {\n this._emitEvent({\n type: 'entitySpawned',\n entityId: result.entity.id,\n prefabType: result.prefabType,\n });\n }\n\n return result;\n }\n\n /**\n * @zh 应用实体销毁消息\n * @en Apply entity despawn message\n *\n * @param data - @zh 二进制数据 @en Binary data\n * @returns @zh 销毁的实体 ID 列表 @en List of despawned entity IDs\n */\n public applyDespawn(data: Uint8Array): number[] {\n if (!this.scene) {\n throw new Error('ComponentSyncSystem not attached to a scene');\n }\n\n const entityIds = processDespawn(this.scene, data, this._syncEntityMap);\n\n for (const entityId of entityIds) {\n this._emitEvent({\n type: 'entityDespawned',\n entityId,\n });\n }\n\n return entityIds;\n }\n\n // =========================================================================\n // Entity Management | 实体管理\n // =========================================================================\n\n /**\n * @zh 通过网络 ID 获取实体\n * @en Get entity by network ID\n */\n public getEntityById(entityId: number): Entity | undefined {\n return this._syncEntityMap.get(entityId);\n }\n\n /**\n * @zh 获取所有匹配的实体\n * @en Get all matching entities\n */\n public getMatchingEntities(): Entity[] {\n return this.entities.slice();\n }\n\n // =========================================================================\n // Internal | 内部方法\n // =========================================================================\n\n protected override process(entities: readonly Entity[]): void {\n // Server mode: auto-sync at interval\n if (this._isServer && this._config.enableDeltaSync) {\n const now = Date.now();\n if (now - this._lastSyncTime >= this._config.syncInterval) {\n // Note: actual broadcast should be done by the user\n // This just updates the sync time\n this._lastSyncTime = now;\n }\n }\n\n // Update entity ID map\n for (const entity of entities) {\n const identity = entity.getComponent(NetworkIdentity);\n if (identity) {\n this._syncEntityMap.set(entity.id, entity);\n }\n }\n }\n\n private _hasChanges(entity: Entity): boolean {\n for (const component of entity.components) {\n const tracker = (component as any)[CHANGE_TRACKER] as ChangeTracker | undefined;\n if (tracker?.hasChanges()) {\n return true;\n }\n }\n return false;\n }\n\n private _clearChangeTrackers(entities: Entity[]): void {\n for (const entity of entities) {\n for (const component of entity.components) {\n const tracker = (component as any)[CHANGE_TRACKER] as ChangeTracker | undefined;\n if (tracker) {\n tracker.clear();\n }\n }\n }\n }\n\n private _emitEvent(event: ComponentSyncEvent): void {\n for (const listener of this._syncListeners) {\n try {\n listener(event);\n } catch (error) {\n console.error('ComponentSyncSystem: event listener error:', error);\n }\n }\n }\n\n protected override onDestroy(): void {\n this._syncEntityMap.clear();\n this._syncListeners.clear();\n }\n}\n\n/**\n * @zh 创建组件同步系统\n * @en Create component sync system\n */\nexport function createComponentSyncSystem(\n config?: Partial<ComponentSyncConfig>,\n isServer: boolean = false\n): ComponentSyncSystem {\n return new ComponentSyncSystem(config, isServer);\n}\n","import { EntitySystem, Entity, type Scene, Matcher } from '@esengine/ecs-framework'\nimport { NetworkIdentity } from '../components/NetworkIdentity'\nimport { NetworkTransform } from '../components/NetworkTransform'\nimport type { NetworkSyncSystem } from './NetworkSyncSystem'\n\n/**\n * @zh 生成消息接口\n * @en Spawn message interface\n */\nexport interface SpawnMessage {\n netId: number\n ownerId: number\n prefab: string\n pos: { x: number; y: number }\n rot?: number\n}\n\n/**\n * @zh 销毁消息接口\n * @en Despawn message interface\n */\nexport interface DespawnMessage {\n netId: number\n}\n\n/**\n * @zh 预制体工厂函数类型\n * @en Prefab factory function type\n */\nexport type PrefabFactory = (scene: Scene, spawn: SpawnMessage) => Entity\n\n/**\n * @zh 网络生成系统\n * @en Network spawn system\n *\n * @zh 处理网络实体的生成和销毁\n * @en Handles spawning and despawning of networked entities\n */\nexport class NetworkSpawnSystem extends EntitySystem {\n private _syncSystem: NetworkSyncSystem\n private _prefabFactories: Map<string, PrefabFactory> = new Map()\n private _localPlayerId: number = 0\n\n constructor(syncSystem: NetworkSyncSystem) {\n super(Matcher.nothing())\n this._syncSystem = syncSystem\n }\n\n /**\n * @zh 设置本地玩家 ID\n * @en Set local player ID\n */\n setLocalPlayerId(id: number): void {\n this._localPlayerId = id\n }\n\n /**\n * @zh 处理生成消息\n * @en Handle spawn message\n */\n handleSpawn(msg: SpawnMessage): Entity | null {\n if (!this.scene) return null\n\n const factory = this._prefabFactories.get(msg.prefab)\n if (!factory) {\n this.logger.warn(`Unknown prefab: ${msg.prefab}`)\n return null\n }\n\n const entity = factory(this.scene, msg)\n\n const identity = entity.addComponent(new NetworkIdentity())\n identity.netId = msg.netId\n identity.ownerId = msg.ownerId\n identity.prefabType = msg.prefab\n identity.bHasAuthority = msg.ownerId === this._localPlayerId\n identity.bIsLocalPlayer = identity.bHasAuthority\n\n const transform = entity.addComponent(new NetworkTransform())\n transform.setTarget(msg.pos.x, msg.pos.y, msg.rot ?? 0)\n transform.snap()\n\n this._syncSystem.registerEntity(msg.netId, entity.id)\n\n return entity\n }\n\n /**\n * @zh 处理销毁消息\n * @en Handle despawn message\n */\n handleDespawn(msg: DespawnMessage): void {\n const entityId = this._syncSystem.getEntityId(msg.netId)\n if (entityId === undefined) return\n\n const entity = this.scene?.findEntityById(entityId)\n if (entity) {\n entity.destroy()\n }\n\n this._syncSystem.unregisterEntity(msg.netId)\n }\n\n /**\n * @zh 注册预制体工厂\n * @en Register prefab factory\n */\n registerPrefab(prefabType: string, factory: PrefabFactory): void {\n this._prefabFactories.set(prefabType, factory)\n }\n\n /**\n * @zh 注销预制体工厂\n * @en Unregister prefab factory\n */\n unregisterPrefab(prefabType: string): void {\n this._prefabFactories.delete(prefabType)\n }\n\n protected override onDestroy(): void {\n this._prefabFactories.clear()\n }\n}\n","/**\n * @zh 网络输入系统\n * @en Network Input System\n *\n * @zh 收集本地玩家输入并发送到服务器,支持与预测系统集成\n * @en Collects local player input and sends to server, supports integration with prediction system\n */\n\nimport { EntitySystem, Matcher } from '@esengine/ecs-framework'\nimport type { PlayerInput } from '../protocol'\nimport type { NetworkService } from '../services/NetworkService'\nimport type { NetworkPredictionSystem } from './NetworkPredictionSystem'\n\n// =============================================================================\n// Types | 类型定义\n// =============================================================================\n\n/**\n * @zh 输入配置\n * @en Input configuration\n */\nexport interface NetworkInputConfig {\n /**\n * @zh 发送输入的最小间隔(毫秒)\n * @en Minimum interval between input sends (milliseconds)\n */\n sendInterval: number\n\n /**\n * @zh 是否合并相同输入\n * @en Whether to merge identical inputs\n */\n mergeIdenticalInputs: boolean\n\n /**\n * @zh 最大输入队列长度\n * @en Maximum input queue length\n */\n maxQueueLength: number\n}\n\nconst DEFAULT_CONFIG: NetworkInputConfig = {\n sendInterval: 16, // ~60fps\n mergeIdenticalInputs: true,\n maxQueueLength: 10,\n}\n\n/**\n * @zh 待发送输入\n * @en Pending input\n */\ninterface PendingInput {\n moveDir?: { x: number; y: number }\n actions?: string[]\n timestamp: number\n}\n\n// =============================================================================\n// NetworkInputSystem | 网络输入系统\n// =============================================================================\n\n/**\n * @zh 网络输入系统\n * @en Network input system\n *\n * @zh 收集本地玩家输入并发送到服务器\n * @en Collects local player input and sends to server\n */\nexport class NetworkInputSystem extends EntitySystem {\n private readonly _networkService: NetworkService\n private readonly _config: NetworkInputConfig\n private _predictionSystem: NetworkPredictionSystem | null = null\n\n private _frame: number = 0\n private _inputSequence: number = 0\n private _inputQueue: PendingInput[] = []\n private _lastSendTime: number = 0\n private _lastMoveDir: { x: number; y: number } = { x: 0, y: 0 }\n\n constructor(networkService: NetworkService, config?: Partial<NetworkInputConfig>) {\n super(Matcher.nothing())\n this._networkService = networkService\n this._config = { ...DEFAULT_CONFIG, ...config }\n }\n\n /**\n * @zh 获取配置\n * @en Get configuration\n */\n get config(): Readonly<NetworkInputConfig> {\n return this._config\n }\n\n /**\n * @zh 获取当前帧号\n * @en Get current frame number\n */\n get frame(): number {\n return this._frame\n }\n\n /**\n * @zh 获取当前输入序列号\n * @en Get current input sequence\n */\n get inputSequence(): number {\n return this._inputSequence\n }\n\n /**\n * @zh 设置预测系统引用\n * @en Set prediction system reference\n */\n setPredictionSystem(system: NetworkPredictionSystem): void {\n this._predictionSystem = system\n }\n\n /**\n * @zh 处理输入队列\n * @en Process input queue\n */\n protected override process(): void {\n if (!this._networkService.isConnected) return\n\n this._frame++\n const now = Date.now()\n\n // Rate limiting\n if (now - this._lastSendTime < this._config.sendInterval) return\n\n // If using prediction system, get input from there\n if (this._predictionSystem) {\n const predictedInput = this._predictionSystem.getInputToSend()\n if (predictedInput) {\n this._networkService.sendInput(predictedInput)\n this._lastSendTime = now\n }\n return\n }\n\n // Otherwise process queue\n if (this._inputQueue.length === 0) return\n\n // Merge inputs if configured\n let mergedInput: PendingInput\n if (this._config.mergeIdenticalInputs && this._inputQueue.length > 1) {\n mergedInput = this._mergeInputs(this._inputQueue)\n this._inputQueue.length = 0\n } else {\n mergedInput = this._inputQueue.shift()!\n }\n\n // Build and send input\n this._inputSequence++\n const input: PlayerInput = {\n seq: this._inputSequence,\n frame: this._frame,\n timestamp: mergedInput.timestamp,\n moveDir: mergedInput.moveDir,\n actions: mergedInput.actions,\n }\n\n this._networkService.sendInput(input)\n this._lastSendTime = now\n }\n\n private _mergeInputs(inputs: PendingInput[]): PendingInput {\n const allActions: string[] = []\n let lastMoveDir: { x: number; y: number } | undefined\n\n for (const input of inputs) {\n if (input.moveDir) {\n lastMoveDir = input.moveDir\n }\n if (input.actions) {\n allActions.push(...input.actions)\n }\n }\n\n return {\n moveDir: lastMoveDir,\n actions: allActions.length > 0 ? allActions : undefined,\n timestamp: inputs[inputs.length - 1].timestamp,\n }\n }\n\n /**\n * @zh 添加移动输入\n * @en Add move input\n */\n public addMoveInput(x: number, y: number): void {\n // Skip if same as last input\n if (\n this._config.mergeIdenticalInputs &&\n this._lastMoveDir.x === x &&\n this._lastMoveDir.y === y &&\n this._inputQueue.length > 0\n ) {\n return\n }\n\n this._lastMoveDir = { x, y }\n\n // Also set input on prediction system\n if (this._predictionSystem) {\n this._predictionSystem.setInput(x, y)\n }\n\n this._addToQueue({ moveDir: { x, y }, timestamp: Date.now() })\n }\n\n /**\n * @zh 添加动作输入\n * @en Add action input\n */\n public addActionInput(action: string): void {\n // Try to add to last input in queue\n const lastInput = this._inputQueue[this._inputQueue.length - 1]\n if (lastInput) {\n lastInput.actions = lastInput.actions || []\n lastInput.actions.push(action)\n } else {\n this._addToQueue({ actions: [action], timestamp: Date.now() })\n }\n\n // Also set on prediction system\n if (this._predictionSystem) {\n this._predictionSystem.setInput(\n this._lastMoveDir.x,\n this._lastMoveDir.y,\n [action]\n )\n }\n }\n\n private _addToQueue(input: PendingInput): void {\n this._inputQueue.push(input)\n\n // Limit queue size\n while (this._inputQueue.length > this._config.maxQueueLength) {\n this._inputQueue.shift()\n }\n }\n\n /**\n * @zh 清空输入队列\n * @en Clear input queue\n */\n public clearQueue(): void {\n this._inputQueue.length = 0\n this._lastMoveDir = { x: 0, y: 0 }\n }\n\n /**\n * @zh 重置状态\n * @en Reset state\n */\n public reset(): void {\n this._frame = 0\n this._inputSequence = 0\n this.clearQueue()\n }\n\n protected override onDestroy(): void {\n this._inputQueue.length = 0\n this._predictionSystem = null\n }\n}\n\n// =============================================================================\n// 工厂函数 | Factory Functions\n// =============================================================================\n\n/**\n * @zh 创建网络输入系统\n * @en Create network input system\n */\nexport function createNetworkInputSystem(\n networkService: NetworkService,\n config?: Partial<NetworkInputConfig>\n): NetworkInputSystem {\n return new NetworkInputSystem(networkService, config)\n}\n","/**\n * @zh 网络预测系统\n * @en Network Prediction System\n *\n * @zh 处理本地玩家的客户端预测和服务器校正\n * @en Handles client-side prediction and server reconciliation for local player\n */\n\nimport { EntitySystem, Matcher, Time, type Entity } from '@esengine/ecs-framework'\nimport { NetworkIdentity } from '../components/NetworkIdentity'\nimport { NetworkTransform } from '../components/NetworkTransform'\nimport type { SyncData, PlayerInput } from '../protocol'\nimport {\n ClientPrediction,\n createClientPrediction,\n type IPredictor,\n type ClientPredictionConfig,\n type ITransformState,\n} from '../sync'\n\n// =============================================================================\n// Types | 类型定义\n// =============================================================================\n\n/**\n * @zh 移动输入\n * @en Movement input\n */\nexport interface MovementInput {\n x: number\n y: number\n actions?: string[]\n}\n\n/**\n * @zh 预测状态(位置 + 旋转)\n * @en Predicted state (position + rotation)\n */\nexport interface PredictedTransform extends ITransformState {\n velocityX: number\n velocityY: number\n}\n\n/**\n * @zh 预测系统配置\n * @en Prediction system configuration\n */\nexport interface NetworkPredictionConfig extends Partial<ClientPredictionConfig> {\n /**\n * @zh 移动速度(单位/秒)\n * @en Movement speed (units/second)\n */\n moveSpeed: number\n\n /**\n * @zh 是否启用预测\n * @en Whether prediction is enabled\n */\n enabled: boolean\n}\n\nconst DEFAULT_CONFIG: NetworkPredictionConfig = {\n moveSpeed: 200,\n enabled: true,\n maxUnacknowledgedInputs: 60,\n reconciliationThreshold: 0.5,\n reconciliationSpeed: 10,\n}\n\n// =============================================================================\n// 默认预测器 | Default Predictor\n// =============================================================================\n\n/**\n * @zh 简单移动预测器\n * @en Simple movement predictor\n */\nclass SimpleMovementPredictor implements IPredictor<PredictedTransform, MovementInput> {\n constructor(private readonly _moveSpeed: number) {}\n\n predict(state: PredictedTransform, input: MovementInput, deltaTime: number): PredictedTransform {\n const velocityX = input.x * this._moveSpeed\n const velocityY = input.y * this._moveSpeed\n\n return {\n x: state.x + velocityX * deltaTime,\n y: state.y + velocityY * deltaTime,\n rotation: state.rotation,\n velocityX,\n velocityY,\n }\n }\n}\n\n// =============================================================================\n// NetworkPredictionSystem | 网络预测系统\n// =============================================================================\n\n/**\n * @zh 网络预测系统\n * @en Network prediction system\n *\n * @zh 处理本地玩家的输入预测和服务器状态校正\n * @en Handles local player input prediction and server state reconciliation\n */\nexport class NetworkPredictionSystem extends EntitySystem {\n private readonly _config: NetworkPredictionConfig\n private readonly _predictor: IPredictor<PredictedTransform, MovementInput>\n private _prediction: ClientPrediction<PredictedTransform, MovementInput> | null = null\n private _localPlayerNetId: number = -1\n private _currentInput: MovementInput = { x: 0, y: 0 }\n private _inputSequence: number = 0\n\n constructor(config?: Partial<NetworkPredictionConfig>) {\n super(Matcher.all(NetworkIdentity, NetworkTransform))\n this._config = { ...DEFAULT_CONFIG, ...config }\n this._predictor = new SimpleMovementPredictor(this._config.moveSpeed)\n }\n\n /**\n * @zh 获取配置\n * @en Get configuration\n */\n get config(): Readonly<NetworkPredictionConfig> {\n return this._config\n }\n\n /**\n * @zh 获取当前输入序列号\n * @en Get current input sequence number\n */\n get inputSequence(): number {\n return this._inputSequence\n }\n\n /**\n * @zh 获取待确认输入数量\n * @en Get pending input count\n */\n get pendingInputCount(): number {\n return this._prediction?.pendingInputCount ?? 0\n }\n\n /**\n * @zh 是否启用预测\n * @en Whether prediction is enabled\n */\n get enabled(): boolean {\n return this._config.enabled\n }\n\n set enabled(value: boolean) {\n this._config.enabled = value\n }\n\n /**\n * @zh 设置本地玩家网络 ID\n * @en Set local player network ID\n */\n setLocalPlayerNetId(netId: number): void {\n this._localPlayerNetId = netId\n this._prediction = createClientPrediction<PredictedTransform, MovementInput>(\n this._predictor,\n {\n maxUnacknowledgedInputs: this._config.maxUnacknowledgedInputs,\n reconciliationThreshold: this._config.reconciliationThreshold,\n reconciliationSpeed: this._config.reconciliationSpeed,\n }\n )\n }\n\n /**\n * @zh 设置移动输入\n * @en Set movement input\n */\n setInput(x: number, y: number, actions?: string[]): void {\n this._currentInput = { x, y, actions }\n }\n\n /**\n * @zh 获取下一个要发送的输入(带序列号)\n * @en Get next input to send (with sequence number)\n */\n getInputToSend(): PlayerInput | null {\n if (!this._prediction) return null\n\n const input = this._prediction.getInputToSend()\n if (!input) return null\n\n return {\n seq: input.sequence,\n frame: 0,\n timestamp: input.timestamp,\n moveDir: { x: input.input.x, y: input.input.y },\n actions: input.input.actions,\n }\n }\n\n /**\n * @zh 处理服务器同步数据进行校正\n * @en Process server sync data for reconciliation\n */\n reconcileWithServer(data: SyncData): void {\n if (!this._prediction || this._localPlayerNetId < 0) return\n\n // Find local player state in sync data\n const localState = data.entities.find(e => e.netId === this._localPlayerNetId)\n if (!localState || !localState.pos) return\n\n const serverState: PredictedTransform = {\n x: localState.pos.x,\n y: localState.pos.y,\n rotation: localState.rot ?? 0,\n velocityX: localState.vel?.x ?? 0,\n velocityY: localState.vel?.y ?? 0,\n }\n\n // Reconcile prediction with server state\n if (data.ackSeq !== undefined) {\n this._prediction.reconcile(\n serverState,\n data.ackSeq,\n (state) => ({ x: state.x, y: state.y }),\n Time.deltaTime\n )\n }\n }\n\n protected override process(entities: readonly Entity[]): void {\n if (!this._config.enabled || !this._prediction) return\n\n const deltaTime = Time.deltaTime\n\n for (const entity of entities) {\n const identity = this.requireComponent(entity, NetworkIdentity)\n\n // Only process local player with authority\n if (!identity.bHasAuthority || identity.netId !== this._localPlayerNetId) continue\n\n const transform = this.requireComponent(entity, NetworkTransform)\n\n // Get current state\n const currentState: PredictedTransform = {\n x: transform.currentX,\n y: transform.currentY,\n rotation: transform.currentRotation,\n velocityX: 0,\n velocityY: 0,\n }\n\n // Record input and get predicted state\n if (this._currentInput.x !== 0 || this._currentInput.y !== 0) {\n const predicted = this._prediction.recordInput(\n this._currentInput,\n currentState,\n deltaTime\n )\n\n // Apply predicted position\n transform.currentX = predicted.x\n transform.currentY = predicted.y\n transform.currentRotation = predicted.rotation\n\n // Update target to match (for rendering)\n transform.targetX = predicted.x\n transform.targetY = predicted.y\n transform.targetRotation = predicted.rotation\n\n this._inputSequence = this._prediction.currentSequence\n }\n\n // Apply correction offset smoothly\n const offset = this._prediction.correctionOffset\n if (Math.abs(offset.x) > 0.01 || Math.abs(offset.y) > 0.01) {\n transform.currentX += offset.x * deltaTime * 5\n transform.currentY += offset.y * deltaTime * 5\n }\n }\n }\n\n /**\n * @zh 重置预测状态\n * @en Reset prediction state\n */\n reset(): void {\n this._prediction?.clear()\n this._inputSequence = 0\n this._currentInput = { x: 0, y: 0 }\n }\n\n protected override onDestroy(): void {\n this._prediction?.clear()\n this._prediction = null\n }\n}\n\n// =============================================================================\n// 工厂函数 | Factory Functions\n// =============================================================================\n\n/**\n * @zh 创建网络预测系统\n * @en Create network prediction system\n */\nexport function createNetworkPredictionSystem(\n config?: Partial<NetworkPredictionConfig>\n): NetworkPredictionSystem {\n return new NetworkPredictionSystem(config)\n}\n","/**\n * @zh 网络 AOI 系统\n * @en Network AOI System\n *\n * @zh 集成 AOI 兴趣区域管理,过滤网络同步数据\n * @en Integrates AOI interest management to filter network sync data\n */\n\nimport { EntitySystem, Matcher, type Entity } from '@esengine/ecs-framework'\nimport { NetworkIdentity } from '../components/NetworkIdentity'\nimport { NetworkTransform } from '../components/NetworkTransform'\nimport type { EntitySyncState } from '../protocol'\n\n// =============================================================================\n// Types | 类型定义\n// =============================================================================\n\n/**\n * @zh AOI 事件类型\n * @en AOI event type\n */\nexport type NetworkAOIEventType = 'enter' | 'exit'\n\n/**\n * @zh AOI 事件\n * @en AOI event\n */\nexport interface NetworkAOIEvent {\n /**\n * @zh 事件类型\n * @en Event type\n */\n type: NetworkAOIEventType\n\n /**\n * @zh 观察者网络 ID(玩家)\n * @en Observer network ID (player)\n */\n observerNetId: number\n\n /**\n * @zh 目标网络 ID(进入/离开视野的实体)\n * @en Target network ID (entity entering/exiting view)\n */\n targetNetId: number\n}\n\n/**\n * @zh AOI 事件监听器\n * @en AOI event listener\n */\nexport type NetworkAOIEventListener = (event: NetworkAOIEvent) => void\n\n/**\n * @zh 网络 AOI 配置\n * @en Network AOI configuration\n */\nexport interface NetworkAOIConfig {\n /**\n * @zh 网格单元格大小\n * @en Grid cell size\n */\n cellSize: number\n\n /**\n * @zh 默认视野范围\n * @en Default view range\n */\n defaultViewRange: number\n\n /**\n * @zh 是否启用 AOI 过滤\n * @en Whether to enable AOI filtering\n */\n enabled: boolean\n}\n\nconst DEFAULT_CONFIG: NetworkAOIConfig = {\n cellSize: 100,\n defaultViewRange: 500,\n enabled: true,\n}\n\n/**\n * @zh 观察者数据\n * @en Observer data\n */\ninterface ObserverData {\n netId: number\n position: { x: number; y: number }\n viewRange: number\n viewRangeSq: number\n cellKey: string\n visibleEntities: Set<number>\n}\n\n// =============================================================================\n// NetworkAOISystem | 网络 AOI 系统\n// =============================================================================\n\n/**\n * @zh 网络 AOI 系统\n * @en Network AOI system\n *\n * @zh 管理网络实体的兴趣区域,过滤同步数据\n * @en Manages network entities' areas of interest and filters sync data\n */\nexport class NetworkAOISystem extends EntitySystem {\n private readonly _config: NetworkAOIConfig\n private readonly _observers: Map<number, ObserverData> = new Map()\n private readonly _cells: Map<string, Set<number>> = new Map()\n private readonly _listeners: Set<NetworkAOIEventListener> = new Set()\n private readonly _entityNetIdMap: Map<Entity, number> = new Map()\n private readonly _netIdEntityMap: Map<number, Entity> = new Map()\n\n constructor(config?: Partial<NetworkAOIConfig>) {\n super(Matcher.all(NetworkIdentity, NetworkTransform))\n this._config = { ...DEFAULT_CONFIG, ...config }\n }\n\n /**\n * @zh 获取配置\n * @en Get configuration\n */\n get config(): Readonly<NetworkAOIConfig> {\n return this._config\n }\n\n /**\n * @zh 是否启用\n * @en Is enabled\n */\n get enabled(): boolean {\n return this._config.enabled\n }\n\n set enabled(value: boolean) {\n this._config.enabled = value\n }\n\n /**\n * @zh 观察者数量\n * @en Observer count\n */\n get observerCount(): number {\n return this._observers.size\n }\n\n // =========================================================================\n // 观察者管理 | Observer Management\n // =========================================================================\n\n /**\n * @zh 添加观察者(通常是玩家实体)\n * @en Add observer (usually player entity)\n */\n addObserver(netId: number, x: number, y: number, viewRange?: number): void {\n if (this._observers.has(netId)) {\n this.updateObserverPosition(netId, x, y)\n return\n }\n\n const range = viewRange ?? this._config.defaultViewRange\n const cellKey = this._getCellKey(x, y)\n const data: ObserverData = {\n netId,\n position: { x, y },\n viewRange: range,\n viewRangeSq: range * range,\n cellKey,\n visibleEntities: new Set(),\n }\n\n this._observers.set(netId, data)\n this._addToCell(cellKey, netId)\n this._updateVisibility(data)\n }\n\n /**\n * @zh 移除观察者\n * @en Remove observer\n */\n removeObserver(netId: number): boolean {\n const data = this._observers.get(netId)\n if (!data) return false\n\n // Emit exit events for all visible entities\n for (const visibleNetId of data.visibleEntities) {\n this._emitEvent({\n type: 'exit',\n observerNetId: netId,\n targetNetId: visibleNetId,\n })\n }\n\n this._removeFromCell(data.cellKey, netId)\n this._observers.delete(netId)\n return true\n }\n\n /**\n * @zh 更新观察者位置\n * @en Update observer position\n */\n updateObserverPosition(netId: number, x: number, y: number): void {\n const data = this._observers.get(netId)\n if (!data) return\n\n const newCellKey = this._getCellKey(x, y)\n if (newCellKey !== data.cellKey) {\n this._removeFromCell(data.cellKey, netId)\n data.cellKey = newCellKey\n this._addToCell(newCellKey, netId)\n }\n\n data.position.x = x\n data.position.y = y\n this._updateVisibility(data)\n }\n\n /**\n * @zh 更新观察者视野范围\n * @en Update observer view range\n */\n updateObserverViewRange(netId: number, viewRange: number): void {\n const data = this._observers.get(netId)\n if (!data) return\n\n data.viewRange = viewRange\n data.viewRangeSq = viewRange * viewRange\n this._updateVisibility(data)\n }\n\n // =========================================================================\n // 实体管理 | Entity Management\n // =========================================================================\n\n /**\n * @zh 注册网络实体\n * @en Register network entity\n */\n registerEntity(entity: Entity, netId: number): void {\n this._entityNetIdMap.set(entity, netId)\n this._netIdEntityMap.set(netId, entity)\n }\n\n /**\n * @zh 注销网络实体\n * @en Unregister network entity\n */\n unregisterEntity(entity: Entity): void {\n const netId = this._entityNetIdMap.get(entity)\n if (netId !== undefined) {\n // Remove from all observers' visible sets\n for (const [, data] of this._observers) {\n if (data.visibleEntities.has(netId)) {\n data.visibleEntities.delete(netId)\n this._emitEvent({\n type: 'exit',\n observerNetId: data.netId,\n targetNetId: netId,\n })\n }\n }\n this._netIdEntityMap.delete(netId)\n }\n this._entityNetIdMap.delete(entity)\n }\n\n // =========================================================================\n // 查询接口 | Query Interface\n // =========================================================================\n\n /**\n * @zh 获取观察者能看到的实体网络 ID 列表\n * @en Get list of entity network IDs visible to observer\n */\n getVisibleEntities(observerNetId: number): number[] {\n const data = this._observers.get(observerNetId)\n return data ? Array.from(data.visibleEntities) : []\n }\n\n /**\n * @zh 获取能看到指定实体的观察者网络 ID 列表\n * @en Get list of observer network IDs that can see the entity\n */\n getObserversOf(entityNetId: number): number[] {\n const observers: number[] = []\n for (const [, data] of this._observers) {\n if (data.visibleEntities.has(entityNetId)) {\n observers.push(data.netId)\n }\n }\n return observers\n }\n\n /**\n * @zh 检查观察者是否能看到目标\n * @en Check if observer can see target\n */\n canSee(observerNetId: number, targetNetId: number): boolean {\n const data = this._observers.get(observerNetId)\n return data?.visibleEntities.has(targetNetId) ?? false\n }\n\n /**\n * @zh 过滤同步数据,只保留观察者能看到的实体\n * @en Filter sync data to only include entities visible to observer\n */\n filterSyncData(observerNetId: number, entities: EntitySyncState[]): EntitySyncState[] {\n if (!this._config.enabled) {\n return entities\n }\n\n const data = this._observers.get(observerNetId)\n if (!data) {\n return entities\n }\n\n return entities.filter(entity => {\n // Always include the observer's own entity\n if (entity.netId === observerNetId) return true\n // Include entities in view\n return data.visibleEntities.has(entity.netId)\n })\n }\n\n // =========================================================================\n // 事件系统 | Event System\n // =========================================================================\n\n /**\n * @zh 添加事件监听器\n * @en Add event listener\n */\n addListener(listener: NetworkAOIEventListener): void {\n this._listeners.add(listener)\n }\n\n /**\n * @zh 移除事件监听器\n * @en Remove event listener\n */\n removeListener(listener: NetworkAOIEventListener): void {\n this._listeners.delete(listener)\n }\n\n // =========================================================================\n // 系统生命周期 | System Lifecycle\n // =========================================================================\n\n protected override process(entities: readonly Entity[]): void {\n if (!this._config.enabled) return\n\n // Update entity positions for AOI calculations\n for (const entity of entities) {\n const identity = this.requireComponent(entity, NetworkIdentity)\n const transform = this.requireComponent(entity, NetworkTransform)\n\n // Register entity if not already registered\n if (!this._entityNetIdMap.has(entity)) {\n this.registerEntity(entity, identity.netId)\n }\n\n // If this entity is an observer (has authority), update its position\n if (identity.bHasAuthority && this._observers.has(identity.netId)) {\n this.updateObserverPosition(\n identity.netId,\n transform.currentX,\n transform.currentY\n )\n }\n }\n\n // Update all observers' visibility based on entity positions\n this._updateAllObserversVisibility(entities)\n }\n\n private _updateAllObserversVisibility(entities: readonly Entity[]): void {\n for (const [, data] of this._observers) {\n const newVisible = new Set<number>()\n\n // Check all entities\n for (const entity of entities) {\n const identity = this.requireComponent(entity, NetworkIdentity)\n const transform = this.requireComponent(entity, NetworkTransform)\n\n // Skip self\n if (identity.netId === data.netId) continue\n\n // Check distance\n const dx = transform.currentX - data.position.x\n const dy = transform.currentY - data.position.y\n const distSq = dx * dx + dy * dy\n\n if (distSq <= data.viewRangeSq) {\n newVisible.add(identity.netId)\n }\n }\n\n // Find entities that entered view\n for (const netId of newVisible) {\n if (!data.visibleEntities.has(netId)) {\n this._emitEvent({\n type: 'enter',\n observerNetId: data.netId,\n targetNetId: netId,\n })\n }\n }\n\n // Find entities that exited view\n for (const netId of data.visibleEntities) {\n if (!newVisible.has(netId)) {\n this._emitEvent({\n type: 'exit',\n observerNetId: data.netId,\n targetNetId: netId,\n })\n }\n }\n\n data.visibleEntities = newVisible\n }\n }\n\n /**\n * @zh 清除所有数据\n * @en Clear all data\n */\n clear(): void {\n this._observers.clear()\n this._cells.clear()\n this._entityNetIdMap.clear()\n this._netIdEntityMap.clear()\n }\n\n protected override onDestroy(): void {\n this.clear()\n this._listeners.clear()\n }\n\n // =========================================================================\n // 私有方法 | Private Methods\n // =========================================================================\n\n private _getCellKey(x: number, y: number): string {\n const cellX = Math.floor(x / this._config.cellSize)\n const cellY = Math.floor(y / this._config.cellSize)\n return `${cellX},${cellY}`\n }\n\n private _addToCell(cellKey: string, netId: number): void {\n let cell = this._cells.get(cellKey)\n if (!cell) {\n cell = new Set()\n this._cells.set(cellKey, cell)\n }\n cell.add(netId)\n }\n\n private _removeFromCell(cellKey: string, netId: number): void {\n const cell = this._cells.get(cellKey)\n if (cell) {\n cell.delete(netId)\n if (cell.size === 0) {\n this._cells.delete(cellKey)\n }\n }\n }\n\n private _updateVisibility(data: ObserverData): void {\n // This is called when an observer moves\n // The full visibility update happens in process() with all entities\n }\n\n private _emitEvent(event: NetworkAOIEvent): void {\n for (const listener of this._listeners) {\n try {\n listener(event)\n } catch (e) {\n console.error('[NetworkAOISystem] Listener error:', e)\n }\n }\n }\n}\n\n// =============================================================================\n// 工厂函数 | Factory Functions\n// =============================================================================\n\n/**\n * @zh 创建网络 AOI 系统\n * @en Create network AOI system\n */\nexport function createNetworkAOISystem(\n config?: Partial<NetworkAOIConfig>\n): NetworkAOISystem {\n return new NetworkAOISystem(config)\n}\n","/**\n * @zh 网络蓝图节点\n * @en Network Blueprint Nodes\n *\n * @zh 提供网络功能的蓝图节点\n * @en Provides blueprint nodes for network functionality\n */\n\nimport type { BlueprintNodeTemplate, BlueprintNode, INodeExecutor, ExecutionResult } from '@esengine/blueprint';\n\n// =============================================================================\n// 执行上下文接口 | Execution Context Interface\n// =============================================================================\n\n/**\n * @zh 网络上下文\n * @en Network context\n */\ninterface NetworkContext {\n entity: {\n getComponent<T>(type: new (...args: unknown[]) => T): T | null;\n };\n isServer: boolean;\n localPlayerId: number;\n evaluateInput(nodeId: string, pinName: string, defaultValue?: unknown): unknown;\n setOutputs(nodeId: string, outputs: Record<string, unknown>): void;\n}\n\n// =============================================================================\n// IsLocalPlayer 节点 | IsLocalPlayer Node\n// =============================================================================\n\n/**\n * @zh IsLocalPlayer 节点模板\n * @en IsLocalPlayer node template\n */\nexport const IsLocalPlayerTemplate: BlueprintNodeTemplate = {\n type: 'IsLocalPlayer',\n title: 'Is Local Player',\n category: 'entity',\n description: 'Check if this entity is the local player / 检查此实体是否是本地玩家',\n keywords: ['network', 'local', 'player', 'authority', 'owner'],\n menuPath: ['Network', 'Is Local Player'],\n isPure: true,\n inputs: [],\n outputs: [\n {\n name: 'isLocal',\n displayName: 'Is Local',\n type: 'bool'\n }\n ],\n color: '#ff9800'\n};\n\n/**\n * @zh IsLocalPlayer 节点执行器\n * @en IsLocalPlayer node executor\n */\nexport class IsLocalPlayerExecutor implements INodeExecutor {\n execute(node: BlueprintNode, context: unknown): ExecutionResult {\n const ctx = context as NetworkContext;\n\n // Try to get NetworkIdentity component\n let isLocal = false;\n if (ctx.entity) {\n const identity = ctx.entity.getComponent(class NetworkIdentity {\n bIsLocalPlayer: boolean = false;\n });\n if (identity) {\n isLocal = identity.bIsLocalPlayer;\n }\n }\n\n return {\n outputs: {\n isLocal\n }\n };\n }\n}\n\n// =============================================================================\n// IsServer 节点 | IsServer Node\n// =============================================================================\n\n/**\n * @zh IsServer 节点模板\n * @en IsServer node template\n */\nexport const IsServerTemplate: BlueprintNodeTemplate = {\n type: 'IsServer',\n title: 'Is Server',\n category: 'entity',\n description: 'Check if running on server / 检查是否在服务器上运行',\n keywords: ['network', 'server', 'authority', 'host'],\n menuPath: ['Network', 'Is Server'],\n isPure: true,\n inputs: [],\n outputs: [\n {\n name: 'isServer',\n displayName: 'Is Server',\n type: 'bool'\n }\n ],\n color: '#ff9800'\n};\n\n/**\n * @zh IsServer 节点执行器\n * @en IsServer node executor\n */\nexport class IsServerExecutor implements INodeExecutor {\n execute(_node: BlueprintNode, context: unknown): ExecutionResult {\n const ctx = context as NetworkContext;\n\n return {\n outputs: {\n isServer: ctx.isServer ?? false\n }\n };\n }\n}\n\n// =============================================================================\n// HasAuthority 节点 | HasAuthority Node\n// =============================================================================\n\n/**\n * @zh HasAuthority 节点模板\n * @en HasAuthority node template\n */\nexport const HasAuthorityTemplate: BlueprintNodeTemplate = {\n type: 'HasAuthority',\n title: 'Has Authority',\n category: 'entity',\n description: 'Check if this entity has authority / 检查此实体是否有权限控制',\n keywords: ['network', 'authority', 'control', 'owner'],\n menuPath: ['Network', 'Has Authority'],\n isPure: true,\n inputs: [],\n outputs: [\n {\n name: 'hasAuthority',\n displayName: 'Has Authority',\n type: 'bool'\n }\n ],\n color: '#ff9800'\n};\n\n/**\n * @zh HasAuthority 节点执行器\n * @en HasAuthority node executor\n */\nexport class HasAuthorityExecutor implements INodeExecutor {\n execute(node: BlueprintNode, context: unknown): ExecutionResult {\n const ctx = context as NetworkContext;\n\n let hasAuthority = false;\n if (ctx.entity) {\n const identity = ctx.entity.getComponent(class NetworkIdentity {\n bHasAuthority: boolean = false;\n });\n if (identity) {\n hasAuthority = identity.bHasAuthority;\n }\n }\n\n return {\n outputs: {\n hasAuthority\n }\n };\n }\n}\n\n// =============================================================================\n// GetNetworkId 节点 | GetNetworkId Node\n// =============================================================================\n\n/**\n * @zh GetNetworkId 节点模板\n * @en GetNetworkId node template\n */\nexport const GetNetworkIdTemplate: BlueprintNodeTemplate = {\n type: 'GetNetworkId',\n title: 'Get Network ID',\n category: 'entity',\n description: 'Get the network ID of this entity / 获取此实体的网络 ID',\n keywords: ['network', 'id', 'netid', 'identity'],\n menuPath: ['Network', 'Get Network ID'],\n isPure: true,\n inputs: [],\n outputs: [\n {\n name: 'netId',\n displayName: 'Net ID',\n type: 'int'\n },\n {\n name: 'ownerId',\n displayName: 'Owner ID',\n type: 'int'\n }\n ],\n color: '#ff9800'\n};\n\n/**\n * @zh GetNetworkId 节点执行器\n * @en GetNetworkId node executor\n */\nexport class GetNetworkIdExecutor implements INodeExecutor {\n execute(node: BlueprintNode, context: unknown): ExecutionResult {\n const ctx = context as NetworkContext;\n\n let netId = 0;\n let ownerId = 0;\n\n if (ctx.entity) {\n const identity = ctx.entity.getComponent(class NetworkIdentity {\n netId: number = 0;\n ownerId: number = 0;\n });\n if (identity) {\n netId = identity.netId;\n ownerId = identity.ownerId;\n }\n }\n\n return {\n outputs: {\n netId,\n ownerId\n }\n };\n }\n}\n\n// =============================================================================\n// GetLocalPlayerId 节点 | GetLocalPlayerId Node\n// =============================================================================\n\n/**\n * @zh GetLocalPlayerId 节点模板\n * @en GetLocalPlayerId node template\n */\nexport const GetLocalPlayerIdTemplate: BlueprintNodeTemplate = {\n type: 'GetLocalPlayerId',\n title: 'Get Local Player ID',\n category: 'entity',\n description: 'Get the local player ID / 获取本地玩家 ID',\n keywords: ['network', 'local', 'player', 'id'],\n menuPath: ['Network', 'Get Local Player ID'],\n isPure: true,\n inputs: [],\n outputs: [\n {\n name: 'playerId',\n displayName: 'Player ID',\n type: 'int'\n }\n ],\n color: '#ff9800'\n};\n\n/**\n * @zh GetLocalPlayerId 节点执行器\n * @en GetLocalPlayerId node executor\n */\nexport class GetLocalPlayerIdExecutor implements INodeExecutor {\n execute(_node: BlueprintNode, context: unknown): ExecutionResult {\n const ctx = context as NetworkContext;\n\n return {\n outputs: {\n playerId: ctx.localPlayerId ?? 0\n }\n };\n }\n}\n\n// =============================================================================\n// 节点定义集合 | Node Definition Collection\n// =============================================================================\n\n/**\n * @zh 网络节点定义集合\n * @en Network node definition collection\n */\nexport const NetworkNodeDefinitions = {\n templates: [\n IsLocalPlayerTemplate,\n IsServerTemplate,\n HasAuthorityTemplate,\n GetNetworkIdTemplate,\n GetLocalPlayerIdTemplate\n ],\n executors: new Map<string, INodeExecutor>([\n ['IsLocalPlayer', new IsLocalPlayerExecutor()],\n ['IsServer', new IsServerExecutor()],\n ['HasAuthority', new HasAuthorityExecutor()],\n ['GetNetworkId', new GetNetworkIdExecutor()],\n ['GetLocalPlayerId', new GetLocalPlayerIdExecutor()]\n ])\n};\n"],"mappings":";;;;;;AAYA,SAASA,OAAAA,YAAW;;;ACJpB,SAASC,WAAW;AA8Pb,IAAMC,eAAeD,IAAIE,OAAO;EACnCC,KAAK;;;;;IAKDC,MAAMJ,IAAIG,IAAG;;;;;IAMbE,OAAOL,IAAIG,IAAG;;;;;IAMdG,WAAWN,IAAIG,IAAG;EACtB;EACAI,KAAK;;;;;IAKDC,OAAOR,IAAIO,IAAG;;;;;IAMdE,MAAMT,IAAIO,IAAG;;;;;IAMbG,OAAOV,IAAIO,IAAG;;;;;IAMdI,SAASX,IAAIO,IAAG;;;;;IAMhBK,WAAWZ,IAAIO,IAAG;EACtB;AACJ,CAAA;;;ACpTA,SAASM,0BAA0B;AAgB5B,IAAMC,sBAAsBD,mBAAmC,gBAAA;AAM/D,IAAME,yBAAyBF,mBAAsC,mBAAA;AAMrE,IAAMG,0BAA0BH,mBAAuC,oBAAA;AAMvE,IAAMI,0BAA0BJ,mBAAuC,oBAAA;AAMvE,IAAMK,+BAA+BL,mBAA4C,yBAAA;AAMjF,IAAMM,wBAAwBN,mBAAqC,kBAAA;;;AC3C1E,SAAuBO,YAA+C;;;ACHtE,SACIC,iBAQG;AAWA,IAAWC,eAAAA,0BAAAA,eAAAA;;;;SAAAA;;AA+BX,IAAMC,cAAN,MAAMA,YAAAA;EAIT,YAA+BC,WAAc;;AAHnCC,mCAA+B;AAC/BC,kCAAAA;SAEqBF,YAAAA;EAAe;;;;;EAM9C,IAAIG,QAAsB;AACtB,WAAO,KAAKD;EAChB;;;;;EAMA,IAAIE,cAAuB;AACvB,WAAO,KAAKF,WAAM;EACtB;;;;;EAMA,IAAIG,SAA8B;AAC9B,WAAO,KAAKJ;EAChB;;;;;EAMA,MAAMK,QAAQC,SAA+C;AACzD,QAAI,KAAKL,WAAM,GAAgC;AAC3C,YAAM,IAAIM,MAAM,iCAAA;IACpB;AAEA,SAAKN,SAAM;AAEX,QAAI;AACA,WAAKD,UAAU,IAAIQ,UAAU,KAAKT,WAAWO,QAAQG,KAAK;QACtD,GAAGH;QACHI,WAAW,6BAAA;AACP,eAAKT,SAAM;AACXK,kBAAQI,YAAS;QACrB,GAHW;QAIXC,cAAc,wBAACC,WAAAA;AACX,eAAKX,SAAM;AACXK,kBAAQK,eAAeC,MAAAA;QAC3B,GAHc;QAIdC,SAASP,QAAQO;MACrB,CAAA;AACA,YAAM,KAAKb,QAAQK,QAAO;AAC1B,WAAKJ,SAAM;IACf,SAASa,KAAK;AACV,WAAKb,SAAM;AACX,WAAKD,UAAU;AACf,YAAMc;IACV;EACJ;;;;;EAMAC,aAAmB;AACf,SAAKf,SAASe,WAAAA;AACd,SAAKf,UAAU;AACf,SAAKC,SAAM;EACf;;;;;EAMAe,KACIC,MACAC,OAC+B;AAC/B,QAAI,CAAC,KAAKlB,SAAS;AACf,aAAOmB,QAAQC,OAAO,IAAIb,MAAM,eAAA,CAAA;IACpC;AACA,WAAO,KAAKP,QAAQgB,KAAKC,MAAMC,KAAAA;EACnC;;;;;EAMAG,KAA4BJ,MAASK,MAAkC;AACnE,SAAKtB,SAASqB,KAAKJ,MAAMK,IAAAA;EAC7B;;;;;EAMAC,GACIN,MACAO,SACI;AACJ,SAAKxB,SAASuB,GAAGN,MAAMO,OAAAA;AACvB,WAAO;EACX;;;;;EAMAC,IACIR,MACAO,SACI;AACJ,SAAKxB,SAASyB,IAAIR,MAAMO,OAAAA;AACxB,WAAO;EACX;;;;;EAMAE,KACIT,MACAO,SACI;AACJ,SAAKxB,SAAS0B,KAAKT,MAAMO,OAAAA;AACzB,WAAO;EACX;AACJ;AAlIa1B;AAAN,IAAMA,aAAN;AA8JA,IAAM6B,sBAAN,MAAMA,4BAA2B7B,WAAAA;EACpC,cAAc;AACV,UAAM8B,YAAAA;EACV;;;;;EAMAC,UAAUX,OAA0B;AAChC,SAAKG,KAAK,SAASH,KAAAA;EACvB;;;;;EAMAY,OAAON,SAAqE;AACxE,WAAO,KAAKD,GAAG,QAAQC,OAAAA;EAC3B;;;;;EAMAO,QAAQP,SAAsE;AAC1E,WAAO,KAAKD,GAAG,SAASC,OAAAA;EAC5B;;;;;EAMAQ,UAAUR,SAAwE;AAC9E,WAAO,KAAKD,GAAG,WAAWC,OAAAA;EAC9B;AACJ;AApCwC1B;AAAjC,IAAM6B,qBAAN;AAsDA,SAASM,qBAA4CC,UAAY;AACpE,MAAIA,UAAU;AACV,WAAO,IAAIC,WAAWD,QAAAA;EAC1B;AACA,SAAO,IAAIE,mBAAAA;AACf;AALgBH;;;ACpQhB,SAASI,gBAAAA,eAAcC,WAAAA,UAASC,YAAyB;;;ACRzD,SAASC,WAAWC,cAAcC,WAAWC,cAAcC,gBAAgB;;;;;;;;;;;;AAWpE,IAAMC,mBAAN,MAAMA,yBAAwBC,UAAAA;EAA9B;;AAOIC;;;;iCAAgB;AAQhBC;;;;mCAAkB;AAMlBC;;;;0CAA0B;AAM1BC;;;;yCAAyB;AAQzBC;;;;sCAAqB;AAQrBC;;;;wCAAuB;AAMvBC;;;;wCAAuB;;;;;;EAMvBC,UAAUC,KAAsB;AACnC,WAAOA,MAAM,KAAKF,gBAAgB,KAAKD;EAC3C;AACJ;AA1DqCN;AAA9B,IAAMD,kBAAN;;;;IAMSW,MAAM;IAAWC,OAAO;IAAUC,UAAU;;;;;;;IAQ5CF,MAAM;IAAWC,OAAO;IAAYC,UAAU;;;;;;;IAoB9CF,MAAM;IAAUC,OAAO;;;;;;;IAQvBD,MAAM;IAAUC,OAAO;IAAiBE,KAAK;;;;;;;IA3C7CC,SAAS;IAAGC,QAAQ;;;;;ACVpC,SAASC,aAAAA,YAAWC,gBAAAA,eAAcC,aAAAA,YAAWC,gBAAAA,eAAcC,YAAAA,iBAAgB;;;;;;;;;;;;AAWpE,IAAMC,oBAAN,MAAMA,0BAAyBC,WAAAA;EAA/B;;AAKIC;;;;mCAAkB;AAMlBC;;;;mCAAkB;AAMlBC;;;;0CAAyB;AAMzBC;;;;oCAAmB;AAMnBC;;;;oCAAmB;AAMnBC;;;;2CAA0B;AAQ1BC;;;;qCAAoB;AAQpBC;;;;wCAAwB;AAQxBC;;;;wCAAuB;AAMvBC;;;;wCAAuB;;;;;;EAMvBC,UAAUC,GAAWC,GAAWC,UAAyB;AAC5D,SAAKb,UAAUW;AACf,SAAKV,UAAUW;AACf,QAAIC,aAAaC,QAAW;AACxB,WAAKZ,iBAAiBW;IAC1B;EACJ;;;;;EAMOE,OAAa;AAChB,SAAKZ,WAAW,KAAKH;AACrB,SAAKI,WAAW,KAAKH;AACrB,SAAKI,kBAAkB,KAAKH;EAChC;AACJ;AAxFsCH;AAA/B,IAAMD,mBAAN;;;;IA0CSkB,MAAM;IAAUC,OAAO;IAAcC,KAAK;IAAKC,KAAK;;;;;;;IAQpDH,MAAM;IAAWC,OAAO;;;;;;;IAQxBD,MAAM;IAAUC,OAAO;IAAiBC,KAAK;;;;;;IA5DzBE,UAAU;MAAC;;;;IAC/BC,SAAS;IAAGC,QAAQ;;;;;ACQ7B,IAAMC,kBAAN,MAAMA,gBAAAA;EAKT,YAAYC,QAA+B;AAJ1BC,mCAA+B,CAAA;AAC/BC;AACAC;AAGb,SAAKD,WAAWF,OAAOI;AACvB,SAAKD,sBAAsBH,OAAOK;EACtC;EAEA,IAAIC,OAAe;AACf,WAAO,KAAKL,QAAQM;EACxB;;;;;EAMA,IAAIF,qBAA6B;AAC7B,WAAO,KAAKF;EAChB;;;;;EAMAK,KAAKC,UAAmC;AAEpC,QAAIC,cAAc,KAAKT,QAAQM;AAC/B,aAASI,IAAI,KAAKV,QAAQM,SAAS,GAAGI,KAAK,GAAGA,KAAK;AAC/C,UAAI,KAAKV,QAAQU,CAAAA,EAAGC,aAAaH,SAASG,WAAW;AACjDF,sBAAcC,IAAI;AAClB;MACJ;AACA,UAAIA,MAAM,GAAG;AACTD,sBAAc;MAClB;IACJ;AAEA,SAAKT,QAAQY,OAAOH,aAAa,GAAGD,QAAAA;AAGpC,WAAO,KAAKR,QAAQM,SAAS,KAAKL,UAAU;AACxC,WAAKD,QAAQa,MAAK;IACtB;EACJ;;;;;EAMAC,0BAA0BC,YAA2E;AACjG,QAAI,KAAKf,QAAQM,SAAS,GAAG;AACzB,aAAO;IACX;AAGA,UAAMU,aAAaD,aAAa,KAAKb;AAGrC,aAASQ,IAAI,GAAGA,IAAI,KAAKV,QAAQM,SAAS,GAAGI,KAAK;AAC9C,YAAMO,OAAO,KAAKjB,QAAQU,CAAAA;AAC1B,YAAMQ,OAAO,KAAKlB,QAAQU,IAAI,CAAA;AAE9B,UAAIO,KAAKN,aAAaK,cAAcE,KAAKP,aAAaK,YAAY;AAC9D,cAAMG,WAAWD,KAAKP,YAAYM,KAAKN;AACvC,cAAMS,IAAID,WAAW,KAAKH,aAAaC,KAAKN,aAAaQ,WAAW;AACpE,eAAO;UAACF;UAAMC;UAAMG,KAAKC,IAAI,GAAGD,KAAKE,IAAI,GAAGH,CAAAA,CAAAA;;MAChD;IACJ;AAGA,QAAIJ,aAAa,KAAKhB,QAAQ,KAAKA,QAAQM,SAAS,CAAA,EAAGK,WAAW;AAC9D,YAAMM,OAAO,KAAKjB,QAAQ,KAAKA,QAAQM,SAAS,CAAA;AAChD,YAAMY,OAAO,KAAKlB,QAAQ,KAAKA,QAAQM,SAAS,CAAA;AAChD,YAAMa,WAAWD,KAAKP,YAAYM,KAAKN;AACvC,YAAMS,IAAID,WAAW,KAAKH,aAAaC,KAAKN,aAAaQ,WAAW;AAEpE,aAAO;QAACF;QAAMC;QAAMG,KAAKE,IAAIH,GAAG,CAAA;;IACpC;AAGA,WAAO;EACX;;;;;EAMAI,YAAsC;AAClC,WAAO,KAAKxB,QAAQM,SAAS,IAAI,KAAKN,QAAQ,KAAKA,QAAQM,SAAS,CAAA,IAAK;EAC7E;;;;;EAMAmB,kBAAkBd,WAAwC;AACtD,WAAO,KAAKX,QAAQ0B,OAAOC,CAAAA,MAAKA,EAAEhB,YAAYA,SAAAA;EAClD;;;;;EAMAiB,QAAc;AACV,SAAK5B,QAAQM,SAAS;EAC1B;AACJ;AA5GaR;AAAN,IAAMA,iBAAN;AAyHA,SAAS+B,qBACZ1B,UAAkB,IAClBC,qBAA6B,KAAG;AAEhC,SAAO,IAAIN,eAAkB;IAAEK;IAASC;EAAmB,CAAA;AAC/D;AALgByB;;;ACtFT,SAASC,KAAKC,GAAWC,GAAWC,GAAS;AAChD,SAAOF,KAAKC,IAAID,KAAKE;AACzB;AAFgBH;AAQT,SAASI,UAAUH,GAAWC,GAAWC,GAAS;AACrD,MAAIE,OAAOH,IAAID;AACf,SAAOI,OAAOC,KAAKC,GAAIF,SAAQC,KAAKC,KAAK;AACzC,SAAOF,OAAO,CAACC,KAAKC,GAAIF,SAAQC,KAAKC,KAAK;AAC1C,SAAON,IAAII,OAAOF;AACtB;AALgBC;AAmBT,SAASI,WACZC,SACAC,QACAC,UACAC,YACAC,WACAC,WAAmBC,UAAQ;AAE3BH,eAAaN,KAAKU,IAAI,MAAQJ,UAAAA;AAC9B,QAAMK,QAAQ,IAAIL;AAClB,QAAMM,IAAID,QAAQJ;AAClB,QAAMM,MAAM,KAAK,IAAID,IAAI,OAAOA,IAAIA,IAAI,QAAQA,IAAIA,IAAIA;AAExD,MAAIE,SAASX,UAAUC;AACvB,QAAMW,YAAYP,WAAWF;AAC7BQ,WAASd,KAAKU,IAAI,CAACK,WAAWf,KAAKgB,IAAID,WAAWD,MAAAA,CAAAA;AAElD,QAAMG,QAAQZ,WAAWM,QAAQG,UAAUP;AAC3C,MAAIW,eAAeb,WAAWM,QAAQM,QAAQJ;AAC9C,MAAIM,WAAWf,UAAUU,SAASG,QAAQJ;AAG1C,MAAKT,SAASD,UAAU,MAAQgB,WAAWf,QAAS;AAChDe,eAAWf;AACXc,mBAAeC,WAAWf,UAAUG;EACxC;AAEA,SAAO;IAACY;IAAUD;;AACtB;AA5BgBhB;;;AC5DT,IAAMkB,yBAAN,MAAMA,uBAAAA;;;;;EAKTC,YAAYC,MAAuBC,IAAqBC,GAA4B;AAChF,WAAO;MACHC,GAAGC,KAAKJ,KAAKG,GAAGF,GAAGE,GAAGD,CAAAA;MACtBG,GAAGD,KAAKJ,KAAKK,GAAGJ,GAAGI,GAAGH,CAAAA;MACtBI,UAAUC,UAAUP,KAAKM,UAAUL,GAAGK,UAAUJ,CAAAA;IACpD;EACJ;;;;;EAMAM,YAAYC,OAAoCC,WAAgD;AAC5F,WAAO;MACHP,GAAGM,MAAMN,IAAIM,MAAME,YAAYD;MAC/BL,GAAGI,MAAMJ,IAAII,MAAMG,YAAYF;MAC/BJ,UAAUG,MAAMH,WAAWG,MAAMI,kBAAkBH;MACnDC,WAAWF,MAAME;MACjBC,WAAWH,MAAMG;MACjBC,iBAAiBJ,MAAMI;IAC3B;EACJ;AACJ;AA3Baf;AAAN,IAAMA,wBAAN;AAqCA,IAAMgB,gCAAN,MAAMA,8BAAAA;;;;;EAKTf,YACIC,MACAC,IACAC,GAC2B;AAC3B,UAAMa,KAAKb,IAAIA;AACf,UAAMc,KAAKD,KAAKb;AAGhB,UAAMe,MAAM,IAAID,KAAK,IAAID,KAAK;AAC9B,UAAMG,MAAMF,KAAK,IAAID,KAAKb;AAC1B,UAAMiB,MAAM,KAAKH,KAAK,IAAID;AAC1B,UAAMK,MAAMJ,KAAKD;AAGjB,UAAMM,KAAK;AAEX,UAAMlB,IAAIc,MAAMjB,KAAKG,IAAIe,MAAMlB,KAAKW,YAAYU,KAAKF,MAAMlB,GAAGE,IAAIiB,MAAMnB,GAAGU,YAAYU;AACvF,UAAMhB,IAAIY,MAAMjB,KAAKK,IAAIa,MAAMlB,KAAKY,YAAYS,KAAKF,MAAMlB,GAAGI,IAAIe,MAAMnB,GAAGW,YAAYS;AAGvF,UAAMC,OAAO,IAAIP,KAAK,IAAIb;AAC1B,UAAMqB,OAAO,IAAIR,KAAK,IAAIb,IAAI;AAC9B,UAAMsB,OAAO,KAAKT,KAAK,IAAIb;AAC3B,UAAMuB,OAAO,IAAIV,KAAK,IAAIb;AAE1B,UAAMS,aAAaW,OAAOtB,KAAKG,IAAIoB,OAAOvB,KAAKW,YAAYU,KAAKG,OAAOvB,GAAGE,IAAIsB,OAAOxB,GAAGU,YAAYU,MAAMA;AAC1G,UAAMT,aAAaU,OAAOtB,KAAKK,IAAIkB,OAAOvB,KAAKY,YAAYS,KAAKG,OAAOvB,GAAGI,IAAIoB,OAAOxB,GAAGW,YAAYS,MAAMA;AAE1G,WAAO;MACHlB;MACAE;MACAC,UAAUC,UAAUP,KAAKM,UAAUL,GAAGK,UAAUJ,CAAAA;MAChDS;MACAC;MACAC,iBAAiBT,KAAKJ,KAAKa,iBAAiBZ,GAAGY,iBAAiBX,CAAAA;IACpE;EACJ;AACJ;AA3CaY;AAAN,IAAMA,+BAAN;AAqDA,SAASY,8BAAAA;AACZ,SAAO,IAAI5B,sBAAAA;AACf;AAFgB4B;AAQT,SAASC,qCAAAA;AACZ,SAAO,IAAIb,6BAAAA;AACf;AAFgBa;;;ACXT,IAAMC,oBAAN,MAAMA,kBAAAA;EAUT,YAAYC,WAAuCC,QAA0C;AAT5EC;AACAC;AACAC,0CAA2C,CAAA;AACpDC,qDAAoC;AACpCC,4CAA2B;AAC3BC,4CAAkC;AAClCC,2CAAiC;AACjCC,6CAA8C;MAAEC,GAAG;MAAGC,GAAG;IAAE;AAG/D,SAAKT,aAAaF;AAClB,SAAKG,UAAU;MACXS,yBAAyB;MACzBC,yBAAyB;MACzBC,qBAAqB;MACrB,GAAGb;IACP;EACJ;;;;;EAMA,IAAIc,iBAAgC;AAChC,WAAO,KAAKP;EAChB;;;;;EAMA,IAAIQ,mBAA6C;AAC7C,WAAO,KAAKP;EAChB;;;;;EAMA,IAAIQ,oBAA4B;AAC5B,WAAO,KAAKb,eAAec;EAC/B;;;;;;;;;;EAWAC,YAAYC,OAAeC,cAAsBC,WAA2B;AACxE,SAAKhB;AAEL,UAAMiB,gBAAwC;MAC1CC,UAAU,KAAKlB;MACfc;MACAK,WAAWC,KAAKC,IAAG;IACvB;AAEA,SAAKvB,eAAewB,KAAKL,aAAAA;AAGzB,WAAO,KAAKnB,eAAec,SAAS,KAAKf,QAAQS,yBAAyB;AACtE,WAAKR,eAAeyB,MAAK;IAC7B;AAGA,SAAKrB,kBAAkB,KAAKN,WAAW4B,QAAQT,cAAcD,OAAOE,SAAAA;AAEpE,WAAO,KAAKd;EAChB;;;;;EAMAuB,iBAAgD;AAC5C,WAAO,KAAK3B,eAAec,SAAS,IAAI,KAAKd,eAAe,KAAKA,eAAec,SAAS,CAAA,IAAK;EAClG;;;;;EAMA,IAAIc,kBAA0B;AAC1B,WAAO,KAAK1B;EAChB;;;;;;;;;;EAWA2B,UACIC,aACAC,sBACAC,aACAd,WACM;AACN,SAAKf,mBAAmB2B;AACxB,SAAK7B,4BAA4B8B;AAGjC,WAAO,KAAK/B,eAAec,SAAS,KAAK,KAAKd,eAAe,CAAA,EAAGoB,YAAYW,sBAAsB;AAC9F,WAAK/B,eAAeyB,MAAK;IAC7B;AAGA,QAAIQ,QAAQH;AACZ,eAAWX,iBAAiB,KAAKnB,gBAAgB;AAC7CiC,cAAQ,KAAKnC,WAAW4B,QAAQO,OAAOd,cAAcH,OAAOE,SAAAA;IAChE;AAGA,UAAMgB,YAAYF,YAAYF,WAAAA;AAC9B,UAAMK,eAAeH,YAAYC,KAAAA;AACjC,UAAMG,SAASF,UAAU5B,IAAI6B,aAAa7B;AAC1C,UAAM+B,SAASH,UAAU3B,IAAI4B,aAAa5B;AAC1C,UAAM+B,iBAAiBC,KAAKC,KAAKJ,SAASA,SAASC,SAASA,MAAAA;AAG5D,QAAIC,iBAAiB,KAAKvC,QAAQU,yBAAyB;AAEvD,YAAMgC,IAAIF,KAAKG,IAAI,GAAG,KAAK3C,QAAQW,sBAAsBQ,SAAAA;AACzD,WAAKb,kBAAkBC,KAAK8B,SAASK;AACrC,WAAKpC,kBAAkBE,KAAK8B,SAASI;IACzC;AAGA,UAAME,YAAY;AAClB,SAAKtC,kBAAkBC,KAAKqC;AAC5B,SAAKtC,kBAAkBE,KAAKoC;AAE5B,SAAKvC,kBAAkB6B;AACvB,WAAOA;EACX;;;;;EAMAW,QAAc;AACV,SAAK5C,eAAec,SAAS;AAC7B,SAAKb,4BAA4B;AACjC,SAAKC,mBAAmB;AACxB,SAAKC,mBAAmB;AACxB,SAAKC,kBAAkB;AACvB,SAAKC,oBAAoB;MAAEC,GAAG;MAAGC,GAAG;IAAE;EAC1C;AACJ;AA5JaZ;AAAN,IAAMA,mBAAN;AAsKA,SAASkD,uBACZjD,WACAC,QAAwC;AAExC,SAAO,IAAIF,iBAAiBC,WAAWC,MAAAA;AAC3C;AALgBgD;;;AC/PT,IAAMC,aAAa;EACtBC,MAAM;EACNC,UAAU,KAAK;EACfC,UAAU,KAAK;EACfC,UAAU,KAAK;EACfC,kBAAkB,KAAK;EACvBC,QAAQ,KAAK;AACjB;AAoHA,IAAMC,iBAAyC;EAC3CC,mBAAmB;EACnBC,mBAAmB;EACnBC,mBAAmB;EACnBC,sBAAsB;AAC1B;AAaO,IAAMC,wBAAN,MAAMA,sBAAAA;EAKT,YAAYC,QAA0C;AAJrCC;AACAC,uCAA4C,oBAAIC,IAAAA;AACzDC,yCAAwB;AAG5B,SAAKH,UAAU;MAAE,GAAGP;MAAgB,GAAGM;IAAO;EAClD;;;;;EAMA,IAAIA,SAA2C;AAC3C,WAAO,KAAKC;EAChB;;;;;EAMAI,SAASC,MAA+B;AACpC,SAAKF;AAEL,UAAMG,iBAAiB,KAAKH,gBAAgB,KAAKH,QAAQH,yBAAyB;AAClF,UAAMU,gBAAoC,CAAA;AAE1C,eAAWC,UAAUH,KAAKI,UAAU;AAChC,YAAMC,YAAY,KAAKT,YAAYU,IAAIH,OAAOI,KAAK;AAEnD,UAAIN,kBAAkB,CAACI,WAAW;AAE9BH,sBAAcM,KAAK,KAAKC,iBAAiBN,MAAAA,CAAAA;MAC7C,OAAO;AAEH,cAAMO,QAAQ,KAAKC,gBAAgBN,WAAWF,MAAAA;AAC9C,YAAIO,OAAO;AACPR,wBAAcM,KAAKE,KAAAA;QACvB;MACJ;AAGA,WAAKd,YAAYgB,IAAIT,OAAOI,OAAO;QAAE,GAAGJ;MAAO,CAAA;IACnD;AAEA,WAAO;MACHU,OAAOb,KAAKa;MACZC,WAAWd,KAAKc;MAChBC,QAAQf,KAAKe;MACbX,UAAUF;MACVD;IACJ;EACJ;;;;;EAMAe,WAAWhB,MAA+B;AACtC,UAAMI,WAA8B,CAAA;AAEpC,eAAWM,SAASV,KAAKI,UAAU;AAC/B,YAAMC,YAAY,KAAKT,YAAYU,IAAII,MAAMH,KAAK;AAClD,YAAMU,YAAY,KAAKC,YAAYb,WAAWK,KAAAA;AAC9CN,eAASI,KAAKS,SAAAA;AAGd,WAAKrB,YAAYgB,IAAIF,MAAMH,OAAOU,SAAAA;IACtC;AAEA,WAAO;MACHJ,OAAOb,KAAKa;MACZC,WAAWd,KAAKc;MAChBC,QAAQf,KAAKe;MACbX;IACJ;EACJ;;;;;EAMAe,aAAaZ,OAAqB;AAC9B,SAAKX,YAAYwB,OAAOb,KAAAA;EAC5B;;;;;EAMAc,QAAc;AACV,SAAKzB,YAAYyB,MAAK;AACtB,SAAKvB,gBAAgB;EACzB;;;;;EAMAwB,oBAA0B;AACtB,SAAKxB,gBAAgB,KAAKH,QAAQH,uBAAuB;EAC7D;;;;EAMQiB,iBAAiBN,QAA2C;AAChE,QAAIoB,QAAQ;AAEZ,QAAIpB,OAAOqB,IAAKD,UAAS1C,WAAWE;AACpC,QAAIoB,OAAOsB,QAAQC,OAAWH,UAAS1C,WAAWG;AAClD,QAAImB,OAAOwB,IAAKJ,UAAS1C,WAAWI;AACpC,QAAIkB,OAAOyB,WAAWF,OAAWH,UAAS1C,WAAWK;AACrD,QAAIiB,OAAO0B,OAAQN,UAAS1C,WAAWM;AAEvC,WAAO;MACHoB,OAAOJ,OAAOI;MACdgB;MACAC,KAAKrB,OAAOqB;MACZC,KAAKtB,OAAOsB;MACZE,KAAKxB,OAAOwB;MACZC,QAAQzB,OAAOyB;MACfC,QAAQ1B,OAAO0B;IACnB;EACJ;EAEQlB,gBACJN,WACAyB,cACuB;AACvB,QAAIP,QAAQ;AACZ,UAAMb,QAA0B;MAC5BH,OAAOuB,aAAavB;MACpBgB,OAAO;IACX;AAGA,QAAIO,aAAaN,KAAK;AAClB,YAAMO,aAAa,CAAC1B,UAAUmB,OAC1BQ,KAAKC,IAAIH,aAAaN,IAAIU,IAAI7B,UAAUmB,IAAIU,CAAC,IAAI,KAAKvC,QAAQN,qBAC9D2C,KAAKC,IAAIH,aAAaN,IAAIW,IAAI9B,UAAUmB,IAAIW,CAAC,IAAI,KAAKxC,QAAQN;AAElE,UAAI0C,YAAY;AACZR,iBAAS1C,WAAWE;AACpB2B,cAAMc,MAAMM,aAAaN;MAC7B;IACJ;AAGA,QAAIM,aAAaL,QAAQC,QAAW;AAChC,YAAMU,aAAa/B,UAAUoB,QAAQC,UACjCM,KAAKC,IAAIH,aAAaL,MAAMpB,UAAUoB,GAAG,IAAI,KAAK9B,QAAQL;AAE9D,UAAI8C,YAAY;AACZb,iBAAS1C,WAAWG;AACpB0B,cAAMe,MAAMK,aAAaL;MAC7B;IACJ;AAGA,QAAIK,aAAaH,KAAK;AAClB,YAAMU,aAAa,CAAChC,UAAUsB,OAC1BK,KAAKC,IAAIH,aAAaH,IAAIO,IAAI7B,UAAUsB,IAAIO,CAAC,IAAI,KAAKvC,QAAQJ,qBAC9DyC,KAAKC,IAAIH,aAAaH,IAAIQ,IAAI9B,UAAUsB,IAAIQ,CAAC,IAAI,KAAKxC,QAAQJ;AAElE,UAAI8C,YAAY;AACZd,iBAAS1C,WAAWI;AACpByB,cAAMiB,MAAMG,aAAaH;MAC7B;IACJ;AAGA,QAAIG,aAAaF,WAAWF,QAAW;AACnC,YAAMY,gBAAgBjC,UAAUuB,WAAWF,UACvCM,KAAKC,IAAIH,aAAaF,SAASvB,UAAUuB,MAAM,IAAI,KAAKjC,QAAQJ;AAEpE,UAAI+C,eAAe;AACff,iBAAS1C,WAAWK;AACpBwB,cAAMkB,SAASE,aAAaF;MAChC;IACJ;AAGA,QAAIE,aAAaD,QAAQ;AACrB,YAAMU,gBAAgB,CAAC,KAAKC,iBAAiBnC,UAAUwB,QAAQC,aAAaD,MAAM;AAElF,UAAIU,eAAe;AACfhB,iBAAS1C,WAAWM;AACpBuB,cAAMmB,SAASC,aAAaD;MAChC;IACJ;AAGA,QAAIN,UAAU,GAAG;AACb,aAAO;IACX;AAEAb,UAAMa,QAAQA;AACd,WAAOb;EACX;EAEQQ,YACJb,WACAK,OACe;AACf,UAAM+B,QAAyB;MAC3BlC,OAAOG,MAAMH;IACjB;AAGA,QAAIG,MAAMa,QAAQ1C,WAAWE,UAAU;AACnC0D,YAAMjB,MAAMd,MAAMc;IACtB,WAAWnB,WAAWmB,KAAK;AACvBiB,YAAMjB,MAAMnB,UAAUmB;IAC1B;AAGA,QAAId,MAAMa,QAAQ1C,WAAWG,UAAU;AACnCyD,YAAMhB,MAAMf,MAAMe;IACtB,WAAWpB,WAAWoB,QAAQC,QAAW;AACrCe,YAAMhB,MAAMpB,UAAUoB;IAC1B;AAGA,QAAIf,MAAMa,QAAQ1C,WAAWI,UAAU;AACnCwD,YAAMd,MAAMjB,MAAMiB;IACtB,WAAWtB,WAAWsB,KAAK;AACvBc,YAAMd,MAAMtB,UAAUsB;IAC1B;AAGA,QAAIjB,MAAMa,QAAQ1C,WAAWK,kBAAkB;AAC3CuD,YAAMb,SAASlB,MAAMkB;IACzB,WAAWvB,WAAWuB,WAAWF,QAAW;AACxCe,YAAMb,SAASvB,UAAUuB;IAC7B;AAGA,QAAIlB,MAAMa,QAAQ1C,WAAWM,QAAQ;AACjCsD,YAAMZ,SAASnB,MAAMmB;IACzB,WAAWxB,WAAWwB,QAAQ;AAC1BY,YAAMZ,SAASxB,UAAUwB;IAC7B;AAEA,WAAOY;EACX;EAEQD,iBACJE,GACAC,GACO;AACP,QAAID,MAAMC,EAAG,QAAO;AACpB,QAAI,CAACD,KAAK,CAACC,EAAG,QAAO;AAErB,UAAMC,QAAQC,OAAOC,KAAKJ,CAAAA;AAC1B,UAAMK,QAAQF,OAAOC,KAAKH,CAAAA;AAE1B,QAAIC,MAAMI,WAAWD,MAAMC,OAAQ,QAAO;AAE1C,eAAWC,OAAOL,OAAO;AACrB,UAAIF,EAAEO,GAAAA,MAASN,EAAEM,GAAAA,EAAM,QAAO;IAClC;AAEA,WAAO;EACX;AACJ;AA1QaxD;AAAN,IAAMA,uBAAN;AAoRA,SAASyD,2BACZxD,QAAwC;AAExC,SAAO,IAAID,qBAAqBC,MAAAA;AACpC;AAJgBwD;;;AC3ahB;EACIC;EACAC;EAGAC;EACAC;EACAC;EAIAC;EACAC;EACAC;EACAC;EACAC;EACAC;EACAC;OAGG;AAmDP,IAAMC,kBAAsC;EACxCC,iBAAiB;EACjBC,cAAc;AAClB;AAyBO,IAAMC,uBAAN,MAAMA,6BAA4BC,aAAAA;EAOrC,YAAYC,QAAuCC,WAAoB,OAAO;AAC1E,UAAMC,QAAQC,IAAIC,eAAAA,CAAAA;AAPLC;AACAC,0CAAsC,oBAAIC,IAAAA;AAC1CC,0CAAkD,oBAAIC,IAAAA;AAC/DC,yCAAwB;AACxBC,qCAAqB;AAIzB,SAAKN,UAAU;MAAE,GAAGV;MAAgB,GAAGK;IAAO;AAC9C,SAAKW,YAAYV;EACrB;;;;;EAMA,IAAWA,SAASW,OAAgB;AAChC,SAAKD,YAAYC;EACrB;;;;;EAMA,IAAWX,WAAoB;AAC3B,WAAO,KAAKU;EAChB;;;;;EAMA,IAAWX,SAAwC;AAC/C,WAAO,KAAKK;EAChB;;;;;EAMOQ,gBAAgBC,UAA4C;AAC/D,SAAKN,eAAeO,IAAID,QAAAA;EAC5B;;;;;EAMOE,mBAAmBF,UAA4C;AAClE,SAAKN,eAAeS,OAAOH,QAAAA;EAC/B;;;;;;;;EASOI,kBAA2CC,gBAAyB;AACvE,UAAMC,WAAsCD,eAAuBE,aAAAA;AACnE,QAAID,UAAU;AACVE,4BAAsBF,SAASG,QAAQJ,cAAAA;IAC3C;EACJ;;;;;;;;;;;EAaOK,kBAAkBC,WAAoB,OAAmB;AAC5D,UAAMC,WAAW,KAAKC,oBAAmB;AACzC,UAAMC,YAAYH,WAAWI,cAAcC,OAAOD,cAAcE;AAEhE,UAAMC,OAAOC,eAAeP,UAAUE,SAAAA;AAGtC,QAAI,CAACH,UAAU;AACX,WAAKS,qBAAqBR,QAAAA;IAC9B;AAEA,WAAOM;EACX;;;;;;;EAQOG,cAAiC;AACpC,UAAMT,WAAW,KAAKC,oBAAmB;AACzC,UAAMS,kBAAkBV,SAASW,OAAOC,CAAAA,WAAU,KAAKC,YAAYD,MAAAA,CAAAA;AAEnE,QAAIF,gBAAgBI,WAAW,GAAG;AAC9B,aAAO;IACX;AAEA,UAAMR,OAAOC,eAAeG,iBAAiBP,cAAcE,KAAK;AAChE,SAAKG,qBAAqBE,eAAAA;AAE1B,WAAOJ;EACX;;;;;EAMOS,YAAYH,QAAgBI,YAAiC;AAChE,WAAOD,YAAYH,QAAQI,UAAAA;EAC/B;;;;;EAMOC,cAAcC,UAA8B;AAC/C,WAAOD,cAAcC,QAAAA;EACzB;;;;;;;;;;;EAaOC,cAAcb,MAAwC;AACzD,QAAI,CAAC,KAAKc,OAAO;AACb,YAAM,IAAIC,MAAM,6CAAA;IACpB;AAEA,UAAMC,SAASC,eAAe,KAAKH,OAAOd,MAAM,KAAK1B,cAAc;AAGnE,eAAW4C,gBAAgBF,OAAOtB,UAAU;AACxC,UAAIwB,aAAaC,OAAO;AACpB,aAAKC,WAAW;UACZC,MAAM;UACNT,UAAUM,aAAaN;QAC3B,CAAA;MACJ,OAAO;AACH,aAAKQ,WAAW;UACZC,MAAM;UACNT,UAAUM,aAAaN;QAC3B,CAAA;MACJ;IACJ;AAEA,WAAOI;EACX;;;;;;;;EASOM,WAAWtB,MAA4C;AAC1D,QAAI,CAAC,KAAKc,OAAO;AACb,YAAM,IAAIC,MAAM,6CAAA;IACpB;AAEA,UAAMC,SAASO,YAAY,KAAKT,OAAOd,MAAM,KAAK1B,cAAc;AAEhE,QAAI0C,QAAQ;AACR,WAAKI,WAAW;QACZC,MAAM;QACNT,UAAUI,OAAOV,OAAOkB;QACxBd,YAAYM,OAAON;MACvB,CAAA;IACJ;AAEA,WAAOM;EACX;;;;;;;;EASOS,aAAazB,MAA4B;AAC5C,QAAI,CAAC,KAAKc,OAAO;AACb,YAAM,IAAIC,MAAM,6CAAA;IACpB;AAEA,UAAMW,YAAYC,eAAe,KAAKb,OAAOd,MAAM,KAAK1B,cAAc;AAEtE,eAAWsC,YAAYc,WAAW;AAC9B,WAAKN,WAAW;QACZC,MAAM;QACNT;MACJ,CAAA;IACJ;AAEA,WAAOc;EACX;;;;;;;;EAUOE,cAAchB,UAAsC;AACvD,WAAO,KAAKtC,eAAeuD,IAAIjB,QAAAA;EACnC;;;;;EAMOjB,sBAAgC;AACnC,WAAO,KAAKD,SAASoC,MAAK;EAC9B;;;;EAMmBC,QAAQrC,UAAmC;AAE1D,QAAI,KAAKf,aAAa,KAAKN,QAAQT,iBAAiB;AAChD,YAAMoE,MAAMC,KAAKD,IAAG;AACpB,UAAIA,MAAM,KAAKtD,iBAAiB,KAAKL,QAAQR,cAAc;AAGvD,aAAKa,gBAAgBsD;MACzB;IACJ;AAGA,eAAW1B,UAAUZ,UAAU;AAC3B,YAAMwC,WAAW5B,OAAO6B,aAAa/D,eAAAA;AACrC,UAAI8D,UAAU;AACV,aAAK5D,eAAe8D,IAAI9B,OAAOkB,IAAIlB,MAAAA;MACvC;IACJ;EACJ;EAEQC,YAAYD,QAAyB;AACzC,eAAW+B,aAAa/B,OAAOgC,YAAY;AACvC,YAAMC,UAAWF,UAAkBG,cAAAA;AACnC,UAAID,SAASE,WAAAA,GAAc;AACvB,eAAO;MACX;IACJ;AACA,WAAO;EACX;EAEQvC,qBAAqBR,UAA0B;AACnD,eAAWY,UAAUZ,UAAU;AAC3B,iBAAW2C,aAAa/B,OAAOgC,YAAY;AACvC,cAAMC,UAAWF,UAAkBG,cAAAA;AACnC,YAAID,SAAS;AACTA,kBAAQG,MAAK;QACjB;MACJ;IACJ;EACJ;EAEQtB,WAAWuB,OAAiC;AAChD,eAAW7D,YAAY,KAAKN,gBAAgB;AACxC,UAAI;AACAM,iBAAS6D,KAAAA;MACb,SAASC,OAAO;AACZC,gBAAQD,MAAM,8CAA8CA,KAAAA;MAChE;IACJ;EACJ;EAEmBE,YAAkB;AACjC,SAAKxE,eAAeoE,MAAK;AACzB,SAAKlE,eAAekE,MAAK;EAC7B;AACJ;AApSyC3E;AAAlC,IAAMD,sBAAN;AA0SA,SAASiF,0BACZ/E,QACAC,WAAoB,OAAK;AAEzB,SAAO,IAAIH,oBAAoBE,QAAQC,QAAAA;AAC3C;AALgB8E;;;ARlUhB,IAAMC,kBAAoC;EACtCC,YAAY;EACZC,oBAAoB;EACpBC,qBAAqB;EACrBC,sBAAsB;EACtBC,yBAAyB;AAC7B;AAcO,IAAMC,qBAAN,MAAMA,2BAA0BC,cAAAA;EAUnC,YAAYC,QAAqC;AAC7C,UAAMC,SAAQC,IAAIC,iBAAiBC,gBAAAA,CAAAA;AAVtBC,0CAAsC,oBAAIC,IAAAA;AAC1CC,4CAAoD,oBAAID,IAAAA;AACxDE;AACAC;AAETC,6CAA4B;AAC5BC,yCAAwB;AACxBC,uCAAsB;AAI1B,SAAKH,UAAU;MAAE,GAAGjB;MAAgB,GAAGQ;IAAO;AAC9C,SAAKQ,gBAAgBK,4BAAAA;EACzB;;;;;EAMA,IAAIb,SAAsC;AACtC,WAAO,KAAKS;EAChB;;;;;EAMA,IAAIK,mBAA2B;AAC3B,WAAO,KAAKJ;EAChB;;;;;EAMA,IAAIK,aAAqB;AACrB,WAAO,KAAKH;EAChB;;;;;EAMAI,eAAeC,MAAsB;AACjC,UAAMC,aAAaD,KAAKE;AAGxB,UAAMC,aAAaC,KAAKC,IAAG;AAC3B,SAAKZ,oBAAoBQ,aAAaE;AACtC,SAAKT,gBAAgBS;AAErB,eAAWG,SAASN,KAAKO,UAAU;AAC/B,WAAKC,oBAAoBF,OAAOL,UAAAA;IACpC;EACJ;;;;;EAMAQ,WAAWC,KAAwB;AAC/B,UAAML,MAAMD,KAAKC,IAAG;AACpB,eAAWC,SAASI,IAAIH,UAAU;AAC9B,YAAMI,WAAW,KAAKvB,eAAewB,IAAIN,MAAMO,KAAK;AACpD,UAAIF,aAAaG,OAAW;AAE5B,YAAMC,SAAS,KAAKC,OAAOC,eAAeN,QAAAA;AAC1C,UAAI,CAACI,OAAQ;AAEb,YAAMG,YAAYH,OAAOI,aAAahC,gBAAAA;AACtC,UAAI+B,aAAaZ,MAAMc,KAAK;AACxBF,kBAAUG,UAAUf,MAAMc,IAAIE,GAAGhB,MAAMc,IAAIG,GAAGjB,MAAMkB,OAAO,CAAA;MAC/D;AAGA,WAAKhB,oBAAoB;QACrBK,OAAOP,MAAMO;QACbO,KAAKd,MAAMc;QACXI,KAAKlB,MAAMkB;MACf,GAAGnB,GAAAA;IACP;EACJ;EAEQG,oBAAoBF,OAAwBL,YAA0B;AAC1E,UAAMU,WAAW,KAAKvB,eAAewB,IAAIN,MAAMO,KAAK;AACpD,QAAIF,aAAaG,OAAW;AAG5B,QAAIW,eAAe,KAAKnC,iBAAiBsB,IAAIN,MAAMO,KAAK;AACxD,QAAI,CAACY,cAAc;AACfA,qBAAe;QACXC,QAAQC,qBACJ,KAAKnC,QAAQhB,YACb,KAAKgB,QAAQf,kBAAkB;QAEnCmD,gBAAgB;MACpB;AACA,WAAKtC,iBAAiBuC,IAAIvB,MAAMO,OAAOY,YAAAA;IAC3C;AAGA,UAAMK,iBAA8C;MAChDR,GAAGhB,MAAMc,KAAKE,KAAK;MACnBC,GAAGjB,MAAMc,KAAKG,KAAK;MACnBQ,UAAUzB,MAAMkB,OAAO;MACvBQ,WAAW1B,MAAM2B,KAAKX,KAAK;MAC3BY,WAAW5B,MAAM2B,KAAKV,KAAK;MAC3BY,iBAAiB7B,MAAM8B,UAAU;IACrC;AAEA,UAAMC,WAAwD;MAC1DnC,WAAWD;MACXK,OAAOwB;IACX;AAEAL,iBAAaC,OAAOY,KAAKD,QAAAA;AACzBZ,iBAAaG,iBAAiB3B;EAClC;EAEmBsC,QAAQhC,UAAmC;AAC1D,UAAMiC,YAAYC,KAAKD;AACvB,UAAMrC,aAAaC,KAAKC,IAAG;AAG3B,SAAKV,cAAcQ,aAAa,KAAKV;AAErC,eAAWsB,UAAUR,UAAU;AAC3B,YAAMW,YAAY,KAAKwB,iBAAiB3B,QAAQ5B,gBAAAA;AAChD,YAAMwD,WAAW,KAAKD,iBAAiB3B,QAAQ7B,eAAAA;AAG/C,UAAIyD,SAASC,cAAe;AAE5B,UAAI1B,UAAU2B,cAAc;AACxB,aAAKC,mBAAmBH,SAAS9B,OAAOK,WAAWsB,SAAAA;MACvD;IACJ;EACJ;EAEQM,mBACJjC,OACAK,WACAsB,WACI;AACJ,UAAMf,eAAe,KAAKnC,iBAAiBsB,IAAIC,KAAAA;AAE/C,QAAIY,gBAAgBA,aAAaC,OAAOqB,QAAQ,GAAG;AAE/C,YAAMC,SAASvB,aAAaC,OAAOuB,0BAA0B,KAAKtD,WAAW;AAE7E,UAAIqD,QAAQ;AACR,cAAM,CAACE,MAAMC,MAAMC,CAAAA,IAAKJ;AACxB,cAAMK,eAAe,KAAK9D,cAAc+D,YAAYJ,KAAK5C,OAAO6C,KAAK7C,OAAO8C,CAAAA;AAE5ElC,kBAAUqC,WAAWF,aAAa/B;AAClCJ,kBAAUsC,WAAWH,aAAa9B;AAClCL,kBAAUuC,kBAAkBJ,aAAatB;AAGzCb,kBAAUwC,UAAUP,KAAK7C,MAAMgB;AAC/BJ,kBAAUyC,UAAUR,KAAK7C,MAAMiB;AAC/BL,kBAAU0C,iBAAiBT,KAAK7C,MAAMyB;AACtC;MACJ;AAGA,UAAI,KAAKvC,QAAQd,qBAAqB;AAClC,cAAMmF,SAASpC,aAAaC,OAAOoC,UAAS;AAC5C,YAAID,QAAQ;AACR,gBAAME,wBAAwB,KAAKpE,cAAckE,OAAO3D;AACxD,cAAI6D,wBAAwB,KAAKA,wBAAwB,KAAKvE,QAAQb,sBAAsB;AACxF,kBAAMqF,eAAe,KAAKzE,cAAc0E,YACpCJ,OAAOvD,OACPyD,wBAAwB,GAAA;AAE5B7C,sBAAUqC,WAAWS,aAAa1C;AAClCJ,sBAAUsC,WAAWQ,aAAazC;AAClCL,sBAAUuC,kBAAkBO,aAAajC;AACzC;UACJ;QACJ;MACJ;IACJ;AAGA,SAAKmC,YAAYhD,WAAWsB,SAAAA;EAChC;EAEQ0B,YAAYhD,WAA6BsB,WAAyB;AACtE,UAAMY,IAAIe,KAAKC,IAAI,GAAGlD,UAAUmD,YAAY7B,SAAAA;AAE5CtB,cAAUqC,aAAarC,UAAUwC,UAAUxC,UAAUqC,YAAYH;AACjElC,cAAUsC,aAAatC,UAAUyC,UAAUzC,UAAUsC,YAAYJ;AAEjE,QAAIkB,YAAYpD,UAAU0C,iBAAiB1C,UAAUuC;AACrD,WAAOa,YAAYH,KAAKI,GAAID,cAAaH,KAAKI,KAAK;AACnD,WAAOD,YAAY,CAACH,KAAKI,GAAID,cAAaH,KAAKI,KAAK;AACpDrD,cAAUuC,mBAAmBa,YAAYlB;EAC7C;;;;;EAMAoB,eAAe3D,OAAeF,UAAwB;AAClD,SAAKvB,eAAeyC,IAAIhB,OAAOF,QAAAA;EACnC;;;;;EAMA8D,iBAAiB5D,OAAqB;AAClC,SAAKzB,eAAesF,OAAO7D,KAAAA;AAC3B,SAAKvB,iBAAiBoF,OAAO7D,KAAAA;EACjC;;;;;EAMA8D,YAAY9D,OAAmC;AAC3C,WAAO,KAAKzB,eAAewB,IAAIC,KAAAA;EACnC;;;;;EAMA+D,kBAAkB/D,OAAwE;AACtF,WAAO,KAAKvB,iBAAiBsB,IAAIC,KAAAA,GAAQa;EAC7C;;;;;EAMAmD,iBAAuB;AACnB,eAAW7E,QAAQ,KAAKV,iBAAiBwF,OAAM,GAAI;AAC/C9E,WAAK0B,OAAOqD,MAAK;IACrB;EACJ;EAEmBC,YAAkB;AACjC,SAAK5F,eAAe2F,MAAK;AACzB,SAAKzF,iBAAiByF,MAAK;EAC/B;AACJ;AAxPuCjG;AAAhC,IAAMD,oBAAN;;;ASvGP,SAASoG,gBAAAA,eAAkCC,WAAAA,gBAAe;AAsCnD,IAAMC,sBAAN,MAAMA,4BAA2BC,cAAAA;EAKpC,YAAYC,YAA+B;AACvC,UAAMC,SAAQC,QAAO,CAAA;AALjBC;AACAC,4CAA+C,oBAAIC,IAAAA;AACnDC,0CAAyB;AAI7B,SAAKH,cAAcH;EACvB;;;;;EAMAO,iBAAiBC,IAAkB;AAC/B,SAAKF,iBAAiBE;EAC1B;;;;;EAMAC,YAAYC,KAAkC;AAC1C,QAAI,CAAC,KAAKC,MAAO,QAAO;AAExB,UAAMC,UAAU,KAAKR,iBAAiBS,IAAIH,IAAII,MAAM;AACpD,QAAI,CAACF,SAAS;AACV,WAAKG,OAAOC,KAAK,mBAAmBN,IAAII,MAAM,EAAE;AAChD,aAAO;IACX;AAEA,UAAMG,SAASL,QAAQ,KAAKD,OAAOD,GAAAA;AAEnC,UAAMQ,WAAWD,OAAOE,aAAa,IAAIC,gBAAAA,CAAAA;AACzCF,aAASG,QAAQX,IAAIW;AACrBH,aAASI,UAAUZ,IAAIY;AACvBJ,aAASK,aAAab,IAAII;AAC1BI,aAASM,gBAAgBd,IAAIY,YAAY,KAAKhB;AAC9CY,aAASO,iBAAiBP,SAASM;AAEnC,UAAME,YAAYT,OAAOE,aAAa,IAAIQ,iBAAAA,CAAAA;AAC1CD,cAAUE,UAAUlB,IAAImB,IAAIC,GAAGpB,IAAImB,IAAIE,GAAGrB,IAAIsB,OAAO,CAAA;AACrDN,cAAUO,KAAI;AAEd,SAAK9B,YAAY+B,eAAexB,IAAIW,OAAOJ,OAAOT,EAAE;AAEpD,WAAOS;EACX;;;;;EAMAkB,cAAczB,KAA2B;AACrC,UAAM0B,WAAW,KAAKjC,YAAYkC,YAAY3B,IAAIW,KAAK;AACvD,QAAIe,aAAaE,OAAW;AAE5B,UAAMrB,SAAS,KAAKN,OAAO4B,eAAeH,QAAAA;AAC1C,QAAInB,QAAQ;AACRA,aAAOuB,QAAO;IAClB;AAEA,SAAKrC,YAAYsC,iBAAiB/B,IAAIW,KAAK;EAC/C;;;;;EAMAqB,eAAenB,YAAoBX,SAA8B;AAC7D,SAAKR,iBAAiBuC,IAAIpB,YAAYX,OAAAA;EAC1C;;;;;EAMAgC,iBAAiBrB,YAA0B;AACvC,SAAKnB,iBAAiByC,OAAOtB,UAAAA;EACjC;EAEmBuB,YAAkB;AACjC,SAAK1C,iBAAiB2C,MAAK;EAC/B;AACJ;AApFwChD;AAAjC,IAAMD,qBAAN;;;AC9BP,SAASkD,gBAAAA,eAAcC,WAAAA,gBAAe;AAiCtC,IAAMC,kBAAqC;EACvCC,cAAc;EACdC,sBAAsB;EACtBC,gBAAgB;AACpB;AAuBO,IAAMC,sBAAN,MAAMA,4BAA2BC,cAAAA;EAWpC,YAAYC,gBAAgCC,QAAsC;AAC9E,UAAMC,SAAQC,QAAO,CAAA;AAXRC;AACAC;AACTC,6CAAoD;AAEpDC,kCAAiB;AACjBC,0CAAyB;AACzBC,uCAA8B,CAAA;AAC9BC,yCAAwB;AACxBC,wCAAyC;MAAEC,GAAG;MAAGC,GAAG;IAAE;AAI1D,SAAKT,kBAAkBJ;AACvB,SAAKK,UAAU;MAAE,GAAGX;MAAgB,GAAGO;IAAO;EAClD;;;;;EAMA,IAAIA,SAAuC;AACvC,WAAO,KAAKI;EAChB;;;;;EAMA,IAAIS,QAAgB;AAChB,WAAO,KAAKP;EAChB;;;;;EAMA,IAAIQ,gBAAwB;AACxB,WAAO,KAAKP;EAChB;;;;;EAMAQ,oBAAoBC,QAAuC;AACvD,SAAKX,oBAAoBW;EAC7B;;;;;EAMmBC,UAAgB;AAC/B,QAAI,CAAC,KAAKd,gBAAgBe,YAAa;AAEvC,SAAKZ;AACL,UAAMa,MAAMC,KAAKD,IAAG;AAGpB,QAAIA,MAAM,KAAKV,gBAAgB,KAAKL,QAAQV,aAAc;AAG1D,QAAI,KAAKW,mBAAmB;AACxB,YAAMgB,iBAAiB,KAAKhB,kBAAkBiB,eAAc;AAC5D,UAAID,gBAAgB;AAChB,aAAKlB,gBAAgBoB,UAAUF,cAAAA;AAC/B,aAAKZ,gBAAgBU;MACzB;AACA;IACJ;AAGA,QAAI,KAAKX,YAAYgB,WAAW,EAAG;AAGnC,QAAIC;AACJ,QAAI,KAAKrB,QAAQT,wBAAwB,KAAKa,YAAYgB,SAAS,GAAG;AAClEC,oBAAc,KAAKC,aAAa,KAAKlB,WAAW;AAChD,WAAKA,YAAYgB,SAAS;IAC9B,OAAO;AACHC,oBAAc,KAAKjB,YAAYmB,MAAK;IACxC;AAGA,SAAKpB;AACL,UAAMqB,QAAqB;MACvBC,KAAK,KAAKtB;MACVM,OAAO,KAAKP;MACZwB,WAAWL,YAAYK;MACvBC,SAASN,YAAYM;MACrBC,SAASP,YAAYO;IACzB;AAEA,SAAK7B,gBAAgBoB,UAAUK,KAAAA;AAC/B,SAAKnB,gBAAgBU;EACzB;EAEQO,aAAaO,QAAsC;AACvD,UAAMC,aAAuB,CAAA;AAC7B,QAAIC;AAEJ,eAAWP,SAASK,QAAQ;AACxB,UAAIL,MAAMG,SAAS;AACfI,sBAAcP,MAAMG;MACxB;AACA,UAAIH,MAAMI,SAAS;AACfE,mBAAWE,KAAI,GAAIR,MAAMI,OAAO;MACpC;IACJ;AAEA,WAAO;MACHD,SAASI;MACTH,SAASE,WAAWV,SAAS,IAAIU,aAAaG;MAC9CP,WAAWG,OAAOA,OAAOT,SAAS,CAAA,EAAGM;IACzC;EACJ;;;;;EAMOQ,aAAa3B,GAAWC,GAAiB;AAE5C,QACI,KAAKR,QAAQT,wBACb,KAAKe,aAAaC,MAAMA,KACxB,KAAKD,aAAaE,MAAMA,KACxB,KAAKJ,YAAYgB,SAAS,GAC5B;AACE;IACJ;AAEA,SAAKd,eAAe;MAAEC;MAAGC;IAAE;AAG3B,QAAI,KAAKP,mBAAmB;AACxB,WAAKA,kBAAkBkC,SAAS5B,GAAGC,CAAAA;IACvC;AAEA,SAAK4B,YAAY;MAAET,SAAS;QAAEpB;QAAGC;MAAE;MAAGkB,WAAWV,KAAKD,IAAG;IAAG,CAAA;EAChE;;;;;EAMOsB,eAAeC,QAAsB;AAExC,UAAMC,YAAY,KAAKnC,YAAY,KAAKA,YAAYgB,SAAS,CAAA;AAC7D,QAAImB,WAAW;AACXA,gBAAUX,UAAUW,UAAUX,WAAW,CAAA;AACzCW,gBAAUX,QAAQI,KAAKM,MAAAA;IAC3B,OAAO;AACH,WAAKF,YAAY;QAAER,SAAS;UAACU;;QAASZ,WAAWV,KAAKD,IAAG;MAAG,CAAA;IAChE;AAGA,QAAI,KAAKd,mBAAmB;AACxB,WAAKA,kBAAkBkC,SACnB,KAAK7B,aAAaC,GAClB,KAAKD,aAAaE,GAClB;QAAC8B;OAAO;IAEhB;EACJ;EAEQF,YAAYZ,OAA2B;AAC3C,SAAKpB,YAAY4B,KAAKR,KAAAA;AAGtB,WAAO,KAAKpB,YAAYgB,SAAS,KAAKpB,QAAQR,gBAAgB;AAC1D,WAAKY,YAAYmB,MAAK;IAC1B;EACJ;;;;;EAMOiB,aAAmB;AACtB,SAAKpC,YAAYgB,SAAS;AAC1B,SAAKd,eAAe;MAAEC,GAAG;MAAGC,GAAG;IAAE;EACrC;;;;;EAMOiC,QAAc;AACjB,SAAKvC,SAAS;AACd,SAAKC,iBAAiB;AACtB,SAAKqC,WAAU;EACnB;EAEmBE,YAAkB;AACjC,SAAKtC,YAAYgB,SAAS;AAC1B,SAAKnB,oBAAoB;EAC7B;AACJ;AAvMwCP;AAAjC,IAAMD,qBAAN;AAiNA,SAASkD,yBACZhD,gBACAC,QAAoC;AAEpC,SAAO,IAAIH,mBAAmBE,gBAAgBC,MAAAA;AAClD;AALgB+C;;;AC7QhB,SAASC,gBAAAA,eAAcC,WAAAA,UAASC,QAAAA,aAAyB;AAqDzD,IAAMC,kBAA0C;EAC5CC,WAAW;EACXC,SAAS;EACTC,yBAAyB;EACzBC,yBAAyB;EACzBC,qBAAqB;AACzB;AAnEA;AA6EA,IAAMC,2BAAN,WAAMA;EACF,YAA6BC,YAAoB;;SAApBA,aAAAA;EAAqB;EAElDC,QAAQC,OAA2BC,OAAsBC,WAAuC;AAC5F,UAAMC,YAAYF,MAAMG,IAAI,KAAKN;AACjC,UAAMO,YAAYJ,MAAMK,IAAI,KAAKR;AAEjC,WAAO;MACHM,GAAGJ,MAAMI,IAAID,YAAYD;MACzBI,GAAGN,MAAMM,IAAID,YAAYH;MACzBK,UAAUP,MAAMO;MAChBJ;MACAE;IACJ;EACJ;AACJ,GAfMR,uCAAN;AA4BO,IAAMW,2BAAN,MAAMA,iCAAgCC,cAAAA;EAQzC,YAAYC,QAA2C;AACnD,UAAMC,SAAQC,IAAIC,iBAAiBC,gBAAAA,CAAAA;AARtBC;AACAC;AACTC,uCAA0E;AAC1EC,6CAA4B;AAC5BC,yCAA+B;MAAEf,GAAG;MAAGE,GAAG;IAAE;AAC5Cc,0CAAyB;AAI7B,SAAKL,UAAU;MAAE,GAAGxB;MAAgB,GAAGmB;IAAO;AAC9C,SAAKM,aAAa,IAAInB,wBAAwB,KAAKkB,QAAQvB,SAAS;EACxE;;;;;EAMA,IAAIkB,SAA4C;AAC5C,WAAO,KAAKK;EAChB;;;;;EAMA,IAAIM,gBAAwB;AACxB,WAAO,KAAKD;EAChB;;;;;EAMA,IAAIE,oBAA4B;AAC5B,WAAO,KAAKL,aAAaK,qBAAqB;EAClD;;;;;EAMA,IAAI7B,UAAmB;AACnB,WAAO,KAAKsB,QAAQtB;EACxB;EAEA,IAAIA,QAAQ8B,OAAgB;AACxB,SAAKR,QAAQtB,UAAU8B;EAC3B;;;;;EAMAC,oBAAoBC,OAAqB;AACrC,SAAKP,oBAAoBO;AACzB,SAAKR,cAAcS,uBACf,KAAKV,YACL;MACItB,yBAAyB,KAAKqB,QAAQrB;MACtCC,yBAAyB,KAAKoB,QAAQpB;MACtCC,qBAAqB,KAAKmB,QAAQnB;IACtC,CAAA;EAER;;;;;EAMA+B,SAASvB,GAAWE,GAAWsB,SAA0B;AACrD,SAAKT,gBAAgB;MAAEf;MAAGE;MAAGsB;IAAQ;EACzC;;;;;EAMAC,iBAAqC;AACjC,QAAI,CAAC,KAAKZ,YAAa,QAAO;AAE9B,UAAMhB,QAAQ,KAAKgB,YAAYY,eAAc;AAC7C,QAAI,CAAC5B,MAAO,QAAO;AAEnB,WAAO;MACH6B,KAAK7B,MAAM8B;MACXC,OAAO;MACPC,WAAWhC,MAAMgC;MACjBC,SAAS;QAAE9B,GAAGH,MAAMA,MAAMG;QAAGE,GAAGL,MAAMA,MAAMK;MAAE;MAC9CsB,SAAS3B,MAAMA,MAAM2B;IACzB;EACJ;;;;;EAMAO,oBAAoBC,MAAsB;AACtC,QAAI,CAAC,KAAKnB,eAAe,KAAKC,oBAAoB,EAAG;AAGrD,UAAMmB,aAAaD,KAAKE,SAASC,KAAKC,CAAAA,MAAKA,EAAEf,UAAU,KAAKP,iBAAiB;AAC7E,QAAI,CAACmB,cAAc,CAACA,WAAWI,IAAK;AAEpC,UAAMC,cAAkC;MACpCtC,GAAGiC,WAAWI,IAAIrC;MAClBE,GAAG+B,WAAWI,IAAInC;MAClBC,UAAU8B,WAAWM,OAAO;MAC5BxC,WAAWkC,WAAWO,KAAKxC,KAAK;MAChCC,WAAWgC,WAAWO,KAAKtC,KAAK;IACpC;AAGA,QAAI8B,KAAKS,WAAWC,QAAW;AAC3B,WAAK7B,YAAY8B,UACbL,aACAN,KAAKS,QACL,CAAC7C,WAAW;QAAEI,GAAGJ,MAAMI;QAAGE,GAAGN,MAAMM;MAAE,IACrC0C,MAAK9C,SAAS;IAEtB;EACJ;EAEmB+C,QAAQX,UAAmC;AAC1D,QAAI,CAAC,KAAKvB,QAAQtB,WAAW,CAAC,KAAKwB,YAAa;AAEhD,UAAMf,YAAY8C,MAAK9C;AAEvB,eAAWgD,UAAUZ,UAAU;AAC3B,YAAMa,WAAW,KAAKC,iBAAiBF,QAAQrC,eAAAA;AAG/C,UAAI,CAACsC,SAASE,iBAAiBF,SAAS1B,UAAU,KAAKP,kBAAmB;AAE1E,YAAMoC,YAAY,KAAKF,iBAAiBF,QAAQpC,gBAAAA;AAGhD,YAAMyC,eAAmC;QACrCnD,GAAGkD,UAAUE;QACblD,GAAGgD,UAAUG;QACblD,UAAU+C,UAAUI;QACpBvD,WAAW;QACXE,WAAW;MACf;AAGA,UAAI,KAAKc,cAAcf,MAAM,KAAK,KAAKe,cAAcb,MAAM,GAAG;AAC1D,cAAMqD,YAAY,KAAK1C,YAAY2C,YAC/B,KAAKzC,eACLoC,cACArD,SAAAA;AAIJoD,kBAAUE,WAAWG,UAAUvD;AAC/BkD,kBAAUG,WAAWE,UAAUrD;AAC/BgD,kBAAUI,kBAAkBC,UAAUpD;AAGtC+C,kBAAUO,UAAUF,UAAUvD;AAC9BkD,kBAAUQ,UAAUH,UAAUrD;AAC9BgD,kBAAUS,iBAAiBJ,UAAUpD;AAErC,aAAKa,iBAAiB,KAAKH,YAAY+C;MAC3C;AAGA,YAAMC,SAAS,KAAKhD,YAAYiD;AAChC,UAAIC,KAAKC,IAAIH,OAAO7D,CAAC,IAAI,QAAQ+D,KAAKC,IAAIH,OAAO3D,CAAC,IAAI,MAAM;AACxDgD,kBAAUE,YAAYS,OAAO7D,IAAIF,YAAY;AAC7CoD,kBAAUG,YAAYQ,OAAO3D,IAAIJ,YAAY;MACjD;IACJ;EACJ;;;;;EAMAmE,QAAc;AACV,SAAKpD,aAAaqD,MAAAA;AAClB,SAAKlD,iBAAiB;AACtB,SAAKD,gBAAgB;MAAEf,GAAG;MAAGE,GAAG;IAAE;EACtC;EAEmBiE,YAAkB;AACjC,SAAKtD,aAAaqD,MAAAA;AAClB,SAAKrD,cAAc;EACvB;AACJ;AA7L6CR;AAAtC,IAAMD,0BAAN;AAuMA,SAASgE,8BACZ9D,QAAyC;AAEzC,SAAO,IAAIF,wBAAwBE,MAAAA;AACvC;AAJgB8D;;;ACxShB,SAASC,gBAAAA,eAAcC,WAAAA,gBAA4B;AAqEnD,IAAMC,kBAAmC;EACrCC,UAAU;EACVC,kBAAkB;EAClBC,SAAS;AACb;AA0BO,IAAMC,oBAAN,MAAMA,0BAAyBC,cAAAA;EAQlC,YAAYC,QAAoC;AAC5C,UAAMC,SAAQC,IAAIC,iBAAiBC,gBAAAA,CAAAA;AARtBC;AACAC,sCAAwC,oBAAIC,IAAAA;AAC5CC,kCAAmC,oBAAID,IAAAA;AACvCE,sCAA2C,oBAAIC,IAAAA;AAC/CC,2CAAuC,oBAAIJ,IAAAA;AAC3CK,2CAAuC,oBAAIL,IAAAA;AAIxD,SAAKF,UAAU;MAAE,GAAGX;MAAgB,GAAGM;IAAO;EAClD;;;;;EAMA,IAAIA,SAAqC;AACrC,WAAO,KAAKK;EAChB;;;;;EAMA,IAAIR,UAAmB;AACnB,WAAO,KAAKQ,QAAQR;EACxB;EAEA,IAAIA,QAAQgB,OAAgB;AACxB,SAAKR,QAAQR,UAAUgB;EAC3B;;;;;EAMA,IAAIC,gBAAwB;AACxB,WAAO,KAAKR,WAAWS;EAC3B;;;;;;;;EAUAC,YAAYC,OAAeC,GAAWC,GAAWC,WAA0B;AACvE,QAAI,KAAKd,WAAWe,IAAIJ,KAAAA,GAAQ;AAC5B,WAAKK,uBAAuBL,OAAOC,GAAGC,CAAAA;AACtC;IACJ;AAEA,UAAMI,QAAQH,aAAa,KAAKf,QAAQT;AACxC,UAAM4B,UAAU,KAAKC,YAAYP,GAAGC,CAAAA;AACpC,UAAMO,OAAqB;MACvBT;MACAU,UAAU;QAAET;QAAGC;MAAE;MACjBC,WAAWG;MACXK,aAAaL,QAAQA;MACrBC;MACAK,iBAAiB,oBAAInB,IAAAA;IACzB;AAEA,SAAKJ,WAAWwB,IAAIb,OAAOS,IAAAA;AAC3B,SAAKK,WAAWP,SAASP,KAAAA;AACzB,SAAKe,kBAAkBN,IAAAA;EAC3B;;;;;EAMAO,eAAehB,OAAwB;AACnC,UAAMS,OAAO,KAAKpB,WAAW4B,IAAIjB,KAAAA;AACjC,QAAI,CAACS,KAAM,QAAO;AAGlB,eAAWS,gBAAgBT,KAAKG,iBAAiB;AAC7C,WAAKO,WAAW;QACZC,MAAM;QACNC,eAAerB;QACfsB,aAAaJ;MACjB,CAAA;IACJ;AAEA,SAAKK,gBAAgBd,KAAKF,SAASP,KAAAA;AACnC,SAAKX,WAAWmC,OAAOxB,KAAAA;AACvB,WAAO;EACX;;;;;EAMAK,uBAAuBL,OAAeC,GAAWC,GAAiB;AAC9D,UAAMO,OAAO,KAAKpB,WAAW4B,IAAIjB,KAAAA;AACjC,QAAI,CAACS,KAAM;AAEX,UAAMgB,aAAa,KAAKjB,YAAYP,GAAGC,CAAAA;AACvC,QAAIuB,eAAehB,KAAKF,SAAS;AAC7B,WAAKgB,gBAAgBd,KAAKF,SAASP,KAAAA;AACnCS,WAAKF,UAAUkB;AACf,WAAKX,WAAWW,YAAYzB,KAAAA;IAChC;AAEAS,SAAKC,SAAST,IAAIA;AAClBQ,SAAKC,SAASR,IAAIA;AAClB,SAAKa,kBAAkBN,IAAAA;EAC3B;;;;;EAMAiB,wBAAwB1B,OAAeG,WAAyB;AAC5D,UAAMM,OAAO,KAAKpB,WAAW4B,IAAIjB,KAAAA;AACjC,QAAI,CAACS,KAAM;AAEXA,SAAKN,YAAYA;AACjBM,SAAKE,cAAcR,YAAYA;AAC/B,SAAKY,kBAAkBN,IAAAA;EAC3B;;;;;;;;EAUAkB,eAAeC,QAAgB5B,OAAqB;AAChD,SAAKN,gBAAgBmB,IAAIe,QAAQ5B,KAAAA;AACjC,SAAKL,gBAAgBkB,IAAIb,OAAO4B,MAAAA;EACpC;;;;;EAMAC,iBAAiBD,QAAsB;AACnC,UAAM5B,QAAQ,KAAKN,gBAAgBuB,IAAIW,MAAAA;AACvC,QAAI5B,UAAU8B,QAAW;AAErB,iBAAW,CAAA,EAAGrB,IAAAA,KAAS,KAAKpB,YAAY;AACpC,YAAIoB,KAAKG,gBAAgBR,IAAIJ,KAAAA,GAAQ;AACjCS,eAAKG,gBAAgBY,OAAOxB,KAAAA;AAC5B,eAAKmB,WAAW;YACZC,MAAM;YACNC,eAAeZ,KAAKT;YACpBsB,aAAatB;UACjB,CAAA;QACJ;MACJ;AACA,WAAKL,gBAAgB6B,OAAOxB,KAAAA;IAChC;AACA,SAAKN,gBAAgB8B,OAAOI,MAAAA;EAChC;;;;;;;;EAUAG,mBAAmBV,eAAiC;AAChD,UAAMZ,OAAO,KAAKpB,WAAW4B,IAAII,aAAAA;AACjC,WAAOZ,OAAOuB,MAAMC,KAAKxB,KAAKG,eAAe,IAAI,CAAA;EACrD;;;;;EAMAsB,eAAeC,aAA+B;AAC1C,UAAMC,YAAsB,CAAA;AAC5B,eAAW,CAAA,EAAG3B,IAAAA,KAAS,KAAKpB,YAAY;AACpC,UAAIoB,KAAKG,gBAAgBR,IAAI+B,WAAAA,GAAc;AACvCC,kBAAUC,KAAK5B,KAAKT,KAAK;MAC7B;IACJ;AACA,WAAOoC;EACX;;;;;EAMAE,OAAOjB,eAAuBC,aAA8B;AACxD,UAAMb,OAAO,KAAKpB,WAAW4B,IAAII,aAAAA;AACjC,WAAOZ,MAAMG,gBAAgBR,IAAIkB,WAAAA,KAAgB;EACrD;;;;;EAMAiB,eAAelB,eAAuBmB,UAAgD;AAClF,QAAI,CAAC,KAAKpD,QAAQR,SAAS;AACvB,aAAO4D;IACX;AAEA,UAAM/B,OAAO,KAAKpB,WAAW4B,IAAII,aAAAA;AACjC,QAAI,CAACZ,MAAM;AACP,aAAO+B;IACX;AAEA,WAAOA,SAASC,OAAOb,CAAAA,WAAAA;AAEnB,UAAIA,OAAO5B,UAAUqB,cAAe,QAAO;AAE3C,aAAOZ,KAAKG,gBAAgBR,IAAIwB,OAAO5B,KAAK;IAChD,CAAA;EACJ;;;;;;;;EAUA0C,YAAYC,UAAyC;AACjD,SAAKnD,WAAWoD,IAAID,QAAAA;EACxB;;;;;EAMAE,eAAeF,UAAyC;AACpD,SAAKnD,WAAWgC,OAAOmB,QAAAA;EAC3B;;;;EAMmBG,QAAQN,UAAmC;AAC1D,QAAI,CAAC,KAAKpD,QAAQR,QAAS;AAG3B,eAAWgD,UAAUY,UAAU;AAC3B,YAAMO,WAAW,KAAKC,iBAAiBpB,QAAQ1C,eAAAA;AAC/C,YAAM+D,YAAY,KAAKD,iBAAiBpB,QAAQzC,gBAAAA;AAGhD,UAAI,CAAC,KAAKO,gBAAgBU,IAAIwB,MAAAA,GAAS;AACnC,aAAKD,eAAeC,QAAQmB,SAAS/C,KAAK;MAC9C;AAGA,UAAI+C,SAASG,iBAAiB,KAAK7D,WAAWe,IAAI2C,SAAS/C,KAAK,GAAG;AAC/D,aAAKK,uBACD0C,SAAS/C,OACTiD,UAAUE,UACVF,UAAUG,QAAQ;MAE1B;IACJ;AAGA,SAAKC,8BAA8Bb,QAAAA;EACvC;EAEQa,8BAA8Bb,UAAmC;AACrE,eAAW,CAAA,EAAG/B,IAAAA,KAAS,KAAKpB,YAAY;AACpC,YAAMiE,aAAa,oBAAI7D,IAAAA;AAGvB,iBAAWmC,UAAUY,UAAU;AAC3B,cAAMO,WAAW,KAAKC,iBAAiBpB,QAAQ1C,eAAAA;AAC/C,cAAM+D,YAAY,KAAKD,iBAAiBpB,QAAQzC,gBAAAA;AAGhD,YAAI4D,SAAS/C,UAAUS,KAAKT,MAAO;AAGnC,cAAMuD,KAAKN,UAAUE,WAAW1C,KAAKC,SAAST;AAC9C,cAAMuD,KAAKP,UAAUG,WAAW3C,KAAKC,SAASR;AAC9C,cAAMuD,SAASF,KAAKA,KAAKC,KAAKA;AAE9B,YAAIC,UAAUhD,KAAKE,aAAa;AAC5B2C,qBAAWV,IAAIG,SAAS/C,KAAK;QACjC;MACJ;AAGA,iBAAWA,SAASsD,YAAY;AAC5B,YAAI,CAAC7C,KAAKG,gBAAgBR,IAAIJ,KAAAA,GAAQ;AAClC,eAAKmB,WAAW;YACZC,MAAM;YACNC,eAAeZ,KAAKT;YACpBsB,aAAatB;UACjB,CAAA;QACJ;MACJ;AAGA,iBAAWA,SAASS,KAAKG,iBAAiB;AACtC,YAAI,CAAC0C,WAAWlD,IAAIJ,KAAAA,GAAQ;AACxB,eAAKmB,WAAW;YACZC,MAAM;YACNC,eAAeZ,KAAKT;YACpBsB,aAAatB;UACjB,CAAA;QACJ;MACJ;AAEAS,WAAKG,kBAAkB0C;IAC3B;EACJ;;;;;EAMAI,QAAc;AACV,SAAKrE,WAAWqE,MAAK;AACrB,SAAKnE,OAAOmE,MAAK;AACjB,SAAKhE,gBAAgBgE,MAAK;AAC1B,SAAK/D,gBAAgB+D,MAAK;EAC9B;EAEmBC,YAAkB;AACjC,SAAKD,MAAK;AACV,SAAKlE,WAAWkE,MAAK;EACzB;;;;EAMQlD,YAAYP,GAAWC,GAAmB;AAC9C,UAAM0D,QAAQC,KAAKC,MAAM7D,IAAI,KAAKb,QAAQV,QAAQ;AAClD,UAAMqF,QAAQF,KAAKC,MAAM5D,IAAI,KAAKd,QAAQV,QAAQ;AAClD,WAAO,GAAGkF,KAAAA,IAASG,KAAAA;EACvB;EAEQjD,WAAWP,SAAiBP,OAAqB;AACrD,QAAIgE,OAAO,KAAKzE,OAAO0B,IAAIV,OAAAA;AAC3B,QAAI,CAACyD,MAAM;AACPA,aAAO,oBAAIvE,IAAAA;AACX,WAAKF,OAAOsB,IAAIN,SAASyD,IAAAA;IAC7B;AACAA,SAAKpB,IAAI5C,KAAAA;EACb;EAEQuB,gBAAgBhB,SAAiBP,OAAqB;AAC1D,UAAMgE,OAAO,KAAKzE,OAAO0B,IAAIV,OAAAA;AAC7B,QAAIyD,MAAM;AACNA,WAAKxC,OAAOxB,KAAAA;AACZ,UAAIgE,KAAKlE,SAAS,GAAG;AACjB,aAAKP,OAAOiC,OAAOjB,OAAAA;MACvB;IACJ;EACJ;EAEQQ,kBAAkBN,MAA0B;EAGpD;EAEQU,WAAW8C,OAA8B;AAC7C,eAAWtB,YAAY,KAAKnD,YAAY;AACpC,UAAI;AACAmD,iBAASsB,KAAAA;MACb,SAASC,GAAG;AACRC,gBAAQC,MAAM,sCAAsCF,CAAAA;MACxD;IACJ;EACJ;AACJ;AA1XsCpF;AAA/B,IAAMD,mBAAN;AAoYA,SAASwF,uBACZtF,QAAkC;AAElC,SAAO,IAAIF,iBAAiBE,MAAAA;AAChC;AAJgBsF;;;AdpZhB,IAAMC,kBAAsC;EACxCC,kBAAkB;EAClBC,qBAAqB;EACrBC,sBAAsB;EACtBC,mBAAmB;EACnBC,WAAW;AACf;AAuDO,IAAMC,iBAAN,MAAMA,eAAAA;EAiBT,YAAYC,QAAuC;AAhBnCC,gCAAO;AACPC,mCAAU;AAETC;AACTC;AACAC;AACAC;AACAC;AACAC,6CAAoD;AACpDC,sCAAsC;AAEtCC,0CAAyB;AACzBC,2CAAyC;AACzCC,2CAAwD;AACxDC,+CAA6C;AAGjD,SAAKV,UAAU;MAAE,GAAGV;MAAgB,GAAGO;IAAO;EAClD;;;;;;;;EAUA,IAAIc,iBAAqC;AACrC,WAAO,KAAKV;EAChB;;;;;EAMA,IAAIW,aAAgC;AAChC,WAAO,KAAKV;EAChB;;;;;EAMA,IAAIW,cAAkC;AAClC,WAAO,KAAKV;EAChB;;;;;EAMA,IAAIW,cAAkC;AAClC,WAAO,KAAKV;EAChB;;;;;EAMA,IAAIW,mBAAmD;AACnD,WAAO,KAAKV;EAChB;;;;;EAMA,IAAIW,YAAqC;AACrC,WAAO,KAAKV;EAChB;;;;;EAMA,IAAIW,gBAAwB;AACxB,WAAO,KAAKV;EAChB;;;;;EAMA,IAAIW,cAAuB;AACvB,WAAO,KAAKjB,iBAAiBiB,eAAe;EAChD;;;;;EAMA,IAAIC,iBAA0B;AAC1B,WAAO,KAAKX,iBAAiBW,kBAAkB;EACnD;;;;;EAMA,IAAIC,sBAA+B;AAC/B,WAAO,KAAKpB,QAAQT,oBAAoB,KAAKc,sBAAsB;EACvE;;;;;EAMA,IAAIgB,eAAwB;AACxB,WAAO,KAAKrB,QAAQL,aAAa,KAAKW,eAAe;EACzD;;;;;;;;EAUAgB,QAAQC,OAAaC,WAAmC;AACpD,SAAKvB,kBAAkB,IAAIwB,mBAAAA;AAE3B,UAAMC,QAAQC,KAAKD;AACnB,QAAIA,OAAO;AACP,WAAKE,cAAcF,KAAAA;IACvB;EACJ;;;;;EAMAG,YAAkB;AACd,SAAKC,qBAAoB;AACzB,SAAK7B,iBAAiB8B,WAAAA;EAC1B;EAEQH,cAAcF,OAAoB;AAEtC,SAAKxB,cAAc,IAAI8B,kBAAkB,KAAKhC,QAAQiC,UAAU;AAChE,SAAK9B,eAAe,IAAI+B,mBAAmB,KAAKhC,WAAW;AAC3D,SAAKE,eAAe,IAAI+B,mBAAmB,KAAKlC,iBAAiB,KAAKD,QAAQoC,WAAW;AAGzF,QAAI,KAAKpC,QAAQT,kBAAkB;AAC/B,WAAKc,oBAAoB,IAAIgC,wBAAwB,KAAKrC,QAAQsC,gBAAgB;AAClF,WAAKlC,aAAamC,oBAAoB,KAAKlC,iBAAiB;AAC5DqB,YAAMc,UAAU,KAAKnC,iBAAiB;IAC1C;AAGA,QAAI,KAAKL,QAAQL,WAAW;AACxB,WAAKW,aAAa,IAAImC,iBAAiB,KAAKzC,QAAQ0C,SAAS;AAC7DhB,YAAMc,UAAU,KAAKlC,UAAU;IACnC;AAEAoB,UAAMc,UAAU,KAAKtC,WAAW;AAChCwB,UAAMc,UAAU,KAAKrC,YAAY;AACjCuB,UAAMc,UAAU,KAAKpC,YAAY;AAEjC,SAAKuC,sBAAqB;EAC9B;EAEQA,wBAA8B;AAClC,SAAK1C,gBACA2C,OAAO,CAACC,SAAAA;AAEL,WAAK3C,YAAY4C,eAAeD,IAAAA;AAGhC,UAAI,KAAKxC,mBAAmB;AACxB,aAAKA,kBAAkB0C,oBAAoBF,IAAAA;MAC/C;IACJ,CAAA,EACCG,QAAQ,CAACH,SAAAA;AACN,WAAK1C,aAAa8C,YAAYJ,IAAAA;IAClC,CAAA,EACCK,UAAU,CAACL,SAAAA;AACR,WAAK1C,aAAagD,cAAcN,IAAAA;IACpC,CAAA;AAGJ,SAAK5C,gBAAgBmD,GAAG,aAAa,CAACP,SAAAA;AAClC,WAAKQ,iBAAiBR,IAAAA;IAC1B,CAAA;EACJ;;;;;;;;EAUA,MAAaS,QAAQC,SAA2C;AAC5D,SAAK7C,sBAAsB6C;AAE3B,QAAI;AAEA,YAAMC,uBAAuBD,QAAQE;AACrCF,cAAQE,eAAe,CAACC,WAAAA;AACpBF,+BAAuBE,MAAAA;AACvB,aAAKC,kBAAkBD,MAAAA;MAC3B;AAEA,YAAM,KAAKzD,gBAAgBqD,QAAQC,OAAAA;AAEnC,YAAMK,SAAS,MAAM,KAAK3D,gBAAgB4D,KAAK,QAAQ;QACnDC,YAAYP,QAAQO;QACpBC,QAAQR,QAAQQ;MACpB,CAAA;AAEA,WAAKxD,iBAAiBqD,OAAOI;AAC7B,WAAK7D,aAAa8D,iBAAiB,KAAK1D,cAAc;AAGtD,UAAI,KAAKF,mBAAmB;MAE5B;AAGA,UAAI,KAAKL,QAAQR,qBAAqB;AAClC,aAAKgB,kBAAkB;UACnB0D,OAAO,KAAKC,wBAAuB;UACnCH,UAAUJ,OAAOI;UACjBD,QAAQH,OAAOG;UACfK,UAAU;UACVjD,gBAAgB;QACpB;MACJ;AAEA,aAAO;IACX,SAASkD,KAAK;AACVC,cAAQC,MAAM,sCAAsCF,GAAAA;AACpD,aAAO;IACX;EACJ;;;;;EAMA,MAAatC,aAA4B;AACrC,SAAKD,qBAAoB;AACzB,SAAKtB,kBAAkB;AAEvB,QAAI;AACA,YAAM,KAAKP,gBAAgB4D,KAAK,SAASW,MAAAA;IAC7C,QAAQ;IAER;AACA,SAAKvE,gBAAgB8B,WAAU;AAC/B,SAAK0C,SAAQ;EACjB;EAEQd,kBAAkBD,QAAuB;AAC7CY,YAAQI,IAAI,iCAAiChB,MAAAA;AAE7C,QAAI,KAAK1D,QAAQR,uBAAuB,KAAKgB,mBAAmB,CAAC,KAAKA,gBAAgBW,gBAAgB;AAClG,WAAKwD,kBAAiB;IAC1B;EACJ;EAEQA,oBAA0B;AAC9B,QAAI,CAAC,KAAKnE,mBAAmB,CAAC,KAAKE,oBAAqB;AAExD,QAAI,KAAKF,gBAAgB4D,YAAY,KAAKpE,QAAQP,sBAAsB;AACpE6E,cAAQC,MAAM,mDAAA;AACd,WAAK/D,kBAAkB;AACvB;IACJ;AAEA,SAAKA,gBAAgBW,iBAAiB;AACtC,SAAKX,gBAAgB4D;AAErBE,YAAQI,IAAI,4CAA4C,KAAKlE,gBAAgB4D,QAAQ,IAAI,KAAKpE,QAAQP,oBAAoB,GAAG;AAE7H,SAAKgB,kBAAkBmE,WAAW,YAAA;AAC9B,UAAI;AACA,cAAM,KAAK3E,gBAAgBqD,QAAQ,KAAK5C,mBAAmB;AAE3D,cAAMkD,SAAS,MAAM,KAAK3D,gBAAgB4D,KAAK,aAAa;UACxDG,UAAU,KAAKxD,gBAAiBwD;UAChCD,QAAQ,KAAKvD,gBAAiBuD;UAC9BG,OAAO,KAAK1D,gBAAiB0D;QACjC,CAAA;AAEA,YAAIN,OAAOiB,SAAS;AAChBP,kBAAQI,IAAI,yCAAA;AACZ,eAAKlE,gBAAiBW,iBAAiB;AACvC,eAAKX,gBAAiB4D,WAAW;AAGjC,cAAIR,OAAOkB,OAAO;AACd,iBAAKzB,iBAAiBO,OAAOkB,KAAK;UACtC;QACJ,OAAO;AACHR,kBAAQC,MAAM,0CAA0CX,OAAOW,KAAK;AACpE,eAAKI,kBAAiB;QAC1B;MACJ,SAASN,KAAK;AACVC,gBAAQC,MAAM,wCAAwCF,GAAAA;AACtD,YAAI,KAAK7D,iBAAiB;AACtB,eAAKA,gBAAgBW,iBAAiB;QAC1C;AACA,aAAKwD,kBAAiB;MAC1B;IACJ,GAAG,KAAK3E,QAAQN,iBAAiB;EACrC;EAEQ2D,iBAAiBR,MAA2B;AAEhD,SAAK3C,YAAY6E,eAAc;AAG/B,eAAWC,cAAcnC,KAAKoC,UAAU;AACpC,WAAK9E,aAAa8C,YAAY+B,UAAAA;AAG9B,UAAIA,WAAWF,OAAO;AAClB,aAAK5E,YAAY4C,eAAe;UAC5BoC,OAAOrC,KAAKqC;UACZC,WAAWtC,KAAKsC;UAChBF,UAAU;YAACD,WAAWF;;QAC1B,CAAA;MACJ;IACJ;EACJ;EAEQhD,uBAA6B;AACjC,QAAI,KAAKrB,iBAAiB;AACtB2E,mBAAa,KAAK3E,eAAe;AACjC,WAAKA,kBAAkB;IAC3B;EACJ;EAEQ0D,0BAAkC;AACtC,WAAO,GAAGkB,KAAKC,IAAG,CAAA,IAAMC,KAAKC,OAAM,EAAGC,SAAS,EAAA,EAAIC,UAAU,GAAG,EAAA,CAAA;EACpE;EAEQjB,WAAiB;AACrB,SAAKlE,iBAAiB;AACtB,SAAKL,aAAa6E,eAAAA;AAClB,SAAK1E,mBAAmBsF,MAAAA;AACxB,SAAKvF,cAAcuF,MAAAA;EACvB;;;;;;;;EAUOC,eAAeC,YAAoBC,SAA8B;AACpE,SAAK3F,cAAcyF,eAAeC,YAAYC,OAAAA;EAClD;;;;;EAMOC,cAAcC,GAAWC,GAAiB;AAC7C,SAAK7F,cAAc8F,aAAaF,GAAGC,CAAAA;EACvC;;;;;EAMOE,gBAAgBC,QAAsB;AACzC,SAAKhG,cAAciG,eAAeD,MAAAA;EACtC;;;;;EAMOE,oBAAoBC,OAAqB;AAC5C,QAAI,KAAKlG,mBAAmB;AACxB,WAAKA,kBAAkBiG,oBAAoBC,KAAAA;IAC/C;EACJ;;;;;EAMOC,qBAAqBC,SAAwB;AAChD,QAAI,KAAKpG,mBAAmB;AACxB,WAAKA,kBAAkBoG,UAAUA;IACrC;EACJ;;;;;;;;EAUOC,eAAeH,OAAeP,GAAWC,GAAWU,WAA0B;AACjF,SAAKrG,YAAYsG,YAAYL,OAAOP,GAAGC,GAAGU,SAAAA;EAC9C;;;;;EAMOE,kBAAkBN,OAAqB;AAC1C,SAAKjG,YAAYwG,eAAeP,KAAAA;EACpC;;;;;EAMOQ,0BAA0BR,OAAeP,GAAWC,GAAiB;AACxE,SAAK3F,YAAY0G,uBAAuBT,OAAOP,GAAGC,CAAAA;EACtD;;;;;EAMOgB,mBAAmBC,eAAiC;AACvD,WAAO,KAAK5G,YAAY2G,mBAAmBC,aAAAA,KAAkB,CAAA;EACjE;;;;;EAMOC,OAAOD,eAAuBE,aAA8B;AAC/D,WAAO,KAAK9G,YAAY6G,OAAOD,eAAeE,WAAAA,KAAgB;EAClE;;;;;EAMOC,cAAcZ,SAAwB;AACzC,QAAI,KAAKnG,YAAY;AACjB,WAAKA,WAAWmG,UAAUA;IAC9B;EACJ;AACJ;AAnca7G;AAAN,IAAMA,gBAAN;;;AepHA,IAAM0H,wBAA+C;EACxDC,MAAM;EACNC,OAAO;EACPC,UAAU;EACVC,aAAa;EACbC,UAAU;IAAC;IAAW;IAAS;IAAU;IAAa;;EACtDC,UAAU;IAAC;IAAW;;EACtBC,QAAQ;EACRC,QAAQ,CAAA;EACRC,SAAS;IACL;MACIC,MAAM;MACNC,aAAa;MACbV,MAAM;IACV;;EAEJW,OAAO;AACX;AAMO,IAAMC,yBAAN,MAAMA,uBAAAA;EACTC,QAAQC,MAAqBC,SAAmC;AA5DpE,QAAAC;AA6DQ,UAAMC,MAAMF;AAGZ,QAAIG,UAAU;AACd,QAAID,IAAIE,QAAQ;AACZ,YAAMC,WAAWH,IAAIE,OAAOE,cAAaL,MAAA,MAAMM;QAAN;AACrCC,gDAA0B;;MAC9B,GAF+CD,OAAAA,KAAAA,oBAANN,IAEzC;AACA,UAAII,UAAU;AACVF,kBAAUE,SAASG;MACvB;IACJ;AAEA,WAAO;MACHf,SAAS;QACLU;MACJ;IACJ;EACJ;AACJ;AArBaN;AAAN,IAAMA,wBAAN;AA+BA,IAAMY,mBAA0C;EACnDxB,MAAM;EACNC,OAAO;EACPC,UAAU;EACVC,aAAa;EACbC,UAAU;IAAC;IAAW;IAAU;IAAa;;EAC7CC,UAAU;IAAC;IAAW;;EACtBC,QAAQ;EACRC,QAAQ,CAAA;EACRC,SAAS;IACL;MACIC,MAAM;MACNC,aAAa;MACbV,MAAM;IACV;;EAEJW,OAAO;AACX;AAMO,IAAMc,oBAAN,MAAMA,kBAAAA;EACTZ,QAAQa,OAAsBX,SAAmC;AAC7D,UAAME,MAAMF;AAEZ,WAAO;MACHP,SAAS;QACLmB,UAAUV,IAAIU,YAAY;MAC9B;IACJ;EACJ;AACJ;AAVaF;AAAN,IAAMA,mBAAN;AAoBA,IAAMG,uBAA8C;EACvD5B,MAAM;EACNC,OAAO;EACPC,UAAU;EACVC,aAAa;EACbC,UAAU;IAAC;IAAW;IAAa;IAAW;;EAC9CC,UAAU;IAAC;IAAW;;EACtBC,QAAQ;EACRC,QAAQ,CAAA;EACRC,SAAS;IACL;MACIC,MAAM;MACNC,aAAa;MACbV,MAAM;IACV;;EAEJW,OAAO;AACX;AAMO,IAAMkB,wBAAN,MAAMA,sBAAAA;EACThB,QAAQC,MAAqBC,SAAmC;AA7JpE,QAAAC;AA8JQ,UAAMC,MAAMF;AAEZ,QAAIe,eAAe;AACnB,QAAIb,IAAIE,QAAQ;AACZ,YAAMC,WAAWH,IAAIE,OAAOE,cAAaL,MAAA,MAAMM;QAAN;AACrCS,+CAAyB;;MAC7B,GAF+CT,OAAAA,KAAAA,oBAANN,IAEzC;AACA,UAAII,UAAU;AACVU,uBAAeV,SAASW;MAC5B;IACJ;AAEA,WAAO;MACHvB,SAAS;QACLsB;MACJ;IACJ;EACJ;AACJ;AApBaD;AAAN,IAAMA,uBAAN;AA8BA,IAAMG,uBAA8C;EACvDhC,MAAM;EACNC,OAAO;EACPC,UAAU;EACVC,aAAa;EACbC,UAAU;IAAC;IAAW;IAAM;IAAS;;EACrCC,UAAU;IAAC;IAAW;;EACtBC,QAAQ;EACRC,QAAQ,CAAA;EACRC,SAAS;IACL;MACIC,MAAM;MACNC,aAAa;MACbV,MAAM;IACV;IACA;MACIS,MAAM;MACNC,aAAa;MACbV,MAAM;IACV;;EAEJW,OAAO;AACX;AAMO,IAAMsB,wBAAN,MAAMA,sBAAAA;EACTpB,QAAQC,MAAqBC,SAAmC;AAvNpE,QAAAC;AAwNQ,UAAMC,MAAMF;AAEZ,QAAImB,QAAQ;AACZ,QAAIC,UAAU;AAEd,QAAIlB,IAAIE,QAAQ;AACZ,YAAMC,WAAWH,IAAIE,OAAOE,cAAaL,MAAA,MAAMM;QAAN;AACrCY,uCAAgB;AAChBC,yCAAkB;;MACtB,GAH+Cb,OAAAA,KAAAA,oBAANN,IAGzC;AACA,UAAII,UAAU;AACVc,gBAAQd,SAASc;AACjBC,kBAAUf,SAASe;MACvB;IACJ;AAEA,WAAO;MACH3B,SAAS;QACL0B;QACAC;MACJ;IACJ;EACJ;AACJ;AAzBaF;AAAN,IAAMA,uBAAN;AAmCA,IAAMG,2BAAkD;EAC3DpC,MAAM;EACNC,OAAO;EACPC,UAAU;EACVC,aAAa;EACbC,UAAU;IAAC;IAAW;IAAS;IAAU;;EACzCC,UAAU;IAAC;IAAW;;EACtBC,QAAQ;EACRC,QAAQ,CAAA;EACRC,SAAS;IACL;MACIC,MAAM;MACNC,aAAa;MACbV,MAAM;IACV;;EAEJW,OAAO;AACX;AAMO,IAAM0B,4BAAN,MAAMA,0BAAAA;EACTxB,QAAQa,OAAsBX,SAAmC;AAC7D,UAAME,MAAMF;AAEZ,WAAO;MACHP,SAAS;QACL8B,UAAUrB,IAAIsB,iBAAiB;MACnC;IACJ;EACJ;AACJ;AAVaF;AAAN,IAAMA,2BAAN;AAoBA,IAAMG,yBAAyB;EAClCC,WAAW;IACP1C;IACAyB;IACAI;IACAI;IACAI;;EAEJM,WAAW,oBAAIC,IAA2B;IACtC;MAAC;MAAiB,IAAI/B,sBAAAA;;IACtB;MAAC;MAAY,IAAIa,iBAAAA;;IACjB;MAAC;MAAgB,IAAII,qBAAAA;;IACrB;MAAC;MAAgB,IAAII,qBAAAA;;IACrB;MAAC;MAAoB,IAAII,yBAAAA;;GAC5B;AACL;","names":["rpc","rpc","gameProtocol","define","api","join","leave","reconnect","msg","input","sync","spawn","despawn","fullState","createServiceToken","NetworkServiceToken","NetworkSyncSystemToken","NetworkSpawnSystemToken","NetworkInputSystemToken","NetworkPredictionSystemToken","NetworkAOISystemToken","Core","RpcClient","NetworkState","RpcService","_protocol","_client","_state","state","isConnected","client","connect","options","Error","RpcClient","url","onConnect","onDisconnect","reason","onError","err","disconnect","call","name","input","Promise","reject","send","data","on","handler","off","once","GameNetworkService","gameProtocol","sendInput","onSync","onSpawn","onDespawn","createNetworkService","protocol","RpcService","GameNetworkService","EntitySystem","Matcher","Time","Component","ECSComponent","Serialize","Serializable","Property","NetworkIdentity","Component","netId","ownerId","bIsLocalPlayer","bHasAuthority","prefabType","syncInterval","lastSyncTime","needsSync","now","type","label","readOnly","min","version","typeId","Component","ECSComponent","Serialize","Serializable","Property","NetworkTransform","Component","targetX","targetY","targetRotation","currentX","currentY","currentRotation","lerpSpeed","bInterpolate","syncInterval","lastSyncTime","setTarget","x","y","rotation","undefined","snap","type","label","min","max","requires","version","typeId","SnapshotBuffer","config","_buffer","_maxSize","_interpolationDelay","maxSize","interpolationDelay","size","length","push","snapshot","insertIndex","i","timestamp","splice","shift","getInterpolationSnapshots","renderTime","targetTime","prev","next","duration","t","Math","max","min","getLatest","getSnapshotsAfter","filter","s","clear","createSnapshotBuffer","lerp","a","b","t","lerpAngle","diff","Math","PI","smoothDamp","current","target","velocity","smoothTime","deltaTime","maxSpeed","Infinity","max","omega","x","exp","change","maxChange","min","temp","newVelocity","newValue","TransformInterpolator","interpolate","from","to","t","x","lerp","y","rotation","lerpAngle","extrapolate","state","deltaTime","velocityX","velocityY","angularVelocity","HermiteTransformInterpolator","t2","t3","h00","h10","h01","h11","dt","dh00","dh10","dh01","dh11","createTransformInterpolator","createHermiteTransformInterpolator","ClientPrediction","predictor","config","_predictor","_config","_pendingInputs","_lastAcknowledgedSequence","_currentSequence","_lastServerState","_predictedState","_correctionOffset","x","y","maxUnacknowledgedInputs","reconciliationThreshold","reconciliationSpeed","predictedState","correctionOffset","pendingInputCount","length","recordInput","input","currentState","deltaTime","inputSnapshot","sequence","timestamp","Date","now","push","shift","predict","getInputToSend","currentSequence","reconcile","serverState","acknowledgedSequence","stateGetter","state","serverPos","predictedPos","errorX","errorY","errorMagnitude","Math","sqrt","t","min","decayRate","clear","createClientPrediction","DeltaFlags","NONE","POSITION","ROTATION","VELOCITY","ANGULAR_VELOCITY","CUSTOM","DEFAULT_CONFIG","positionThreshold","rotationThreshold","velocityThreshold","fullSnapshotInterval","StateDeltaCompressor","config","_config","_lastStates","Map","_frameCounter","compress","data","isFullSnapshot","deltaEntities","entity","entities","lastState","get","netId","push","_createFullDelta","delta","_calculateDelta","set","frame","timestamp","ackSeq","decompress","fullState","_applyDelta","removeEntity","delete","clear","forceFullSnapshot","flags","pos","rot","undefined","vel","angVel","custom","currentState","posChanged","Math","abs","x","y","rotChanged","velChanged","angVelChanged","customChanged","_customDataEqual","state","a","b","keysA","Object","keys","keysB","length","key","createStateDeltaCompressor","EntitySystem","Matcher","SyncOperation","SYNC_METADATA","CHANGE_TRACKER","encodeSnapshot","encodeSpawn","encodeDespawn","decodeSnapshot","decodeSpawn","processDespawn","registerSyncComponent","DEFAULT_CONFIG","enableDeltaSync","syncInterval","ComponentSyncSystem","EntitySystem","config","isServer","Matcher","all","NetworkIdentity","_config","_syncEntityMap","Map","_syncListeners","Set","_lastSyncTime","_isServer","value","addSyncListener","listener","add","removeSyncListener","delete","registerComponent","componentClass","metadata","SYNC_METADATA","registerSyncComponent","typeId","encodeAllEntities","fullSync","entities","getMatchingEntities","operation","SyncOperation","FULL","DELTA","data","encodeSnapshot","_clearChangeTrackers","encodeDelta","changedEntities","filter","entity","_hasChanges","length","encodeSpawn","prefabType","encodeDespawn","entityId","applySnapshot","scene","Error","result","decodeSnapshot","entityResult","isNew","_emitEvent","type","applySpawn","decodeSpawn","id","applyDespawn","entityIds","processDespawn","getEntityById","get","slice","process","now","Date","identity","getComponent","set","component","components","tracker","CHANGE_TRACKER","hasChanges","clear","event","error","console","onDestroy","createComponentSyncSystem","DEFAULT_CONFIG","bufferSize","interpolationDelay","enableExtrapolation","maxExtrapolationTime","useHermiteInterpolation","NetworkSyncSystem","EntitySystem","config","Matcher","all","NetworkIdentity","NetworkTransform","_netIdToEntity","Map","_entitySnapshots","_interpolator","_config","_serverTimeOffset","_lastSyncTime","_renderTime","createTransformInterpolator","serverTimeOffset","renderTime","handleSyncData","data","serverTime","timestamp","clientTime","Date","now","state","entities","_processEntityState","handleSync","msg","entityId","get","netId","undefined","entity","scene","findEntityById","transform","getComponent","pos","setTarget","x","y","rot","snapshotData","buffer","createSnapshotBuffer","lastServerTime","set","transformState","rotation","velocityX","vel","velocityY","angularVelocity","angVel","snapshot","push","process","deltaTime","Time","requireComponent","identity","bHasAuthority","bInterpolate","_interpolateEntity","size","result","getInterpolationSnapshots","prev","next","t","interpolated","interpolate","currentX","currentY","currentRotation","targetX","targetY","targetRotation","latest","getLatest","timeSinceLastSnapshot","extrapolated","extrapolate","_simpleLerp","Math","min","lerpSpeed","angleDiff","PI","registerEntity","unregisterEntity","delete","getEntityId","getSnapshotBuffer","clearSnapshots","values","clear","onDestroy","EntitySystem","Matcher","NetworkSpawnSystem","EntitySystem","syncSystem","Matcher","nothing","_syncSystem","_prefabFactories","Map","_localPlayerId","setLocalPlayerId","id","handleSpawn","msg","scene","factory","get","prefab","logger","warn","entity","identity","addComponent","NetworkIdentity","netId","ownerId","prefabType","bHasAuthority","bIsLocalPlayer","transform","NetworkTransform","setTarget","pos","x","y","rot","snap","registerEntity","handleDespawn","entityId","getEntityId","undefined","findEntityById","destroy","unregisterEntity","registerPrefab","set","unregisterPrefab","delete","onDestroy","clear","EntitySystem","Matcher","DEFAULT_CONFIG","sendInterval","mergeIdenticalInputs","maxQueueLength","NetworkInputSystem","EntitySystem","networkService","config","Matcher","nothing","_networkService","_config","_predictionSystem","_frame","_inputSequence","_inputQueue","_lastSendTime","_lastMoveDir","x","y","frame","inputSequence","setPredictionSystem","system","process","isConnected","now","Date","predictedInput","getInputToSend","sendInput","length","mergedInput","_mergeInputs","shift","input","seq","timestamp","moveDir","actions","inputs","allActions","lastMoveDir","push","undefined","addMoveInput","setInput","_addToQueue","addActionInput","action","lastInput","clearQueue","reset","onDestroy","createNetworkInputSystem","EntitySystem","Matcher","Time","DEFAULT_CONFIG","moveSpeed","enabled","maxUnacknowledgedInputs","reconciliationThreshold","reconciliationSpeed","SimpleMovementPredictor","_moveSpeed","predict","state","input","deltaTime","velocityX","x","velocityY","y","rotation","NetworkPredictionSystem","EntitySystem","config","Matcher","all","NetworkIdentity","NetworkTransform","_config","_predictor","_prediction","_localPlayerNetId","_currentInput","_inputSequence","inputSequence","pendingInputCount","value","setLocalPlayerNetId","netId","createClientPrediction","setInput","actions","getInputToSend","seq","sequence","frame","timestamp","moveDir","reconcileWithServer","data","localState","entities","find","e","pos","serverState","rot","vel","ackSeq","undefined","reconcile","Time","process","entity","identity","requireComponent","bHasAuthority","transform","currentState","currentX","currentY","currentRotation","predicted","recordInput","targetX","targetY","targetRotation","currentSequence","offset","correctionOffset","Math","abs","reset","clear","onDestroy","createNetworkPredictionSystem","EntitySystem","Matcher","DEFAULT_CONFIG","cellSize","defaultViewRange","enabled","NetworkAOISystem","EntitySystem","config","Matcher","all","NetworkIdentity","NetworkTransform","_config","_observers","Map","_cells","_listeners","Set","_entityNetIdMap","_netIdEntityMap","value","observerCount","size","addObserver","netId","x","y","viewRange","has","updateObserverPosition","range","cellKey","_getCellKey","data","position","viewRangeSq","visibleEntities","set","_addToCell","_updateVisibility","removeObserver","get","visibleNetId","_emitEvent","type","observerNetId","targetNetId","_removeFromCell","delete","newCellKey","updateObserverViewRange","registerEntity","entity","unregisterEntity","undefined","getVisibleEntities","Array","from","getObserversOf","entityNetId","observers","push","canSee","filterSyncData","entities","filter","addListener","listener","add","removeListener","process","identity","requireComponent","transform","bHasAuthority","currentX","currentY","_updateAllObserversVisibility","newVisible","dx","dy","distSq","clear","onDestroy","cellX","Math","floor","cellY","cell","event","e","console","error","createNetworkAOISystem","DEFAULT_CONFIG","enablePrediction","enableAutoReconnect","maxReconnectAttempts","reconnectInterval","enableAOI","NetworkPlugin","config","name","version","_config","_networkService","_syncSystem","_spawnSystem","_inputSystem","_predictionSystem","_aoiSystem","_localPlayerId","_reconnectState","_reconnectTimer","_lastConnectOptions","networkService","syncSystem","spawnSystem","inputSystem","predictionSystem","aoiSystem","localPlayerId","isConnected","isReconnecting","isPredictionEnabled","isAOIEnabled","install","_core","_services","GameNetworkService","scene","Core","_setupSystems","uninstall","_clearReconnectTimer","disconnect","NetworkSyncSystem","syncConfig","NetworkSpawnSystem","NetworkInputSystem","inputConfig","NetworkPredictionSystem","predictionConfig","setPredictionSystem","addSystem","NetworkAOISystem","aoiConfig","_setupMessageHandlers","onSync","data","handleSyncData","reconcileWithServer","onSpawn","handleSpawn","onDespawn","handleDespawn","on","_handleFullState","connect","options","originalOnDisconnect","onDisconnect","reason","_handleDisconnect","result","call","playerName","roomId","playerId","setLocalPlayerId","token","_generateReconnectToken","attempts","err","console","error","undefined","_cleanup","log","_attemptReconnect","setTimeout","success","state","clearSnapshots","entityData","entities","frame","timestamp","clearTimeout","Date","now","Math","random","toString","substring","reset","registerPrefab","prefabType","factory","sendMoveInput","x","y","addMoveInput","sendActionInput","action","addActionInput","setLocalPlayerNetId","netId","setPredictionEnabled","enabled","addAOIObserver","viewRange","addObserver","removeAOIObserver","removeObserver","updateAOIObserverPosition","updateObserverPosition","getVisibleEntities","observerNetId","canSee","targetNetId","setAOIEnabled","IsLocalPlayerTemplate","type","title","category","description","keywords","menuPath","isPure","inputs","outputs","name","displayName","color","IsLocalPlayerExecutor","execute","node","context","_a","ctx","isLocal","entity","identity","getComponent","NetworkIdentity","bIsLocalPlayer","IsServerTemplate","IsServerExecutor","_node","isServer","HasAuthorityTemplate","HasAuthorityExecutor","hasAuthority","bHasAuthority","GetNetworkIdTemplate","GetNetworkIdExecutor","netId","ownerId","GetLocalPlayerIdTemplate","GetLocalPlayerIdExecutor","playerId","localPlayerId","NetworkNodeDefinitions","templates","executors","Map"]}
|