Add code UI and prefab chat system
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ef0c718e5723bd04fb3428c7ac73293a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fc27ce7f5294b7249aabcaedd048af17
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,27 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: b526dcb3716f21e4e815d1c561a7b86b, type: 3}
|
||||
m_Name: ChatSystemSO
|
||||
m_EditorClassIdentifier:
|
||||
channelIcons:
|
||||
- channel: 0
|
||||
icon: {fileID: 21300000, guid: 67a57872a39a6db44b5d0f897b6f4bc7, type: 3}
|
||||
- channel: 2
|
||||
icon: {fileID: 21300000, guid: 3750ab7485f9c3040b167900bfc0a504, type: 3}
|
||||
- channel: 14
|
||||
icon: {fileID: 21300000, guid: 4c42fa6e60df2184fa1a7d606bdbac8c, type: 3}
|
||||
- channel: 8
|
||||
icon: {fileID: 21300000, guid: dd1b391834096ea45903ba0bb867cfd8, type: 3}
|
||||
- channel: 13
|
||||
icon: {fileID: 21300000, guid: 1a86a071038d5a346ad7580a256dbb08, type: 3}
|
||||
- channel: 3
|
||||
icon: {fileID: 21300000, guid: 3750ab7485f9c3040b167900bfc0a504, type: 3}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 43f54723aa074c74e83e5be28975bee5
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4b164adef5d22054f8b052ae26529214
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using CSNetwork.GPDataType;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BrewMonster.Scripts.ChatUI
|
||||
{
|
||||
[Serializable]
|
||||
public struct ChannelIconMapping
|
||||
{
|
||||
public ChatChannel channel;
|
||||
public string iconName;
|
||||
public Sprite icon;
|
||||
}
|
||||
|
||||
[CreateAssetMenu(fileName = "ChatSystemSO", menuName = "Scriptable Objects/ChatSystemSO")]
|
||||
public class ChatSystemSO : ScriptableObject
|
||||
{
|
||||
[Header("Channel Icons")]
|
||||
public List<ChannelIconMapping> channelIcons = new List<ChannelIconMapping>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b526dcb3716f21e4e815d1c561a7b86b
|
||||
@@ -1,15 +1,24 @@
|
||||
using BrewMonster.Scripts.Task.UI;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace BrewMonster.Scripts.ChatUI
|
||||
{
|
||||
public class ChatMessageView : MonoBehaviour
|
||||
{
|
||||
public Image iconImage;
|
||||
public TextMeshProUGUI messageText;
|
||||
|
||||
public void Bind(string message)
|
||||
public void Bind(Sprite iconSprite, string message)
|
||||
{
|
||||
if (iconImage != null)
|
||||
{
|
||||
iconImage.sprite = iconSprite;
|
||||
iconImage.gameObject.SetActive(iconSprite != null);
|
||||
}
|
||||
messageText.text = message;
|
||||
GetComponent<IRefreshLayout>().RefreshLayout();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,20 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using CSNetwork;
|
||||
using CSNetwork.GPDataType;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Pool;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace BrewMonster.Scripts.ChatUI
|
||||
{
|
||||
[Serializable]
|
||||
public struct ChatMessageData
|
||||
{
|
||||
public string message;
|
||||
public byte channel;
|
||||
}
|
||||
|
||||
public class ChatPanelUI : MonoBehaviour
|
||||
{
|
||||
[Header("UI")] public ScrollRect scrollRect;
|
||||
@@ -18,7 +26,11 @@ namespace BrewMonster.Scripts.ChatUI
|
||||
[Header("Config")] public int maxVisibleMessages = 30;
|
||||
public int maxStoredMessages = 2000;
|
||||
|
||||
private List<string> _messages = new();
|
||||
[Header("Chat System Data")]
|
||||
public ChatSystemSO chatSystemSO;
|
||||
private Dictionary<byte, Sprite> _iconCache;
|
||||
|
||||
private List<ChatMessageData> _messages = new();
|
||||
private List<ChatMessageView> _visibleViews = new();
|
||||
|
||||
private ObjectPool<ChatMessageView> _pool;
|
||||
@@ -27,6 +39,15 @@ namespace BrewMonster.Scripts.ChatUI
|
||||
|
||||
void Awake()
|
||||
{
|
||||
_iconCache = new Dictionary<byte, Sprite>();
|
||||
if (chatSystemSO != null && chatSystemSO.channelIcons != null)
|
||||
{
|
||||
foreach (var mapping in chatSystemSO.channelIcons)
|
||||
{
|
||||
_iconCache[(byte)mapping.channel] = mapping.icon;
|
||||
}
|
||||
}
|
||||
|
||||
EventBus.Subscribe<GameSession.ChatMessageEvent>(OnChatMessageReceived);
|
||||
_pool = new ObjectPool<ChatMessageView>(
|
||||
CreateItem,
|
||||
@@ -50,7 +71,7 @@ namespace BrewMonster.Scripts.ChatUI
|
||||
{
|
||||
ChatThreadDispatcher.Instance.Post(() =>
|
||||
{
|
||||
AddMessage(x.context);
|
||||
AddMessage(x.context, x.channel);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -91,9 +112,10 @@ namespace BrewMonster.Scripts.ChatUI
|
||||
return scrollRect.verticalNormalizedPosition <= 0.001f;
|
||||
}
|
||||
|
||||
public void AddMessage(string msg)
|
||||
public void AddMessage(string msg, byte channel)
|
||||
{
|
||||
_messages.Add(msg);
|
||||
var data = new ChatMessageData { message = msg, channel = channel };
|
||||
_messages.Add(data);
|
||||
|
||||
if (_messages.Count > maxStoredMessages)
|
||||
_messages.RemoveAt(0);
|
||||
@@ -101,18 +123,20 @@ namespace BrewMonster.Scripts.ChatUI
|
||||
if (!chatPanelUIGO.activeSelf)
|
||||
return;
|
||||
|
||||
AddMessageView(msg);
|
||||
AddMessageView(data);
|
||||
|
||||
if (_userAtBottom)
|
||||
ScrollToBottom();
|
||||
}
|
||||
|
||||
void AddMessageView(string msg)
|
||||
void AddMessageView(ChatMessageData data)
|
||||
{
|
||||
var view = _pool.Get();
|
||||
view.transform.SetParent(content, false);
|
||||
view.transform.SetAsLastSibling();
|
||||
view.Bind(msg);
|
||||
|
||||
Sprite icon = _iconCache.ContainsKey(data.channel) ? _iconCache[data.channel] : null;
|
||||
view.Bind(icon, data.message);
|
||||
|
||||
_visibleViews.Add(view);
|
||||
|
||||
@@ -140,7 +164,10 @@ namespace BrewMonster.Scripts.ChatUI
|
||||
var view = _pool.Get();
|
||||
view.transform.SetParent(content, false);
|
||||
view.transform.SetAsLastSibling();
|
||||
view.Bind(_messages[i]);
|
||||
|
||||
var data = _messages[i];
|
||||
Sprite icon = _iconCache.ContainsKey(data.channel) ? _iconCache[data.channel] : null;
|
||||
view.Bind(icon, data.message);
|
||||
|
||||
_visibleViews.Add(view);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 76085330a08c2444b879074150f2cbd6
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,74 @@
|
||||
using System.Collections.Generic;
|
||||
using CSNetwork.GPDataType;
|
||||
|
||||
namespace BrewMonster.UI
|
||||
{
|
||||
public static class DlgChat
|
||||
{
|
||||
private static readonly Dictionary<ChatChannel, string> ChannelColors = new Dictionary<ChatChannel, string>
|
||||
{
|
||||
{ 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" },
|
||||
{ ChatChannel.GP_CHAT_DAMAGE, "C0C0C0" },
|
||||
{ ChatChannel.GP_CHAT_FIGHT, "FF7E00" },
|
||||
{ ChatChannel.GP_CHAT_TRADE, "FF742E" },
|
||||
{ ChatChannel.GP_CHAT_SYSTEM, "BED293" },
|
||||
{ ChatChannel.GP_CHAT_BROADCAST, "FF3600" },
|
||||
{ ChatChannel.GP_CHAT_MISC, "9AA6FF" },
|
||||
{ ChatChannel.GP_CHAT_INSTANCE, "EC0D3C" },
|
||||
{ ChatChannel.GP_CHAT_SUPERFARCRY, "ff9b3e" },
|
||||
{ ChatChannel.GP_CHAT_BATTLE, "FFFFFF" },
|
||||
{ ChatChannel.GP_CHAT_COUNTRY, "FFFFFF" }
|
||||
};
|
||||
|
||||
public const string NPC_COLOR = "C8FF64";
|
||||
public const string KING_COLOR = "8A2BE2";
|
||||
|
||||
/// <summary>
|
||||
/// Formats a message with TextMeshPro color tags based on the channel.
|
||||
/// </summary>
|
||||
public static string FormatMessage(string message, ChatChannel channel)
|
||||
{
|
||||
if (string.IsNullOrEmpty(message)) return string.Empty;
|
||||
if (ChannelColors.TryGetValue(channel, out string hexColor))
|
||||
return $"<color=#{hexColor}>{message}</color>";
|
||||
return message;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Formats a message with a specific hex color tag.
|
||||
/// </summary>
|
||||
public static string FormatWithColor(string text, string hexColor)
|
||||
{
|
||||
if (string.IsNullOrEmpty(text)) return string.Empty;
|
||||
return $"<color=#{hexColor}>{text}</color>";
|
||||
}
|
||||
|
||||
/// <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>
|
||||
public static string GetChatColor(ChatChannel channel, int idPlayer = -1)
|
||||
{
|
||||
if (ChannelColors.TryGetValue(channel, out string hexColor))
|
||||
return hexColor;
|
||||
return "FFFFFF";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a channel icon/image prefix string.
|
||||
/// Currently returns empty — placeholder for future TMP sprite implementation.
|
||||
/// Mirrors GetChatChannelImage() in C++.
|
||||
/// </summary>
|
||||
public static string GetChatChannelImage(ChatChannel channel)
|
||||
{
|
||||
// TODO: return TMP sprite tag per channel when assets are ready
|
||||
// e.g. return $"<sprite name=\"chat_icon_{channel}\">";
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8da4a558e68d9bc4f80cd25584ef5f87
|
||||
@@ -8,16 +8,18 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using BrewMonster.Network;
|
||||
using BrewMonster.Scripts;
|
||||
using CSNetwork;
|
||||
using CSNetwork.GPDataType;
|
||||
using PerfectWorld.UI.MiniMap;
|
||||
using UnityEngine;
|
||||
using BrewMonster.PerfectWorld.Scripts.UI;
|
||||
|
||||
namespace BrewMonster.UI
|
||||
{
|
||||
public class CECGameUIMan : AUIManager
|
||||
{
|
||||
public const int LAYOUTDATA_VERSION = 15;
|
||||
|
||||
|
||||
DlgNPC m_pDlgNPC;
|
||||
CDlgPetList m_pDlgPetList;
|
||||
public NPC_ESSENCE? m_pCurNPCEssence;
|
||||
@@ -141,13 +143,13 @@ namespace BrewMonster.UI
|
||||
public bool UpdateTask(uint idTask, int reason)
|
||||
{
|
||||
Debug.Log($"[EC_GameUIMan] UpdateTask: idTask={idTask}, reason={reason}");
|
||||
DlgTaskTrace pDlg = GetDialog("Win_QuestMinion").GetComponent<DlgTaskTrace>();
|
||||
DlgTaskTrace pDlg = GetDialog("Win_QuestMinion").GetComponent<DlgTaskTrace>();
|
||||
if (pDlg) {
|
||||
//pDlg->SetBtnUnTraceY(-1, 0);
|
||||
pDlg.UpdateContributionTask();
|
||||
if (reason == TaskTemplConstants.TASK_SVR_NOTIFY_NEW)
|
||||
pDlg.OnTaskNew(idTask);
|
||||
}
|
||||
pDlg.OnTaskNew(idTask);
|
||||
}
|
||||
|
||||
// TODO
|
||||
// ���´����������
|
||||
@@ -162,7 +164,7 @@ namespace BrewMonster.UI
|
||||
|
||||
if (reason == TaskTemplConstants.TASK_SVR_NOTIFY_STORAGE)
|
||||
{
|
||||
// TODO
|
||||
// TODO
|
||||
// CDlgTaskList* pDlg = (CDlgTaskList*)GetDialog("Win_QuestList");
|
||||
// if (pDlg && pDlg.IsShow())
|
||||
// {
|
||||
@@ -197,7 +199,7 @@ namespace BrewMonster.UI
|
||||
/// </summary>
|
||||
public void GetUserLayout(byte[] pData, int startIndex, ref uint dwUISize)
|
||||
{
|
||||
|
||||
|
||||
CECHostPlayer pHost = EC_Game.GetGameRun()?.GetHostPlayer();
|
||||
if (pHost == null)
|
||||
{
|
||||
@@ -310,7 +312,7 @@ namespace BrewMonster.UI
|
||||
Array.Copy(layoutBytes, 0, pData, startIndex, (int)dwUISize);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// <summary>Copy string into fixed ushort[] (for SAVE_MARK.szName).</summary>
|
||||
@@ -336,7 +338,7 @@ namespace BrewMonster.UI
|
||||
m_IconMap = new Dictionary<byte, (string, Sprite[])>();
|
||||
m_pDlgTask = GetDialog(CECUIHelper.DlgTaskName).GetComponent<DlgTask>();
|
||||
m_pDlgTask.Show(false);
|
||||
|
||||
|
||||
m_pDlgMiniMap = GetDialog("Win_Map").GetComponent<CDlgMiniMap>();
|
||||
|
||||
m_IconMap[(byte)EC_GAMEUI_ICONS.ICONS_SKILL] = (SKILL_ICONLIST_NAME, Resources.LoadAll<Sprite>(SKILL_ICONLIST_NAME));
|
||||
@@ -388,14 +390,171 @@ namespace BrewMonster.UI
|
||||
m_pDlgTask.TraceTask(ulTaskId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*CDlgPopMsg m_pDlgPopMsg;
|
||||
void AddHeartBeatHint(string pszMsg)
|
||||
{
|
||||
m_pDlgPopMsg->Add(pszMsg);
|
||||
}*/
|
||||
|
||||
/// <summary>
|
||||
/// Adds a message to the chat system.
|
||||
/// Mirrors CECGameUIMan::AddChatMessage in C++ (EC_GameUIMan.cpp).
|
||||
/// </summary>
|
||||
/// <param name="pszMsg">Message text.</param>
|
||||
/// <param name="cChannel">Chat channel.</param>
|
||||
/// <param name="idPlayer">Sender role ID (-1 = system).</param>
|
||||
/// <param name="szName">Sender name (optional).</param>
|
||||
/// <param name="byFlag">Message flag byte (CHANNEL_FRIEND, CHANNEL_GAMETALK, etc.).</param>
|
||||
/// <param name="cEmotion">Emotion set ID; high-bit indicates king speaker on GP_CHAT_COUNTRY.</param>
|
||||
/// <param name="pItem">Linked item (not fully supported yet).</param>
|
||||
/// <param name="pszMsgOrigion">Original unformatted message (for logging/history).</param>
|
||||
public void AddChatMessage(string pszMsg, ChatChannel cChannel, int idPlayer = -1, string szName = null,
|
||||
byte byFlag = 0, int cEmotion = 0, object pItem = null, string pszMsgOrigion = null)
|
||||
{
|
||||
// C++:
|
||||
// bool bIsKing = false;
|
||||
// if( cChannel == GP_CHAT_COUNTRY && (cEmotion & 0x80) ) { cEmotion &= ~0x80; bIsKing = true; }
|
||||
bool bIsKing = false;
|
||||
if (cChannel == ChatChannel.GP_CHAT_COUNTRY && (cEmotion & 0x80) != 0)
|
||||
{
|
||||
cEmotion &= ~0x80;
|
||||
bIsKing = true;
|
||||
}
|
||||
|
||||
// C++: ACString strModified = FilterEmotionSet(pszMsg, cEmotion);
|
||||
string strModified = pszMsg;
|
||||
|
||||
// C++: 修正给GM的额外信息 (Fix extra info for GM)
|
||||
// (Skipped in Unity for now)
|
||||
|
||||
// C++: 考虑本地化对某些内容不显示的要求 ... (Hide if empty)
|
||||
if (string.IsNullOrEmpty(strModified))
|
||||
return;
|
||||
|
||||
// C++: 标明来自GT频道的消息 (Mark GT channel message)
|
||||
// if (byFlag == CHANNEL_GAMETALK) strModified += GetStringFromTable(9312);
|
||||
|
||||
pszMsg = strModified;
|
||||
|
||||
// C++: if( PlayerIsBlack(idPlayer) ) return;
|
||||
// (Blacklist check skipped)
|
||||
|
||||
// C++: if( cChannel == GP_CHAT_SYSTEM && a_stricmp(pszMsg, GetStringFromTable(809)) == 0 ) return;
|
||||
// (System message filter skipped)
|
||||
|
||||
// C++: if( byFlag == CHANNEL_FRIEND || byFlag == CHANNEL_FRIEND_RE || byFlag == CHANNEL_GAMETALK)
|
||||
// AddFriendMessage(...)
|
||||
|
||||
// C++: else if( byFlag == CHANNEL_USERINFO ) ... (Refresh friend info)
|
||||
|
||||
// C++: FilterBadWords for Player messages
|
||||
// if( cChannel == GP_CHAT_LOCAL || cChannel == GP_CHAT_FARCRY || ... )
|
||||
// if (ISPLAYERID(idPlayer)) g_pGame->GetGameRun()->GetUIManager()->FilterBadWords(msg.strMsg);
|
||||
bool isPlayerChannel = cChannel == ChatChannel.GP_CHAT_LOCAL
|
||||
|| cChannel == ChatChannel.GP_CHAT_FARCRY
|
||||
|| cChannel == ChatChannel.GP_CHAT_TEAM
|
||||
|| cChannel == ChatChannel.GP_CHAT_FACTION
|
||||
|| cChannel == ChatChannel.GP_CHAT_WHISPER
|
||||
|| cChannel == ChatChannel.GP_CHAT_TRADE
|
||||
|| cChannel == ChatChannel.GP_CHAT_SUPERFARCRY
|
||||
|| cChannel == ChatChannel.GP_CHAT_BATTLE
|
||||
|| cChannel == ChatChannel.GP_CHAT_COUNTRY;
|
||||
|
||||
if (isPlayerChannel && idPlayer > 0) // idPlayer > 0 is equivalent to C++ ISPLAYERID(id)
|
||||
{
|
||||
// TODO: pszMsg = FilterBadWords(pszMsg); when API is available
|
||||
}
|
||||
|
||||
// C++: Booth Message check (cChannel == GP_CHAT_WHISPER && pszMsg ends with "!#")
|
||||
// (Skipped)
|
||||
|
||||
// C++: TransformNameColor(pItem, strName, clrName);
|
||||
|
||||
// C++: msgWithColor += ... Color assignments ...
|
||||
/*if( ISNPCID(idPlayer) ) msgWithColor += _AL("^C8FF64");
|
||||
else if (cChannel == ChatChannel.GP_CHAT_COUNTRY && bIsKing)
|
||||
{
|
||||
msgWithColor += CDlgChat::m_pszKingColor;
|
||||
}
|
||||
else
|
||||
{
|
||||
msgWithColor += CDlgChat::GetChatColor(cChannel, idPlayer);
|
||||
}*/
|
||||
string colorHex;
|
||||
if (GPDataTypeHelper.ISNPCID(idPlayer))
|
||||
{
|
||||
colorHex = DlgChat.NPC_COLOR;
|
||||
}
|
||||
else if (cChannel == ChatChannel.GP_CHAT_COUNTRY && bIsKing)
|
||||
{
|
||||
colorHex = DlgChat.KING_COLOR;
|
||||
}
|
||||
else
|
||||
{
|
||||
colorHex = DlgChat.GetChatColor(cChannel, idPlayer);
|
||||
}
|
||||
|
||||
// C++: msgWithColor += GetChatChannelImage(cChannel);
|
||||
string channelImage = DlgChat.GetChatChannelImage(cChannel);
|
||||
|
||||
// C++: if( cChannel == GP_CHAT_COUNTRY && bIsKing ) msgWithColor += GetStringFromTable(10310);
|
||||
|
||||
// Map the final string structure
|
||||
// In C++, the FixedMsg adds &name& or ^&name^& formats to color player names.
|
||||
// When building the string, C++ prefixes the color code (colorHex) before the message,
|
||||
// which usually means the name is colored. But the content might have its own color reset.
|
||||
// We use a regular expression to find `&...&` and wrap ONLY the name in reality.
|
||||
string parsedMsg = pszMsg;
|
||||
if (parsedMsg.Contains("&"))
|
||||
{
|
||||
// Convert &Cuong& into <color=#HexColor>Cuong</color>
|
||||
parsedMsg = System.Text.RegularExpressions.Regex.Replace(
|
||||
parsedMsg,
|
||||
@"&([^&]+)&",
|
||||
$"<color=#{colorHex}>$1</color>"
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If there's no &, we just colorize the whole string by default (e.g., system messages)
|
||||
parsedMsg = $"<color=#{colorHex}>{parsedMsg}</color>";
|
||||
}
|
||||
|
||||
// Channel icon prefix + message text
|
||||
string formattedMsg = $"{channelImage}{parsedMsg}";
|
||||
|
||||
// C++: Write to m_pDlgChatWhisper, Chat1, Chat2, SuperFarCry
|
||||
// Unity equivalent: Dispatch to EventBus for ChatPanelUI to handle
|
||||
Debug.Log($"[Cuong][{cChannel}] {formattedMsg}");
|
||||
EventBus.Publish(new GameSession.ChatMessageEvent(formattedMsg, (byte)cChannel));
|
||||
|
||||
// C++: AddChatMessage also handles head bubble via pPlayer->SetLastSaidWords
|
||||
// Unity equivalent: Publish EventChatMessageOnTopPlayer
|
||||
bool showsAboveHead = cChannel == ChatChannel.GP_CHAT_LOCAL
|
||||
|| cChannel == ChatChannel.GP_CHAT_FARCRY
|
||||
|| cChannel == ChatChannel.GP_CHAT_TEAM
|
||||
|| cChannel == ChatChannel.GP_CHAT_SUPERFARCRY
|
||||
|| cChannel == ChatChannel.GP_CHAT_BATTLE
|
||||
|| cChannel == ChatChannel.GP_CHAT_COUNTRY;
|
||||
|
||||
if (showsAboveHead && idPlayer > 0)
|
||||
{
|
||||
EventBus.PublishChannel(idPlayer, new EventChatMessageOnTopPlayer(idPlayer, pszMsg));
|
||||
}
|
||||
|
||||
// C++: if( cChannel == GP_CHAT_BROADCAST && byFlag == 0 ) SetMarqueeMsg(strConverted);
|
||||
if (cChannel == ChatChannel.GP_CHAT_BROADCAST && byFlag == 0)
|
||||
{
|
||||
// TODO: SetMarqueeMsg(pszMsg); when marquee UI is available
|
||||
}
|
||||
|
||||
// C++: AutoReply Logic
|
||||
// else if( gs.bAutoReply && cChannel == GP_CHAT_WHISPER ... )
|
||||
// (Skipped)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public enum EC_GAMEUI_ICONS : byte
|
||||
{
|
||||
ICONS_ACTION = 0,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,80 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1 &4840989851120023906
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 7561970608330542274}
|
||||
- component: {fileID: 3553552199954260740}
|
||||
- component: {fileID: 2098686458651577804}
|
||||
m_Layer: 5
|
||||
m_Name: Icon
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &7561970608330542274
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4840989851120023906}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 1869019404724936087}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 0, y: 0}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 94, y: 40}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &3553552199954260740
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4840989851120023906}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &2098686458651577804
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4840989851120023906}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 0
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 0
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_Sprite: {fileID: 21300000, guid: 67a57872a39a6db44b5d0f897b6f4bc7, type: 3}
|
||||
m_Type: 0
|
||||
m_PreserveAspect: 1
|
||||
m_FillCenter: 1
|
||||
m_FillMethod: 4
|
||||
m_FillAmount: 1
|
||||
m_FillClockwise: 1
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
--- !u!1 &6240941777052618231
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -11,6 +86,7 @@ GameObject:
|
||||
- component: {fileID: 5390685607869309037}
|
||||
- component: {fileID: 7228077960814023056}
|
||||
- component: {fileID: 5305392080666511277}
|
||||
- component: {fileID: 3572582094725395276}
|
||||
m_Layer: 5
|
||||
m_Name: Text (TMP)
|
||||
m_TagString: Untagged
|
||||
@@ -32,11 +108,11 @@ RectTransform:
|
||||
m_Children: []
|
||||
m_Father: {fileID: 1869019404724936087}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 1, y: 1}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 0}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
m_AnchorMin: {x: 0, y: 1}
|
||||
m_AnchorMax: {x: 0, y: 1}
|
||||
m_AnchoredPosition: {x: 394, y: -5}
|
||||
m_SizeDelta: {x: 600, y: 0}
|
||||
m_Pivot: {x: 0.5, y: 1}
|
||||
--- !u!222 &7228077960814023056
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -65,7 +141,17 @@ MonoBehaviour:
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_text: New Text
|
||||
m_text: 'afdsaf sadf
|
||||
|
||||
safsadfsa
|
||||
|
||||
asdf
|
||||
|
||||
sadf
|
||||
|
||||
sad
|
||||
|
||||
'
|
||||
m_isRightToLeft: 0
|
||||
m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
|
||||
m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
|
||||
@@ -92,15 +178,15 @@ MonoBehaviour:
|
||||
m_faceColor:
|
||||
serializedVersion: 2
|
||||
rgba: 4294967295
|
||||
m_fontSize: 36
|
||||
m_fontSizeBase: 36
|
||||
m_fontSize: 30
|
||||
m_fontSizeBase: 30
|
||||
m_fontWeight: 400
|
||||
m_enableAutoSizing: 0
|
||||
m_fontSizeMin: 18
|
||||
m_fontSizeMax: 72
|
||||
m_fontStyle: 0
|
||||
m_HorizontalAlignment: 1
|
||||
m_VerticalAlignment: 8192
|
||||
m_VerticalAlignment: 256
|
||||
m_textAlignment: 65535
|
||||
m_characterSpacing: 0
|
||||
m_wordSpacing: 0
|
||||
@@ -136,6 +222,20 @@ MonoBehaviour:
|
||||
m_hasFontAssetChanged: 0
|
||||
m_baseMaterial: {fileID: 0}
|
||||
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
|
||||
--- !u!114 &3572582094725395276
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 6240941777052618231}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 3245ec927659c4140ac4f8d17403cc18, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_HorizontalFit: 0
|
||||
m_VerticalFit: 2
|
||||
--- !u!1 &6627717456258223658
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -148,6 +248,9 @@ GameObject:
|
||||
- component: {fileID: 616079771158270572}
|
||||
- component: {fileID: 3486315639058223012}
|
||||
- component: {fileID: 1976417251556044024}
|
||||
- component: {fileID: -887576589064363463}
|
||||
- component: {fileID: 8910872808253115585}
|
||||
- component: {fileID: 2909592183608440979}
|
||||
m_Layer: 5
|
||||
m_Name: prefab_TextContents
|
||||
m_TagString: Untagged
|
||||
@@ -167,13 +270,14 @@ RectTransform:
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
- {fileID: 7561970608330542274}
|
||||
- {fileID: 5390685607869309037}
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 0, y: 0}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 800, y: 50}
|
||||
m_SizeDelta: {x: 700, y: 0}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &616079771158270572
|
||||
CanvasRenderer:
|
||||
@@ -225,4 +329,58 @@ MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: 179d32c667fc2f641bdcb7afb18046b9, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
iconImage: {fileID: 0}
|
||||
messageText: {fileID: 5305392080666511277}
|
||||
--- !u!114 &-887576589064363463
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 6627717456258223658}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 3245ec927659c4140ac4f8d17403cc18, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_HorizontalFit: 0
|
||||
m_VerticalFit: 2
|
||||
--- !u!114 &8910872808253115585
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 6627717456258223658}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 30649d3a9faa99c48a7b1166b86bf2a0, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Padding:
|
||||
m_Left: 0
|
||||
m_Right: 0
|
||||
m_Top: 5
|
||||
m_Bottom: 0
|
||||
m_ChildAlignment: 0
|
||||
m_Spacing: 0
|
||||
m_ChildForceExpandWidth: 0
|
||||
m_ChildForceExpandHeight: 1
|
||||
m_ChildControlWidth: 0
|
||||
m_ChildControlHeight: 0
|
||||
m_ChildScaleWidth: 0
|
||||
m_ChildScaleHeight: 1
|
||||
m_ReverseArrangement: 0
|
||||
--- !u!114 &2909592183608440979
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 6627717456258223658}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 4cf21a97aa5c9445c9859afa14de01ad, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
_rectTransform: {fileID: 1869019404724936087}
|
||||
|
||||
Reference in New Issue
Block a user