合并主场景和个人小屋
This commit is contained in:
@@ -68,6 +68,9 @@ enum LoginMode {
|
||||
|
||||
# ============ 成员变量 ============
|
||||
|
||||
# 当前用户ID(静态变量,用于BaseLevel等场景访问)
|
||||
static var current_user_id: String = ""
|
||||
|
||||
# 登录状态
|
||||
var current_login_mode: LoginMode = LoginMode.PASSWORD
|
||||
var is_processing: bool = false
|
||||
@@ -91,14 +94,13 @@ var _refresh_token: String = "" # JWT刷新令牌(长期,用于获取
|
||||
var _user_info: Dictionary = {} # 用户信息
|
||||
var _token_expiry: float = 0.0 # access_token过期时间(Unix时间戳)
|
||||
|
||||
# 游戏 token(兼容旧代码,保留但标记为废弃)
|
||||
# 游戏 token(废弃,保留供旧接口)
|
||||
var _game_token: String = "" # @deprecated 使用 _access_token 替代
|
||||
|
||||
# ============ 生命周期方法 ============
|
||||
|
||||
# 初始化管理器
|
||||
func _init() -> void:
|
||||
print("AuthManager 初始化完成")
|
||||
_load_auth_data()
|
||||
|
||||
# 清理资源
|
||||
@@ -121,7 +123,7 @@ func cleanup() -> void:
|
||||
# - 保存用户信息
|
||||
func _save_tokens_to_memory(data: Dictionary) -> void:
|
||||
if not data.has("data"):
|
||||
print("⚠️ 登录响应中没有 data 字段")
|
||||
push_warning("AuthManager: 登录响应中没有 data 字段")
|
||||
return
|
||||
|
||||
var token_data: Dictionary = data.data
|
||||
@@ -130,12 +132,11 @@ func _save_tokens_to_memory(data: Dictionary) -> void:
|
||||
_user_info = token_data.get("user", {})
|
||||
_token_expiry = Time.get_unix_time_from_system() + float(token_data.get("expires_in", 0))
|
||||
|
||||
# 保持兼容性:设置 _game_token
|
||||
_game_token = _access_token
|
||||
# 设置当前用户ID(用于BaseLevel等场景)
|
||||
if _user_info.has("id"):
|
||||
AuthManager.current_user_id = str(_user_info.id)
|
||||
|
||||
print("✅ Token已保存到内存")
|
||||
print(" Access Token: ", _access_token.substr(0, 20) + "...")
|
||||
print(" 用户: ", _user_info.get("username", "未知"))
|
||||
_game_token = _access_token
|
||||
|
||||
# 保存 Token 到本地(ConfigFile)
|
||||
#
|
||||
@@ -165,10 +166,8 @@ func _save_tokens_to_local(data: Dictionary) -> void:
|
||||
config.set_value("auth", "saved_at", auth_data["saved_at"])
|
||||
|
||||
var error: Error = config.save(AUTH_CONFIG_PATH)
|
||||
if error == OK:
|
||||
print("✅ Token已保存到本地: ", AUTH_CONFIG_PATH)
|
||||
else:
|
||||
print("❌ 保存Token到本地失败,错误码: ", error)
|
||||
if error != OK:
|
||||
push_error("AuthManager: 保存Token到本地失败,错误码: %d" % error)
|
||||
|
||||
# 从本地加载 Token(游戏启动时调用)
|
||||
#
|
||||
@@ -177,14 +176,13 @@ func _save_tokens_to_local(data: Dictionary) -> void:
|
||||
# - access_token 需要通过 refresh_token 刷新获取
|
||||
func _load_auth_data() -> void:
|
||||
if not FileAccess.file_exists(AUTH_CONFIG_PATH):
|
||||
print("ℹ️ 本地不存在认证数据")
|
||||
return
|
||||
|
||||
var config: ConfigFile = ConfigFile.new()
|
||||
var error: Error = config.load(AUTH_CONFIG_PATH)
|
||||
|
||||
if error != OK:
|
||||
print("❌ 加载本地认证数据失败,错误码: ", error)
|
||||
push_error("AuthManager: 加载本地认证数据失败,错误码: %d" % error)
|
||||
return
|
||||
|
||||
_refresh_token = config.get_value("auth", "refresh_token", "")
|
||||
@@ -196,10 +194,8 @@ func _load_auth_data() -> void:
|
||||
"id": user_id,
|
||||
"username": username
|
||||
}
|
||||
print("✅ 已从本地加载认证数据")
|
||||
print(" 用户: ", username)
|
||||
else:
|
||||
print("⚠️ 本地认证数据无效(没有 refresh_token)")
|
||||
push_warning("AuthManager: 本地认证数据无效(没有 refresh_token)")
|
||||
|
||||
# 清除本地认证数据(登出时调用)
|
||||
#
|
||||
@@ -215,11 +211,10 @@ func _clear_auth_data() -> void:
|
||||
|
||||
if FileAccess.file_exists(AUTH_CONFIG_PATH):
|
||||
DirAccess.remove_absolute(AUTH_CONFIG_PATH)
|
||||
print("✅ 已清除本地认证数据")
|
||||
|
||||
# ============ Token 访问方法 ============
|
||||
|
||||
# 设置游戏 token(兼容旧代码,推荐使用 _save_tokens_to_memory)
|
||||
# 设置游戏 token(建议优先使用 _save_tokens_to_memory)
|
||||
#
|
||||
# 参数:
|
||||
# token: String - 游戏认证 token
|
||||
@@ -230,7 +225,6 @@ func _clear_auth_data() -> void:
|
||||
func set_game_token(token: String) -> void:
|
||||
_game_token = token
|
||||
_access_token = token # 同步更新 access_token
|
||||
print("AuthManager: 游戏 token 已设置")
|
||||
|
||||
# 获取游戏 token
|
||||
#
|
||||
@@ -768,4 +762,4 @@ func _is_valid_identifier(identifier: String) -> bool:
|
||||
func _is_valid_phone(phone: String) -> bool:
|
||||
var regex = RegEx.new()
|
||||
regex.compile("^\\+?[1-9]\\d{1,14}$")
|
||||
return regex.search(phone) != null
|
||||
return regex.search(phone) != null
|
||||
|
||||
@@ -99,7 +99,7 @@ const CHAT_ERROR_MESSAGES: Dictionary = {
|
||||
# ============================================================================
|
||||
|
||||
# WebSocket 管理器
|
||||
var _websocket_manager: WebSocketManager
|
||||
var _websocket_manager: ChatWebSocketManager
|
||||
|
||||
# 是否已登录
|
||||
var _is_logged_in: bool = false
|
||||
@@ -132,10 +132,8 @@ var _pending_self_messages: Array[Dictionary] = []
|
||||
|
||||
# 初始化
|
||||
func _ready() -> void:
|
||||
print("ChatManager 初始化完成")
|
||||
|
||||
# 创建 WebSocket 管理器
|
||||
_websocket_manager = WebSocketManager.new()
|
||||
_websocket_manager = ChatWebSocketManager.new()
|
||||
add_child(_websocket_manager)
|
||||
|
||||
# 连接信号
|
||||
@@ -159,7 +157,6 @@ func _exit_tree() -> void:
|
||||
# ChatManager.set_game_token("your_game_token")
|
||||
func set_game_token(token: String) -> void:
|
||||
_game_token = token
|
||||
print("ChatManager: 游戏 token 已设置")
|
||||
|
||||
# 获取游戏 token
|
||||
#
|
||||
@@ -178,13 +175,10 @@ func connect_to_chat_server() -> void:
|
||||
push_warning("聊天服务器已连接")
|
||||
return
|
||||
|
||||
print("=== ChatManager 开始连接 ===")
|
||||
_websocket_manager.connect_to_game_server()
|
||||
|
||||
# 断开聊天服务器
|
||||
func disconnect_from_chat_server() -> void:
|
||||
print("=== ChatManager 断开连接 ===")
|
||||
|
||||
# 发送登出消息
|
||||
if _is_logged_in:
|
||||
var logout_data := {"type": "logout"}
|
||||
@@ -278,12 +272,9 @@ func send_chat_message(content: String, scope: String = "local") -> void:
|
||||
"is_self": true
|
||||
})
|
||||
|
||||
print("📤 发送聊天消息: ", content)
|
||||
|
||||
# 消息发送完成回调
|
||||
func _on_chat_message_sent(request_id: String, success: bool, data: Dictionary, error_info: Dictionary) -> void:
|
||||
func _on_chat_message_sent(_request_id: String, success: bool, data: Dictionary, error_info: Dictionary) -> void:
|
||||
if success:
|
||||
print("✅ 消息发送成功: ", data)
|
||||
var message_id: String = str(data.get("data", {}).get("id", ""))
|
||||
var timestamp: float = Time.get_unix_time_from_system()
|
||||
chat_message_sent.emit(message_id, timestamp)
|
||||
@@ -292,7 +283,6 @@ func _on_chat_message_sent(request_id: String, success: bool, data: Dictionary,
|
||||
"timestamp": timestamp
|
||||
})
|
||||
else:
|
||||
print("❌ 消息发送失败: ", error_info)
|
||||
_handle_error("SEND_FAILED", error_info.get("message", "发送失败"))
|
||||
|
||||
# 更新玩家位置
|
||||
@@ -319,8 +309,6 @@ func update_player_position(x: float, y: float, map_id: String) -> void:
|
||||
var json_string := JSON.stringify(position_data)
|
||||
_websocket_manager.send_message(json_string)
|
||||
|
||||
print("📍 更新位置: (%.2f, %.2f) in %s" % [x, y, map_id])
|
||||
|
||||
# ============================================================================
|
||||
# 公共 API - 频率限制
|
||||
# ============================================================================
|
||||
@@ -375,7 +363,6 @@ func get_message_history() -> Array[Dictionary]:
|
||||
# 清空消息历史
|
||||
func clear_message_history() -> void:
|
||||
_message_history.clear()
|
||||
print("🧹 清空消息历史")
|
||||
|
||||
# 重置当前会话(每次登录/重连时调用)
|
||||
#
|
||||
@@ -392,7 +379,6 @@ func reset_session() -> void:
|
||||
_history_loading = false
|
||||
_has_more_history = true
|
||||
_oldest_message_timestamp = 0.0
|
||||
print("🔄 重置聊天会话")
|
||||
|
||||
# 加载历史消息(按需从 Zulip 后端获取)
|
||||
#
|
||||
@@ -411,36 +397,26 @@ func reset_session() -> void:
|
||||
# 注意:
|
||||
# - 这是异步操作,需要通过 Zulip API 实现
|
||||
# - 当前实现为占位符,需要后端 API 支持
|
||||
func load_history(count: int = HISTORY_PAGE_SIZE) -> void:
|
||||
func load_history(_count: int = HISTORY_PAGE_SIZE) -> void:
|
||||
if _history_loading:
|
||||
print("⏳ 历史消息正在加载中...")
|
||||
return
|
||||
|
||||
if not _has_more_history:
|
||||
print("📚 没有更多历史消息")
|
||||
return
|
||||
|
||||
_history_loading = true
|
||||
print("📜 开始加载历史消息,数量: ", count)
|
||||
|
||||
# TODO: 实现从 Zulip 后端获取历史消息
|
||||
# NetworkManager.get_chat_history(_oldest_message_timestamp, count, _on_history_loaded)
|
||||
|
||||
# 临时实现:模拟历史消息加载(测试用)
|
||||
# await get_tree().create_timer(1.0).timeout
|
||||
# _on_history_loaded([])
|
||||
|
||||
# 历史消息加载完成回调
|
||||
func _on_history_loaded(messages: Array) -> void:
|
||||
_history_loading = false
|
||||
|
||||
if messages.is_empty():
|
||||
_has_more_history = false
|
||||
print("📚 没有更多历史消息")
|
||||
return
|
||||
|
||||
print("📜 历史消息加载完成,数量: ", messages.size())
|
||||
|
||||
# 将历史消息插入到当前会话历史开头
|
||||
for i in range(messages.size() - 1, -1, -1):
|
||||
var message: Dictionary = messages[i]
|
||||
@@ -477,8 +453,6 @@ func _connect_signals() -> void:
|
||||
|
||||
# 发送登录消息
|
||||
func _send_login_message() -> void:
|
||||
print("📤 发送登录消息...")
|
||||
|
||||
var login_data := {
|
||||
"type": "login",
|
||||
"token": _game_token
|
||||
@@ -486,14 +460,9 @@ func _send_login_message() -> void:
|
||||
|
||||
var json_string := JSON.stringify(login_data)
|
||||
_websocket_manager.send_message(json_string)
|
||||
|
||||
print(" Token: ", _game_token.left(20) + "..." if _game_token.length() > 20 else _game_token)
|
||||
|
||||
# 连接状态变化
|
||||
func _on_connection_state_changed(state: int) -> void:
|
||||
var state_names := ["DISCONNECTED", "CONNECTING", "CONNECTED", "RECONNECTING", "ERROR"]
|
||||
print("📡 ChatManager: 连接状态变化 - ", state_names[state])
|
||||
|
||||
# 发射信号
|
||||
chat_connection_state_changed.emit(state)
|
||||
|
||||
@@ -517,7 +486,7 @@ func _on_data_received(message: String) -> void:
|
||||
var parse_result := json.parse(message)
|
||||
|
||||
if parse_result != OK:
|
||||
print("❌ ChatManager: JSON 解析失败 - ", message)
|
||||
push_error("ChatManager: JSON 解析失败")
|
||||
return
|
||||
|
||||
var data: Dictionary = json.data
|
||||
@@ -541,13 +510,10 @@ func _on_data_received(message: String) -> void:
|
||||
"position_updated":
|
||||
_handle_position_updated(data)
|
||||
_:
|
||||
print("⚠️ ChatManager: 未处理的消息类型 - ", message_type)
|
||||
print(" 消息内容: ", data)
|
||||
push_warning("ChatManager: 未处理的消息类型 %s" % message_type)
|
||||
|
||||
# 处理登录成功
|
||||
func _handle_login_success(data: Dictionary) -> void:
|
||||
print("✅ ChatManager: 登录成功")
|
||||
|
||||
_is_logged_in = true
|
||||
_current_username = data.get("username", "")
|
||||
_current_map = data.get("currentMap", "")
|
||||
@@ -555,9 +521,6 @@ func _handle_login_success(data: Dictionary) -> void:
|
||||
# 重置当前会话缓存(每次登录/重连都清空,重新开始接收消息)
|
||||
reset_session()
|
||||
|
||||
print(" 用户名: ", _current_username)
|
||||
print(" 地图: ", _current_map)
|
||||
|
||||
# 通过 EventSystem 广播(Signal Up)
|
||||
EventSystem.emit_event(EventNames.CHAT_LOGIN_SUCCESS, {
|
||||
"username": _current_username,
|
||||
@@ -568,8 +531,6 @@ func _handle_login_success(data: Dictionary) -> void:
|
||||
func _handle_login_error(data: Dictionary) -> void:
|
||||
var error_message: String = data.get("message", "登录失败")
|
||||
|
||||
print("❌ ChatManager: 登录失败 - ", error_message)
|
||||
|
||||
_is_logged_in = false
|
||||
|
||||
# 通过 EventSystem 广播错误(Signal Up)
|
||||
@@ -583,8 +544,6 @@ func _handle_chat_sent(data: Dictionary) -> void:
|
||||
var message_id: String = str(data.get("messageId", ""))
|
||||
var timestamp: float = data.get("timestamp", 0.0)
|
||||
|
||||
print("✅ 消息发送成功: ", message_id)
|
||||
|
||||
# 发射信号
|
||||
chat_message_sent.emit(message_id, timestamp)
|
||||
|
||||
@@ -598,8 +557,6 @@ func _handle_chat_sent(data: Dictionary) -> void:
|
||||
func _handle_chat_error(data: Dictionary) -> void:
|
||||
var error_message: String = data.get("message", "消息发送失败")
|
||||
|
||||
print("❌ ChatManager: 聊天错误 - ", error_message)
|
||||
|
||||
# 通过 EventSystem 广播错误(Signal Up)
|
||||
EventSystem.emit_event(EventNames.CHAT_ERROR_OCCURRED, {
|
||||
"error_code": "CHAT_SEND_FAILED",
|
||||
@@ -627,8 +584,6 @@ func _handle_chat_render(data: Dictionary) -> void:
|
||||
from_user = _current_username
|
||||
is_self = true
|
||||
|
||||
print("📨 收到聊天消息: ", from_user, " -> ", content)
|
||||
|
||||
# 添加到历史
|
||||
_add_message_to_history({
|
||||
"from_user": from_user,
|
||||
@@ -688,8 +643,6 @@ func _handle_position_updated(data: Dictionary) -> void:
|
||||
var stream: String = data.get("stream", "")
|
||||
var topic: String = data.get("topic", "")
|
||||
|
||||
print("✅ 位置更新成功: ", stream, " / ", topic)
|
||||
|
||||
# 发射信号
|
||||
chat_position_updated.emit(stream, topic)
|
||||
|
||||
@@ -716,7 +669,7 @@ func _on_socket_error(error: String) -> void:
|
||||
|
||||
# 处理错误
|
||||
func _handle_error(error_code: String, error_message: String) -> void:
|
||||
print("❌ ChatManager 错误: [", error_code, "] ", error_message)
|
||||
push_error("ChatManager: [%s] %s" % [error_code, error_message])
|
||||
|
||||
# 获取用户友好的错误消息
|
||||
var user_message: String = CHAT_ERROR_MESSAGES.get(error_code, error_message) as String
|
||||
|
||||
@@ -57,7 +57,6 @@ var game_version: String = "1.0.0" # 游戏版本号
|
||||
# 初始化游戏管理器
|
||||
# 在节点准备就绪时调用,设置初始状态
|
||||
func _ready():
|
||||
print("GameManager 初始化完成")
|
||||
change_state(GameState.AUTH) # 启动时进入认证状态
|
||||
|
||||
# ============ 状态管理方法 ============
|
||||
@@ -81,9 +80,6 @@ func change_state(new_state: GameState):
|
||||
previous_state = current_state
|
||||
current_state = new_state
|
||||
|
||||
# 输出状态变更日志
|
||||
print("游戏状态变更: ", GameState.keys()[previous_state], " -> ", GameState.keys()[current_state])
|
||||
|
||||
# 发送状态变更信号
|
||||
game_state_changed.emit(new_state)
|
||||
|
||||
@@ -100,7 +96,7 @@ func get_current_state() -> GameState:
|
||||
# GameState - 上一个游戏状态
|
||||
#
|
||||
# 使用场景:
|
||||
# - 从暂停状态恢复时,返回到之前的状态
|
||||
# - 从暂停状态恢复时,返回到暂停前状态
|
||||
# - 错误处理时回退到安全状态
|
||||
func get_previous_state() -> GameState:
|
||||
return previous_state
|
||||
@@ -114,14 +110,12 @@ func get_previous_state() -> GameState:
|
||||
#
|
||||
# 功能:
|
||||
# - 存储当前登录用户信息
|
||||
# - 输出用户设置日志
|
||||
#
|
||||
# 注意事项:
|
||||
# - 用户登录成功后调用此方法
|
||||
# - 用户登出时应传入空字符串
|
||||
func set_current_user(username: String):
|
||||
current_user = username
|
||||
print("当前用户设置为: ", username)
|
||||
|
||||
# 获取当前登录用户
|
||||
#
|
||||
|
||||
155
_Core/managers/LocationManager.gd
Normal file
155
_Core/managers/LocationManager.gd
Normal file
@@ -0,0 +1,155 @@
|
||||
extends Node
|
||||
|
||||
# ============================================================================
|
||||
# LocationManager.gd - 位置同步管理器
|
||||
# ============================================================================
|
||||
# 负责与后端 WebSocket 服务进行位置同步和多人会话管理
|
||||
#
|
||||
# 协议文档: new_docs/game_architecture_design.md
|
||||
# 后端地址: wss://whaletownend.xinghangee.icu/location-broadcast
|
||||
# ============================================================================
|
||||
|
||||
signal connected_to_server()
|
||||
signal connection_closed()
|
||||
signal connection_error()
|
||||
signal session_joined(data: Dictionary)
|
||||
signal user_joined(data: Dictionary)
|
||||
signal user_left(data: Dictionary)
|
||||
signal position_updated(data: Dictionary)
|
||||
|
||||
const WS_URL = "wss://whaletownend.xinghangee.icu/location-broadcast"
|
||||
const PING_INTERVAL = 25.0 # 秒
|
||||
|
||||
var _socket: WebSocketPeer
|
||||
var _connected: bool = false
|
||||
var _ping_timer: float = 0.0
|
||||
var _auth_token: String = ""
|
||||
|
||||
func _ready():
|
||||
_socket = WebSocketPeer.new()
|
||||
process_mode = Node.PROCESS_MODE_ALWAYS # 保证暂停时也能处理网络
|
||||
|
||||
func _process(delta):
|
||||
_socket.poll()
|
||||
var state = _socket.get_ready_state()
|
||||
|
||||
if state == WebSocketPeer.STATE_OPEN:
|
||||
if not _connected:
|
||||
_on_connected()
|
||||
|
||||
# 处理接收到的数据包
|
||||
while _socket.get_available_packet_count() > 0:
|
||||
var packet = _socket.get_packet()
|
||||
_handle_packet(packet)
|
||||
|
||||
# 心跳处理
|
||||
_ping_timer += delta
|
||||
if _ping_timer >= PING_INTERVAL:
|
||||
_send_heartbeat()
|
||||
_ping_timer = 0.0
|
||||
|
||||
elif state == WebSocketPeer.STATE_CLOSED:
|
||||
if _connected:
|
||||
_on_disconnected()
|
||||
|
||||
func connect_to_server():
|
||||
if _socket.get_ready_state() == WebSocketPeer.STATE_OPEN:
|
||||
return
|
||||
|
||||
var err = _socket.connect_to_url(WS_URL)
|
||||
if err != OK:
|
||||
push_error("LocationManager: WebSocket 连接请求失败,错误码: %d" % err)
|
||||
connection_error.emit()
|
||||
else:
|
||||
# Godot WebSocket connect is non-blocking, wait for state change in _process
|
||||
pass
|
||||
|
||||
func close_connection():
|
||||
_socket.close()
|
||||
|
||||
func set_auth_token(token: String):
|
||||
_auth_token = token
|
||||
|
||||
# ============ 协议发送 ============
|
||||
|
||||
func send_packet(event: String, data: Dictionary):
|
||||
if _socket.get_ready_state() != WebSocketPeer.STATE_OPEN:
|
||||
return
|
||||
|
||||
var message = {
|
||||
"event": event,
|
||||
"data": data
|
||||
}
|
||||
var json_str = JSON.stringify(message)
|
||||
_socket.put_packet(json_str.to_utf8_buffer())
|
||||
|
||||
func join_session(map_id: String, initial_pos: Vector2):
|
||||
var data = {
|
||||
"sessionId": map_id,
|
||||
"initialPosition": {
|
||||
"x": initial_pos.x,
|
||||
"y": initial_pos.y,
|
||||
"mapId": map_id
|
||||
},
|
||||
"token": _auth_token
|
||||
}
|
||||
send_packet("join_session", data)
|
||||
|
||||
func leave_session(map_id: String):
|
||||
send_packet("leave_session", {"sessionId": map_id})
|
||||
|
||||
func send_position_update(map_id: String, pos: Vector2, anim_data: Dictionary = {}):
|
||||
var data = {
|
||||
"x": pos.x,
|
||||
"y": pos.y,
|
||||
"mapId": map_id,
|
||||
"metadata": anim_data
|
||||
}
|
||||
if map_id == "":
|
||||
push_warning("LocationManager: position_update 的 map_id 为空")
|
||||
send_packet("position_update", data)
|
||||
|
||||
func _send_heartbeat():
|
||||
send_packet("heartbeat", {"timestamp": Time.get_unix_time_from_system()})
|
||||
|
||||
# ============ 事件处理 ============
|
||||
|
||||
func _on_connected():
|
||||
_connected = true
|
||||
connected_to_server.emit()
|
||||
|
||||
func _on_disconnected():
|
||||
_connected = false
|
||||
connection_closed.emit()
|
||||
|
||||
func _handle_packet(packet: PackedByteArray):
|
||||
var json_str = packet.get_string_from_utf8()
|
||||
var json = JSON.new()
|
||||
var err = json.parse(json_str)
|
||||
|
||||
if err != OK:
|
||||
push_error("LocationManager: JSON 解析失败 - %s" % json.get_error_message())
|
||||
return
|
||||
|
||||
var message = json.data
|
||||
if not message is Dictionary or not message.has("event"):
|
||||
return
|
||||
|
||||
var event = message["event"]
|
||||
var data = message.get("data", {})
|
||||
|
||||
match event:
|
||||
"session_joined":
|
||||
session_joined.emit(data)
|
||||
"user_joined":
|
||||
user_joined.emit(data)
|
||||
"user_left":
|
||||
user_left.emit(data)
|
||||
"position_update":
|
||||
position_updated.emit(data)
|
||||
"heartbeat_response":
|
||||
pass # 静默处理
|
||||
"error":
|
||||
push_error("LocationManager: WebSocket 错误事件 - %s" % JSON.stringify(data))
|
||||
_:
|
||||
push_warning("LocationManager: 未处理的 WebSocket 事件 %s" % event)
|
||||
1
_Core/managers/LocationManager.gd.uid
Normal file
1
_Core/managers/LocationManager.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://biyq426f66nkb
|
||||
@@ -109,13 +109,6 @@ class RequestInfo:
|
||||
var active_requests: Dictionary = {} # 存储所有活动请求 {request_id: RequestInfo}
|
||||
var request_counter: int = 0 # 请求计数器,用于生成唯一ID
|
||||
|
||||
# ============ 生命周期方法 ============
|
||||
|
||||
# 初始化网络管理器
|
||||
# 在节点准备就绪时调用
|
||||
func _ready():
|
||||
print("NetworkManager 已初始化")
|
||||
|
||||
# ============ 公共API接口 ============
|
||||
|
||||
# 发送GET请求
|
||||
@@ -193,14 +186,6 @@ func delete_request(endpoint: String, callback: Callable = Callable(), timeout:
|
||||
#
|
||||
# 回调函数签名:
|
||||
# func callback(success: bool, data: Dictionary, error_info: Dictionary)
|
||||
#
|
||||
# 使用示例:
|
||||
# NetworkManager.login("user@example.com", "password123", func(success, data, error):
|
||||
# if success:
|
||||
# print("登录成功: ", data)
|
||||
# else:
|
||||
# print("登录失败: ", error.message)
|
||||
# )
|
||||
func login(identifier: String, password: String, callback: Callable = Callable()) -> String:
|
||||
var data = {
|
||||
"identifier": identifier,
|
||||
@@ -472,41 +457,24 @@ func send_request(endpoint: String, method: RequestType, headers: PackedStringAr
|
||||
var godot_method = _convert_to_godot_method(method)
|
||||
var error = http_request.request(full_url, headers, godot_method, body)
|
||||
|
||||
print("=== 发送网络请求 ===")
|
||||
print("请求ID: ", request_id)
|
||||
print("URL: ", full_url)
|
||||
print("方法: ", RequestType.keys()[method])
|
||||
print("Headers: ", headers)
|
||||
print("Body: ", body if body.length() < 200 else body.substr(0, 200) + "...")
|
||||
print("发送结果: ", error)
|
||||
|
||||
if error != OK:
|
||||
print("请求发送失败,错误代码: ", error)
|
||||
push_error("NetworkManager: 请求发送失败,错误码: %d" % error)
|
||||
_handle_request_error(request_id, ErrorType.NETWORK_ERROR, "网络请求发送失败: " + str(error))
|
||||
return ""
|
||||
|
||||
return request_id
|
||||
|
||||
# 请求完成回调
|
||||
func _on_request_completed(request_id: String, result: int, response_code: int,
|
||||
headers: PackedStringArray, body: PackedByteArray):
|
||||
print("=== 网络请求完成 ===")
|
||||
print("请求ID: ", request_id)
|
||||
print("结果: ", result)
|
||||
print("状态码: ", response_code)
|
||||
print("响应头: ", headers)
|
||||
|
||||
func _on_request_completed(request_id: String, _result: int, response_code: int,
|
||||
_headers: PackedStringArray, body: PackedByteArray):
|
||||
# 获取请求信息
|
||||
if not active_requests.has(request_id):
|
||||
print("警告: 未找到请求ID ", request_id)
|
||||
push_warning("NetworkManager: 未找到请求ID %s" % request_id)
|
||||
return
|
||||
|
||||
var _request_info = active_requests[request_id]
|
||||
var response_text = body.get_string_from_utf8()
|
||||
|
||||
print("响应体长度: ", body.size(), " 字节")
|
||||
print("响应内容: ", response_text if response_text.length() < 500 else response_text.substr(0, 500) + "...")
|
||||
|
||||
# 处理网络连接失败
|
||||
if response_code == 0:
|
||||
_handle_request_error(request_id, ErrorType.NETWORK_ERROR, "网络连接失败,请检查网络连接")
|
||||
@@ -542,13 +510,11 @@ func _handle_response(request_id: String, response_code: int, data: Dictionary):
|
||||
# 特殊情况:206测试模式 - 根据API文档,这是成功的测试模式响应
|
||||
elif response_code == 206 and error_code == "TEST_MODE_ONLY":
|
||||
is_success = true
|
||||
print("🧪 测试模式响应: ", message)
|
||||
# 201创建成功
|
||||
elif response_code == 201:
|
||||
is_success = true
|
||||
|
||||
if is_success:
|
||||
print("✅ 请求成功: ", request_id)
|
||||
# 发送成功信号
|
||||
request_completed.emit(request_id, true, data)
|
||||
|
||||
@@ -556,8 +522,6 @@ func _handle_response(request_id: String, response_code: int, data: Dictionary):
|
||||
if request_info.callback.is_valid():
|
||||
request_info.callback.call(true, data, {})
|
||||
else:
|
||||
print("❌ 请求失败: ", request_id, " - HTTP:", response_code, " 错误码:", error_code, " 消息:", message)
|
||||
|
||||
# 确定错误类型
|
||||
var error_type = _determine_error_type(response_code, error_code)
|
||||
|
||||
@@ -579,7 +543,7 @@ func _handle_response(request_id: String, response_code: int, data: Dictionary):
|
||||
|
||||
# 处理请求错误
|
||||
func _handle_request_error(request_id: String, error_type: ErrorType, message: String):
|
||||
print("❌ 请求错误: ", request_id, " - ", message)
|
||||
push_error("NetworkManager: 请求错误 %s - %s" % [request_id, message])
|
||||
|
||||
# 发送错误信号
|
||||
request_failed.emit(request_id, ErrorType.keys()[error_type], message)
|
||||
@@ -638,8 +602,6 @@ func _cleanup_request(request_id: String):
|
||||
|
||||
# 从活动请求中移除
|
||||
active_requests.erase(request_id)
|
||||
|
||||
print("🧹 清理请求: ", request_id)
|
||||
|
||||
# 转换请求方法
|
||||
func _convert_to_godot_method(method: RequestType) -> HTTPClient.Method:
|
||||
@@ -662,14 +624,12 @@ func _convert_to_godot_method(method: RequestType) -> HTTPClient.Method:
|
||||
# 取消请求
|
||||
func cancel_request(request_id: String) -> bool:
|
||||
if active_requests.has(request_id):
|
||||
print("🚫 取消请求: ", request_id)
|
||||
_cleanup_request(request_id)
|
||||
return true
|
||||
return false
|
||||
|
||||
# 取消所有请求
|
||||
func cancel_all_requests():
|
||||
print("🚫 取消所有请求")
|
||||
var request_ids = active_requests.keys()
|
||||
for request_id in request_ids:
|
||||
cancel_request(request_id)
|
||||
|
||||
@@ -128,21 +128,15 @@ func handle_send_verification_code_response(success: bool, data: Dictionary, err
|
||||
var error_code = data.get("error_code", "")
|
||||
if error_code == "TEST_MODE_ONLY":
|
||||
result.success = true
|
||||
result.message = "🧪 测试模式:验证码已生成,请查看控制台"
|
||||
result.message = "🧪 测试模式:验证码已生成"
|
||||
result.toast_type = "success"
|
||||
|
||||
# 在控制台显示验证码
|
||||
if data.has("data") and data.data.has("verification_code"):
|
||||
print("🔑 测试模式验证码: ", data.data.verification_code)
|
||||
result.message += "\n验证码: " + str(data.data.verification_code)
|
||||
else:
|
||||
result.success = true
|
||||
result.message = "📧 验证码已发送到您的邮箱,请查收"
|
||||
result.toast_type = "success"
|
||||
|
||||
# 开发环境下显示验证码
|
||||
if data.has("data") and data.data.has("verification_code"):
|
||||
print("🔑 开发环境验证码: ", data.data.verification_code)
|
||||
else:
|
||||
result = _handle_send_code_error(data, error_info)
|
||||
|
||||
@@ -156,18 +150,15 @@ func handle_send_login_code_response(success: bool, data: Dictionary, error_info
|
||||
var error_code = data.get("error_code", "")
|
||||
if error_code == "TEST_MODE_ONLY":
|
||||
result.success = true
|
||||
result.message = "测试模式:登录验证码已生成,请查看控制台"
|
||||
result.message = "测试模式:登录验证码已生成"
|
||||
result.toast_type = "success"
|
||||
|
||||
if data.has("data") and data.data.has("verification_code"):
|
||||
print("测试模式登录验证码: ", data.data.verification_code)
|
||||
result.message += "\n验证码: " + str(data.data.verification_code)
|
||||
else:
|
||||
result.success = true
|
||||
result.message = "登录验证码已发送,请查收"
|
||||
result.toast_type = "success"
|
||||
|
||||
if data.has("data") and data.data.has("verification_code"):
|
||||
print("开发环境登录验证码: ", data.data.verification_code)
|
||||
else:
|
||||
result = _handle_send_login_code_error(data, error_info)
|
||||
|
||||
@@ -214,18 +205,15 @@ func handle_resend_email_verification_response(success: bool, data: Dictionary,
|
||||
var error_code = data.get("error_code", "")
|
||||
if error_code == "TEST_MODE_ONLY":
|
||||
result.success = true
|
||||
result.message = "🧪 测试模式:验证码已重新生成,请查看控制台"
|
||||
result.message = "🧪 测试模式:验证码已重新生成"
|
||||
result.toast_type = "success"
|
||||
|
||||
if data.has("data") and data.data.has("verification_code"):
|
||||
print("🔑 测试模式重新发送验证码: ", data.data.verification_code)
|
||||
result.message += "\n验证码: " + str(data.data.verification_code)
|
||||
else:
|
||||
result.success = true
|
||||
result.message = "📧 验证码已重新发送到您的邮箱,请查收"
|
||||
result.toast_type = "success"
|
||||
|
||||
if data.has("data") and data.data.has("verification_code"):
|
||||
print("🔑 开发环境重新发送验证码: ", data.data.verification_code)
|
||||
else:
|
||||
result = _handle_resend_email_verification_error(data, error_info)
|
||||
|
||||
@@ -239,18 +227,15 @@ func handle_forgot_password_response(success: bool, data: Dictionary, error_info
|
||||
var error_code = data.get("error_code", "")
|
||||
if error_code == "TEST_MODE_ONLY":
|
||||
result.success = true
|
||||
result.message = "🧪 测试模式:重置验证码已生成,请查看控制台"
|
||||
result.message = "🧪 测试模式:重置验证码已生成"
|
||||
result.toast_type = "success"
|
||||
|
||||
if data.has("data") and data.data.has("verification_code"):
|
||||
print("🔑 测试模式重置验证码: ", data.data.verification_code)
|
||||
result.message += "\n验证码: " + str(data.data.verification_code)
|
||||
else:
|
||||
result.success = true
|
||||
result.message = "📧 重置验证码已发送,请查收"
|
||||
result.toast_type = "success"
|
||||
|
||||
if data.has("data") and data.data.has("verification_code"):
|
||||
print("🔑 开发环境重置验证码: ", data.data.verification_code)
|
||||
else:
|
||||
result = _handle_forgot_password_error(data, error_info)
|
||||
|
||||
|
||||
@@ -36,6 +36,8 @@ signal scene_change_started(scene_name: String)
|
||||
# 场景状态
|
||||
var current_scene_name: String = "" # 当前场景名称
|
||||
var is_changing_scene: bool = false # 是否正在切换场景
|
||||
var _next_scene_position: Variant = null # 下一个场景的初始位置 (Vector2 or null)
|
||||
var _next_spawn_name: String = "" # 下一个场景的出生点名称 (String)
|
||||
|
||||
# 场景路径映射表
|
||||
# 将场景名称映射到实际的文件路径
|
||||
@@ -47,16 +49,14 @@ var scene_paths: Dictionary = {
|
||||
"battle": "res://scenes/maps/battle_scene.tscn", # 战斗场景 - 战斗系统
|
||||
"inventory": "res://scenes/ui/InventoryWindow.tscn", # 背包界面
|
||||
"shop": "res://scenes/ui/ShopWindow.tscn", # 商店界面
|
||||
"settings": "res://scenes/ui/SettingsWindow.tscn" # 设置界面
|
||||
"settings": "res://scenes/ui/SettingsWindow.tscn", # 设置界面
|
||||
"square": "res://scenes/Maps/square.tscn", # 广场地图
|
||||
"room": "res://scenes/Maps/room.tscn", # 房间地图
|
||||
"fountain": "res://scenes/Maps/fountain.tscn", # 喷泉地图
|
||||
"datawhale_home": "res://scenes/Maps/datawhale_home.tscn", # 数据鲸鱼之家
|
||||
"community": "res://scenes/Maps/community.tscn" # 社区地图
|
||||
}
|
||||
|
||||
# ============ 生命周期方法 ============
|
||||
|
||||
# 初始化场景管理器
|
||||
# 在节点准备就绪时调用
|
||||
func _ready():
|
||||
print("SceneManager 初始化完成")
|
||||
|
||||
# ============ 场景切换方法 ============
|
||||
|
||||
# 切换到指定场景
|
||||
@@ -77,8 +77,6 @@ func _ready():
|
||||
#
|
||||
# 使用示例:
|
||||
# var success = SceneManager.change_scene("main", true)
|
||||
# if success:
|
||||
# print("场景切换成功")
|
||||
#
|
||||
# 注意事项:
|
||||
# - 场景切换是异步操作
|
||||
@@ -87,16 +85,15 @@ func _ready():
|
||||
func change_scene(scene_name: String, use_transition: bool = true):
|
||||
# 防止重复切换
|
||||
if is_changing_scene:
|
||||
print("场景切换中,忽略新的切换请求")
|
||||
push_warning("SceneManager: 场景切换中,忽略新的切换请求")
|
||||
return false
|
||||
|
||||
# 检查场景是否存在
|
||||
if not scene_paths.has(scene_name):
|
||||
print("错误: 未找到场景 ", scene_name)
|
||||
push_error("SceneManager: 未找到场景 %s" % scene_name)
|
||||
return false
|
||||
|
||||
var scene_path = scene_paths[scene_name]
|
||||
print("开始切换场景: ", current_scene_name, " -> ", scene_name)
|
||||
|
||||
# 设置切换状态
|
||||
is_changing_scene = true
|
||||
@@ -109,7 +106,7 @@ func change_scene(scene_name: String, use_transition: bool = true):
|
||||
# 执行场景切换
|
||||
var error = get_tree().change_scene_to_file(scene_path)
|
||||
if error != OK:
|
||||
print("场景切换失败: ", error)
|
||||
push_error("SceneManager: 场景切换失败 %s -> %s, 错误码: %d" % [current_scene_name, scene_name, error])
|
||||
is_changing_scene = false
|
||||
return false
|
||||
|
||||
@@ -122,18 +119,83 @@ func change_scene(scene_name: String, use_transition: bool = true):
|
||||
if use_transition:
|
||||
await hide_transition()
|
||||
|
||||
print("场景切换完成: ", scene_name)
|
||||
return true
|
||||
|
||||
# ============ 查询方法 ============
|
||||
|
||||
# 获取当前场景名称
|
||||
#
|
||||
#
|
||||
# 返回值:
|
||||
# String - 当前场景的名称
|
||||
func get_current_scene_name() -> String:
|
||||
return current_scene_name
|
||||
|
||||
# ============ 场景位置和出生点管理 ============
|
||||
|
||||
# 设置下一个场景的初始位置
|
||||
#
|
||||
# 参数:
|
||||
# pos: Vector2 - 玩家在下一个场景的初始位置
|
||||
#
|
||||
# 功能:
|
||||
# - 用于场景切换时传递玩家位置信息
|
||||
# - 配合 DoorTeleport 等传送机制使用
|
||||
#
|
||||
# 使用示例:
|
||||
# SceneManager.set_next_scene_position(Vector2(100, 200))
|
||||
# SceneManager.change_scene("room")
|
||||
func set_next_scene_position(pos: Vector2) -> void:
|
||||
_next_scene_position = pos
|
||||
|
||||
# 获取并清除下一个场景的初始位置
|
||||
#
|
||||
# 返回值:
|
||||
# Variant - Vector2 位置或 null(如果未设置)
|
||||
#
|
||||
# 功能:
|
||||
# - 获取预设的场景初始位置
|
||||
# - 获取后自动清除,避免影响后续场景切换
|
||||
#
|
||||
# 注意事项:
|
||||
# - 此方法会清除存储的位置,只能获取一次
|
||||
# - 如果未设置位置,返回 null
|
||||
func get_next_scene_position() -> Variant:
|
||||
var pos = _next_scene_position
|
||||
_next_scene_position = null
|
||||
return pos
|
||||
|
||||
# 设置下一个场景的出生点名称
|
||||
#
|
||||
# 参数:
|
||||
# spawn_name: String - 出生点节点的名称
|
||||
#
|
||||
# 功能:
|
||||
# - 指定玩家在下一个场景应该出现在哪个出生点
|
||||
# - 配合场景中的 Marker2D 出生点使用
|
||||
#
|
||||
# 使用示例:
|
||||
# SceneManager.set_next_spawn_name("DoorExit")
|
||||
# SceneManager.change_scene("square")
|
||||
func set_next_spawn_name(spawn_name: String) -> void:
|
||||
_next_spawn_name = spawn_name
|
||||
|
||||
# 获取并清除下一个场景的出生点名称
|
||||
#
|
||||
# 返回值:
|
||||
# String - 出生点名称(如果未设置则返回空字符串)
|
||||
#
|
||||
# 功能:
|
||||
# - 获取预设的出生点名称
|
||||
# - 获取后自动清除,避免影响后续场景切换
|
||||
#
|
||||
# 注意事项:
|
||||
# - 此方法会清除存储的名称,只能获取一次
|
||||
# - 如果未设置名称,返回空字符串
|
||||
func get_next_spawn_name() -> String:
|
||||
var name = _next_spawn_name
|
||||
_next_spawn_name = ""
|
||||
return name
|
||||
|
||||
# ============ 场景注册方法 ============
|
||||
|
||||
# 注册新场景
|
||||
@@ -150,7 +212,6 @@ func get_current_scene_name() -> String:
|
||||
# SceneManager.register_scene("boss_battle", "res://scenes/boss/boss_battle.tscn")
|
||||
func register_scene(scene_name: String, scene_path: String):
|
||||
scene_paths[scene_name] = scene_path
|
||||
print("注册场景: ", scene_name, " -> ", scene_path)
|
||||
|
||||
# ============ 过渡效果方法 ============
|
||||
|
||||
@@ -166,8 +227,7 @@ func register_scene(scene_name: String, scene_path: String):
|
||||
#
|
||||
# TODO: 实现淡入淡出、滑动等过渡效果
|
||||
func show_transition():
|
||||
# TODO: 实现场景切换过渡效果
|
||||
print("显示场景切换过渡效果")
|
||||
# TODO: 实现场景切换过渡效果(当前仅占位延时)
|
||||
await get_tree().create_timer(0.2).timeout
|
||||
|
||||
# 隐藏场景切换过渡效果
|
||||
@@ -182,6 +242,5 @@ func show_transition():
|
||||
#
|
||||
# TODO: 实现与show_transition()对应的隐藏效果
|
||||
func hide_transition():
|
||||
# TODO: 隐藏场景切换过渡效果
|
||||
print("隐藏场景切换过渡效果")
|
||||
# TODO: 隐藏场景切换过渡效果(当前仅占位延时)
|
||||
await get_tree().create_timer(0.2).timeout
|
||||
|
||||
@@ -40,7 +40,6 @@ var toast_counter: int = 0 # Toast计数器,用于生成
|
||||
# container: Control - Toast消息的容器节点
|
||||
func setup(container: Control):
|
||||
toast_container = container
|
||||
print("ToastManager 初始化完成")
|
||||
|
||||
# ============ 公共方法 ============
|
||||
|
||||
@@ -51,10 +50,9 @@ func setup(container: Control):
|
||||
# is_success: bool - 是否为成功消息(影响颜色)
|
||||
func show_toast(message: String, is_success: bool = true):
|
||||
if toast_container == null:
|
||||
print("错误: toast_container 节点不存在")
|
||||
push_error("ToastManager: toast_container 节点不存在")
|
||||
return
|
||||
|
||||
print("显示Toast消息: ", message, " 成功: ", is_success)
|
||||
_create_toast_instance(message, is_success)
|
||||
|
||||
# 清理所有Toast
|
||||
@@ -123,21 +121,17 @@ func _create_toast_instance(message: String, is_success: bool):
|
||||
|
||||
# 平台特定的字体处理
|
||||
if is_web:
|
||||
print("Web平台Toast字体处理")
|
||||
# Web平台使用主题文件
|
||||
var chinese_theme = load("res://assets/ui/chinese_theme.tres")
|
||||
if chinese_theme:
|
||||
text_label.theme = chinese_theme
|
||||
print("Web平台应用中文主题")
|
||||
else:
|
||||
print("Web平台中文主题加载失败")
|
||||
push_warning("ToastManager: Web平台中文主题加载失败,使用默认字体")
|
||||
else:
|
||||
print("桌面平台Toast字体处理")
|
||||
# 桌面平台直接加载中文字体
|
||||
var desktop_chinese_font = load("res://assets/fonts/msyh.ttc")
|
||||
if desktop_chinese_font:
|
||||
text_label.add_theme_font_override("font", desktop_chinese_font)
|
||||
print("桌面平台使用中文字体")
|
||||
|
||||
text_label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
|
||||
text_label.custom_minimum_size = Vector2(280, 0)
|
||||
@@ -231,4 +225,4 @@ func _rearrange_toasts():
|
||||
if is_instance_valid(toast):
|
||||
var tween = toast_container.create_tween()
|
||||
tween.tween_property(toast, "position:y", current_y, 0.2)
|
||||
current_y += toast.size.y + 15
|
||||
current_y += toast.size.y + 15
|
||||
|
||||
@@ -21,7 +21,7 @@ extends Node
|
||||
# - 通过信号通知连接状态变化
|
||||
# ============================================================================
|
||||
|
||||
class_name WebSocketManager
|
||||
class_name ChatWebSocketManager
|
||||
|
||||
# ============================================================================
|
||||
# 信号定义
|
||||
@@ -118,8 +118,6 @@ const HEARTBEAT_INTERVAL: float = 30.0
|
||||
|
||||
# 初始化
|
||||
func _ready() -> void:
|
||||
print("WebSocketManager 初始化完成")
|
||||
|
||||
# 设置重连定时器
|
||||
_setup_reconnect_timer()
|
||||
|
||||
@@ -135,11 +133,6 @@ func _process(_delta: float) -> void:
|
||||
_check_websocket_state()
|
||||
|
||||
var state: WebSocketPeer.State = _websocket_peer.get_ready_state()
|
||||
|
||||
# 调试:打印状态变化
|
||||
if _connection_state == ConnectionState.CONNECTING:
|
||||
var peer_state_name = ["DISCONNECTED", "CONNECTING", "OPEN", "CLOSING", "CLOSED"][state]
|
||||
print("📡 WebSocket 状态: peer=%s, manager=%s" % [peer_state_name, ConnectionState.keys()[_connection_state]])
|
||||
|
||||
if state == WebSocketPeer.STATE_OPEN:
|
||||
# 接收数据
|
||||
@@ -153,9 +146,6 @@ func _process(_delta: float) -> void:
|
||||
# 发射消息接收信号
|
||||
data_received.emit(message)
|
||||
|
||||
# 打印调试信息
|
||||
print("📨 WebSocket 收到消息: ", message)
|
||||
|
||||
# 清理
|
||||
func _exit_tree() -> void:
|
||||
_disconnect()
|
||||
@@ -178,17 +168,13 @@ func connect_to_game_server() -> void:
|
||||
push_warning("已经在连接或已连接状态")
|
||||
return
|
||||
|
||||
print("=== WebSocketManager 开始连接 ===")
|
||||
print("服务器 URL: ", WEBSOCKET_URL)
|
||||
print("WebSocket 连接中...")
|
||||
|
||||
_set_connection_state(ConnectionState.CONNECTING)
|
||||
_clean_close = true
|
||||
_reconnect_attempt = 0
|
||||
|
||||
var err: Error = _websocket_peer.connect_to_url(WEBSOCKET_URL)
|
||||
if err != OK:
|
||||
print("❌ WebSocket 连接失败: ", error_string(err))
|
||||
push_error("WebSocketManager: 连接失败 - %s" % error_string(err))
|
||||
_set_connection_state(ConnectionState.ERROR)
|
||||
return
|
||||
|
||||
@@ -197,7 +183,6 @@ func connect_to_game_server() -> void:
|
||||
|
||||
# 断开 WebSocket 连接
|
||||
func disconnect_websocket() -> void:
|
||||
print("=== WebSocketManager 断开连接 ===")
|
||||
_disconnect()
|
||||
|
||||
# 断开连接(内部方法)
|
||||
@@ -243,15 +228,14 @@ func get_connection_state() -> ConnectionState:
|
||||
# Error - 错误码,OK 表示成功
|
||||
func send_message(message: String) -> Error:
|
||||
if _websocket_peer.get_ready_state() != WebSocketPeer.STATE_OPEN:
|
||||
print("❌ WebSocket 未连接,无法发送消息")
|
||||
push_warning("WebSocketManager: 未连接,无法发送消息")
|
||||
return ERR_UNCONFIGURED
|
||||
|
||||
var err: Error = _websocket_peer.send_text(message)
|
||||
if err != OK:
|
||||
print("❌ WebSocket 发送消息失败: ", error_string(err))
|
||||
push_error("WebSocketManager: 发送消息失败 - %s" % error_string(err))
|
||||
return err
|
||||
|
||||
print("📤 发送 WebSocket 消息: ", message)
|
||||
return OK
|
||||
|
||||
# ============================================================================
|
||||
@@ -272,10 +256,6 @@ func enable_auto_reconnect(enabled: bool, max_attempts: int = DEFAULT_MAX_RECONN
|
||||
_max_reconnect_attempts = max_attempts
|
||||
_reconnect_base_delay = base_delay
|
||||
|
||||
print("自动重连: ", "启用" if enabled else "禁用")
|
||||
print("最大重连次数: ", _max_reconnect_attempts)
|
||||
print("基础重连延迟: ", _reconnect_base_delay, " 秒")
|
||||
|
||||
# 获取重连信息
|
||||
#
|
||||
# 返回值:
|
||||
@@ -298,7 +278,6 @@ func _set_connection_state(new_state: ConnectionState) -> void:
|
||||
return
|
||||
|
||||
_connection_state = new_state
|
||||
print("📡 连接状态变更: ", ConnectionState.keys()[new_state])
|
||||
|
||||
# 发射信号
|
||||
connection_state_changed.emit(new_state)
|
||||
@@ -332,27 +311,19 @@ func _check_websocket_state() -> void:
|
||||
WebSocketPeer.STATE_CLOSED:
|
||||
# 连接关闭
|
||||
var code: int = _websocket_peer.get_close_code()
|
||||
var reason: String = _websocket_peer.get_close_reason()
|
||||
print("🔌 WebSocket 关闭: code=%d, reason=%s" % [code, reason])
|
||||
_on_websocket_closed(code != 0) # code=0 表示正常关闭
|
||||
|
||||
# WebSocket 连接成功处理
|
||||
func _on_websocket_connected() -> void:
|
||||
print("✅ WebSocketManager: WebSocket 连接成功")
|
||||
|
||||
# 如果是重连,发射重连成功信号
|
||||
if _connection_state == ConnectionState.RECONNECTING:
|
||||
_reconnect_attempt = 0
|
||||
reconnection_succeeded.emit()
|
||||
print("🔄 重连成功")
|
||||
|
||||
_set_connection_state(ConnectionState.CONNECTED)
|
||||
|
||||
# WebSocket 连接关闭处理
|
||||
func _on_websocket_closed(clean_close: bool) -> void:
|
||||
print("🔌 WebSocketManager: WebSocket 连接断开")
|
||||
print(" 正常关闭: ", clean_close)
|
||||
|
||||
_clean_close = clean_close
|
||||
|
||||
# 如果是异常断开且启用了自动重连
|
||||
@@ -379,7 +350,7 @@ func _setup_reconnect_timer() -> void:
|
||||
func _attempt_reconnect() -> void:
|
||||
# 检查是否超过最大重连次数
|
||||
if _reconnect_attempt >= _max_reconnect_attempts:
|
||||
print("❌ 达到最大重连次数 (", _max_reconnect_attempts, "),停止重连")
|
||||
push_error("WebSocketManager: 达到最大重连次数 (%d),停止重连" % _max_reconnect_attempts)
|
||||
reconnection_failed.emit(_reconnect_attempt, _max_reconnect_attempts)
|
||||
_set_connection_state(ConnectionState.ERROR)
|
||||
return
|
||||
@@ -389,8 +360,6 @@ func _attempt_reconnect() -> void:
|
||||
|
||||
# 计算重连延迟(指数退避)
|
||||
var delay: float = _calculate_reconnect_delay()
|
||||
print("🔄 尝试重连 (", _reconnect_attempt, "/", _max_reconnect_attempts, ")")
|
||||
print(" 延迟: ", delay, " 秒")
|
||||
|
||||
# 启动重连定时器
|
||||
_reconnect_timer.start(delay)
|
||||
@@ -405,7 +374,6 @@ func _calculate_reconnect_delay() -> float:
|
||||
|
||||
# 重连定时器超时处理
|
||||
func _on_reconnect_timeout() -> void:
|
||||
print("⏰ 重连定时器超时,开始重连...")
|
||||
_clean_close = false
|
||||
connect_to_game_server()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user