Merge pull request 'Change UI Chat' (#256) from feature/chat into develop
Reviewed-on: https://git.pthub.vn/Unity/perfect-world-unity/pulls/256
This commit is contained in:
@@ -2,6 +2,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using BrewMonster.Network;
|
||||
using BrewMonster.Scripts.UI;
|
||||
using CSNetwork;
|
||||
using CSNetwork.GPDataType;
|
||||
using CSNetwork.Protocols;
|
||||
|
||||
@@ -16,7 +17,7 @@ namespace BrewMonster.Scripts.Chat
|
||||
{
|
||||
m_aPendingProtocols.Add(p);
|
||||
}
|
||||
|
||||
|
||||
// Add one player's id to a buffer in order to get his name later
|
||||
public static void AddChatPlayerID(int id)
|
||||
{
|
||||
@@ -25,7 +26,7 @@ namespace BrewMonster.Scripts.Chat
|
||||
m_aPendingPlayers.Add(id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static bool ShouldBlockByLevel(chatmessage p)
|
||||
{
|
||||
int levelBlock = EC_Game.GetConfigs().GetBlackListSettings().levelBlock;
|
||||
@@ -46,73 +47,71 @@ namespace BrewMonster.Scripts.Chat
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool PolicyResolver(Protocol pProtocol, chatmessage p, ref string strTemp)
|
||||
/// <summary>
|
||||
/// [Port] OnPrtcChatMessage policy chat handling (EC_GameSession.cpp:4597-4621)
|
||||
/// Xử lý Policy Chat (chat từ NPC/hệ thống với tham số đặc biệt $A, $S, $I...).
|
||||
/// Nếu là Policy Chat: thay thế các ký tự đặc biệt, format tọa độ.
|
||||
/// Nếu không: chỉ convert ký tự ^ và & cho hiển thị an toàn.
|
||||
/// </summary>
|
||||
/// <param name="pProtocol">Protocol gốc (để add vào pending nếu name chưa ready)</param>
|
||||
/// <param name="p">Chat message data</param>
|
||||
/// <param name="strTemp">ref: nội dung chat (đã qua FilterInvalidTags), sẽ bị thay đổi nếu là policy chat</param>
|
||||
/// <param name="szMsg">out: chuỗi đã convert sẵn cho hiển thị (tương đương ACHAR szMsg[1024] trong C++)</param>
|
||||
/// <returns>true = xử lý xong, false = cần chờ (pending name từ server)</returns>
|
||||
public static bool PolicyResolver(Protocol pProtocol, chatmessage p, ref string strTemp, out string szMsg)
|
||||
{
|
||||
szMsg = strTemp;
|
||||
|
||||
if (IsPolicyChat(p))
|
||||
{
|
||||
// Todo: check logic
|
||||
// C++: CHAT_S2C::CreatPolicyChatParameter(p->data)
|
||||
CHAT_S2C.PolicyChatParameter pPolicyChatPara = CHAT_S2C.CreatPolicyChatParameter(p.Data);
|
||||
if (pPolicyChatPara != null && p.Data.Size > 0)
|
||||
|
||||
// C++: if (!pPolicyChatPara && p->data.size() > 0) → parse failed nhưng có data → hiển thị "???"
|
||||
if (pPolicyChatPara == null && p.Data.Size > 0)
|
||||
{
|
||||
strTemp = ("???");
|
||||
strTemp = "???";
|
||||
}
|
||||
else
|
||||
{
|
||||
// C++: if (pPolicyChatPara && !pPolicyChatPara->IsNameReady())
|
||||
if (pPolicyChatPara != null && !pPolicyChatPara.IsNameReady())
|
||||
{
|
||||
pPolicyChatPara.GetNameFromServer();
|
||||
m_aPendingProtocols.Add(pProtocol);
|
||||
szMsg = strTemp;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Thay thế ký tự đặc biệt trong policy chat ($A → tên NPC, v.v.)
|
||||
strTemp = CECUIHelper.PolicySpecialCharReplace(strTemp, pPolicyChatPara);
|
||||
|
||||
// Format tọa độ nếu channel hỗ trợ
|
||||
if (CanFormatCoordText(p))
|
||||
{
|
||||
//strTemp = CECUIHelper.FormatCoordText(strTemp);
|
||||
// TODO: strTemp = CECUIHelper.FormatCoordText(strTemp);
|
||||
}
|
||||
}
|
||||
//int strLen = strTemp.GetLength();
|
||||
//wcsncpy(szMsg, strTemp, strLen);
|
||||
//szMsg[strLen] = 0;
|
||||
|
||||
// C++: wcsncpy(szMsg, strTemp, strLen) — Policy chat không cần convert ^ &
|
||||
szMsg = strTemp;
|
||||
}
|
||||
else
|
||||
{
|
||||
//AUI_ConvertChatString(strTemp, szMsg, false);
|
||||
// C++: AUI_ConvertChatString(strTemp, szMsg, false)
|
||||
// Convert ký tự ^ và & cho hiển thị an toàn
|
||||
char[] convBuf = new char[1024];
|
||||
string input = strTemp;
|
||||
AUICommon.AUI_ConvertChatString(ref input, ref convBuf, false);
|
||||
|
||||
// Tìm null terminator và tạo string
|
||||
int len = Array.IndexOf(convBuf, '\0');
|
||||
szMsg = len >= 0 ? new string(convBuf, 0, len) : new string(convBuf);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*private void AUI_ConvertChatString(string pszChat, string pszConv, bool bName)
|
||||
{
|
||||
int i, nLen = 0;
|
||||
if (pszChat != null || pszConv != null)
|
||||
return;
|
||||
|
||||
pszConv[0] = 0;
|
||||
for( i = 0; i < (int)a_strlen(pszChat); i++ )
|
||||
{
|
||||
if( pszChat[i] == '^' )
|
||||
{
|
||||
pszConv[nLen] = '^';
|
||||
pszConv[nLen + 1] = '^';
|
||||
nLen += 2;
|
||||
}
|
||||
else if( pszChat[i] == '&' )
|
||||
{
|
||||
pszConv[nLen] = '^';
|
||||
pszConv[nLen + 1] = '&';
|
||||
nLen += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
pszConv[nLen] = pszChat[i];
|
||||
nLen++;
|
||||
}
|
||||
}
|
||||
pszConv[nLen] = 0;
|
||||
}*/
|
||||
|
||||
private static bool IsPolicyChat(chatmessage p)
|
||||
{
|
||||
bool bOK = false;
|
||||
@@ -240,4 +239,4 @@ namespace BrewMonster.Scripts.Chat
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -343,7 +343,7 @@ namespace CSNetwork
|
||||
else
|
||||
{
|
||||
sb.Append('{').Append(argIndex++).Append('}');
|
||||
|
||||
|
||||
i++;
|
||||
// Nhảy qua các ký tự định dạng (ví dụ: %02d, %ls, %f)
|
||||
while (i < format.Length && (char.IsDigit(format[i]) || format[i] == '.' || format[i] == 'l' || format[i] == 'u' || format[i] == 'd' || format[i] == 's' || format[i] == 'f' || format[i] == 'x'))
|
||||
@@ -366,6 +366,88 @@ namespace CSNetwork
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// [Port] CECGameUIMan::FilterInvalidTags (EC_GameUIMan.cpp:6424)
|
||||
/// Lọc bỏ các tag đặc biệt không hợp lệ trong nội dung chat nhận từ server.
|
||||
/// - Emotion (biểu cảm): luôn giữ lại.
|
||||
/// - IvtrItem (link vật phẩm): giữ hoặc loại tùy bFilterItem.
|
||||
/// - Tất cả loại khác (image, coord...): luôn bị loại bỏ (thay bằng text thuần).
|
||||
/// </summary>
|
||||
public static string FilterInvalidTags(string szText, bool bFilterItem)
|
||||
{
|
||||
return AUI_FilterEditboxItem(szText, (EditBoxItemBase pItem) =>
|
||||
{
|
||||
var type = pItem.GetType();
|
||||
|
||||
if (type == EditboxItemType.enumEIEmotion)
|
||||
return false;
|
||||
|
||||
if (type == EditboxItemType.enumEIIvtrlItem)
|
||||
{
|
||||
pItem.SetInfo("");
|
||||
return bFilterItem;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// [Port] CECGameUIMan::AUI_FilterEditboxItem (EC_GameUIMan.cpp:6477)
|
||||
/// Duyệt qua các EditboxItem trong text, filter trả về true thì item bị loại
|
||||
/// (thay bằng tên hiển thị dạng text thuần), false thì giữ nguyên.
|
||||
/// </summary>
|
||||
public static string AUI_FilterEditboxItem(string szText, Func<EditBoxItemBase, bool> filter)
|
||||
{
|
||||
EditBoxItemsSet itemsSet = new EditBoxItemsSet();
|
||||
string strText = UnmarshalEditBoxText(szText, itemsSet);
|
||||
|
||||
int nCount = itemsSet.GetItemCount();
|
||||
if (nCount == 0)
|
||||
return szText;
|
||||
|
||||
var it = itemsSet.GetItemIterator();
|
||||
int i = 0;
|
||||
var itemsToFilter = new List<KeyValuePair<char, string>>();
|
||||
|
||||
while (it.MoveNext() && i < nCount)
|
||||
{
|
||||
EditBoxItemBase pItem = it.Current.Value;
|
||||
if (pItem != null && filter(pItem))
|
||||
{
|
||||
itemsToFilter.Add(new KeyValuePair<char, string>(it.Current.Key, pItem.GetName()));
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
foreach (var kv in itemsToFilter)
|
||||
{
|
||||
strText = AUI_ReplaceEditboxItem(strText, kv.Key, kv.Value);
|
||||
}
|
||||
|
||||
return MarshalEditBoxText(strText, itemsSet);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// [Port] CECGameUIMan::AUI_ReplaceEditboxItem (EC_GameUIMan.cpp:6431)
|
||||
/// Thay thế ký tự EditboxItem code trong chuỗi bằng một đoạn text thay thế.
|
||||
/// </summary>
|
||||
public static string AUI_ReplaceEditboxItem(string szText, char cItem, string szSubText)
|
||||
{
|
||||
if (string.IsNullOrEmpty(szText) || !IsEditboxItemCode(cItem))
|
||||
return szText ?? "";
|
||||
|
||||
var sb = new StringBuilder(szText.Length);
|
||||
for (int i = 0; i < szText.Length; i++)
|
||||
{
|
||||
if (szText[i] == cItem)
|
||||
sb.Append(szSubText ?? "");
|
||||
else
|
||||
sb.Append(szText[i]);
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2073,15 +2073,15 @@ namespace CSNetwork
|
||||
string szMsg = null;
|
||||
string strTemp = Encoding.Unicode.GetString(p.Msg.ToArray(), 0, p.Msg.Length);
|
||||
string strMsgOrigion = strTemp;
|
||||
// Todo: Show Text on Ui Game
|
||||
//strTemp = pGameUI.FilterInvalidTags(strTemp, pItem==NULL);
|
||||
/*if (!Chat_GameSession.PolicyResolver(pProtocol, p, ref strTemp))
|
||||
// [Port] CECGameUIMan::FilterInvalidTags — Lọc các tag đặc biệt không hợp lệ
|
||||
strTemp = AUICommon.FilterInvalidTags(strTemp, pItem == null);
|
||||
if (!Chat_GameSession.PolicyResolver(pProtocol, p, ref strTemp, out szMsg))
|
||||
{
|
||||
Debug.Log("[Cuong] 2");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Chat_GameSession.HanldeGPChatSystem(p, bCalledagain))
|
||||
/*if (Chat_GameSession.HanldeGPChatSystem(p, bCalledagain))
|
||||
{
|
||||
Debug.Log("[Cuong] 3");
|
||||
}*/
|
||||
@@ -2168,7 +2168,7 @@ namespace CSNetwork
|
||||
string str = string.Format(
|
||||
fmt,
|
||||
szName,
|
||||
strTemp
|
||||
szMsg
|
||||
);
|
||||
// [Port] Gọi AddChatMessage để hiển thị lên UI Chat Box.
|
||||
// AddChatMessage bên trong đã tự publish ChatMessageEvent (cho ChatPanelUI)
|
||||
@@ -2192,7 +2192,7 @@ namespace CSNetwork
|
||||
string message = string.Format(
|
||||
template,
|
||||
pNPC.GetName(),
|
||||
strTemp
|
||||
szMsg
|
||||
);
|
||||
|
||||
EC_Game.GetGameRun().AddChatMessage(
|
||||
|
||||
@@ -546,7 +546,10 @@ namespace BrewMonster.UI
|
||||
|
||||
if (showsAboveHead && idPlayer > 0)
|
||||
{
|
||||
EventBus.PublishChannel(idPlayer, new EventChatMessageOnTopPlayer(idPlayer, pszMsg));
|
||||
// C++: pPlayer->SetLastSaidWords(strTemp, ...) — strTemp là nội dung chat thuần,
|
||||
// KHÔNG bao gồm tên người chơi. Dùng pszMsgOrigion thay vì pszMsg.
|
||||
string bubbleText = !string.IsNullOrEmpty(pszMsgOrigion) ? pszMsgOrigion : pszMsg;
|
||||
EventBus.PublishChannel(idPlayer, new EventChatMessageOnTopPlayer(idPlayer, bubbleText));
|
||||
}
|
||||
|
||||
// C++: if( cChannel == GP_CHAT_BROADCAST && byFlag == 0 ) SetMarqueeMsg(strConverted);
|
||||
|
||||
@@ -700,7 +700,7 @@ GameObject:
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
m_IsActive: 0
|
||||
--- !u!224 &4963429530816417249
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -718,7 +718,7 @@ RectTransform:
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.5, y: 0}
|
||||
m_AnchorMax: {x: 0.5, y: 0}
|
||||
m_AnchoredPosition: {x: -396, y: 79}
|
||||
m_AnchoredPosition: {x: -495, y: 55}
|
||||
m_SizeDelta: {x: 75, y: 75}
|
||||
m_Pivot: {x: 0.5, y: 0}
|
||||
--- !u!1 &4030418742857763219
|
||||
@@ -892,7 +892,7 @@ RectTransform:
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.5, y: 0}
|
||||
m_AnchorMax: {x: 0.5, y: 0}
|
||||
m_AnchoredPosition: {x: -346.5, y: 50}
|
||||
m_AnchoredPosition: {x: -483, y: 26}
|
||||
m_SizeDelta: {x: 706.4468, y: 450}
|
||||
m_Pivot: {x: 0, y: 0}
|
||||
--- !u!222 &5213722908587404148
|
||||
@@ -961,7 +961,7 @@ RectTransform:
|
||||
m_GameObject: {fileID: 4425286880128952433}
|
||||
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_LocalScale: {x: 1, y: 1.5, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
- {fileID: 5425127200754731771}
|
||||
@@ -2623,7 +2623,7 @@ GameObject:
|
||||
- component: {fileID: 6422370174043654984}
|
||||
- component: {fileID: 5572451279827723964}
|
||||
- component: {fileID: 7570271903590474125}
|
||||
- component: {fileID: 1824650527810444928}
|
||||
- component: {fileID: 1219475443647629663}
|
||||
m_Layer: 5
|
||||
m_Name: Content
|
||||
m_TagString: Untagged
|
||||
@@ -2690,7 +2690,7 @@ MonoBehaviour:
|
||||
m_ChildScaleWidth: 0
|
||||
m_ChildScaleHeight: 0
|
||||
m_ReverseArrangement: 0
|
||||
--- !u!114 &1824650527810444928
|
||||
--- !u!114 &1219475443647629663
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
@@ -2739,8 +2739,8 @@ RectTransform:
|
||||
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_AnchoredPosition: {x: 0, y: 8.5}
|
||||
m_SizeDelta: {x: 0, y: -17}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &4906838759260176767
|
||||
CanvasRenderer:
|
||||
@@ -2830,8 +2830,8 @@ RectTransform:
|
||||
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: -13.292114}
|
||||
m_SizeDelta: {x: 0, y: -86.5841}
|
||||
m_AnchoredPosition: {x: 0, y: -13.292}
|
||||
m_SizeDelta: {x: 0, y: -86.584}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &7307691078876554531
|
||||
CanvasRenderer:
|
||||
|
||||
@@ -110,9 +110,9 @@ RectTransform:
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 1}
|
||||
m_AnchorMax: {x: 0, y: 1}
|
||||
m_AnchoredPosition: {x: 399.5, y: -5}
|
||||
m_AnchoredPosition: {x: 99, y: -5}
|
||||
m_SizeDelta: {x: 601, y: 0}
|
||||
m_Pivot: {x: 0.5, y: 1}
|
||||
m_Pivot: {x: 0, y: 1}
|
||||
--- !u!222 &7228077960814023056
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -250,7 +250,7 @@ GameObject:
|
||||
- component: {fileID: 1976417251556044024}
|
||||
- component: {fileID: -887576589064363463}
|
||||
- component: {fileID: 8910872808253115585}
|
||||
- component: {fileID: 2909592183608440979}
|
||||
- component: {fileID: 6178869782871973483}
|
||||
m_Layer: 5
|
||||
m_Name: prefab_TextContents
|
||||
m_TagString: Untagged
|
||||
@@ -276,9 +276,9 @@ RectTransform:
|
||||
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_AnchoredPosition: {x: -350, y: 88.255005}
|
||||
m_SizeDelta: {x: 700, y: 0}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
m_Pivot: {x: 0, y: 1}
|
||||
--- !u!222 &616079771158270572
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -371,7 +371,7 @@ MonoBehaviour:
|
||||
m_ChildScaleWidth: 0
|
||||
m_ChildScaleHeight: 1
|
||||
m_ReverseArrangement: 0
|
||||
--- !u!114 &2909592183608440979
|
||||
--- !u!114 &6178869782871973483
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
|
||||
@@ -52,7 +52,7 @@ namespace BrewMonster.Scripts.ChatUI
|
||||
|
||||
if (strText.Length <= 0)
|
||||
{
|
||||
ChangeFocus();
|
||||
//ChangeFocus();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ namespace BrewMonster.Scripts.ChatUI
|
||||
|
||||
SaveHistory(resolvedChannel, strText, nPack, nSlot, now);
|
||||
|
||||
ChangeFocus();
|
||||
//ChangeFocus();
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
@@ -294,14 +294,14 @@ namespace BrewMonster.Scripts.ChatUI
|
||||
{
|
||||
CECUIManager.Instance.FilterBadWords(ref text);
|
||||
}
|
||||
|
||||
|
||||
private void AddChatMessage(string msg, ChatChannel channel, int idPlayer = -1, string pszPlayer = "", byte byFlag = 0)
|
||||
{
|
||||
string strModified = msg;
|
||||
|
||||
|
||||
// 1. Filter bad words
|
||||
CECUIManager.Instance.FilterBadWords(ref strModified);
|
||||
|
||||
|
||||
if (string.IsNullOrEmpty(strModified))
|
||||
return;
|
||||
|
||||
@@ -320,13 +320,13 @@ namespace BrewMonster.Scripts.ChatUI
|
||||
string colorHex = GetChannelColorHex(channel);
|
||||
string prefix = GetChannelPrefix(channel);
|
||||
string sender = string.IsNullOrEmpty(pszPlayer) ? "" : $"{pszPlayer}: ";
|
||||
|
||||
|
||||
string finalMsg = $"<color=#{colorHex}>{prefix}{sender}{strModified}</color>";
|
||||
|
||||
// 5. Publish event
|
||||
EventBus.Publish(new GameSession.ChatMessageEvent(finalMsg, (byte)channel));
|
||||
|
||||
Debug.Log(finalMsg);
|
||||
|
||||
Debug.Log("[Cuong] AddChatMessage" + finalMsg);
|
||||
}
|
||||
|
||||
private string GetChannelColorHex(ChatChannel channel)
|
||||
@@ -365,4 +365,4 @@ namespace BrewMonster.Scripts.ChatUI
|
||||
private int GetPlayerItemCount(int id) => 0;
|
||||
private int GetPlayerLevel() => 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user