@esengine/network 1.0.0 → 2.1.1

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/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.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 * @esengine/network\n *\n * 基于 TSRPC 的网络同步模块(客户端)\n * TSRPC-based network synchronization module (client)\n */\n\n// ============================================================================\n// Re-export from protocols | 从协议包重新导出\n// ============================================================================\n\nexport type {\n ServiceType,\n Vec2,\n IEntityState,\n IPlayerInput,\n MsgSync,\n MsgInput,\n MsgSpawn,\n MsgDespawn,\n ReqJoin,\n ResJoin\n} from '@esengine/network-protocols';\n\nexport { serviceProto } from '@esengine/network-protocols';\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 { NetworkService, ENetworkState } from './services/NetworkService';\nexport type { INetworkCallbacks } 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 { NetworkSpawnSystem } from './systems/NetworkSpawnSystem';\nexport type { PrefabFactory } 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 * 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","import { type IPlugin, Core, type ServiceContainer, type Scene } from '@esengine/ecs-framework';\nimport { NetworkService } from './services/NetworkService';\nimport { NetworkSyncSystem } from './systems/NetworkSyncSystem';\nimport { NetworkSpawnSystem, type PrefabFactory } from './systems/NetworkSpawnSystem';\nimport { NetworkInputSystem } from './systems/NetworkInputSystem';\n\n/**\n * 网络插件\n * Network plugin\n *\n * 提供基于 TSRPC 的网络同步功能。\n * Provides TSRPC-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 * // 连接到服务器 | Connect to server\n * await networkPlugin.connect('ws://localhost:3000', 'Player1');\n *\n * // 注册预制体 | Register prefab\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 = '1.0.0';\n\n private _networkService!: NetworkService;\n private _syncSystem!: NetworkSyncSystem;\n private _spawnSystem!: NetworkSpawnSystem;\n private _inputSystem!: NetworkInputSystem;\n\n /**\n * 网络服务\n * Network service\n */\n get networkService(): NetworkService {\n return this._networkService;\n }\n\n /**\n * 同步系统\n * Sync system\n */\n get syncSystem(): NetworkSyncSystem {\n return this._syncSystem;\n }\n\n /**\n * 生成系统\n * Spawn system\n */\n get spawnSystem(): NetworkSpawnSystem {\n return this._spawnSystem;\n }\n\n /**\n * 输入系统\n * Input system\n */\n get inputSystem(): NetworkInputSystem {\n return this._inputSystem;\n }\n\n /**\n * 是否已连接\n * Is connected\n */\n get isConnected(): boolean {\n return this._networkService?.isConnected ?? false;\n }\n\n /**\n * 安装插件\n * Install plugin\n */\n install(_core: Core, _services: ServiceContainer): void {\n this._networkService = new NetworkService();\n\n // 当场景加载时添加系统\n // Add systems when scene loads\n const scene = Core.scene;\n if (scene) {\n this._setupSystems(scene as Scene);\n }\n }\n\n /**\n * 卸载插件\n * Uninstall plugin\n */\n uninstall(): void {\n this._networkService?.disconnect();\n }\n\n private _setupSystems(scene: Scene): void {\n this._syncSystem = new NetworkSyncSystem(this._networkService);\n this._spawnSystem = new NetworkSpawnSystem(this._networkService, 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\n /**\n * 连接到服务器\n * Connect to server\n */\n public async connect(serverUrl: string, playerName: string, roomId?: string): Promise<boolean> {\n return this._networkService.connect(serverUrl, playerName, roomId);\n }\n\n /**\n * 断开连接\n * Disconnect\n */\n public async disconnect(): Promise<void> {\n await this._networkService.disconnect();\n }\n\n /**\n * 注册预制体工厂\n * Register prefab factory\n */\n public registerPrefab(prefabType: string, factory: PrefabFactory): void {\n this._spawnSystem?.registerPrefab(prefabType, factory);\n }\n\n /**\n * 发送移动输入\n * Send move input\n */\n public sendMoveInput(x: number, y: number): void {\n this._inputSystem?.addMoveInput(x, y);\n }\n\n /**\n * 发送动作输入\n * Send action input\n */\n public sendActionInput(action: string): void {\n this._inputSystem?.addActionInput(action);\n }\n}\n","import { WsClient } from 'tsrpc-browser';\nimport {\n serviceProto,\n type ServiceType,\n type MsgSync,\n type MsgSpawn,\n type MsgDespawn,\n type IPlayerInput\n} from '@esengine/network-protocols';\n\n/**\n * 连接状态\n * Connection state\n */\nexport const enum ENetworkState {\n Disconnected = 0,\n Connecting = 1,\n Connected = 2\n}\n\n/**\n * 网络事件回调\n * Network event callbacks\n */\nexport interface INetworkCallbacks {\n onConnected?: (clientId: number, roomId: string) => void;\n onDisconnected?: () => void;\n onSync?: (msg: MsgSync) => void;\n onSpawn?: (msg: MsgSpawn) => void;\n onDespawn?: (msg: MsgDespawn) => void;\n onError?: (error: Error) => void;\n}\n\n/**\n * 创建 TSRPC 客户端\n * Create TSRPC client\n */\nfunction createClient(serverUrl: string): WsClient<ServiceType> {\n return new WsClient(serviceProto, {\n server: serverUrl,\n json: true,\n logLevel: 'warn'\n });\n}\n\n/**\n * 网络服务\n * Network service\n *\n * 基于 TSRPC 的网络服务封装,提供类型安全的网络通信。\n * TSRPC-based network service wrapper with type-safe communication.\n */\nexport class NetworkService {\n private _client: WsClient<ServiceType> | null = null;\n private _state: ENetworkState = ENetworkState.Disconnected;\n private _clientId: number = 0;\n private _roomId: string = '';\n private _callbacks: INetworkCallbacks = {};\n\n get state(): ENetworkState {\n return this._state;\n }\n\n get clientId(): number {\n return this._clientId;\n }\n\n get roomId(): string {\n return this._roomId;\n }\n\n get isConnected(): boolean {\n return this._state === ENetworkState.Connected;\n }\n\n /**\n * 设置回调\n * Set callbacks\n */\n setCallbacks(callbacks: INetworkCallbacks): void {\n this._callbacks = { ...this._callbacks, ...callbacks };\n }\n\n /**\n * 连接到服务器\n * Connect to server\n */\n async connect(serverUrl: string, playerName: string, roomId?: string): Promise<boolean> {\n if (this._state !== ENetworkState.Disconnected) {\n return false;\n }\n\n this._state = ENetworkState.Connecting;\n this._client = createClient(serverUrl);\n this._setupListeners();\n\n // 连接\n // Connect\n const connectResult = await this._client.connect();\n if (!connectResult.isSucc) {\n this._state = ENetworkState.Disconnected;\n this._callbacks.onError?.(new Error(connectResult.errMsg));\n return false;\n }\n\n // 加入房间\n // Join room\n const joinResult = await this._client.callApi('Join', {\n playerName,\n roomId\n });\n\n if (!joinResult.isSucc) {\n await this._client.disconnect();\n this._state = ENetworkState.Disconnected;\n this._callbacks.onError?.(new Error(joinResult.err.message));\n return false;\n }\n\n this._clientId = joinResult.res.clientId;\n this._roomId = joinResult.res.roomId;\n this._state = ENetworkState.Connected;\n this._callbacks.onConnected?.(this._clientId, this._roomId);\n\n return true;\n }\n\n /**\n * 断开连接\n * Disconnect\n */\n async disconnect(): Promise<void> {\n if (this._client) {\n await this._client.disconnect();\n }\n this._state = ENetworkState.Disconnected;\n this._clientId = 0;\n this._roomId = '';\n this._client = null;\n }\n\n /**\n * 发送输入\n * Send input\n */\n sendInput(input: IPlayerInput): void {\n if (!this.isConnected || !this._client) return;\n this._client.sendMsg('Input', { input });\n }\n\n private _setupListeners(): void {\n if (!this._client) return;\n\n this._client.listenMsg('Sync', (msg) => {\n this._callbacks.onSync?.(msg);\n });\n\n this._client.listenMsg('Spawn', (msg) => {\n this._callbacks.onSpawn?.(msg);\n });\n\n this._client.listenMsg('Despawn', (msg) => {\n this._callbacks.onDespawn?.(msg);\n });\n\n this._client.flows.postDisconnectFlow.push((v) => {\n this._state = ENetworkState.Disconnected;\n this._callbacks.onDisconnected?.();\n return v;\n });\n }\n}\n","import { EntitySystem, Matcher, Time, type Entity } from '@esengine/ecs-framework';\nimport type { MsgSync } from '@esengine/network-protocols';\nimport { NetworkIdentity } from '../components/NetworkIdentity';\nimport { NetworkTransform } from '../components/NetworkTransform';\nimport type { NetworkService } from '../services/NetworkService';\n\n/**\n * 网络同步系统\n * Network sync system\n *\n * 处理网络实体的状态同步和插值。\n * Handles state synchronization and interpolation for networked entities.\n */\nexport class NetworkSyncSystem extends EntitySystem {\n private _networkService: NetworkService;\n private _netIdToEntity: Map<number, number> = new Map();\n\n constructor(networkService: NetworkService) {\n super(Matcher.all(NetworkIdentity, NetworkTransform));\n this._networkService = networkService;\n }\n\n protected override onInitialize(): void {\n this._networkService.setCallbacks({\n onSync: this._handleSync.bind(this)\n });\n }\n\n /**\n * 处理实体列表\n * Process entities\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 // 只有非本地玩家需要插值\n // Only non-local players need interpolation\n if (!identity.bHasAuthority && transform.bInterpolate) {\n this._interpolate(transform, deltaTime);\n }\n }\n }\n\n /**\n * 注册网络实体\n * Register network entity\n */\n public registerEntity(netId: number, entityId: number): void {\n this._netIdToEntity.set(netId, entityId);\n }\n\n /**\n * 注销网络实体\n * Unregister network entity\n */\n public unregisterEntity(netId: number): void {\n this._netIdToEntity.delete(netId);\n }\n\n /**\n * 根据网络 ID 获取实体 ID\n * Get entity ID by network ID\n */\n public getEntityId(netId: number): number | undefined {\n return this._netIdToEntity.get(netId);\n }\n\n private _handleSync(msg: MsgSync): 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);\n }\n }\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 // 角度插值需要处理环绕\n // Angle interpolation needs to handle wrap-around\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 type { MsgSpawn, MsgDespawn } from '@esengine/network-protocols';\nimport { NetworkIdentity } from '../components/NetworkIdentity';\nimport { NetworkTransform } from '../components/NetworkTransform';\nimport type { NetworkService } from '../services/NetworkService';\nimport type { NetworkSyncSystem } from './NetworkSyncSystem';\n\n/**\n * 预制体工厂函数类型\n * Prefab factory function type\n */\nexport type PrefabFactory = (scene: Scene, spawn: MsgSpawn) => Entity;\n\n/**\n * 网络生成系统\n * Network spawn system\n *\n * 处理网络实体的生成和销毁。\n * Handles spawning and despawning of networked entities.\n */\nexport class NetworkSpawnSystem extends EntitySystem {\n private _networkService: NetworkService;\n private _syncSystem: NetworkSyncSystem;\n private _prefabFactories: Map<string, PrefabFactory> = new Map();\n\n constructor(networkService: NetworkService, syncSystem: NetworkSyncSystem) {\n // 不查询任何实体,此系统只响应网络消息\n // Don't query any entities, this system only responds to network messages\n super(Matcher.nothing());\n this._networkService = networkService;\n this._syncSystem = syncSystem;\n }\n\n protected override onInitialize(): void {\n this._networkService.setCallbacks({\n onSpawn: this._handleSpawn.bind(this),\n onDespawn: this._handleDespawn.bind(this)\n });\n }\n\n /**\n * 注册预制体工厂\n * Register prefab factory\n */\n public registerPrefab(prefabType: string, factory: PrefabFactory): void {\n this._prefabFactories.set(prefabType, factory);\n }\n\n /**\n * 注销预制体工厂\n * Unregister prefab factory\n */\n public unregisterPrefab(prefabType: string): void {\n this._prefabFactories.delete(prefabType);\n }\n\n private _handleSpawn(msg: MsgSpawn): void {\n if (!this.scene) return;\n\n const factory = this._prefabFactories.get(msg.prefab);\n if (!factory) {\n this.logger.warn(`Unknown prefab: ${msg.prefab}`);\n return;\n }\n\n const entity = factory(this.scene, msg);\n\n // 添加网络组件\n // Add network components\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._networkService.clientId;\n identity.bIsLocalPlayer = identity.bHasAuthority;\n\n const transform = entity.addComponent(new NetworkTransform());\n transform.setTarget(msg.pos.x, msg.pos.y, msg.rot);\n transform.snap();\n\n // 注册到同步系统\n // Register to sync system\n this._syncSystem.registerEntity(msg.netId, entity.id);\n }\n\n private _handleDespawn(msg: MsgDespawn): 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 protected override onDestroy(): void {\n this._prefabFactories.clear();\n }\n}\n","import { EntitySystem, Matcher } from '@esengine/ecs-framework';\nimport type { IPlayerInput } from '@esengine/network-protocols';\nimport type { NetworkService } from '../services/NetworkService';\n\n/**\n * 网络输入系统\n * Network input system\n *\n * 收集本地玩家输入并发送到服务器。\n * 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: IPlayerInput[] = [];\n\n constructor(networkService: NetworkService) {\n // 不查询任何实体,此系统只处理输入\n // Don't query any entities, this system only handles input\n super(Matcher.nothing());\n this._networkService = networkService;\n }\n\n /**\n * 处理输入队列\n * Process input queue\n */\n protected override process(): void {\n if (!this._networkService.isConnected) return;\n\n this._frame++;\n\n // 发送队列中的输入\n // Send queued inputs\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 * 添加移动输入\n * 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 * 添加动作输入\n * 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":["serviceProto","createServiceToken","NetworkServiceToken","NetworkSyncSystemToken","NetworkSpawnSystemToken","NetworkInputSystemToken","Core","WsClient","serviceProto","ENetworkState","createClient","serverUrl","WsClient","serviceProto","server","json","logLevel","NetworkService","_client","_state","_clientId","_roomId","_callbacks","state","clientId","roomId","isConnected","setCallbacks","callbacks","connect","playerName","_setupListeners","connectResult","isSucc","onError","Error","errMsg","joinResult","callApi","disconnect","err","message","res","onConnected","sendInput","input","sendMsg","listenMsg","msg","onSync","onSpawn","onDespawn","flows","postDisconnectFlow","push","v","onDisconnected","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","networkService","Matcher","all","NetworkIdentity","NetworkTransform","_networkService","_netIdToEntity","Map","onInitialize","setCallbacks","onSync","_handleSync","bind","process","entities","deltaTime","Time","entity","transform","requireComponent","identity","bHasAuthority","bInterpolate","_interpolate","registerEntity","netId","entityId","set","unregisterEntity","delete","getEntityId","get","msg","state","undefined","scene","findEntityById","getComponent","pos","setTarget","x","y","rot","t","Math","min","lerpSpeed","currentX","targetX","currentY","targetY","angleDiff","targetRotation","currentRotation","PI","onDestroy","clear","EntitySystem","Matcher","NetworkSpawnSystem","EntitySystem","networkService","syncSystem","Matcher","nothing","_networkService","_syncSystem","_prefabFactories","Map","onInitialize","setCallbacks","onSpawn","_handleSpawn","bind","onDespawn","_handleDespawn","registerPrefab","prefabType","factory","set","unregisterPrefab","delete","msg","scene","get","prefab","logger","warn","entity","identity","addComponent","NetworkIdentity","netId","ownerId","bHasAuthority","clientId","bIsLocalPlayer","transform","NetworkTransform","setTarget","pos","x","y","rot","snap","registerEntity","id","entityId","getEntityId","undefined","findEntityById","destroy","unregisterEntity","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","networkService","syncSystem","spawnSystem","inputSystem","isConnected","install","_core","_services","NetworkService","scene","Core","_setupSystems","uninstall","disconnect","NetworkSyncSystem","NetworkSpawnSystem","NetworkInputSystem","addSystem","connect","serverUrl","playerName","roomId","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/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"]}
@@ -0,0 +1,160 @@
1
+ /**
2
+ * @zh 游戏网络协议定义
3
+ * @en Game Network Protocol Definition
4
+ *
5
+ * @zh 定义客户端与服务器之间的通信协议
6
+ * @en Defines the communication protocol between client and server
7
+ */
8
+ /**
9
+ * @zh 玩家输入
10
+ * @en Player input
11
+ */
12
+ export interface PlayerInput {
13
+ /**
14
+ * @zh 帧序号
15
+ * @en Frame number
16
+ */
17
+ frame: number;
18
+ /**
19
+ * @zh 移动方向
20
+ * @en Move direction
21
+ */
22
+ moveDir?: {
23
+ x: number;
24
+ y: number;
25
+ };
26
+ /**
27
+ * @zh 动作列表
28
+ * @en Action list
29
+ */
30
+ actions?: string[];
31
+ }
32
+ /**
33
+ * @zh 实体同步状态
34
+ * @en Entity sync state
35
+ */
36
+ export interface EntitySyncState {
37
+ netId: number;
38
+ pos?: {
39
+ x: number;
40
+ y: number;
41
+ };
42
+ rot?: number;
43
+ }
44
+ /**
45
+ * @zh 同步消息
46
+ * @en Sync message
47
+ */
48
+ export interface SyncData {
49
+ /**
50
+ * @zh 服务器帧号
51
+ * @en Server frame number
52
+ */
53
+ frame: number;
54
+ /**
55
+ * @zh 实体状态列表
56
+ * @en Entity state list
57
+ */
58
+ entities: EntitySyncState[];
59
+ }
60
+ /**
61
+ * @zh 生成消息
62
+ * @en Spawn message
63
+ */
64
+ export interface SpawnData {
65
+ netId: number;
66
+ ownerId: number;
67
+ prefab: string;
68
+ pos: {
69
+ x: number;
70
+ y: number;
71
+ };
72
+ rot?: number;
73
+ }
74
+ /**
75
+ * @zh 销毁消息
76
+ * @en Despawn message
77
+ */
78
+ export interface DespawnData {
79
+ netId: number;
80
+ }
81
+ /**
82
+ * @zh 加入房间请求
83
+ * @en Join room request
84
+ */
85
+ export interface JoinRequest {
86
+ playerName: string;
87
+ roomId?: string;
88
+ }
89
+ /**
90
+ * @zh 加入房间响应
91
+ * @en Join room response
92
+ */
93
+ export interface JoinResponse {
94
+ playerId: number;
95
+ roomId: string;
96
+ }
97
+ /**
98
+ * @zh 默认游戏网络协议
99
+ * @en Default game network protocol
100
+ *
101
+ * @example
102
+ * ```typescript
103
+ * // 使用默认协议
104
+ * const service = new NetworkService(gameProtocol)
105
+ *
106
+ * // 或者扩展协议
107
+ * const customProtocol = rpc.define({
108
+ * api: {
109
+ * ...gameProtocol.api,
110
+ * customApi: rpc.api<CustomInput, CustomOutput>(),
111
+ * },
112
+ * msg: {
113
+ * ...gameProtocol.msg,
114
+ * customMsg: rpc.msg<CustomData>(),
115
+ * },
116
+ * })
117
+ * ```
118
+ */
119
+ export declare const gameProtocol: {
120
+ api: {
121
+ /**
122
+ * @zh 加入房间
123
+ * @en Join room
124
+ */
125
+ join: import("@esengine/rpc").ApiDef<JoinRequest, JoinResponse>;
126
+ /**
127
+ * @zh 离开房间
128
+ * @en Leave room
129
+ */
130
+ leave: import("@esengine/rpc").ApiDef<void, void>;
131
+ };
132
+ msg: {
133
+ /**
134
+ * @zh 玩家输入
135
+ * @en Player input
136
+ */
137
+ input: import("@esengine/rpc").MsgDef<PlayerInput>;
138
+ /**
139
+ * @zh 状态同步
140
+ * @en State sync
141
+ */
142
+ sync: import("@esengine/rpc").MsgDef<SyncData>;
143
+ /**
144
+ * @zh 实体生成
145
+ * @en Entity spawn
146
+ */
147
+ spawn: import("@esengine/rpc").MsgDef<SpawnData>;
148
+ /**
149
+ * @zh 实体销毁
150
+ * @en Entity despawn
151
+ */
152
+ despawn: import("@esengine/rpc").MsgDef<DespawnData>;
153
+ };
154
+ };
155
+ /**
156
+ * @zh 游戏协议类型
157
+ * @en Game protocol type
158
+ */
159
+ export type GameProtocol = typeof gameProtocol;
160
+ //# sourceMappingURL=protocol.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAQH;;;GAGG;AACH,MAAM,WAAW,WAAW;IACxB;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAA;IAEb;;;OAGG;IACH,OAAO,CAAC,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IAElC;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;CACrB;AAED;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC5B,KAAK,EAAE,MAAM,CAAA;IACb,GAAG,CAAC,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IAC9B,GAAG,CAAC,EAAE,MAAM,CAAA;CACf;AAED;;;GAGG;AACH,MAAM,WAAW,QAAQ;IACrB;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAA;IAEb;;;OAGG;IACH,QAAQ,EAAE,eAAe,EAAE,CAAA;CAC9B;AAED;;;GAGG;AACH,MAAM,WAAW,SAAS;IACtB,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,GAAG,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAA;CACf;AAED;;;GAGG;AACH,MAAM,WAAW,WAAW;IACxB,KAAK,EAAE,MAAM,CAAA;CAChB;AAMD;;;GAGG;AACH,MAAM,WAAW,WAAW;IACxB,UAAU,EAAE,MAAM,CAAA;IAClB,MAAM,CAAC,EAAE,MAAM,CAAA;CAClB;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IACzB,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;CACjB;AAMD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,YAAY;;QAEjB;;;WAGG;;QAGH;;;WAGG;;;;QAIH;;;WAGG;;QAGH;;;WAGG;;QAGH;;;WAGG;;QAGH;;;WAGG;;;CAGT,CAAA;AAEF;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,OAAO,YAAY,CAAA"}