UNPKG

@esengine/network-shared

Version:

ECS Framework网络层 - 共享组件和协议

1 lines 424 kB
{"version":3,"file":"index.mjs","sources":["../bin/types/NetworkTypes.js","../bin/types/TransportTypes.js","../bin/types/RpcTypes.js","../bin/protocols/MessageManager.js","../bin/events/NetworkEvents.js","../bin/transport/ErrorHandler.js","../bin/components/NetworkIdentity.js","../bin/transport/HeartbeatManager.js","../bin/serialization/JSONSerializer.js","../bin/serialization/MessageCompressor.js","../bin/serialization/SyncVarSerializer.js","../bin/decorators/SyncVar.js","../bin/decorators/RpcDecorators.js","../bin/utils/EventEmitter.js","../bin/rpc/RpcMetadataManager.js","../bin/rpc/RpcCallHandler.js","../bin/rpc/RpcCallProxy.js","../bin/rpc/RpcReliabilityManager.js","../bin/sync/SyncVarManager.js","../bin/sync/DeltaSync.js","../bin/monitoring/BandwidthMonitor.js","../bin/reconnection/ReconnectionManager.js","../bin/persistence/DataPersistence.js","../bin/state/StateSnapshot.js","../bin/serialization/AdvancedSerializer.js"],"sourcesContent":["/**\n * 网络层核心类型定义\n */\n/**\n * 网络消息类型枚举\n */\nexport var MessageType;\n(function (MessageType) {\n // 连接管理\n MessageType[\"CONNECT\"] = \"connect\";\n MessageType[\"DISCONNECT\"] = \"disconnect\";\n MessageType[\"HEARTBEAT\"] = \"heartbeat\";\n // 数据同步\n MessageType[\"SYNC_VAR\"] = \"sync_var\";\n MessageType[\"SYNC_BATCH\"] = \"sync_batch\";\n MessageType[\"SYNC_SNAPSHOT\"] = \"sync_snapshot\";\n // RPC调用\n MessageType[\"RPC_CALL\"] = \"rpc_call\";\n MessageType[\"RPC_RESPONSE\"] = \"rpc_response\";\n // 实体管理\n MessageType[\"ENTITY_CREATE\"] = \"entity_create\";\n MessageType[\"ENTITY_DESTROY\"] = \"entity_destroy\";\n MessageType[\"ENTITY_UPDATE\"] = \"entity_update\";\n // 房间管理\n MessageType[\"JOIN_ROOM\"] = \"join_room\";\n MessageType[\"LEAVE_ROOM\"] = \"leave_room\";\n MessageType[\"ROOM_STATE\"] = \"room_state\";\n // 游戏事件\n MessageType[\"GAME_EVENT\"] = \"game_event\";\n // 系统消息\n MessageType[\"ERROR\"] = \"error\";\n MessageType[\"WARNING\"] = \"warning\";\n MessageType[\"INFO\"] = \"info\";\n})(MessageType || (MessageType = {}));\n/**\n * 同步权限类型\n */\nexport var AuthorityType;\n(function (AuthorityType) {\n /** 服务端权限 */\n AuthorityType[\"Server\"] = \"server\";\n /** 客户端权限 */\n AuthorityType[\"Client\"] = \"client\";\n /** 共享权限 */\n AuthorityType[\"Shared\"] = \"shared\";\n})(AuthorityType || (AuthorityType = {}));\n/**\n * 网络作用域\n */\nexport var NetworkScope;\n(function (NetworkScope) {\n /** 全局可见 */\n NetworkScope[\"Global\"] = \"global\";\n /** 房间内可见 */\n NetworkScope[\"Room\"] = \"room\";\n /** 仅拥有者可见 */\n NetworkScope[\"Owner\"] = \"owner\";\n /** 附近玩家可见 */\n NetworkScope[\"Nearby\"] = \"nearby\";\n /** 自定义作用域 */\n NetworkScope[\"Custom\"] = \"custom\";\n})(NetworkScope || (NetworkScope = {}));\n/**\n * 同步模式\n */\nexport var SyncMode;\n(function (SyncMode) {\n /** 同步给所有客户端 */\n SyncMode[\"All\"] = \"all\";\n /** 只同步给拥有者 */\n SyncMode[\"Owner\"] = \"owner\";\n /** 同步给除拥有者外的客户端 */\n SyncMode[\"Others\"] = \"others\";\n /** 同步给附近的客户端 */\n SyncMode[\"Nearby\"] = \"nearby\";\n /** 自定义同步逻辑 */\n SyncMode[\"Custom\"] = \"custom\";\n})(SyncMode || (SyncMode = {}));\n/**\n * RPC目标\n */\nexport var RpcTarget;\n(function (RpcTarget) {\n /** 服务端 */\n RpcTarget[\"Server\"] = \"server\";\n /** 客户端 */\n RpcTarget[\"Client\"] = \"client\";\n /** 所有客户端 */\n RpcTarget[\"All\"] = \"all\";\n /** 除发送者外的客户端 */\n RpcTarget[\"Others\"] = \"others\";\n /** 拥有者客户端 */\n RpcTarget[\"Owner\"] = \"owner\";\n /** 附近的客户端 */\n RpcTarget[\"Nearby\"] = \"nearby\";\n})(RpcTarget || (RpcTarget = {}));\n/**\n * 房间状态\n */\nexport var RoomState;\n(function (RoomState) {\n /** 等待中 */\n RoomState[\"Waiting\"] = \"waiting\";\n /** 游戏中 */\n RoomState[\"Playing\"] = \"playing\";\n /** 已暂停 */\n RoomState[\"Paused\"] = \"paused\";\n /** 已结束 */\n RoomState[\"Finished\"] = \"finished\";\n})(RoomState || (RoomState = {}));\n/**\n * 网络错误类型\n */\nexport var NetworkErrorType;\n(function (NetworkErrorType) {\n NetworkErrorType[\"CONNECTION_FAILED\"] = \"connection_failed\";\n NetworkErrorType[\"CONNECTION_LOST\"] = \"connection_lost\";\n NetworkErrorType[\"AUTHENTICATION_FAILED\"] = \"authentication_failed\";\n NetworkErrorType[\"PERMISSION_DENIED\"] = \"permission_denied\";\n NetworkErrorType[\"RATE_LIMITED\"] = \"rate_limited\";\n NetworkErrorType[\"INVALID_MESSAGE\"] = \"invalid_message\";\n NetworkErrorType[\"TIMEOUT\"] = \"timeout\";\n NetworkErrorType[\"UNKNOWN\"] = \"unknown\";\n})(NetworkErrorType || (NetworkErrorType = {}));\n//# sourceMappingURL=NetworkTypes.js.map","/**\n * 传输层接口定义\n */\n/**\n * 连接状态\n */\nexport var ConnectionState;\n(function (ConnectionState) {\n /** 断开连接 */\n ConnectionState[\"Disconnected\"] = \"disconnected\";\n /** 连接中 */\n ConnectionState[\"Connecting\"] = \"connecting\";\n /** 已连接 */\n ConnectionState[\"Connected\"] = \"connected\";\n /** 重连中 */\n ConnectionState[\"Reconnecting\"] = \"reconnecting\";\n /** 连接失败 */\n ConnectionState[\"Failed\"] = \"failed\";\n})(ConnectionState || (ConnectionState = {}));\n//# sourceMappingURL=TransportTypes.js.map","/**\n * RPC错误类型\n */\nexport var RpcErrorType;\n(function (RpcErrorType) {\n /** 方法不存在 */\n RpcErrorType[\"METHOD_NOT_FOUND\"] = \"method_not_found\";\n /** 参数无效 */\n RpcErrorType[\"INVALID_ARGUMENTS\"] = \"invalid_arguments\";\n /** 权限不足 */\n RpcErrorType[\"PERMISSION_DENIED\"] = \"permission_denied\";\n /** 调用超时 */\n RpcErrorType[\"TIMEOUT\"] = \"timeout\";\n /** 速率限制 */\n RpcErrorType[\"RATE_LIMITED\"] = \"rate_limited\";\n /** 网络错误 */\n RpcErrorType[\"NETWORK_ERROR\"] = \"network_error\";\n /** 服务端错误 */\n RpcErrorType[\"SERVER_ERROR\"] = \"server_error\";\n /** 客户端错误 */\n RpcErrorType[\"CLIENT_ERROR\"] = \"client_error\";\n /** 未知错误 */\n RpcErrorType[\"UNKNOWN\"] = \"unknown\";\n})(RpcErrorType || (RpcErrorType = {}));\n/**\n * RPC调用状态\n */\nexport var RpcCallStatus;\n(function (RpcCallStatus) {\n /** 待发送 */\n RpcCallStatus[\"PENDING\"] = \"pending\";\n /** 已发送 */\n RpcCallStatus[\"SENT\"] = \"sent\";\n /** 处理中 */\n RpcCallStatus[\"PROCESSING\"] = \"processing\";\n /** 已完成 */\n RpcCallStatus[\"COMPLETED\"] = \"completed\";\n /** 已失败 */\n RpcCallStatus[\"FAILED\"] = \"failed\";\n /** 已超时 */\n RpcCallStatus[\"TIMEOUT\"] = \"timeout\";\n /** 已取消 */\n RpcCallStatus[\"CANCELLED\"] = \"cancelled\";\n})(RpcCallStatus || (RpcCallStatus = {}));\n//# sourceMappingURL=RpcTypes.js.map","/**\n * 消息管理器\n * 负责消息ID生成、时间戳管理和消息验证\n */\nimport { createLogger } from '@esengine/ecs-framework';\nimport { MessageType } from '../types/NetworkTypes';\n/**\n * 消息ID生成器类型\n */\nexport var MessageIdGeneratorType;\n(function (MessageIdGeneratorType) {\n MessageIdGeneratorType[\"UUID\"] = \"uuid\";\n MessageIdGeneratorType[\"SNOWFLAKE\"] = \"snowflake\";\n MessageIdGeneratorType[\"SEQUENTIAL\"] = \"sequential\";\n MessageIdGeneratorType[\"TIMESTAMP\"] = \"timestamp\";\n})(MessageIdGeneratorType || (MessageIdGeneratorType = {}));\n/**\n * Snowflake ID生成器\n */\nclass SnowflakeIdGenerator {\n constructor(workerId = 1, datacenterId = 1) {\n this.sequence = 0;\n this.lastTimestamp = -1;\n this.workerId = workerId & ((1 << SnowflakeIdGenerator.WORKER_ID_BITS) - 1);\n this.datacenterId = datacenterId & ((1 << SnowflakeIdGenerator.DATACENTER_ID_BITS) - 1);\n }\n generate() {\n let timestamp = Date.now();\n if (timestamp < this.lastTimestamp) {\n throw new Error('时钟回拨,无法生成ID');\n }\n if (timestamp === this.lastTimestamp) {\n this.sequence = (this.sequence + 1) & ((1 << SnowflakeIdGenerator.SEQUENCE_BITS) - 1);\n if (this.sequence === 0) {\n // 等待下一毫秒\n while (timestamp <= this.lastTimestamp) {\n timestamp = Date.now();\n }\n }\n }\n else {\n this.sequence = 0;\n }\n this.lastTimestamp = timestamp;\n const id = ((timestamp - SnowflakeIdGenerator.EPOCH) << 22) |\n (this.datacenterId << 17) |\n (this.workerId << 12) |\n this.sequence;\n return id.toString();\n }\n}\nSnowflakeIdGenerator.EPOCH = 1640995200000; // 2022-01-01 00:00:00 UTC\nSnowflakeIdGenerator.WORKER_ID_BITS = 5;\nSnowflakeIdGenerator.DATACENTER_ID_BITS = 5;\nSnowflakeIdGenerator.SEQUENCE_BITS = 12;\n/**\n * 消息管理器\n */\nexport class MessageManager {\n /**\n * 构造函数\n */\n constructor(config = {}) {\n this.logger = createLogger('MessageManager');\n // ID生成器\n this.sequentialId = 0;\n // 消息去重和排序\n this.recentMessageIds = new Set();\n this.pendingMessages = new Map();\n this.messageSequence = new Map();\n this.config = {\n idGenerator: MessageIdGeneratorType.UUID,\n enableTimestampValidation: true,\n maxTimestampDrift: 60000, // 1分钟\n enableMessageDeduplication: true,\n deduplicationWindowMs: 300000, // 5分钟\n enableMessageOrdering: false,\n orderingWindowMs: 10000, // 10秒\n maxPendingMessages: 1000,\n ...config\n };\n this.stats = {\n totalGenerated: 0,\n totalValidated: 0,\n validMessages: 0,\n invalidMessages: 0,\n duplicateMessages: 0,\n outOfOrderMessages: 0,\n timestampErrors: 0\n };\n this.snowflakeGenerator = new SnowflakeIdGenerator();\n this.startCleanupTimer();\n }\n /**\n * 生成消息ID\n */\n generateMessageId() {\n this.stats.totalGenerated++;\n switch (this.config.idGenerator) {\n case MessageIdGeneratorType.UUID:\n return this.generateUUID();\n case MessageIdGeneratorType.SNOWFLAKE:\n return this.snowflakeGenerator.generate();\n case MessageIdGeneratorType.SEQUENTIAL:\n return (++this.sequentialId).toString();\n case MessageIdGeneratorType.TIMESTAMP:\n return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n default:\n return this.generateUUID();\n }\n }\n /**\n * 创建网络消息\n */\n createMessage(type, data, senderId, options = {}) {\n const message = {\n type,\n messageId: this.generateMessageId(),\n timestamp: options.timestamp || Date.now(),\n senderId,\n data,\n reliable: options.reliable,\n priority: options.priority\n };\n return message;\n }\n /**\n * 验证消息\n */\n validateMessage(message, senderId) {\n this.stats.totalValidated++;\n const errors = [];\n const warnings = [];\n // 基础字段验证\n if (!message.messageId) {\n errors.push('消息ID不能为空');\n }\n if (!message.type) {\n errors.push('消息类型不能为空');\n }\n else if (!Object.values(MessageType).includes(message.type)) {\n errors.push(`无效的消息类型: ${message.type}`);\n }\n if (!message.timestamp) {\n errors.push('时间戳不能为空');\n }\n if (!message.senderId) {\n errors.push('发送者ID不能为空');\n }\n // 发送者验证\n if (senderId && message.senderId !== senderId) {\n errors.push('消息发送者ID不匹配');\n }\n // 时间戳验证\n if (this.config.enableTimestampValidation && message.timestamp) {\n const now = Date.now();\n const drift = Math.abs(now - message.timestamp);\n if (drift > this.config.maxTimestampDrift) {\n errors.push(`时间戳偏移过大: ${drift}ms > ${this.config.maxTimestampDrift}ms`);\n this.stats.timestampErrors++;\n }\n if (message.timestamp > now + 10000) { // 未来10秒以上\n warnings.push('消息时间戳来自未来');\n }\n }\n // 消息去重验证\n if (this.config.enableMessageDeduplication) {\n if (this.recentMessageIds.has(message.messageId)) {\n errors.push('重复的消息ID');\n this.stats.duplicateMessages++;\n }\n else {\n this.recentMessageIds.add(message.messageId);\n }\n }\n const isValid = errors.length === 0;\n if (isValid) {\n this.stats.validMessages++;\n }\n else {\n this.stats.invalidMessages++;\n }\n return {\n isValid,\n errors,\n warnings\n };\n }\n /**\n * 处理消息排序\n */\n processMessageOrdering(message) {\n if (!this.config.enableMessageOrdering) {\n return [message];\n }\n const senderId = message.senderId;\n const currentSequence = this.messageSequence.get(senderId) || 0;\n // 检查消息是否按顺序到达\n const messageTimestamp = message.timestamp;\n const expectedSequence = currentSequence + 1;\n // 简单的时间戳排序逻辑\n if (messageTimestamp >= expectedSequence) {\n // 消息按顺序到达\n this.messageSequence.set(senderId, messageTimestamp);\n return this.flushPendingMessages(senderId).concat([message]);\n }\n else {\n // 消息乱序,暂存\n this.pendingMessages.set(message.messageId, message);\n this.stats.outOfOrderMessages++;\n // 检查是否超出最大待处理数量\n if (this.pendingMessages.size > this.config.maxPendingMessages) {\n this.logger.warn('待处理消息数量过多,清理旧消息');\n this.cleanupOldPendingMessages();\n }\n return [];\n }\n }\n /**\n * 获取统计信息\n */\n getStats() {\n return { ...this.stats };\n }\n /**\n * 重置统计信息\n */\n resetStats() {\n this.stats = {\n totalGenerated: 0,\n totalValidated: 0,\n validMessages: 0,\n invalidMessages: 0,\n duplicateMessages: 0,\n outOfOrderMessages: 0,\n timestampErrors: 0\n };\n }\n /**\n * 更新配置\n */\n updateConfig(newConfig) {\n const oldConfig = { ...this.config };\n Object.assign(this.config, newConfig);\n // 如果去重配置改变,清理相关数据\n if (!this.config.enableMessageDeduplication && oldConfig.enableMessageDeduplication) {\n this.recentMessageIds.clear();\n }\n // 如果排序配置改变,清理相关数据\n if (!this.config.enableMessageOrdering && oldConfig.enableMessageOrdering) {\n this.pendingMessages.clear();\n this.messageSequence.clear();\n }\n this.logger.info('消息管理器配置已更新:', newConfig);\n }\n /**\n * 销毁管理器\n */\n destroy() {\n if (this.cleanupTimer) {\n clearInterval(this.cleanupTimer);\n this.cleanupTimer = undefined;\n }\n this.recentMessageIds.clear();\n this.pendingMessages.clear();\n this.messageSequence.clear();\n }\n /**\n * 生成UUID\n */\n generateUUID() {\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {\n const r = Math.random() * 16 | 0;\n const v = c === 'x' ? r : (r & 0x3 | 0x8);\n return v.toString(16);\n });\n }\n /**\n * 刷新待处理消息\n */\n flushPendingMessages(senderId) {\n const flushedMessages = [];\n const messagesToRemove = [];\n for (const [messageId, message] of this.pendingMessages) {\n if (message.senderId === senderId) {\n flushedMessages.push(message);\n messagesToRemove.push(messageId);\n }\n }\n // 移除已处理的消息\n messagesToRemove.forEach(id => this.pendingMessages.delete(id));\n // 按时间戳排序\n flushedMessages.sort((a, b) => a.timestamp - b.timestamp);\n return flushedMessages;\n }\n /**\n * 清理过期的待处理消息\n */\n cleanupOldPendingMessages() {\n const now = Date.now();\n const messagesToRemove = [];\n for (const [messageId, message] of this.pendingMessages) {\n if (now - message.timestamp > this.config.orderingWindowMs) {\n messagesToRemove.push(messageId);\n }\n }\n messagesToRemove.forEach(id => this.pendingMessages.delete(id));\n if (messagesToRemove.length > 0) {\n this.logger.debug(`清理了 ${messagesToRemove.length} 个过期的待处理消息`);\n }\n }\n /**\n * 启动清理定时器\n */\n startCleanupTimer() {\n this.cleanupTimer = setInterval(() => {\n this.performCleanup();\n }, 60000); // 每分钟清理一次\n }\n /**\n * 执行清理操作\n */\n performCleanup() {\n const now = Date.now();\n // 清理过期的消息ID(用于去重)\n if (this.config.enableMessageDeduplication) {\n // 由于Set没有时间戳,我们定期清理所有ID\n // 这是一个简化实现,实际项目中可以使用更复杂的数据结构\n if (this.recentMessageIds.size > 10000) {\n this.recentMessageIds.clear();\n this.logger.debug('清理了过期的消息ID缓存');\n }\n }\n // 清理过期的待处理消息\n if (this.config.enableMessageOrdering) {\n this.cleanupOldPendingMessages();\n }\n }\n /**\n * 获取消息处理报告\n */\n getProcessingReport() {\n const totalProcessed = this.stats.validMessages + this.stats.invalidMessages;\n const validRate = totalProcessed > 0 ? (this.stats.validMessages / totalProcessed) * 100 : 0;\n const duplicateRate = totalProcessed > 0 ? (this.stats.duplicateMessages / totalProcessed) * 100 : 0;\n return {\n stats: this.getStats(),\n validationRate: validRate,\n duplicateRate: duplicateRate,\n pendingMessagesCount: this.pendingMessages.size,\n cachedMessageIdsCount: this.recentMessageIds.size,\n recommendation: this.generateRecommendation(validRate, duplicateRate)\n };\n }\n /**\n * 生成优化建议\n */\n generateRecommendation(validRate, duplicateRate) {\n if (validRate < 90) {\n return '消息验证失败率较高,建议检查消息格式和发送逻辑';\n }\n else if (duplicateRate > 5) {\n return '重复消息较多,建议检查客户端重发逻辑或调整去重窗口';\n }\n else if (this.pendingMessages.size > this.config.maxPendingMessages * 0.8) {\n return '待处理消息过多,建议优化网络或调整排序窗口';\n }\n else {\n return '消息处理正常';\n }\n }\n /**\n * 批量验证消息\n */\n validateMessageBatch(messages, senderId) {\n return messages.map(message => this.validateMessage(message, senderId));\n }\n /**\n * 获取消息年龄(毫秒)\n */\n getMessageAge(message) {\n return Date.now() - message.timestamp;\n }\n /**\n * 检查消息是否过期\n */\n isMessageExpired(message, maxAge = 300000) {\n return this.getMessageAge(message) > maxAge;\n }\n}\n//# sourceMappingURL=MessageManager.js.map","/**\n * 网络事件类型枚举\n * 定义网络层中的所有事件类型\n */\nexport var NetworkEventType;\n(function (NetworkEventType) {\n // 连接相关事件\n NetworkEventType[\"CONNECTION_ESTABLISHED\"] = \"network:connection:established\";\n NetworkEventType[\"CONNECTION_LOST\"] = \"network:connection:lost\";\n NetworkEventType[\"CONNECTION_ERROR\"] = \"network:connection:error\";\n NetworkEventType[\"CONNECTION_TIMEOUT\"] = \"network:connection:timeout\";\n NetworkEventType[\"RECONNECTION_STARTED\"] = \"network:reconnection:started\";\n NetworkEventType[\"RECONNECTION_SUCCEEDED\"] = \"network:reconnection:succeeded\";\n NetworkEventType[\"RECONNECTION_FAILED\"] = \"network:reconnection:failed\";\n // 网络身份相关事件\n NetworkEventType[\"IDENTITY_CREATED\"] = \"network:identity:created\";\n NetworkEventType[\"IDENTITY_DESTROYED\"] = \"network:identity:destroyed\";\n NetworkEventType[\"IDENTITY_OWNER_CHANGED\"] = \"network:identity:owner:changed\";\n NetworkEventType[\"IDENTITY_AUTHORITY_CHANGED\"] = \"network:identity:authority:changed\";\n NetworkEventType[\"IDENTITY_SYNC_ENABLED\"] = \"network:identity:sync:enabled\";\n NetworkEventType[\"IDENTITY_SYNC_DISABLED\"] = \"network:identity:sync:disabled\";\n NetworkEventType[\"IDENTITY_PROPERTY_CHANGED\"] = \"network:identity:property:changed\";\n NetworkEventType[\"IDENTITY_VISIBLE_CHANGED\"] = \"network:identity:visible:changed\";\n // 同步相关事件\n NetworkEventType[\"SYNC_STARTED\"] = \"network:sync:started\";\n NetworkEventType[\"SYNC_COMPLETED\"] = \"network:sync:completed\";\n NetworkEventType[\"SYNC_FAILED\"] = \"network:sync:failed\";\n NetworkEventType[\"SYNC_RATE_CHANGED\"] = \"network:sync:rate:changed\";\n NetworkEventType[\"SYNC_PRIORITY_CHANGED\"] = \"network:sync:priority:changed\";\n // RPC相关事件\n NetworkEventType[\"RPC_CALL_SENT\"] = \"network:rpc:call:sent\";\n NetworkEventType[\"RPC_CALL_RECEIVED\"] = \"network:rpc:call:received\";\n NetworkEventType[\"RPC_RESPONSE_SENT\"] = \"network:rpc:response:sent\";\n NetworkEventType[\"RPC_RESPONSE_RECEIVED\"] = \"network:rpc:response:received\";\n NetworkEventType[\"RPC_ERROR\"] = \"network:rpc:error\";\n NetworkEventType[\"RPC_TIMEOUT\"] = \"network:rpc:timeout\";\n // 消息相关事件\n NetworkEventType[\"MESSAGE_SENT\"] = \"network:message:sent\";\n NetworkEventType[\"MESSAGE_RECEIVED\"] = \"network:message:received\";\n NetworkEventType[\"MESSAGE_QUEUED\"] = \"network:message:queued\";\n NetworkEventType[\"MESSAGE_DROPPED\"] = \"network:message:dropped\";\n NetworkEventType[\"MESSAGE_RETRY\"] = \"network:message:retry\";\n NetworkEventType[\"MESSAGE_ACKNOWLEDGED\"] = \"network:message:acknowledged\";\n // 房间相关事件\n NetworkEventType[\"ROOM_JOINED\"] = \"network:room:joined\";\n NetworkEventType[\"ROOM_LEFT\"] = \"network:room:left\";\n NetworkEventType[\"ROOM_CREATED\"] = \"network:room:created\";\n NetworkEventType[\"ROOM_DESTROYED\"] = \"network:room:destroyed\";\n NetworkEventType[\"ROOM_PLAYER_JOINED\"] = \"network:room:player:joined\";\n NetworkEventType[\"ROOM_PLAYER_LEFT\"] = \"network:room:player:left\";\n // 客户端相关事件\n NetworkEventType[\"CLIENT_CONNECTED\"] = \"network:client:connected\";\n NetworkEventType[\"CLIENT_DISCONNECTED\"] = \"network:client:disconnected\";\n NetworkEventType[\"CLIENT_AUTHENTICATED\"] = \"network:client:authenticated\";\n NetworkEventType[\"CLIENT_KICKED\"] = \"network:client:kicked\";\n NetworkEventType[\"CLIENT_TIMEOUT\"] = \"network:client:timeout\";\n // 服务器相关事件\n NetworkEventType[\"SERVER_STARTED\"] = \"network:server:started\";\n NetworkEventType[\"SERVER_STOPPED\"] = \"network:server:stopped\";\n NetworkEventType[\"SERVER_ERROR\"] = \"network:server:error\";\n NetworkEventType[\"SERVER_OVERLOADED\"] = \"network:server:overloaded\";\n // 数据相关事件\n NetworkEventType[\"DATA_SYNCHRONIZED\"] = \"network:data:synchronized\";\n NetworkEventType[\"DATA_CONFLICT\"] = \"network:data:conflict\";\n NetworkEventType[\"DATA_CORRUPTED\"] = \"network:data:corrupted\";\n NetworkEventType[\"DATA_VALIDATED\"] = \"network:data:validated\";\n // 性能相关事件\n NetworkEventType[\"BANDWIDTH_WARNING\"] = \"network:bandwidth:warning\";\n NetworkEventType[\"LATENCY_HIGH\"] = \"network:latency:high\";\n NetworkEventType[\"PACKET_LOSS_DETECTED\"] = \"network:packet:loss:detected\";\n NetworkEventType[\"PERFORMANCE_DEGRADED\"] = \"network:performance:degraded\";\n})(NetworkEventType || (NetworkEventType = {}));\n/**\n * 网络事件优先级\n */\nexport var NetworkEventPriority;\n(function (NetworkEventPriority) {\n NetworkEventPriority[NetworkEventPriority[\"LOW\"] = 10] = \"LOW\";\n NetworkEventPriority[NetworkEventPriority[\"NORMAL\"] = 20] = \"NORMAL\";\n NetworkEventPriority[NetworkEventPriority[\"HIGH\"] = 30] = \"HIGH\";\n NetworkEventPriority[NetworkEventPriority[\"CRITICAL\"] = 40] = \"CRITICAL\";\n NetworkEventPriority[NetworkEventPriority[\"EMERGENCY\"] = 50] = \"EMERGENCY\";\n})(NetworkEventPriority || (NetworkEventPriority = {}));\n/**\n * 网络事件工具类\n */\nexport class NetworkEventUtils {\n /**\n * 创建网络身份事件数据\n */\n static createIdentityEventData(networkId, ownerId, oldValue, newValue) {\n return {\n timestamp: Date.now(),\n networkId,\n ownerId,\n oldValue,\n newValue\n };\n }\n /**\n * 创建RPC事件数据\n */\n static createRpcEventData(rpcId, methodName, clientId, parameters, result, error) {\n return {\n timestamp: Date.now(),\n clientId,\n rpcId,\n methodName,\n parameters,\n result,\n error\n };\n }\n /**\n * 创建消息事件数据\n */\n static createMessageEventData(messageId, messageType, payload, reliable = true, clientId) {\n const size = JSON.stringify(payload).length;\n return {\n timestamp: Date.now(),\n clientId,\n messageId,\n messageType,\n payload,\n reliable,\n size\n };\n }\n /**\n * 创建连接事件数据\n */\n static createConnectionEventData(clientId, address, reason, reconnectAttempt) {\n return {\n timestamp: Date.now(),\n clientId,\n address,\n reason,\n reconnectAttempt\n };\n }\n /**\n * 创建房间事件数据\n */\n static createRoomEventData(roomId, playerId, playerCount, maxPlayers) {\n return {\n timestamp: Date.now(),\n roomId,\n playerId,\n playerCount,\n maxPlayers\n };\n }\n /**\n * 创建性能事件数据\n */\n static createPerformanceEventData(metric, value, threshold, duration, clientId) {\n return {\n timestamp: Date.now(),\n clientId,\n metric,\n value,\n threshold,\n duration\n };\n }\n}\n//# sourceMappingURL=NetworkEvents.js.map","/**\n * 网络错误处理器\n * 提供统一的错误处理、分类和恢复策略\n */\nimport { createLogger } from '@esengine/ecs-framework';\nimport { NetworkErrorType } from '../types/NetworkTypes';\n/**\n * 错误严重级别\n */\nexport var ErrorSeverity;\n(function (ErrorSeverity) {\n ErrorSeverity[\"Low\"] = \"low\";\n ErrorSeverity[\"Medium\"] = \"medium\";\n ErrorSeverity[\"High\"] = \"high\";\n ErrorSeverity[\"Critical\"] = \"critical\"; // 严重错误,需要立即处理\n})(ErrorSeverity || (ErrorSeverity = {}));\n/**\n * 错误恢复策略\n */\nexport var RecoveryStrategy;\n(function (RecoveryStrategy) {\n RecoveryStrategy[\"Ignore\"] = \"ignore\";\n RecoveryStrategy[\"Retry\"] = \"retry\";\n RecoveryStrategy[\"Reconnect\"] = \"reconnect\";\n RecoveryStrategy[\"Restart\"] = \"restart\";\n RecoveryStrategy[\"Escalate\"] = \"escalate\"; // 上报错误\n})(RecoveryStrategy || (RecoveryStrategy = {}));\n/**\n * 网络错误处理器\n */\nexport class ErrorHandler {\n /**\n * 构造函数\n */\n constructor(config = {}) {\n this.logger = createLogger('ErrorHandler');\n this.eventHandlers = {};\n // 错误恢复状态\n this.retryAttempts = new Map();\n this.pendingRecoveries = new Set();\n // 错误分类规则\n this.severityRules = new Map();\n this.recoveryRules = new Map();\n this.config = {\n maxRetryAttempts: 3,\n retryDelay: 1000,\n enableAutoRecovery: true,\n enableErrorReporting: false,\n ...config\n };\n this.stats = {\n totalErrors: 0,\n errorsByType: {},\n errorsBySeverity: {},\n recoveredErrors: 0,\n unrecoveredErrors: 0\n };\n this.initializeDefaultRules();\n }\n /**\n * 处理错误\n */\n handleError(error, context) {\n const networkError = this.normalizeError(error, context);\n const severity = this.classifyErrorSeverity(networkError);\n // 更新统计\n this.updateStats(networkError, severity);\n this.logger.error(`网络错误 [${severity}]: ${networkError.message}`, {\n type: networkError.type,\n code: networkError.code,\n details: networkError.details,\n context\n });\n // 触发错误事件\n this.eventHandlers.errorOccurred?.(networkError, severity);\n // 处理严重错误\n if (severity === ErrorSeverity.Critical) {\n this.eventHandlers.criticalError?.(networkError);\n }\n // 尝试自动恢复\n if (this.config.enableAutoRecovery) {\n this.attemptRecovery(networkError, severity);\n }\n // 错误报告\n if (this.config.enableErrorReporting) {\n this.reportError(networkError, severity);\n }\n }\n /**\n * 设置错误分类规则\n */\n setErrorSeverityRule(errorType, severity) {\n this.severityRules.set(errorType, severity);\n }\n /**\n * 设置错误恢复策略\n */\n setRecoveryStrategy(errorType, strategy) {\n this.recoveryRules.set(errorType, strategy);\n }\n /**\n * 获取错误统计\n */\n getStats() {\n return { ...this.stats };\n }\n /**\n * 重置统计信息\n */\n resetStats() {\n this.stats = {\n totalErrors: 0,\n errorsByType: {},\n errorsBySeverity: {},\n recoveredErrors: 0,\n unrecoveredErrors: 0\n };\n this.retryAttempts.clear();\n this.pendingRecoveries.clear();\n }\n /**\n * 设置事件处理器\n */\n on(event, handler) {\n this.eventHandlers[event] = handler;\n }\n /**\n * 移除事件处理器\n */\n off(event) {\n delete this.eventHandlers[event];\n }\n /**\n * 更新配置\n */\n updateConfig(newConfig) {\n Object.assign(this.config, newConfig);\n this.logger.info('错误处理器配置已更新:', newConfig);\n }\n /**\n * 手动标记错误已恢复\n */\n markErrorRecovered(errorId) {\n this.retryAttempts.delete(errorId);\n this.pendingRecoveries.delete(errorId);\n this.stats.recoveredErrors++;\n }\n /**\n * 检查错误是否可恢复\n */\n isRecoverable(errorType) {\n const strategy = this.recoveryRules.get(errorType);\n return strategy !== undefined && strategy !== RecoveryStrategy.Ignore;\n }\n /**\n * 标准化错误对象\n */\n normalizeError(error, context) {\n if ('type' in error && 'message' in error && 'timestamp' in error) {\n return error;\n }\n // 将普通Error转换为INetworkError\n return {\n type: this.determineErrorType(error),\n message: error.message || '未知错误',\n code: error.code,\n details: {\n context,\n stack: error.stack,\n name: error.name\n },\n timestamp: Date.now()\n };\n }\n /**\n * 确定错误类型\n */\n determineErrorType(error) {\n const message = error.message.toLowerCase();\n if (message.includes('timeout')) {\n return NetworkErrorType.TIMEOUT;\n }\n else if (message.includes('connection')) {\n return NetworkErrorType.CONNECTION_LOST;\n }\n else if (message.includes('auth')) {\n return NetworkErrorType.AUTHENTICATION_FAILED;\n }\n else if (message.includes('permission')) {\n return NetworkErrorType.PERMISSION_DENIED;\n }\n else if (message.includes('rate') || message.includes('limit')) {\n return NetworkErrorType.RATE_LIMITED;\n }\n else if (message.includes('invalid') || message.includes('format')) {\n return NetworkErrorType.INVALID_MESSAGE;\n }\n else {\n return NetworkErrorType.UNKNOWN;\n }\n }\n /**\n * 分类错误严重程度\n */\n classifyErrorSeverity(error) {\n // 使用自定义规则\n const customSeverity = this.severityRules.get(error.type);\n if (customSeverity) {\n return customSeverity;\n }\n // 默认分类规则\n switch (error.type) {\n case NetworkErrorType.CONNECTION_FAILED:\n case NetworkErrorType.CONNECTION_LOST:\n return ErrorSeverity.High;\n case NetworkErrorType.AUTHENTICATION_FAILED:\n case NetworkErrorType.PERMISSION_DENIED:\n return ErrorSeverity.Critical;\n case NetworkErrorType.TIMEOUT:\n case NetworkErrorType.RATE_LIMITED:\n return ErrorSeverity.Medium;\n case NetworkErrorType.INVALID_MESSAGE:\n return ErrorSeverity.Low;\n default:\n return ErrorSeverity.Medium;\n }\n }\n /**\n * 更新统计信息\n */\n updateStats(error, severity) {\n this.stats.totalErrors++;\n this.stats.errorsByType[error.type] = (this.stats.errorsByType[error.type] || 0) + 1;\n this.stats.errorsBySeverity[severity] = (this.stats.errorsBySeverity[severity] || 0) + 1;\n this.stats.lastError = error;\n }\n /**\n * 尝试错误恢复\n */\n attemptRecovery(error, severity) {\n const strategy = this.recoveryRules.get(error.type);\n if (!strategy || strategy === RecoveryStrategy.Ignore) {\n return;\n }\n const errorId = this.generateErrorId(error);\n // 检查是否已经在恢复中\n if (this.pendingRecoveries.has(errorId)) {\n return;\n }\n // 检查重试次数\n const retryCount = this.retryAttempts.get(errorId) || 0;\n if (retryCount >= this.config.maxRetryAttempts) {\n this.stats.unrecoveredErrors++;\n this.eventHandlers.errorUnrecoverable?.(error);\n return;\n }\n this.pendingRecoveries.add(errorId);\n this.retryAttempts.set(errorId, retryCount + 1);\n this.logger.info(`尝试错误恢复: ${strategy} (第 ${retryCount + 1} 次)`, {\n errorType: error.type,\n strategy\n });\n // 延迟执行恢复策略\n setTimeout(() => {\n this.executeRecoveryStrategy(error, strategy, errorId);\n }, this.config.retryDelay * (retryCount + 1));\n }\n /**\n * 执行恢复策略\n */\n executeRecoveryStrategy(error, strategy, errorId) {\n try {\n switch (strategy) {\n case RecoveryStrategy.Retry:\n // 这里应该重试导致错误的操作\n // 具体实现需要外部提供重试回调\n break;\n case RecoveryStrategy.Reconnect:\n // 这里应该触发重连\n // 具体实现需要外部处理\n break;\n case RecoveryStrategy.Restart:\n // 这里应该重启相关服务\n // 具体实现需要外部处理\n break;\n case RecoveryStrategy.Escalate:\n // 上报错误给上层处理\n this.logger.error('错误需要上层处理:', error);\n break;\n }\n this.pendingRecoveries.delete(errorId);\n this.eventHandlers.errorRecovered?.(error, strategy);\n }\n catch (recoveryError) {\n this.logger.error('错误恢复失败:', recoveryError);\n this.pendingRecoveries.delete(errorId);\n }\n }\n /**\n * 报告错误\n */\n async reportError(error, severity) {\n if (!this.config.errorReportingEndpoint) {\n return;\n }\n try {\n const report = {\n error,\n severity,\n timestamp: Date.now(),\n userAgent: typeof navigator !== 'undefined' ? navigator.userAgent : 'Node.js',\n url: typeof window !== 'undefined' ? window.location.href : 'server'\n };\n // 发送错误报告\n await fetch(this.config.errorReportingEndpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify(report)\n });\n }\n catch (reportError) {\n this.logger.error('发送错误报告失败:', reportError);\n }\n }\n /**\n * 生成错误ID\n */\n generateErrorId(error) {\n return `${error.type}-${error.code || 'no-code'}-${error.timestamp}`;\n }\n /**\n * 初始化默认规则\n */\n initializeDefaultRules() {\n // 默认严重程度规则\n this.severityRules.set(NetworkErrorType.CONNECTION_FAILED, ErrorSeverity.High);\n this.severityRules.set(NetworkErrorType.CONNECTION_LOST, ErrorSeverity.High);\n this.severityRules.set(NetworkErrorType.AUTHENTICATION_FAILED, ErrorSeverity.Critical);\n this.severityRules.set(NetworkErrorType.PERMISSION_DENIED, ErrorSeverity.Critical);\n this.severityRules.set(NetworkErrorType.TIMEOUT, ErrorSeverity.Medium);\n this.severityRules.set(NetworkErrorType.RATE_LIMITED, ErrorSeverity.Medium);\n this.severityRules.set(NetworkErrorType.INVALID_MESSAGE, ErrorSeverity.Low);\n // 默认恢复策略\n this.recoveryRules.set(NetworkErrorType.CONNECTION_FAILED, RecoveryStrategy.Reconnect);\n this.recoveryRules.set(NetworkErrorType.CONNECTION_LOST, RecoveryStrategy.Reconnect);\n this.recoveryRules.set(NetworkErrorType.TIMEOUT, RecoveryStrategy.Retry);\n this.recoveryRules.set(NetworkErrorType.RATE_LIMITED, RecoveryStrategy.Retry);\n this.recoveryRules.set(NetworkErrorType.INVALID_MESSAGE, RecoveryStrategy.Ignore);\n this.recoveryRules.set(NetworkErrorType.AUTHENTICATION_FAILED, RecoveryStrategy.Escalate);\n this.recoveryRules.set(NetworkErrorType.PERMISSION_DENIED, RecoveryStrategy.Escalate);\n }\n /**\n * 获取错误趋势分析\n */\n getErrorTrends() {\n const totalErrors = this.stats.totalErrors;\n if (totalErrors === 0) {\n return { trend: 'stable', recommendation: '系统运行正常' };\n }\n const criticalRate = (this.stats.errorsBySeverity[ErrorSeverity.Critical] || 0) / totalErrors;\n const recoveryRate = this.stats.recoveredErrors / totalErrors;\n if (criticalRate > 0.1) {\n return { trend: 'critical', recommendation: '存在严重错误,需要立即处理' };\n }\n else if (recoveryRate < 0.5) {\n return { trend: 'degrading', recommendation: '错误恢复率偏低,建议检查恢复策略' };\n }\n else if (totalErrors > 100) {\n return { trend: 'high_volume', recommendation: '错误量较大,建议分析根本原因' };\n }\n else {\n return { trend: 'stable', recommendation: '错误处理正常' };\n }\n }\n}\n//# sourceMappingURL=ErrorHandler.js.map","/**\n * 网络身份组件\n */\nimport { Component, Emitter } from '@esengine/ecs-framework';\nimport { AuthorityType, NetworkScope } from '../types/NetworkTypes';\nimport { NetworkEventType, NetworkEventUtils } from '../events/NetworkEvents';\n/**\n * 网络身份组件\n *\n * 为实体提供网络同步能力的核心组件。\n * 每个需要网络同步的实体都必须拥有此组件。\n *\n * 集成了事件系统,当属性变化时自动发射事件用于网络同步。\n */\nexport class NetworkIdentity extends Component {\n constructor() {\n super(...arguments);\n /**\n * 事件发射器\n * 用于发射网络相关事件\n */\n this.eventEmitter = new Emitter();\n /**\n * 网络ID (全局唯一)\n * 用于在网络中标识实体\n */\n this.networkId = 0;\n /**\n * 拥有者ID\n * 表示哪个客户端拥有此实体的控制权\n */\n this.ownerId = '';\n /**\n * 权限类型\n * 决定哪一端对此实体有控制权\n */\n this.authority = AuthorityType.Server;\n /**\n * 同步频率 (Hz)\n * 每秒同步的次数\n */\n this.syncRate = 20;\n /**\n * 网络作用域\n * 决定哪些客户端可以看到此实体\n */\n this.scope = NetworkScope.Room;\n /**\n * 是否是本地玩家\n * 标识此实体是否代表本地玩家\n */\n this.isLocalPlayer = false;\n /**\n * 是否启用网络同步\n * 临时禁用/启用同步\n */\n this.syncEnabled = true;\n /**\n * 同步优先级\n * 影响同步的顺序和频率,数值越高优先级越高\n */\n this.priority = 0;\n /**\n * 距离阈值\n * 用于附近同步模式,超过此距离的客户端不会收到同步\n */\n this.distanceThreshold = 100;\n /**\n * 最后同步时间\n * 记录上次同步的时间戳\n */\n this.lastSyncTime = 0;\n /**\n * 是否可见\n * 控制实体是否对其他客户端可见\n */\n this.visible = true;\n }\n /**\n * 获取实体的同步权重\n * 基于优先级和距离计算\n */\n getSyncWeight(distance) {\n let weight = this.priority;\n if (distance !== undefined && this.scope === NetworkScope.Nearby) {\n // 距离越近权重越高\n const distanceFactor = Math.max(0, 1 - (distance / this.distanceThreshold));\n weight *= distanceFactor;\n }\n return weight;\n }\n /**\n * 检查是否应该同步给指定客户端\n */\n shouldSyncToClient(clientId, distance) {\n if (!this.syncEnabled || !this.visible) {\n return false;\n }\n switch (this.scope) {\n case NetworkScope.Global:\n return true;\n case NetworkScope.Room:\n return true; // 由房间管理器控制\n case NetworkScope.Owner:\n return clientId === this.ownerId;\n case NetworkScope.Nearby:\n return distance !== undefined && distance <= this.distanceThreshold;\n case NetworkScope.Custom:\n return this.customSyncFilter ? this.customSyncFilter(clientId) : false;\n default:\n return false;\n }\n }\n /**\n * 检查客户端是否有权限修改此实体\n */\n hasAuthority(clientId) {\n switch (this.authority) {\n case AuthorityType.Server:\n return false; // 只有服务端有权限\n case AuthorityType.Client:\n return clientId === this.ownerId;\n case AuthorityType.Shared:\n return true; // 任何人都可以修改\n default:\n return false;\n }\n }\n /**\n * 设置拥有者\n */\n setOwner(clientId) {\n const oldOwner = this.ownerId;\n this.ownerId = clientId;\n // 发射拥有者变化事件\n this.emitEvent(NetworkEventType.IDENTITY_OWNER_CHANGED, NetworkEventUtils.createIdentityEventData(this.networkId, clientId, oldOwner, clientId));\n }\n /**\n * 设置权限类型\n */\n setAuthority(authority) {\n const oldAuthority = this.authority;\n this.authority = authority;\n // 发射权限变化事件\n this.emitEvent(NetworkEventType.IDENTITY_AUTHORITY_CHANGED, NetworkEventUtils.createIdentityEventData(this.networkId, this.ownerId, oldAuthority, authority));\n }\n /**\n * 设置同步状态\n */\n setSyncEnabled(enabled) {\n const oldEnabled = this.syncEnabled;\n this.syncEnabled = enabled;\n // 发射同步状态变化事件\n const eventType = enabled\n ? NetworkEventType.IDENTITY_SYNC_ENABLED\n : NetworkEventType.IDENTITY_SYNC_DISABLED;\n this.emitEvent(eventType, NetworkEventUtils.createIdentityEventData(this.networkId, this.ownerId, oldEnabled, enabled));\n }\n /**\n * 设置同步频率\n */\n setSyncRate(rate) {\n const oldRate = this.syncRate;\n this.syncRate = rate;\n // 发射同步频率变化事件\n this.emitEvent(NetworkEventType.SYNC_RATE_CHANGED, NetworkEventUtils.createIdentityEventData(this.networkId, this.ownerId, oldRate, rate));\n }\n /**\n * 添加事件监听器\n */\n addEventListener(eventType, handler) {\n this.eventEmitter.addObserver(eventType, handler, this);\n }\n /**\n * 移除事件监听器\n */\n removeEventListener(eventType, handler) {\n this.eventEmitter.removeObserver(eventType, handler);\n }\n /**\n * 发射事件\n * @private\n */\n emitEvent(eventType, data) {\n this.eventEmitter.emit(eventType, data);\n }\n /**\n * 监听属性变化事件\n */\n onPropertyChanged(handler) {\n this.addEventListener(NetworkEventType.IDENTITY_PROPERTY_CHANGED, handler);\n }\n /**\n * 监听拥有者变化事件\n */\n onOwnerChanged(handler) {\n this.addEventListener(NetworkEventType.IDENTITY_OWNER_CHANGED, handler);\n }\n /**\n * 监听权限变化事件\n */\n onAuthorityChanged(handler) {\n this.addEventListener(NetworkEventType.IDENTITY_AUTHORITY_CHANGED, handler);\n }\n /**\n * 监听同步状态变化事件\n */\n onSyncStateChanged(handler) {\n this.addEventListener(NetworkEventType.IDENTITY_SYNC_ENABLED, handler);\n this.addEventListener(NetworkEventType.IDENTITY_SYNC_DISABLED, handler);\n }\n /**\n * 获取调试信息\n */\n getDebugInfo() {\n return {\n networkId: this.networkId,\n ownerId: this.ownerId,\n authority: this.authority,\n scope: this.scope,\n syncRate: this.syncRate,\n priority: this.priority,\n syncEnabled: this.syncEnabled,\n visible: this.visible,\n lastSyncTime: this.lastSyncTime\n };\n }\n /**\n * 组件销毁时清理事件监听器\n */\n dispose() {\n // 清理所有事件监听器\n this.eventEmitter.dispose();\n }\n}\n//# sourceMappingURL=NetworkIdentity.js.map","/**\n * 心跳管理器\n * 负责管理网络连接的心跳检测,包括延迟测算和连接健康检测\n */\nimport { createLogger } from '@esengine/ecs-framework';\nimport { MessageType } from '../types/NetworkTypes';\n/**\n * 心跳管理器\n */\nexport class HeartbeatManager {\n /**\n * 构造函数\n */\n constructor(config = {}) {\n this.logger = createLogger('HeartbeatManager');\n this.eventHandlers = {};\n // 延迟测量\n this.pendingPings = new Map();\n this.latencyHistory = [];\n this.sequence = 0;\n // 统计信息\n this.sentCount = 0;\n this.receivedCount = 0;\n this.config = {\n interval: 30000, // 30秒\n timeout: 60000, // 60秒\n maxMissedHeartbeats: 3, // 最大丢失3次\n enableLatencyMeasurement: true,\n ...config\n };\n this.status = {\n isHealthy: true,\n lastHeartbeat: Date.now(),\n missedHeartbeats: 0\n };\n }\n /**\n * 启动心跳\n */\n start(sendCallback) {\n this.sendHeartbeat = sendCallback;\n this.startHeartbeatTimer();\n this.logger.info('心跳管理器已启动');\n }\n /**\n * 停止心跳\n */\n stop() {\n this.stopHeartbeatTimer();\n this.stopTimeoutTimer();\n this.pendingPings.clear();\n this.logger.info('心跳管理器已停止');\n }\n /**\n * 处理接收到的心跳响应\n */\n handleHeartbeatResponse(message) {\n const now = Date.now();\n this.status.lastHeartbeat = now;\n this.receivedCount++;\n // 重置丢失心跳计数\n this.status.missedHeartbeats = 0;\n // 计算延迟\n if (this.config.enableLatencyMeasurement && message.sequence !== undefined) {\n const sentTime = this.pendingPings.get(message.sequence);\n if (sentTime) {\n const latency = now - sentTime;\n this.updateLatency(latency);\n this.pendingPings.delete(message.sequence);\n this.eventHandlers.heartbeatReceived?.(latency);\n }\n }\n // 更新健康状态\n this.updateHealthStatus(true);\n // 停止超时定时器\n this.stopTimeoutTimer();\n }\n /**\n * 处理心跳超时\n */\n handleHeartbeatTimeout() {\n this.status.missedHeartbeats++;\n this.logger.warn(`心跳超时,丢失次数: ${this.status.missedHeartbeats}`);\n // 触发超时事件\n this.eventHandlers.heartbeatTimeout?.(this.status.missedHeartbeats);\n // 检查是否达到最大丢失次数\n if (this.status.missedHeartbeats >= this.config.maxMissedHeartbeats) {\n this.updateHealthStatus(false);\n }\n }\n /**\n * 获取心跳状态\n */\n getStatus() {\n return { ...this.status };\n }\n /**\n * 获取统计信息\n */\n getStats() {\n const packetLoss = this.sentCount > 0 ?\n ((this.sentCount - this.receivedCount) / this.sentCount) * 100 : 0;\n return {\n sentCount: this.sentCount,\n receivedCount: this.receivedCount,\n packetLoss,\n averageLatency: this.status.averageLatency,\n currentLatency: this.status.latency,\n isHealthy: this.status.isHealthy,\n missedHeartbeats: this.status.missedHeartbeats,\n latencyHistory: [...this.latencyHistory]\n };\n }\n /**\n * 设置事件处理器\n */\n on(event, handler) {\n this.eventHandlers[event] = handler;\n }\n /**\n * 移除事件处理器\n */\n off(event) {\n delete this.eventHandlers[event];\n }\n /**\n * 手动发送心跳\n */\n sendHeartbeatNow() {\n this.doSendHeartbeat();\n }\n /**\n * 更新配置\n */\n updateConfig(newConfig) {\n Object.assign(this.config, newConfig);\n this.logger.info('心跳配置已更新:', newConfig);\n // 重启定时器以应用新配置\n if (this.heartbeatTimer) {\n this.stop();\n if (this.sendHeartbeat) {\n this.start(this.sendHeartbeat);\n }\n }\n }\n /**\n * 启动心跳定时器\n */\n startHeartbeatTimer() {\n this.heartbeatTimer = window.setInterval(() => {\n this.doSendHeartbeat();\n }, this.config.interval);\n }\n /**\n * 停止心跳定时器\n */\n stopHeartbeatTimer() {\n if (this.heartbeatTimer) {\n clearInterval(this.heartbeatTimer);\n this.heartbeatTimer = undefined;\n }\n }\n /**\n * 启动超时定时器\n */\n startTimeoutTimer() {\n this.timeoutTimer = window.setTimeout(() => {\n this.handleHeartbeatTimeout();\n }, this.config.timeout);\n }\n /**\n * 停止超时定时器\n */\n stopTimeoutTimer() {\n if (this.timeoutTimer) {\n