extends Node # ============================================================================ # WebSocketManager.gd - WebSocket 连接生命周期管理 # ============================================================================ # 管理 WebSocket 连接状态、自动重连和错误恢复 # # 核心职责: # - 连接状态管理(断开、连接中、已连接、重连中) # - 自动重连机制(指数退避) # - 连接错误恢复 # - Socket.IO 客户端封装 # # 使用方式: # WebSocketManager.connect_to_game_server() # WebSocketManager.connection_state_changed.connect(_on_state_changed) # # 注意事项: # - 作为自动加载单例,全局可访问 # - 自动处理连接断开和重连 # - 通过信号通知连接状态变化 # ============================================================================ class_name WebSocketManager # ============================================================================ # 信号定义 # ============================================================================ # 连接状态变化信号 # 参数: # new_state: ConnectionState - 新的连接状态 signal connection_state_changed(new_state: ConnectionState) # 连接丢失信号 signal connection_lost() # 重连成功信号 signal reconnection_succeeded() # 重连失败信号 # 参数: # attempt: int - 当前重连尝试次数 # max_attempts: int - 最大重连次数 signal reconnection_failed(attempt: int, max_attempts: int) # ============================================================================ # 枚举定义 # ============================================================================ # 连接状态枚举 enum ConnectionState { DISCONNECTED, # 未连接 CONNECTING, # 连接中 CONNECTED, # 已连接 RECONNECTING, # 重连中 ERROR # 错误状态 } # ============================================================================ # 常量定义 # ============================================================================ # WebSocket 服务器 URL const WEBSOCKET_URL: String = "wss://whaletownend.xinghangee.icu/game" # 默认最大重连次数 const DEFAULT_MAX_RECONNECT_ATTEMPTS: int = 5 # 默认重连基础延迟(秒) const DEFAULT_RECONNECT_BASE_DELAY: float = 3.0 # 最大重连延迟(秒) const MAX_RECONNECT_DELAY: float = 30.0 # ============================================================================ # 成员变量 # ============================================================================ # Socket.IO 客户端 var _socket_client: SocketIOClient # 当前连接状态 var _connection_state: ConnectionState = ConnectionState.DISCONNECTED # 自动重连启用标志 var _auto_reconnect_enabled: bool = true # 最大重连次数 var _max_reconnect_attempts: int = DEFAULT_MAX_RECONNECT_ATTEMPTS # 重连基础延迟 var _reconnect_base_delay: float = DEFAULT_RECONNECT_BASE_DELAY # 当前重连尝试次数 var _reconnect_attempt: int = 0 # 重连定时器 var _reconnect_timer: Timer = Timer.new() # 是否为正常关闭(非异常断开) var _clean_close: bool = true # ============================================================================ # 生命周期方法 # ============================================================================ # 初始化 func _ready() -> void: print("WebSocketManager 初始化完成") # 创建 Socket.IO 客户端 _socket_client = SocketIOClient.new() add_child(_socket_client) # 连接信号 _socket_client.connected.connect(_on_socket_connected) _socket_client.disconnected.connect(_on_socket_disconnected) _socket_client.error_occurred.connect(_on_socket_error) # 设置重连定时器 _setup_reconnect_timer() # 清理 func _exit_tree() -> void: if is_instance_valid(_reconnect_timer): _reconnect_timer.stop() _reconnect_timer.queue_free() # ============================================================================ # 公共 API - 连接管理 # ============================================================================ # 连接到游戏服务器 func connect_to_game_server() -> void: if _connection_state == ConnectionState.CONNECTED or _connection_state == ConnectionState.CONNECTING: push_warning("已经在连接或已连接状态") return print("=== WebSocketManager 开始连接 ===") _set_connection_state(ConnectionState.CONNECTING) _clean_close = true _reconnect_attempt = 0 _socket_client.connect_to_server(WEBSOCKET_URL) # 断开 WebSocket 连接 func disconnect_websocket() -> void: print("=== WebSocketManager 断开连接 ===") _clean_close = true # 停止重连定时器 _reconnect_timer.stop() # 断开客户端 _socket_client.disconnect_from_server() _set_connection_state(ConnectionState.DISCONNECTED) # 检查 WebSocket 是否已连接 # # 返回值: # bool - WebSocket 是否已连接 func is_websocket_connected() -> bool: return _connection_state == ConnectionState.CONNECTED # 获取当前连接状态 # # 返回值: # ConnectionState - 当前连接状态 func get_connection_state() -> ConnectionState: return _connection_state # ============================================================================ # 公共 API - 自动重连 # ============================================================================ # 启用/禁用自动重连 # # 参数: # enabled: bool - 是否启用自动重连 # max_attempts: int - 最大重连次数(默认 5) # base_delay: float - 基础重连延迟,秒(默认 3.0) # # 使用示例: # WebSocketManager.enable_auto_reconnect(true, 5, 3.0) func enable_auto_reconnect(enabled: bool, max_attempts: int = DEFAULT_MAX_RECONNECT_ATTEMPTS, base_delay: float = DEFAULT_RECONNECT_BASE_DELAY) -> void: _auto_reconnect_enabled = enabled _max_reconnect_attempts = max_attempts _reconnect_base_delay = base_delay print("自动重连: ", "启用" if enabled else "禁用") print("最大重连次数: ", _max_reconnect_attempts) print("基础重连延迟: ", _reconnect_base_delay, " 秒") # 获取 Socket.IO 客户端 # # 返回值: # SocketIOClient - Socket.IO 客户端实例 # # 使用示例: # var socket = WebSocketManager.get_socket_client() # socket.emit("chat", {"t": "chat", "content": "Hello"}) func get_socket_client() -> SocketIOClient: return _socket_client # ============================================================================ # 内部方法 - 连接状态管理 # ============================================================================ # 设置连接状态 func _set_connection_state(new_state: ConnectionState) -> void: if _connection_state == new_state: return _connection_state = new_state print("📡 连接状态变更: ", ConnectionState.keys()[new_state]) # 发射信号 connection_state_changed.emit(new_state) # ============================================================================ # 内部方法 - Socket 事件处理 # ============================================================================ # Socket 连接成功处理 func _on_socket_connected() -> void: print("✅ WebSocketManager: Socket 连接成功") # 如果是重连,发射重连成功信号 if _connection_state == ConnectionState.RECONNECTING: _reconnect_attempt = 0 reconnection_succeeded.emit() print("🔄 重连成功") _set_connection_state(ConnectionState.CONNECTED) # Socket 连接断开处理 func _on_socket_disconnected(clean_close: bool) -> void: print("🔌 WebSocketManager: Socket 连接断开") print(" 正常关闭: ", clean_close) _clean_close = clean_close # 如果是异常断开且启用了自动重连 if not clean_close and _auto_reconnect_enabled: connection_lost.emit() _attempt_reconnect() else: _set_connection_state(ConnectionState.DISCONNECTED) # Socket 错误处理 func _on_socket_error(error: String) -> void: print("❌ WebSocketManager: Socket 错误 - ", error) _set_connection_state(ConnectionState.ERROR) # ============================================================================ # 内部方法 - 重连机制 # ============================================================================ # 设置重连定时器 func _setup_reconnect_timer() -> void: _reconnect_timer = Timer.new() _reconnect_timer.one_shot = true _reconnect_timer.autostart = false add_child(_reconnect_timer) _reconnect_timer.timeout.connect(_on_reconnect_timeout) # 尝试重连 func _attempt_reconnect() -> void: # 检查是否超过最大重连次数 if _reconnect_attempt >= _max_reconnect_attempts: print("❌ 达到最大重连次数 (", _max_reconnect_attempts, "),停止重连") reconnection_failed.emit(_reconnect_attempt, _max_reconnect_attempts) _set_connection_state(ConnectionState.ERROR) return _reconnect_attempt += 1 _set_connection_state(ConnectionState.RECONNECTING) # 计算重连延迟(指数退避) var delay := _calculate_reconnect_delay() print("🔄 尝试重连 (", _reconnect_attempt, "/", _max_reconnect_attempts, ")") print(" 延迟: ", delay, " 秒") # 启动重连定时器 _reconnect_timer.start(delay) # 计算重连延迟(指数退避) func _calculate_reconnect_delay() -> float: # 指数退避: base_delay * 2^(attempt-1) var delay: float = _reconnect_base_delay * pow(2.0, _reconnect_attempt - 1) # 限制最大延迟 return min(delay, MAX_RECONNECT_DELAY) # 重连定时器超时处理 func _on_reconnect_timeout() -> void: print("⏰ 重连定时器超时,开始重连...") _socket_client.connect_to_server(WEBSOCKET_URL) # ============================================================================ # 工具方法 # ============================================================================ # 获取连接状态描述 # # 返回值: # String - 连接状态描述 func get_state_description() -> String: match _connection_state: ConnectionState.DISCONNECTED: return "未连接" ConnectionState.CONNECTING: return "连接中" ConnectionState.CONNECTED: return "已连接" ConnectionState.RECONNECTING: return "重连中 (%d/%d)" % [_reconnect_attempt, _max_reconnect_attempts] ConnectionState.ERROR: return "错误" _: return "未知状态" # 获取重连信息 # # 返回值: # Dictionary - 重连信息 {enabled, attempt, max_attempts, delay} func get_reconnect_info() -> Dictionary: return { "enabled": _auto_reconnect_enabled, "attempt": _reconnect_attempt, "max_attempts": _max_reconnect_attempts, "next_delay": _calculate_reconnect_delay() if _connection_state == ConnectionState.RECONNECTING else 0.0 }