add logic whisper

This commit is contained in:
CuongNV
2026-04-02 11:42:34 +07:00
parent 9674159b82
commit aad2789f58
2 changed files with 82 additions and 13 deletions
+19 -3
View File
@@ -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";
/// <summary>
/// Formats a message with TextMeshPro color tags based on the channel.
@@ -55,10 +59,22 @@ namespace BrewMonster.UI
/// <summary>
/// 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).
/// </summary>
/// <param name="channel">Chat channel</param>
/// <param name="idPlayer">Sender/recipient role ID — used to check friend status for GP_CHAT_WHISPER</param>
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";
+63 -10
View File
@@ -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 = $"<color=#0065FE>{target}: {msg}</color>";
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"
};
}