forked from datawhale/whale-town-front
修bug
This commit is contained in:
@@ -122,6 +122,10 @@ var _current_map: String = ""
|
||||
# 游戏 token
|
||||
var _game_token: String = ""
|
||||
|
||||
# 发送后本地回显去重(避免服务端也回发导致重复显示)
|
||||
const SELF_ECHO_DEDUPE_WINDOW: float = 10.0
|
||||
var _pending_self_messages: Array[Dictionary] = []
|
||||
|
||||
# ============================================================================
|
||||
# 生命周期方法
|
||||
# ============================================================================
|
||||
@@ -240,7 +244,10 @@ func send_chat_message(content: String, scope: String = "local") -> void:
|
||||
|
||||
# 发送消息(JSON 字符串)
|
||||
var json_string := JSON.stringify(message_data)
|
||||
_websocket_manager.send_message(json_string)
|
||||
var send_err: Error = _websocket_manager.send_message(json_string)
|
||||
if send_err != OK:
|
||||
_handle_error("SEND_FAILED", "WebSocket send failed: %s" % error_string(send_err))
|
||||
return
|
||||
|
||||
# 记录发送时间
|
||||
_record_message_timestamp()
|
||||
@@ -253,6 +260,24 @@ func send_chat_message(content: String, scope: String = "local") -> void:
|
||||
"is_self": true
|
||||
})
|
||||
|
||||
var now_timestamp: float = Time.get_unix_time_from_system()
|
||||
|
||||
# 记录待去重的“自己消息”(如果服务端也回发 chat_render,则避免重复显示)
|
||||
_pending_self_messages.append({
|
||||
"content": content,
|
||||
"expires_at": now_timestamp + SELF_ECHO_DEDUPE_WINDOW
|
||||
})
|
||||
|
||||
# 本地回显:UI 目前只订阅 CHAT_MESSAGE_RECEIVED,所以这里也发一次 received
|
||||
chat_message_received.emit(_current_username, content, true, now_timestamp)
|
||||
EventSystem.emit_event(EventNames.CHAT_MESSAGE_RECEIVED, {
|
||||
"from_user": _current_username,
|
||||
"content": content,
|
||||
"show_bubble": true,
|
||||
"timestamp": now_timestamp,
|
||||
"is_self": true
|
||||
})
|
||||
|
||||
print("📤 发送聊天消息: ", content)
|
||||
|
||||
# 消息发送完成回调
|
||||
@@ -427,6 +452,7 @@ func _on_history_loaded(messages: Array) -> void:
|
||||
"content": message.get("content", ""),
|
||||
"show_bubble": false,
|
||||
"timestamp": message.get("timestamp", 0.0),
|
||||
"is_self": (not _current_username.is_empty() and message.get("from_user", "") == _current_username),
|
||||
"is_history": true # 标记为历史消息
|
||||
})
|
||||
|
||||
@@ -504,6 +530,8 @@ func _on_data_received(message: String) -> void:
|
||||
_handle_login_success(data)
|
||||
"login_error":
|
||||
_handle_login_error(data)
|
||||
"chat":
|
||||
_handle_chat_render(data)
|
||||
"chat_sent":
|
||||
_handle_chat_sent(data)
|
||||
"chat_error":
|
||||
@@ -580,10 +608,24 @@ func _handle_chat_error(data: Dictionary) -> void:
|
||||
|
||||
# 处理接收到的聊天消息
|
||||
func _handle_chat_render(data: Dictionary) -> void:
|
||||
var from_user: String = data.get("from", "")
|
||||
var content: String = data.get("txt", "")
|
||||
var show_bubble: bool = data.get("bubble", false)
|
||||
var timestamp: float = float(data.get("timestamp", "0.0"))
|
||||
# 兼容不同后端字段命名:
|
||||
# - chat_render: {from, txt, bubble, timestamp}
|
||||
# - chat: {content, scope, (可选 from/username/timestamp)}
|
||||
var from_user: String = data.get("from", data.get("from_user", data.get("username", "")))
|
||||
var content: String = data.get("txt", data.get("content", ""))
|
||||
var show_bubble: bool = bool(data.get("bubble", data.get("show_bubble", false)))
|
||||
|
||||
var timestamp: float = _parse_chat_timestamp_to_unix(data.get("timestamp", 0.0))
|
||||
|
||||
var is_self: bool = (not _current_username.is_empty() and from_user == _current_username)
|
||||
if is_self and _consume_pending_self_message(content):
|
||||
# 已经本地回显过,避免重复显示
|
||||
return
|
||||
|
||||
# 如果服务端没带发送者信息,但内容匹配最近自己发送的消息,则认为是自己消息
|
||||
if from_user.is_empty() and _consume_pending_self_message(content):
|
||||
from_user = _current_username
|
||||
is_self = true
|
||||
|
||||
print("📨 收到聊天消息: ", from_user, " -> ", content)
|
||||
|
||||
@@ -592,7 +634,7 @@ func _handle_chat_render(data: Dictionary) -> void:
|
||||
"from_user": from_user,
|
||||
"content": content,
|
||||
"timestamp": timestamp,
|
||||
"is_self": false
|
||||
"is_self": is_self
|
||||
})
|
||||
|
||||
# 发射信号
|
||||
@@ -603,9 +645,44 @@ func _handle_chat_render(data: Dictionary) -> void:
|
||||
"from_user": from_user,
|
||||
"content": content,
|
||||
"show_bubble": show_bubble,
|
||||
"timestamp": timestamp
|
||||
"timestamp": timestamp,
|
||||
"is_self": is_self
|
||||
})
|
||||
|
||||
# 解析聊天消息时间戳(兼容 unix 秒 / ISO 8601 字符串)
|
||||
func _parse_chat_timestamp_to_unix(timestamp_raw: Variant) -> float:
|
||||
if typeof(timestamp_raw) == TYPE_INT or typeof(timestamp_raw) == TYPE_FLOAT:
|
||||
var ts := float(timestamp_raw)
|
||||
return ts if ts > 0.0 else Time.get_unix_time_from_system()
|
||||
|
||||
var ts_str := str(timestamp_raw)
|
||||
if ts_str.strip_edges().is_empty():
|
||||
return Time.get_unix_time_from_system()
|
||||
|
||||
# 纯数字字符串(必须整串都是数字/小数点,避免把 ISO 字符串前缀 "2026" 误判成时间戳)
|
||||
var numeric_regex := RegEx.new()
|
||||
numeric_regex.compile("^\\s*-?\\d+(?:\\.\\d+)?\\s*$")
|
||||
if numeric_regex.search(ts_str) != null:
|
||||
var ts_num := float(ts_str)
|
||||
return ts_num if ts_num > 0.0 else Time.get_unix_time_from_system()
|
||||
|
||||
# ISO 8601: 2026-01-19T15:15:43.930Z
|
||||
var regex := RegEx.new()
|
||||
regex.compile("(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2})")
|
||||
var result := regex.search(ts_str)
|
||||
if result == null:
|
||||
return Time.get_unix_time_from_system()
|
||||
|
||||
var utc_dict := {
|
||||
"year": int(result.get_string(1)),
|
||||
"month": int(result.get_string(2)),
|
||||
"day": int(result.get_string(3)),
|
||||
"hour": int(result.get_string(4)),
|
||||
"minute": int(result.get_string(5)),
|
||||
"second": int(result.get_string(6))
|
||||
}
|
||||
return Time.get_unix_time_from_datetime_dict(utc_dict)
|
||||
|
||||
# 处理位置更新成功
|
||||
func _handle_position_updated(data: Dictionary) -> void:
|
||||
var stream: String = data.get("stream", "")
|
||||
@@ -665,6 +742,24 @@ func _record_message_timestamp() -> void:
|
||||
var current_time := Time.get_unix_time_from_system()
|
||||
_message_timestamps.append(current_time)
|
||||
|
||||
# 消费一个待去重的“自己消息”(允许相同内容多次发送:每次消费一个)
|
||||
func _consume_pending_self_message(content: String) -> bool:
|
||||
var now := Time.get_unix_time_from_system()
|
||||
|
||||
# 先清理过期项
|
||||
for i in range(_pending_self_messages.size() - 1, -1, -1):
|
||||
var item: Dictionary = _pending_self_messages[i]
|
||||
if float(item.get("expires_at", 0.0)) < now:
|
||||
_pending_self_messages.remove_at(i)
|
||||
|
||||
# 再匹配内容
|
||||
for i in range(_pending_self_messages.size() - 1, -1, -1):
|
||||
if str(_pending_self_messages[i].get("content", "")) == content:
|
||||
_pending_self_messages.remove_at(i)
|
||||
return true
|
||||
|
||||
return false
|
||||
|
||||
# 添加消息到当前会话历史
|
||||
func _add_message_to_history(message: Dictionary) -> void:
|
||||
_message_history.append(message)
|
||||
|
||||
Reference in New Issue
Block a user