From aad2789f58df554f2ef933e06f7d02a8ee0ab3ca Mon Sep 17 00:00:00 2001 From: CuongNV <> Date: Thu, 2 Apr 2026 11:42:34 +0700 Subject: [PATCH] add logic whisper --- .../PerfectWorld/Scripts/UI/Chat/DlgChat.cs | 22 +++++- Assets/Scripts/ChatInputHandler.cs | 73 ++++++++++++++++--- 2 files changed, 82 insertions(+), 13 deletions(-) diff --git a/Assets/PerfectWorld/Scripts/UI/Chat/DlgChat.cs b/Assets/PerfectWorld/Scripts/UI/Chat/DlgChat.cs index 236e8b1530..ed432b3e49 100644 --- a/Assets/PerfectWorld/Scripts/UI/Chat/DlgChat.cs +++ b/Assets/PerfectWorld/Scripts/UI/Chat/DlgChat.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using BrewMonster.Network; using CSNetwork.GPDataType; namespace BrewMonster.UI @@ -29,8 +30,11 @@ namespace BrewMonster.UI { ChatChannel.GP_CHAT_COUNTRY, "FFFFFF" } }; - public const string NPC_COLOR = "C8FF64"; - public const string KING_COLOR = "8A2BE2"; + public const string NPC_COLOR = "C8FF64"; + public const string KING_COLOR = "8A2BE2"; + // [Port] C++: CDlgChat::m_pszWhisperFriendColor = "^FF4AB0" + // Màu hồng cho whisper từ/tới bạn bè trong danh sách + public const string WHISPER_FRIEND_COLOR = "FF4AB0"; /// /// Formats a message with TextMeshPro color tags based on the channel. @@ -55,10 +59,22 @@ namespace BrewMonster.UI /// /// Returns the hex color string for a given channel. /// Mirrors CDlgChat::GetChatColor in C++. - /// idPlayer is reserved for future per-player coloring (e.g. friend highlight). /// + /// Chat channel + /// Sender/recipient role ID — used to check friend status for GP_CHAT_WHISPER public static string GetChatColor(ChatChannel channel, int idPlayer = -1) { + // [Port] C++: DlgChat.cpp dòng 142-157 + // if (iChannel == GP_CHAT_WHISPER && pFriendMan->GetFriendByID(idPlayer)) + // return m_pszWhisperFriendColor; // "^FF4AB0" (hồng) + if (channel == ChatChannel.GP_CHAT_WHISPER && idPlayer > 0) + { + var host = EC_Game.GetGameRun()?.GetHostPlayer(); + var friendMan = host?.GetFriendMan(); + if (friendMan != null && friendMan.GetFriendByID(idPlayer).HasValue) + return WHISPER_FRIEND_COLOR; + } + if (ChannelColors.TryGetValue(channel, out string hexColor)) return hexColor; return "FFFFFF"; diff --git a/Assets/Scripts/ChatInputHandler.cs b/Assets/Scripts/ChatInputHandler.cs index c44b26a58d..9204c57da9 100644 --- a/Assets/Scripts/ChatInputHandler.cs +++ b/Assets/Scripts/ChatInputHandler.cs @@ -4,6 +4,7 @@ using TMPro; using CSNetwork.GPDataType; using System.Collections.Generic; using BrewMonster.Network; +using BrewMonster.UI; using CSNetwork; namespace BrewMonster.Scripts.ChatUI @@ -433,11 +434,54 @@ namespace BrewMonster.Scripts.ChatUI // [Port] C++: CDlgChat::OnCommand_speak → privatechat branch // Gửi tin nhắn mật (whisper) lên server qua GameSession. - UnityGameSession.Instance.GameSession.SendPrivateChatData(target, msg, 0, 0, pack, slot); + // Tra cứu ID của người nhận từ danh sách bạn bè (giống C++: pFriend ? pFriend->id : -1) + int idTarget = GetCharacterIdByName(target); + UnityGameSession.Instance.GameSession.SendPrivateChatData(target, msg, 0, idTarget, pack, slot); - // Server không echo whisper lại cho chính mình → hiện local echo - string localEcho = $"{target}: {msg}"; - EventBus.Publish(new GameSession.ChatMessageEvent(localEcho, (byte)ChatChannel.GP_CHAT_WHISPER)); + // [Port] C++: DlgChat.cpp dòng 1531-1532 + // Server KHÔNG echo whisper lại cho người gửi → phải hiển thị local. + // C++ dùng: a_sprintf(szMsg, GetStringFromTable(233), szName, szText) + // → format "对&Name&说:msg" — dấu & được thêm bởi FORMAT STRING, không phải bởi caller. + // C# dùng FIXMSG_PRIVATECHAT2 tương ứng; fallback nếu format string lỗi. + // QUAN TRỌNG: chỉ truyền target (không có & bao quanh) vào string.Format. + // Nếu format string đã có &{0}& thì kết quả đúng là "&target&". + // Nếu format string không có & thì AddChatMessage cũng chỉ wrap màu bình thường. + // Tránh truyền "&target&" vì kết quả sẽ là "&&target&&" → regex chỉ match "target" + // nhưng để lại & dư ở ngoài → UI hiển thị "&target&" thay vì link sạch. + CECStringTab pStrTab = EC_Game.GetFixedMsgs(); + string fmt = AUICommon.ConvertPrintfToCSharpFormat(pStrTab.GetWideString((int)FixedMsg.FIXMSG_PRIVATECHAT2)); + string localMsg; + try + { + localMsg = string.Format(fmt, target, msg); + } + catch + { + // Fallback: dùng &target& để AddChatMessage tạo link — format không có & thì mình thêm + localMsg = $"&{target}&: {msg}"; + } + + CECGameUIMan pGameUI = EC_Game.GetGameRun()?.GetUIManager()?.GetInGameUIMan(); + if (pGameUI != null) + { + // idTarget là ID người NHẬN (hoặc -1 nếu không tìm thấy trong friend list) + // AddChatMessage sẽ convert &target& thành TMP link tag có dạng idTarget|target + pGameUI.AddChatMessage(localMsg, ChatChannel.GP_CHAT_WHISPER, idTarget, null, 0, 0, null, msg); + } + } + + // [Port] C++: pFriendMan->GetFriendByName(name) → pFriend->id + // Tìm character ID của người chơi theo tên từ friend list. + // Trả về -1 nếu không tìm thấy (giống C++ trả về idFriend = -1). + private int GetCharacterIdByName(string name) + { + if (string.IsNullOrEmpty(name)) return -1; + var host = EC_Game.GetGameRun()?.GetHostPlayer(); + if (host == null) return -1; + var friendMan = host.GetFriendMan(); + if (friendMan == null) return -1; + var friend = friendMan.GetFriendByName(name); + return friend.HasValue ? friend.Value.Id : -1; } // ===================================================== @@ -507,14 +551,23 @@ namespace BrewMonster.Scripts.ChatUI private string GetChannelColorHex(ChatChannel channel) { - // Simplified mapping based on common PW colors + // [Port] C++: CDlgChat::m_pszColor[] — DlgChat.cpp dòng 120-136 + // Giữ đúng màu gốc cho các kênh dùng trong local error messages return channel switch { - ChatChannel.GP_CHAT_TEAM => "00FFFF", // Cyan - ChatChannel.GP_CHAT_FACTION => "00FF00", // Green - ChatChannel.GP_CHAT_FARCRY => "FFFF00", // Yellow - ChatChannel.GP_CHAT_WHISPER => "FF00FF", // Magenta - _ => "FFFFFF" // White + ChatChannel.GP_CHAT_LOCAL => "FFFFFF", + ChatChannel.GP_CHAT_FARCRY => "FFE400", + ChatChannel.GP_CHAT_TEAM => "00FF00", + ChatChannel.GP_CHAT_FACTION => "00FFFC", + ChatChannel.GP_CHAT_WHISPER => "0065FE", // C++: "^0065FE" — KHÔNG phải FF00FF + ChatChannel.GP_CHAT_TRADE => "FF742E", + ChatChannel.GP_CHAT_SYSTEM => "BED293", + ChatChannel.GP_CHAT_BROADCAST => "FF3600", + ChatChannel.GP_CHAT_MISC => "9AA6FF", + ChatChannel.GP_CHAT_SUPERFARCRY => "ff9b3e", + ChatChannel.GP_CHAT_BATTLE => "FFFFFF", + ChatChannel.GP_CHAT_COUNTRY => "FFFFFF", + _ => "FFFFFF" }; }