# whisper_chat_system.gd —— 40250 独立多标签私聊与任务栏闪烁通知系统 1:1 # 严格对照: # Client/Eternexus/root/uiwhisper.py (WhisperDialog, WhisperButton) # ClientVS22/source/UserInterface/PythonChat.cpp (RenderWhisper, WhisperMode) # ClientVS22/source/UserInterface/PythonPlayer.cpp (ToggleIgnoreTarget, IsIgnoreTarget) extends RefCounted const COLOR_NORMAL := "#FFFFFF" const COLOR_GM := "#FFE700" # 官方 GM 专属亮金黄色 const COLOR_SYSTEM := "#00FFFF" enum DialogState { VISIBLE, # 展开在前台 MINIMIZED, # 最小化到底部任务栏 CLOSED # 完全关闭 } class WhisperMessage: var sender: String var content: String var timestamp: int var is_gm: bool = false func _init(p_sender: String, p_content: String, p_time: int, p_is_gm: bool = false) -> void: sender = p_sender content = p_content timestamp = p_time is_gm = p_is_gm class WhisperConversation: var target_name: String var is_gamemaster: bool = false var state: int = DialogState.VISIBLE var is_blinking: bool = false # 任务栏闪烁标识 var unread_count: int = 0 var history: Array = [] # Array of WhisperMessage func _init(p_target: String, p_is_gm: bool = false) -> void: target_name = p_target is_gamemaster = p_is_gm state = DialogState.VISIBLE is_blinking = false unread_count = 0 history = [] var main_player_name: String = "Hero" var conversations: Dictionary = {} # target_name -> WhisperConversation var ignored_targets: Dictionary = {} # target_name -> bool var current_time: int = 1000 func _init(player_name: String = "Hero") -> void: main_player_name = player_name conversations.clear() ignored_targets.clear() current_time = 1000 # 1. 打开或激活与某人的私聊窗口 (uiwhisper.py: OpenWhisperDialog) func open_conversation(target_name: String) -> WhisperConversation: if target_name.is_empty(): return null var conv: WhisperConversation = null if conversations.has(target_name): conv = conversations[target_name] conv.state = DialogState.VISIBLE conv.is_blinking = false conv.unread_count = 0 else: var is_gm: bool = target_name.begins_with("[GM]") conv = WhisperConversation.new(target_name, is_gm) conversations[target_name] = conv return conv # 2. 最小化私聊窗口到任务栏 (uiwhisper.py: Minimize) func minimize_conversation(target_name: String) -> bool: if not conversations.has(target_name): return false conversations[target_name].state = DialogState.MINIMIZED return true # 3. 关闭私聊窗口 (uiwhisper.py: Close) func close_conversation(target_name: String) -> bool: if not conversations.has(target_name): return false conversations[target_name].state = DialogState.CLOSED return true # 4. 收到私聊消息 (1:1 PythonChat::AppendWhisper) func receive_whisper(sender_name: String, text: String, is_gm_override: bool = false) -> Dictionary: var res := { "delivered": false, "blocked_by_ignore": false, "triggered_blink": false, "conversation": null, "error_code": "OK" } # 检查黑名单免打扰 (ToggleIgnoreTarget / IsIgnoreTarget) if is_ignored(sender_name): res["blocked_by_ignore"] = true res["error_code"] = "BLOCKED_BY_IGNORE" return res var is_gm: bool = is_gm_override or sender_name.begins_with("[GM]") # 获取或创建会话 var conv: WhisperConversation = null if conversations.has(sender_name): conv = conversations[sender_name] else: conv = WhisperConversation.new(sender_name, is_gm) conv.state = DialogState.MINIMIZED # 新收到的私聊若未预先开启则最小化并在任务栏闪烁 conversations[sender_name] = conv var msg = WhisperMessage.new(sender_name, text, current_time, is_gm) conv.history.append(msg) # 若处于最小化或后台,激活任务栏闪烁与未读计数 if conv.state == DialogState.MINIMIZED or conv.state == DialogState.CLOSED: conv.is_blinking = true conv.unread_count += 1 res["triggered_blink"] = true res["delivered"] = true res["conversation"] = conv return res # 5. 发送私聊消息 func send_whisper(target_name: String, text: String) -> Dictionary: var res := { "success": false, "error_code": "OK", "message": "" } if target_name.is_empty(): res["error_code"] = "EMPTY_TARGET" return res if text.strip_edges().is_empty(): res["error_code"] = "EMPTY_MESSAGE" return res var conv = open_conversation(target_name) var msg = WhisperMessage.new(main_player_name, text, current_time, false) conv.history.append(msg) res["success"] = true return res # 6. 拉黑/解除拉黑目标 (1:1 player.ToggleIgnoreTarget) func toggle_ignore_target(target_name: String) -> bool: if target_name.is_empty(): return false if ignored_targets.has(target_name): ignored_targets.erase(target_name) return false # 现在未拉黑 else: ignored_targets[target_name] = true return true # 现在已拉黑 func is_ignored(target_name: String) -> bool: return ignored_targets.get(target_name, false) # 7. 获取当前所有在任务栏闪烁的会话列表 func get_blinking_conversations() -> Array: var list: Array = [] for k in conversations: var c: WhisperConversation = conversations[k] if c.is_blinking: list.append(c) return list