add UI chat
This commit is contained in:
@@ -22,21 +22,13 @@ namespace BrewMonster.Scripts.Chat
|
||||
public struct chat_item_base
|
||||
{
|
||||
public short cmd_id;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
public struct chat_equip_item
|
||||
{
|
||||
public short cmd_id;
|
||||
public int type;
|
||||
public int expire_date;
|
||||
public int proc_type;
|
||||
public ushort content_length;
|
||||
public byte[] content;
|
||||
|
||||
public int LenghtHeader()
|
||||
{
|
||||
return Marshal.SizeOf<short>() + (Marshal.SizeOf<int>() * 3) + Marshal.SizeOf<ushort>();
|
||||
}
|
||||
public char where;
|
||||
public short index;
|
||||
}
|
||||
|
||||
struct chat_generalcard_collection
|
||||
@@ -47,6 +39,21 @@ namespace BrewMonster.Scripts.Chat
|
||||
|
||||
public static class CHAT_S2C
|
||||
{
|
||||
public struct chat_equip_item
|
||||
{
|
||||
public short cmd_id;
|
||||
public int type;
|
||||
public int expire_date;
|
||||
public int proc_type;
|
||||
public ushort content_length;
|
||||
public byte[] content;
|
||||
|
||||
public int LenghtHeader()
|
||||
{
|
||||
return Marshal.SizeOf<short>() + (Marshal.SizeOf<int>() * 3) + Marshal.SizeOf<ushort>();
|
||||
}
|
||||
}
|
||||
|
||||
public enum EChatS2CCommand : short
|
||||
{
|
||||
CHAT_EQUIP_ITEM,
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace BrewMonster.Scripts.Chat
|
||||
{
|
||||
public class TestChat : MonoSingleton<TestChat>
|
||||
{
|
||||
public ChatInputHandler testChat;
|
||||
public string text;
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
DontDestroyOnLoad(gameObject);
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (Input.GetKeyDown(KeyCode.C))
|
||||
{
|
||||
testChat.Send(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 71c6bd36af2b4627838a10eb95f147b6
|
||||
timeCreated: 1772782953
|
||||
@@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using CSNetwork;
|
||||
using UnityEngine;
|
||||
@@ -9,6 +10,7 @@ namespace BrewMonster.Scripts.ChatUI
|
||||
public class ChatPanelUI : MonoBehaviour
|
||||
{
|
||||
[Header("UI")] public ScrollRect scrollRect;
|
||||
public GameObject chatPanelUIGO;
|
||||
public RectTransform content;
|
||||
public ChatMessageView messagePrefab;
|
||||
//public GameObject newMessageIndicator;
|
||||
@@ -25,8 +27,7 @@ namespace BrewMonster.Scripts.ChatUI
|
||||
|
||||
void Awake()
|
||||
{
|
||||
EventBus.Subscribe<GameSession.ChatMessageEvent>(
|
||||
(x) => AddMessage(x.context));
|
||||
EventBus.Subscribe<GameSession.ChatMessageEvent>(OnChatMessageReceived);
|
||||
_pool = new ObjectPool<ChatMessageView>(
|
||||
CreateItem,
|
||||
OnGetItem,
|
||||
@@ -40,6 +41,21 @@ namespace BrewMonster.Scripts.ChatUI
|
||||
scrollRect.onValueChanged.AddListener(OnScrollChanged);
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
EventBus.Unsubscribe<GameSession.ChatMessageEvent>(OnChatMessageReceived);
|
||||
}
|
||||
|
||||
private void OnChatMessageReceived(GameSession.ChatMessageEvent x)
|
||||
{
|
||||
Debug.Log("[Cuong] OnChatMessageReceived " + x.context);
|
||||
|
||||
ChatThreadDispatcher.Instance.Post(() =>
|
||||
{
|
||||
AddMessage(x.context);
|
||||
});
|
||||
}
|
||||
|
||||
ChatMessageView CreateItem()
|
||||
{
|
||||
var item = Instantiate(messagePrefab);
|
||||
@@ -84,16 +100,13 @@ namespace BrewMonster.Scripts.ChatUI
|
||||
if (_messages.Count > maxStoredMessages)
|
||||
_messages.RemoveAt(0);
|
||||
|
||||
if (!chatPanelUIGO.activeSelf)
|
||||
return;
|
||||
|
||||
AddMessageView(msg);
|
||||
|
||||
if (_userAtBottom)
|
||||
{
|
||||
ScrollToBottom();
|
||||
}
|
||||
else
|
||||
{
|
||||
//newMessageIndicator.SetActive(true);
|
||||
}
|
||||
}
|
||||
|
||||
void AddMessageView(string msg)
|
||||
@@ -150,5 +163,14 @@ namespace BrewMonster.Scripts.ChatUI
|
||||
_visibleViews.Clear();
|
||||
_messages.Clear();
|
||||
}
|
||||
|
||||
public void OnHandlerChatButton()
|
||||
{
|
||||
bool open = !chatPanelUIGO.activeSelf;
|
||||
chatPanelUIGO.SetActive(open);
|
||||
|
||||
if (open)
|
||||
RefreshVisible();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BrewMonster.Scripts.ChatUI
|
||||
{
|
||||
/// <summary>
|
||||
/// Responsible for switching chat messages from background threads to Unity main thread.
|
||||
/// Only handles chat related actions.
|
||||
/// </summary>
|
||||
public class ChatThreadDispatcher : MonoSingleton<ChatThreadDispatcher>
|
||||
{
|
||||
private static readonly ConcurrentQueue<Action> _queue = new ConcurrentQueue<Action>();
|
||||
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
DontDestroyOnLoad(gameObject);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called from ANY thread (network thread safe)
|
||||
/// </summary>
|
||||
public void Post(Action action)
|
||||
{
|
||||
if (action == null)
|
||||
return;
|
||||
|
||||
_queue.Enqueue(action);
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
while (_queue.TryDequeue(out var action))
|
||||
{
|
||||
try
|
||||
{
|
||||
action?.Invoke();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError($"ChatThreadDispatcher error: {e}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 00392315a7ee47e7a9527eda504fb312
|
||||
timeCreated: 1773310087
|
||||
@@ -270,7 +270,7 @@ namespace BrewMonster.Common
|
||||
{
|
||||
m_UseItemCmdList.Clear();
|
||||
|
||||
// 重置 C2S 命令计时器
|
||||
// ���� C2S �����ʱ��
|
||||
m_CounterMap[(int)CommandID.USE_ITEM].Reset(true);
|
||||
|
||||
m_EnterSanctuaryList.Clear();
|
||||
@@ -280,7 +280,7 @@ namespace BrewMonster.Common
|
||||
m_PresentInfoList.Clear();
|
||||
m_CounterMap[(int)CommandID.PLAYER_GIVE_PRESENT].Reset(true);
|
||||
|
||||
// 重置协议计时器
|
||||
// ����Э���ʱ��
|
||||
m_GetPlayerBriefInfoList.Clear();
|
||||
m_CounterMap2[(int)ProtocolType.PROTOCOL_GETPLAYERBRIEFINFO].Reset(true);
|
||||
|
||||
@@ -377,13 +377,13 @@ namespace BrewMonster.Common
|
||||
getplayerbriefinfo p = m_GetPlayerBriefInfoList[0];
|
||||
if (p.Playerlist.Count != 0)
|
||||
{
|
||||
// 获取第一个玩家id并向服务器发送协议
|
||||
// ��ȡ��һ�����id�������������Э��
|
||||
getplayerbriefinfo temp = p;
|
||||
temp.Playerlist.Clear();
|
||||
temp.Playerlist.Add(p.Playerlist[0]);
|
||||
UnityGameSession.Instance.GameSession.SendProtocol(temp);
|
||||
|
||||
// 从列表中清除
|
||||
// ��������
|
||||
p.Playerlist.Remove(p.Playerlist[0]);
|
||||
}
|
||||
|
||||
@@ -670,12 +670,12 @@ namespace BrewMonster.Common
|
||||
}
|
||||
|
||||
// Send protocols ...
|
||||
void SendGetPlayerBriefInfo(int iNumPlayer, int[] aIDs, int iReason)
|
||||
public void SendGetPlayerBriefInfo(int iNumPlayer, int[] aIDs, int iReason)
|
||||
{
|
||||
if (iNumPlayer == 0 || aIDs == null || aIDs.Length == 0)
|
||||
return;
|
||||
|
||||
// 1.合并添加到列表
|
||||
// 1.�ϲ���ӵ��б�
|
||||
getplayerbriefinfo p = new getplayerbriefinfo();
|
||||
p.Roleid = EC_Game.GetGameRun().GetHostPlayer().GetCharacterID();
|
||||
p.Reason = (byte)iReason;
|
||||
@@ -687,7 +687,7 @@ namespace BrewMonster.Common
|
||||
if (p.Playerlist.Count > 0)
|
||||
m_GetPlayerBriefInfoList.Add(p);
|
||||
|
||||
// 2.检查并发送
|
||||
// 2.��鲢����
|
||||
SendCachedGetPlayerBriefInfo();
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,8 @@ namespace BrewMonster.Scripts.Managers
|
||||
public class EC_Inventory
|
||||
{
|
||||
// ===== Instance-based inventory (per-pack) =====
|
||||
|
||||
public static int IVTRTYPE_CLIENT_GENERALCARD_PACK = 1024; // �ͻ��˱��ذ����� ���ڿ���ͼ��Ҫ����ѻ�ÿ���ͨ�����췢�͡�Ϊ��ͳһ�������촰�ڵ���Ʒ�����ӱ��ذ�����
|
||||
|
||||
// Item array: index is slot, null means empty.
|
||||
private EC_IvtrItem[] m_aItems = Array.Empty<EC_IvtrItem>();
|
||||
|
||||
@@ -27,12 +28,6 @@ namespace BrewMonster.Scripts.Managers
|
||||
IVTRTYPE_GENERALCARD_BOX = 7; // ���ư���
|
||||
};
|
||||
|
||||
// ע�� IVTRTYPE_CLIENT_GENERALCARD_PACK ö��ֵ���ܺ������ Inventory type ֵ�ظ�����
|
||||
public static class IVTRTYPE_PACK_CLIENT_GENERALCAR
|
||||
{
|
||||
public const int IVTRTYPE_CLIENT_GENERALCARD_PACK = 1024; // �ͻ��˱��ذ����� ���ڿ���ͼ��Ҫ����ѻ�ÿ���ͨ�����췢�͡�Ϊ��ͳһ�������촰�ڵ���Ʒ�����ӱ��ذ�����
|
||||
};
|
||||
|
||||
public EC_Inventory()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -13,9 +13,8 @@ using UnityEngine;
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public class CECObject : MonoBehaviour
|
||||
public partial class CECObject : MonoBehaviour
|
||||
{
|
||||
|
||||
protected static int ALPHA_HASH = Shader.PropertyToID("_Alpha");
|
||||
protected Quaternion targetRotation;
|
||||
protected Quaternion startRotation; // Store starting rotation for Slerp
|
||||
|
||||
@@ -1645,6 +1645,8 @@ namespace CSNetwork
|
||||
gamedatasend.Data = C2SCommandFactory.CreateNakeCmd(C2SCommand.CommandID.ENTER_PK_PROTECTED);
|
||||
SendProtocol(gamedatasend);
|
||||
}
|
||||
|
||||
public const int SUPER_FAR_CRY_EMOTION_SET = 6;
|
||||
/// <summary>
|
||||
/// Convert string become byte (Encoding.Unicode trong .NET = UTF-16 LE)
|
||||
/// </summary>
|
||||
@@ -1654,16 +1656,85 @@ namespace CSNetwork
|
||||
/// <param name="iSlot"></param>
|
||||
public void SendChatData(byte cChannel, in string szMsg, int iPack, int iSlot)
|
||||
{
|
||||
EventBus.Publish(new EventChatMessageOnTopPlayer(szMsg));
|
||||
EventBus.Publish(new ChatMessageEvent(szMsg));
|
||||
publicchat publicChat = new publicchat();
|
||||
publicChat.Channel = cChannel;
|
||||
publicChat.Roleid = m_iCharID;
|
||||
if (string.IsNullOrEmpty(szMsg))
|
||||
return;
|
||||
|
||||
publicchat p = new publicchat();
|
||||
p.Channel = cChannel;
|
||||
p.Roleid = m_iCharID;
|
||||
if (iPack == EC_Inventory.IVTRTYPE_CLIENT_GENERALCARD_PACK)
|
||||
{
|
||||
CECHostPlayer pHost = EC_Game.GetGameRun().GetHostPlayer();
|
||||
EC_Inventory clientPack =
|
||||
pHost != null ? pHost.GetPack(EC_Inventory.IVTRTYPE_CLIENT_GENERALCARD_PACK) : null;
|
||||
|
||||
if (pHost != null && clientPack != null)
|
||||
{
|
||||
EC_IvtrItem pCard = clientPack.GetItem(iSlot);
|
||||
|
||||
if (pCard != null)
|
||||
{
|
||||
short cmd = (short)CHAT_S2C.EChatS2CCommand.CHAT_GENERALCARD_COLLECTION;
|
||||
int cardId = pCard.GetTemplateID();
|
||||
|
||||
byte[] bytes = new byte[6];
|
||||
|
||||
BitConverter.GetBytes(cmd).CopyTo(bytes, 0);
|
||||
BitConverter.GetBytes(cardId).CopyTo(bytes, 2);
|
||||
Debug.Log($"[Cuong] SendChatData {bytes}");
|
||||
p.Data.Replace(bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (iPack >= 0 && iSlot >= 0)
|
||||
{
|
||||
byte[] bytes = new byte[5];
|
||||
|
||||
short cmd = (short)CHAT_S2C.EChatS2CCommand.CHAT_EQUIP_ITEM;
|
||||
short index = (short)iSlot;
|
||||
byte where = (byte)iPack;
|
||||
|
||||
BitConverter.GetBytes(cmd).CopyTo(bytes, 0);
|
||||
bytes[2] = where;
|
||||
BitConverter.GetBytes(index).CopyTo(bytes, 3);
|
||||
p.Data.Replace(bytes);
|
||||
}
|
||||
|
||||
byte[] unicodeBytes = Encoding.Unicode.GetBytes(szMsg);
|
||||
publicChat.Msg.Replace(unicodeBytes);
|
||||
SendProtocol(publicChat);
|
||||
p.Msg.Replace(unicodeBytes);
|
||||
SendProtocol(p);
|
||||
|
||||
if (cChannel is (byte)ChatChannel.GP_CHAT_LOCAL
|
||||
or (byte)ChatChannel.GP_CHAT_FARCRY
|
||||
or (byte)ChatChannel.GP_CHAT_SUPERFARCRY
|
||||
or (byte)ChatChannel.GP_CHAT_BATTLE
|
||||
or (byte)ChatChannel.GP_CHAT_COUNTRY) {
|
||||
CECHostPlayer pHost = EC_Game.GetGameRun().GetHostPlayer();
|
||||
//int nEmotionSet = pHost.GetCurEmotionSet();
|
||||
int nEmotionSet = 0;
|
||||
string strMsg = szMsg;
|
||||
if (cChannel == (byte)ChatChannel.GP_CHAT_SUPERFARCRY)
|
||||
{
|
||||
if (strMsg.Length > 8)
|
||||
{
|
||||
strMsg = strMsg.Substring(0, strMsg.Length - 8);
|
||||
}
|
||||
nEmotionSet = SUPER_FAR_CRY_EMOTION_SET;
|
||||
}
|
||||
|
||||
EC_IvtrItem pItem = null;
|
||||
if (iPack >= 0 && iSlot >= 0) {
|
||||
EC_Inventory pPack = pHost.GetPack(iPack);
|
||||
if (pPack != null) {
|
||||
pItem = pPack.GetItem(iSlot);
|
||||
}
|
||||
}
|
||||
//pHost.SetLastSaidWords(strMsg, nEmotionSet, pItem);
|
||||
Debug.Log("[Cuong] EventChatMessageOnTopPlayer " + strMsg);
|
||||
EventBus.Publish(new EventChatMessageOnTopPlayer(pHost.GetCharacterID(),szMsg));
|
||||
}
|
||||
}
|
||||
|
||||
public void LoadConfigData()
|
||||
{
|
||||
getuiconfig p = new getuiconfig();
|
||||
@@ -1698,10 +1769,51 @@ namespace CSNetwork
|
||||
|
||||
private bool OnPrtcWorldChat(Protocol pProtocol, bool bCalledagain)
|
||||
{
|
||||
worldchat p = (worldchat)pProtocol;
|
||||
/*if (p.Channel == (byte)ChatChannel.GP_CHAT_FARCRY && p.Roleid == 24)
|
||||
{
|
||||
OnTaskChatMessage(p.Msg.RawBuffer, p.Msg.Size);
|
||||
return true;
|
||||
}*/
|
||||
|
||||
// TODO: Porting logic OnPrtcWorldChat hoàn chỉnh từ C++ if needed
|
||||
Debug.Log("[Cuong] OnPrtcWorldChat");
|
||||
return true;
|
||||
}
|
||||
|
||||
/*private void OnTaskChatMessage(byte[] pBuf, int sz)
|
||||
{
|
||||
... logic ẩn ...
|
||||
}*/
|
||||
|
||||
private bool OnBattleChatMessage(chatmessage p, List<int> pPendingFactions)
|
||||
{
|
||||
// Tương đương OnBattleChatMessage trong C++
|
||||
// Hiện tại đơn giản hóa việc hiển thị, thực tế cần parse nội dung Battle cụ thể
|
||||
Debug.Log($"[Battle Chat] RoleID: {p.Srcroleid}");
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool OnFortressChatMessage(chatmessage p, List<int> pPendingFactions)
|
||||
{
|
||||
// Tương đương OnFortressChatMessage trong C++
|
||||
Debug.Log($"[Fortress Chat] RoleID: {p.Srcroleid}");
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool OnKingChatMessage(chatmessage p, bool bGetPlayerName = true)
|
||||
{
|
||||
// Tương đương OnKingChatMessage trong C++
|
||||
Debug.Log($"[King Chat] RoleID: {p.Srcroleid}");
|
||||
return true;
|
||||
}
|
||||
|
||||
private void OnFactionPVPChatMessage(chatmessage p)
|
||||
{
|
||||
// Tương đương OnFactionPVPChatMessage trong C++
|
||||
Debug.Log($"[FactionPVP Chat] RoleID: {p.Srcroleid}");
|
||||
}
|
||||
|
||||
private bool OnPrtcChatMessage(Protocol pProtocol, bool bCalledagain)
|
||||
{
|
||||
CECGameUIMan pGameUI = EC_Game.GetGameRun().GetUIManager().GetInGameUIMan();
|
||||
@@ -1716,20 +1828,20 @@ namespace CSNetwork
|
||||
return true;
|
||||
}
|
||||
|
||||
EC_IvtrItem pItem = CHAT_S2C.CreateChatItem(p.Data);
|
||||
// Todo: Dead Game
|
||||
///EC_IvtrItem pItem = CHAT_S2C.CreateChatItem(p.Data);
|
||||
|
||||
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))
|
||||
/*if (!Chat_GameSession.PolicyResolver(pProtocol, p, ref strTemp))
|
||||
{
|
||||
Debug.Log("[Cuong] 2");
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
if (Chat_GameSession.HanldeGPChatSystem(p, bCalledagain))
|
||||
{
|
||||
Debug.Log("[Cuong] 3");
|
||||
@@ -1740,19 +1852,54 @@ namespace CSNetwork
|
||||
{
|
||||
if (p.Channel == (byte)ChatChannel.GP_CHAT_SYSTEM && p.Srcroleid > 0)
|
||||
{
|
||||
Debug.Log("[Cuong] 4");
|
||||
switch (p.Srcroleid)
|
||||
{
|
||||
case 1: case 2: case 3: case 4: case 6: case 7: // Battle Message
|
||||
if (!bCalledagain)
|
||||
{
|
||||
List<int> pending = new List<int>();
|
||||
if (!OnBattleChatMessage(p, pending))
|
||||
{
|
||||
// Handle pending faction info
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 18: case 19: case 20: case 21: case 22: // Auction Message
|
||||
// pGameUI.AddSysAuctionMessage(...)
|
||||
Debug.Log("[Auction] " + strTemp);
|
||||
EventBus.Publish(new ChatMessageEvent(strTemp, p.Channel));
|
||||
break;
|
||||
case 24: // Task Message
|
||||
// OnTaskChatMessage(p.Data.RawBuffer, p.Data.Size);
|
||||
break;
|
||||
case 29: case 30: case 31: case 32: case 33: case 34:
|
||||
case 35: case 36: case 37: case 38: case 39: case 40:
|
||||
case 41: case 42: case 43: case 45: // Fortress Message
|
||||
OnFortressChatMessage(p, null);
|
||||
break;
|
||||
case 46: case 47: case 48: case 49: // Country Battle
|
||||
// OnCountryChatMessage(p);
|
||||
break;
|
||||
case 50: case 51: case 52: case 53: case 54:
|
||||
case 55: case 56: case 57: case 58: case 59: // King Chat
|
||||
OnKingChatMessage(p);
|
||||
break;
|
||||
case 60: case 61: case 62: case 63: case 64: // Faction PVP
|
||||
OnFactionPVPChatMessage(p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log("[Cuong] 5");
|
||||
EventBus.Publish(new ChatMessageEvent(strTemp));
|
||||
//EC_Game.GetGameRun().AddChatMessage(szMsg, p.Channel, p.Srcroleid, null, 0, p.Emotion);
|
||||
EventBus.Publish(new ChatMessageEvent(strTemp, p.Channel));
|
||||
}
|
||||
}else if (p.Channel == (byte)ChatChannel.GP_CHAT_INSTANCE && p.Srcroleid == 1)
|
||||
{
|
||||
Debug.Log("[Cuong] 6");
|
||||
Chat_GameSession.AUICTranslate trans;
|
||||
//EC_Game.GetGameRun().GetUIManager().GetInGameUIMan().AddHeartBeatHint(trans.Translate(szMsg ));
|
||||
// Chat_GameSession.AUICTranslate trans;
|
||||
// EC_Game.GetGameRun().GetUIManager().GetInGameUIMan().AddHeartBeatHint(trans.Translate(szMsg ));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1762,9 +1909,9 @@ namespace CSNetwork
|
||||
if (ISPLAYERID(p.Srcroleid))
|
||||
{
|
||||
string szName = EC_Game.GetGameRun().GetPlayerName(p.Srcroleid, false);
|
||||
Debug.Log("[Cuong] Other Msg " + szName);
|
||||
if (szName == null)
|
||||
if (string.IsNullOrEmpty(strTemp))
|
||||
{
|
||||
Debug.Log("[Cuong] Other 0");
|
||||
if (!bCalledagain)
|
||||
{
|
||||
Chat_GameSession.AddElemForPendingProtocols(pProtocol);
|
||||
@@ -1774,41 +1921,35 @@ namespace CSNetwork
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log("[Cuong] Other 1");
|
||||
char[] szText = new char[80];
|
||||
AUICommon.AUI_ConvertChatString(szName, szText, false);
|
||||
|
||||
string str = string.Format(
|
||||
pStrTab.GetWideString((int)FixedMsg.FIXMSG_CHAT),
|
||||
szName,
|
||||
szMsg
|
||||
strTemp
|
||||
);
|
||||
// Convert to EventBus
|
||||
/*EC_Game.GetGameRun().AddChatMessage(str, p.Channel, p.Srcroleid,
|
||||
null, 0, p.Emotion, pItem, strMsgOrigion); */
|
||||
EventBus.Publish(new ChatMessageEvent(str));
|
||||
|
||||
EC_Game.GetGameRun().AddChatMessage(strTemp, p.Channel, p.Srcroleid,
|
||||
null, 0, p.Emotion, null, strMsgOrigion);
|
||||
EventBus.Publish(new ChatMessageEvent(strTemp, p.Channel));
|
||||
// Set player's last said words
|
||||
CECPlayer pPlayer = EC_Game.GetGameRun().GetWorld().GetPlayerMan().GetPlayer(p.Srcroleid);
|
||||
Debug.Log("[Cuong] name " + pPlayer == null ? "null" : "have name");
|
||||
if (pPlayer != null)
|
||||
{
|
||||
if (p.Channel == (byte)ChatChannel.GP_CHAT_SUPERFARCRY) {
|
||||
if (strTemp.Length > 8)
|
||||
strTemp = strTemp.Substring(0, strTemp.Length - 8);
|
||||
else
|
||||
strTemp = "";
|
||||
}
|
||||
//pPlayer.SetLastSaidWords(strTemp, p.Emotion, pItem);
|
||||
Debug.Log("[Cuong] " + pPlayer);
|
||||
EventBus.Publish(new EventChatMessageOnTopPlayer(strTemp));
|
||||
EventBus.PublishChannel(p.Srcroleid, new EventChatMessageOnTopPlayer(p.Srcroleid, strTemp));
|
||||
//pPlayer.SetLastSaidWords(strTemp, p.Emotion);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(ISNPCID(p.Srcroleid))
|
||||
{
|
||||
Debug.Log("[Cuong] ISNPCID " + strTemp);
|
||||
CECNPC pNPC = EC_Game.GetGameRun().GetWorld().GetNPCMan().GetNPC(p.Srcroleid);
|
||||
|
||||
if (pNPC)
|
||||
if (pNPC != null)
|
||||
{
|
||||
string str;
|
||||
string template = pStrTab.GetWideString((int)FixedMsg.FIXMSG_CHAT2);
|
||||
@@ -1816,17 +1957,17 @@ namespace CSNetwork
|
||||
string message = string.Format(
|
||||
template,
|
||||
pNPC.GetName(),
|
||||
szMsg
|
||||
strTemp
|
||||
);
|
||||
|
||||
/*EC_Game.GetGameRun().AddChatMessage(
|
||||
EC_Game.GetGameRun().AddChatMessage(
|
||||
message,
|
||||
p.Channel,
|
||||
p.Srcroleid,
|
||||
null,
|
||||
0,
|
||||
p.Emotion
|
||||
);*/
|
||||
);
|
||||
EventBus.Publish(new ChatMessageEvent(message));
|
||||
|
||||
CECUIHelper.RemoveNameFlagFromNPCChat(strTemp, out szMsg);
|
||||
@@ -1841,10 +1982,12 @@ namespace CSNetwork
|
||||
public struct ChatMessageEvent
|
||||
{
|
||||
public string context;
|
||||
public byte channel;
|
||||
|
||||
public ChatMessageEvent(string context)
|
||||
public ChatMessageEvent(string context, byte channel = 0)
|
||||
{
|
||||
this.context = context;
|
||||
this.channel = channel;
|
||||
}
|
||||
}
|
||||
public void OnPrtcGetConfigRe(Protocol pProtocol)
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using BrewMonster.Scripts.ChatUI;
|
||||
using CSNetwork.GPDataType;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
@@ -16,6 +19,10 @@ namespace BrewMonster.PerfectWorld.Scripts.UI
|
||||
|
||||
[Header("References")]
|
||||
[SerializeField] private CECPlayer hostplayer;
|
||||
|
||||
[SerializeField] private float chatDisplayDuration = 5f;
|
||||
|
||||
private CancellationTokenSource _chatCts;
|
||||
|
||||
private const string DefaultLayerName = "Default";
|
||||
private bool _isVisible;
|
||||
@@ -38,17 +45,19 @@ namespace BrewMonster.PerfectWorld.Scripts.UI
|
||||
SetVisible(true);
|
||||
|
||||
RefreshName();
|
||||
EventBus.Subscribe<EventChatMessageOnTopPlayer>((x)=> SetChatMessage(x));
|
||||
EventBus.SubscribeChannel<EventChatMessageOnTopPlayer>(hostplayer.GetCharacterID(), SetChatMessage);
|
||||
EventBus.SubscribeChannel<cmd_self_info_00>(hostplayer.m_PlayerInfo.cid, UpdateHostPlayerInfoUI);
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
_chatCts?.Cancel();
|
||||
_chatCts?.Dispose();
|
||||
if (hostplayer == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
EventBus.Unsubscribe<EventChatMessageOnTopPlayer>(SetChatMessage);
|
||||
EventBus.UnsubscribeChannel<EventChatMessageOnTopPlayer>(hostplayer.GetCharacterID(), SetChatMessage);
|
||||
EventBus.UnsubscribeChannel<cmd_self_info_00>(hostplayer.m_PlayerInfo.cid, UpdateHostPlayerInfoUI);
|
||||
}
|
||||
|
||||
@@ -127,21 +136,59 @@ namespace BrewMonster.PerfectWorld.Scripts.UI
|
||||
|
||||
private void SetChatMessage(EventChatMessageOnTopPlayer cxt)
|
||||
{
|
||||
Debug.Log("[Cuong] SetChatMessage");
|
||||
if (chatText == null)
|
||||
{
|
||||
BMLogger.LogError("Don't have chatText TMProUI");
|
||||
return;
|
||||
}
|
||||
chatText.text = cxt.context;
|
||||
ChatThreadDispatcher.Instance.Post(() =>{
|
||||
SetLastSaidWords(cxt.context);
|
||||
});
|
||||
}
|
||||
|
||||
public void SetLastSaidWords(string message, float duration = -1f)
|
||||
{
|
||||
if (chatText == null || string.IsNullOrEmpty(message))
|
||||
return;
|
||||
|
||||
chatText.text = message;
|
||||
chatText.gameObject.SetActive(true);
|
||||
|
||||
// cancel timer cũ
|
||||
_chatCts?.Cancel();
|
||||
_chatCts = new CancellationTokenSource();
|
||||
|
||||
float time = duration > 0 ? duration : chatDisplayDuration;
|
||||
|
||||
HideChatAsync(time, _chatCts.Token).Forget();
|
||||
}
|
||||
|
||||
private async UniTaskVoid HideChatAsync(float time, CancellationToken token)
|
||||
{
|
||||
try
|
||||
{
|
||||
await UniTask.Delay(
|
||||
TimeSpan.FromSeconds(time),
|
||||
cancellationToken: token
|
||||
);
|
||||
|
||||
if (chatText != null)
|
||||
chatText.gameObject.SetActive(false);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
// chat mới đến → timer cũ bị cancel
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public struct EventChatMessageOnTopPlayer
|
||||
{
|
||||
public int roleId;
|
||||
public string context;
|
||||
public EventChatMessageOnTopPlayer(string context)
|
||||
public EventChatMessageOnTopPlayer(int roleId, string context)
|
||||
{
|
||||
this.roleId = roleId;
|
||||
this.context = context;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,142 @@ RectTransform:
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: -20, y: -20}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!1 &964780034169504921
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 7133716985767026273}
|
||||
- component: {fileID: 7030320337240937342}
|
||||
- component: {fileID: 6160464800274915712}
|
||||
m_Layer: 5
|
||||
m_Name: Text (TMP)
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &7133716985767026273
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 964780034169504921}
|
||||
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: 4454076196230765805}
|
||||
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}
|
||||
--- !u!222 &7030320337240937342
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 964780034169504921}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &6160464800274915712
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 964780034169504921}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_text: Chat
|
||||
m_isRightToLeft: 0
|
||||
m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
|
||||
m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
|
||||
m_fontSharedMaterials: []
|
||||
m_fontMaterial: {fileID: 0}
|
||||
m_fontMaterials: []
|
||||
m_fontColor32:
|
||||
serializedVersion: 2
|
||||
rgba: 4281479730
|
||||
m_fontColor: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1}
|
||||
m_enableVertexGradient: 0
|
||||
m_colorMode: 3
|
||||
m_fontColorGradient:
|
||||
topLeft: {r: 1, g: 1, b: 1, a: 1}
|
||||
topRight: {r: 1, g: 1, b: 1, a: 1}
|
||||
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
|
||||
bottomRight: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_fontColorGradientPreset: {fileID: 0}
|
||||
m_spriteAsset: {fileID: 0}
|
||||
m_tintAllSprites: 0
|
||||
m_StyleSheet: {fileID: 0}
|
||||
m_TextStyleHashCode: -1183493901
|
||||
m_overrideHtmlColors: 0
|
||||
m_faceColor:
|
||||
serializedVersion: 2
|
||||
rgba: 4294967295
|
||||
m_fontSize: 36
|
||||
m_fontSizeBase: 36
|
||||
m_fontWeight: 400
|
||||
m_enableAutoSizing: 0
|
||||
m_fontSizeMin: 18
|
||||
m_fontSizeMax: 72
|
||||
m_fontStyle: 1
|
||||
m_HorizontalAlignment: 2
|
||||
m_VerticalAlignment: 512
|
||||
m_textAlignment: 65535
|
||||
m_characterSpacing: 0
|
||||
m_wordSpacing: 0
|
||||
m_lineSpacing: 0
|
||||
m_lineSpacingMax: 0
|
||||
m_paragraphSpacing: 0
|
||||
m_charWidthMaxAdj: 0
|
||||
m_TextWrappingMode: 1
|
||||
m_wordWrappingRatios: 0.4
|
||||
m_overflowMode: 0
|
||||
m_linkedTextComponent: {fileID: 0}
|
||||
parentLinkedComponent: {fileID: 0}
|
||||
m_enableKerning: 0
|
||||
m_ActiveFontFeatures: 6e72656b
|
||||
m_enableExtraPadding: 0
|
||||
checkPaddingRequired: 0
|
||||
m_isRichText: 1
|
||||
m_EmojiFallbackSupport: 1
|
||||
m_parseCtrlCharacters: 1
|
||||
m_isOrthographic: 1
|
||||
m_isCullingEnabled: 0
|
||||
m_horizontalMapping: 0
|
||||
m_verticalMapping: 0
|
||||
m_uvLineOffset: 0
|
||||
m_geometrySortingOrder: 0
|
||||
m_IsTextObjectScaleStatic: 0
|
||||
m_VertexBufferAutoSizeReduction: 0
|
||||
m_useMaxVisibleDescender: 1
|
||||
m_pageToDisplay: 1
|
||||
m_margin: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_isUsingLegacyAnimationComponent: 0
|
||||
m_isVolumetricText: 0
|
||||
m_hasFontAssetChanged: 0
|
||||
m_baseMaterial: {fileID: 0}
|
||||
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
|
||||
--- !u!1 &1002556096278408428
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -291,6 +427,42 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier:
|
||||
m_Padding: {x: -8, y: -5, z: -8, w: -5}
|
||||
m_Softness: {x: 0, y: 0}
|
||||
--- !u!1 &2806664982819397903
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 4963429530816417249}
|
||||
m_Layer: 5
|
||||
m_Name: Panel
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &4963429530816417249
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2806664982819397903}
|
||||
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:
|
||||
- {fileID: 4454076196230765805}
|
||||
m_Father: {fileID: 6199635200021499044}
|
||||
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}
|
||||
--- !u!1 &4190358850504021446
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -302,7 +474,6 @@ GameObject:
|
||||
- component: {fileID: 1983722419643715407}
|
||||
- component: {fileID: 5213722908587404148}
|
||||
- component: {fileID: 343348515878574983}
|
||||
- component: {fileID: 7869768243714293468}
|
||||
- component: {fileID: 4104602819061927609}
|
||||
m_Layer: 5
|
||||
m_Name: Chat_PanelUI
|
||||
@@ -369,23 +540,6 @@ MonoBehaviour:
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
--- !u!114 &7869768243714293468
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4190358850504021446}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 5790dcd71bafcec4697f10b5366bec2c, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
scrollRect: {fileID: 5786096855155260472}
|
||||
content: {fileID: 6422370174043654984}
|
||||
messagePrefab: {fileID: 1976417251556044024, guid: dcc75569599675f46a99bc66a87efc9a, type: 3}
|
||||
maxVisibleMessages: 30
|
||||
maxStoredMessages: 2000
|
||||
--- !u!114 &4104602819061927609
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -399,7 +553,7 @@ MonoBehaviour:
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
inputField: {fileID: 2725480406471239880}
|
||||
sendButton: {fileID: 0}
|
||||
maxChatLength: 256
|
||||
--- !u!1 &4425286880128952433
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -946,6 +1100,139 @@ MonoBehaviour:
|
||||
m_hasFontAssetChanged: 0
|
||||
m_baseMaterial: {fileID: 0}
|
||||
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
|
||||
--- !u!1 &6847709244521616304
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 4454076196230765805}
|
||||
- component: {fileID: 5054963699385999060}
|
||||
- component: {fileID: 8898467712372273739}
|
||||
- component: {fileID: 8167470961996667984}
|
||||
m_Layer: 5
|
||||
m_Name: Button
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &4454076196230765805
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 6847709244521616304}
|
||||
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:
|
||||
- {fileID: 7133716985767026273}
|
||||
m_Father: {fileID: 4963429530816417249}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
||||
m_AnchoredPosition: {x: -746.7, y: 304}
|
||||
m_SizeDelta: {x: 160, y: 50}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &5054963699385999060
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 6847709244521616304}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &8898467712372273739
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 6847709244521616304}
|
||||
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: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_Type: 1
|
||||
m_PreserveAspect: 0
|
||||
m_FillCenter: 1
|
||||
m_FillMethod: 4
|
||||
m_FillAmount: 1
|
||||
m_FillClockwise: 1
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
--- !u!114 &8167470961996667984
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 6847709244521616304}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Navigation:
|
||||
m_Mode: 3
|
||||
m_WrapAround: 0
|
||||
m_SelectOnUp: {fileID: 0}
|
||||
m_SelectOnDown: {fileID: 0}
|
||||
m_SelectOnLeft: {fileID: 0}
|
||||
m_SelectOnRight: {fileID: 0}
|
||||
m_Transition: 1
|
||||
m_Colors:
|
||||
m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
|
||||
m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
|
||||
m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
|
||||
m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
|
||||
m_ColorMultiplier: 1
|
||||
m_FadeDuration: 0.1
|
||||
m_SpriteState:
|
||||
m_HighlightedSprite: {fileID: 0}
|
||||
m_PressedSprite: {fileID: 0}
|
||||
m_SelectedSprite: {fileID: 0}
|
||||
m_DisabledSprite: {fileID: 0}
|
||||
m_AnimationTriggers:
|
||||
m_NormalTrigger: Normal
|
||||
m_HighlightedTrigger: Highlighted
|
||||
m_PressedTrigger: Pressed
|
||||
m_SelectedTrigger: Selected
|
||||
m_DisabledTrigger: Disabled
|
||||
m_Interactable: 1
|
||||
m_TargetGraphic: {fileID: 8898467712372273739}
|
||||
m_OnClick:
|
||||
m_PersistentCalls:
|
||||
m_Calls:
|
||||
- m_Target: {fileID: 5696601840968024233}
|
||||
m_TargetAssemblyTypeName: BrewMonster.Scripts.ChatUI.ChatPanelUI, Assembly-CSharp
|
||||
m_MethodName: OnHandlerChatButton
|
||||
m_Mode: 1
|
||||
m_Arguments:
|
||||
m_ObjectArgument: {fileID: 0}
|
||||
m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
|
||||
m_IntArgument: 0
|
||||
m_FloatArgument: 0
|
||||
m_StringArgument:
|
||||
m_BoolArgument: 0
|
||||
m_CallState: 2
|
||||
--- !u!1 &7245224818833188742
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -958,6 +1245,7 @@ GameObject:
|
||||
- component: {fileID: 1112302134216474585}
|
||||
- component: {fileID: 4776314709450025773}
|
||||
- component: {fileID: 7685278791772274093}
|
||||
- component: {fileID: 5696601840968024233}
|
||||
m_Layer: 5
|
||||
m_Name: ChatCanvas
|
||||
m_TagString: Untagged
|
||||
@@ -977,6 +1265,7 @@ RectTransform:
|
||||
m_LocalScale: {x: 0, y: 0, z: 0}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
- {fileID: 4963429530816417249}
|
||||
- {fileID: 1983722419643715407}
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
@@ -1048,6 +1337,24 @@ MonoBehaviour:
|
||||
m_BlockingMask:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
--- !u!114 &5696601840968024233
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7245224818833188742}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 5790dcd71bafcec4697f10b5366bec2c, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
scrollRect: {fileID: 5786096855155260472}
|
||||
chatPanelUIGO: {fileID: 4190358850504021446}
|
||||
content: {fileID: 6422370174043654984}
|
||||
messagePrefab: {fileID: 1976417251556044024, guid: dcc75569599675f46a99bc66a87efc9a, type: 3}
|
||||
maxVisibleMessages: 30
|
||||
maxStoredMessages: 2000
|
||||
--- !u!1 &7942261885143240354
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -1252,8 +1559,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: 15}
|
||||
m_SizeDelta: {x: 0, y: -30}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &7307691078876554531
|
||||
CanvasRenderer:
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1 &1735791580658873054
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 1508221814777778566}
|
||||
- component: {fileID: 5062616109990871891}
|
||||
m_Layer: 0
|
||||
m_Name: ChatThreadDispatcher
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &1508221814777778566
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1735791580658873054}
|
||||
serializedVersion: 2
|
||||
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: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!114 &5062616109990871891
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1735791580658873054}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 00392315a7ee47e7a9527eda504fb312, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 820475c3b63a5de4b9b311fe9e0de9b5
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,19 +1,41 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine;
|
||||
using TMPro;
|
||||
using BrewMonster;
|
||||
using BrewMonster.Network;
|
||||
using CSNetwork.GPDataType;
|
||||
using EditorAttributes;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using BrewMonster.Scripts.Task;
|
||||
|
||||
namespace BrewMonster.Scripts.ChatUI
|
||||
{
|
||||
/// <summary>
|
||||
/// Handles chat input from TMP_InputField and provides task-sharing functionality.
|
||||
/// Converted from CDlgTaskTrace::OnCommand_Chat (DlgTaskTrace.cpp line 888).
|
||||
/// </summary>
|
||||
public class ChatInputHandler : MonoBehaviour
|
||||
{
|
||||
[Header("UI References")]
|
||||
[Header("UI References")]
|
||||
public TMP_InputField inputField; // Ô gõ text
|
||||
|
||||
[Header("Chat Settings")]
|
||||
[Tooltip("Giới hạn số ký tự tối đa cho mỗi tin nhắn chat")]
|
||||
public int maxChatLength = 256;
|
||||
|
||||
// ===== Constants from C++ source =====
|
||||
private const string INDENTATION = " ";
|
||||
private const int MAX_ITEM_WANTED = 10;
|
||||
private const int MAX_MONSTER_WANTED = 3;
|
||||
private const int MAX_PLAYER_WANTED = MAX_MONSTER_WANTED;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
inputField.onSubmit.AddListener(OnSubmit);
|
||||
|
||||
// Giới hạn ký tự trực tiếp trên InputField
|
||||
if (inputField.characterLimit <= 0 || inputField.characterLimit > maxChatLength)
|
||||
inputField.characterLimit = maxChatLength;
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
@@ -21,7 +43,7 @@ namespace BrewMonster.Scripts.ChatUI
|
||||
inputField.onSubmit.RemoveListener(OnSubmit);
|
||||
}
|
||||
|
||||
// Khi nhấn Enter
|
||||
// ===== Khi nhấn Enter =====
|
||||
private void OnSubmit(string text)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(text))
|
||||
@@ -30,9 +52,15 @@ namespace BrewMonster.Scripts.ChatUI
|
||||
HandleUserInput(text);
|
||||
}
|
||||
|
||||
// Hàm xử lý input (gửi server)
|
||||
// ===== Hàm xử lý input (gửi server) =====
|
||||
private void HandleUserInput(string text)
|
||||
{
|
||||
// Áp dụng giới hạn ký tự
|
||||
text = TruncateText(text, maxChatLength);
|
||||
|
||||
// Lọc từ cấm (bad words filter)
|
||||
CECUIManager.Instance?.FilterBadWords(ref text);
|
||||
|
||||
UnityGameSession.SendChatData(
|
||||
(byte)ChatChannel.GP_CHAT_LOCAL,
|
||||
text,
|
||||
@@ -52,5 +80,188 @@ namespace BrewMonster.Scripts.ChatUI
|
||||
|
||||
HandleUserInput(text);
|
||||
}
|
||||
|
||||
// =================================================================
|
||||
// SECTION: OnCommand_Chat - Chia sẻ trạng thái nhiệm vụ lên chat
|
||||
// Converted from CDlgTaskTrace::OnCommand_Chat (DlgTaskTrace.cpp)
|
||||
// =================================================================
|
||||
|
||||
/// <summary>
|
||||
/// Builds a chat message describing task progress and sends it to the appropriate channel.
|
||||
/// Gọi hàm này khi người chơi bấm nút "Chia sẻ nhiệm vụ" trên giao diện Task Trace.
|
||||
/// </summary>
|
||||
/// <param name="idTask">ID của nhiệm vụ cần chia sẻ.</param>
|
||||
public void OnCommand_Chat(uint idTask)
|
||||
{
|
||||
// TODO: Replace with actual EC_Game Unity Wrapper when available
|
||||
// CECHostPlayer pHost = EC_Game.GetGameRun()?.GetHostPlayer();
|
||||
// CECTaskInterface pTask = pHost.GetTaskInterface();
|
||||
// ATaskTempl pTemp = pTask.GetTaskTemplMan().GetTaskTemplByID(idTask);
|
||||
|
||||
// --- MOCK DATA FOR COMPILATION ---
|
||||
bool bActiveTask = true;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
// string strName = pTemp.GetName();
|
||||
string strName = $"[Task_{idTask}]";
|
||||
strName = DeleteColorStr(strName);
|
||||
sb.Append(strName);
|
||||
|
||||
/*
|
||||
// --- Lấy thông tin trạng thái task ---
|
||||
Task_State_info tsi = new Task_State_info();
|
||||
pTask.GetTaskStateInfo(idTask, ref tsi, bActiveTask);
|
||||
|
||||
// --- NPC trao thưởng (nếu có thể hoàn thành task) ---
|
||||
int nANPC = (int)pTemp.GetAwardNPC();
|
||||
if (nANPC > 0 && pTask.CanFinishTask(idTask))
|
||||
...
|
||||
*/
|
||||
|
||||
// --- MOCK LOGIC TO APPEND PROGRESS ---
|
||||
sb.Append(INDENTATION);
|
||||
sb.AppendFormat(GetStringFromTable(248), GetItemName(123), 2, 10); // Mock item progress
|
||||
|
||||
// --- Cắt bớt trailing '\r' ---
|
||||
string strText = sb.ToString().TrimEnd('\r');
|
||||
|
||||
// --- Áp dụng giới hạn ký tự ---
|
||||
strText = TruncateText(strText, maxChatLength);
|
||||
|
||||
// --- Xác định kênh chat: Team nếu có đội, Local nếu không ---
|
||||
byte channel = (byte)ChatChannel.GP_CHAT_LOCAL;
|
||||
|
||||
// --- Gửi lên server ---
|
||||
UnityGameSession.SendChatData(channel, strText, 0, 0);
|
||||
|
||||
Debug.Log($"[ChatInputHandler] OnCommand_Chat: Sent mock task {idTask} to channel {channel}, length={strText.Length}");
|
||||
}
|
||||
|
||||
// =================================================================
|
||||
// SECTION: Helper methods
|
||||
// =================================================================
|
||||
|
||||
/// <summary>
|
||||
/// Cắt chuỗi nếu vượt quá giới hạn ký tự, thêm dấu "..." ở cuối.
|
||||
/// </summary>
|
||||
private static string TruncateText(string text, int maxLength)
|
||||
{
|
||||
if (string.IsNullOrEmpty(text) || maxLength <= 0)
|
||||
return text;
|
||||
|
||||
if (text.Length <= maxLength)
|
||||
return text;
|
||||
|
||||
// Trừ 3 ký tự để chèn "..."
|
||||
if (maxLength > 3)
|
||||
return text.Substring(0, maxLength - 3) + "...";
|
||||
else
|
||||
return text.Substring(0, maxLength);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Xóa các mã màu "^xxxxxx" ra khỏi chuỗi.
|
||||
/// Tương đương CDlgTaskTrace::DeleteColorStr trong C++.
|
||||
/// </summary>
|
||||
private static string DeleteColorStr(string str)
|
||||
{
|
||||
if (string.IsNullOrEmpty(str))
|
||||
return str;
|
||||
|
||||
StringBuilder result = new StringBuilder(str.Length);
|
||||
for (int i = 0; i < str.Length; i++)
|
||||
{
|
||||
if (str[i] == '^' && i + 6 < str.Length)
|
||||
{
|
||||
// Kiểm tra 6 ký tự tiếp theo có phải hex không
|
||||
bool isColorCode = true;
|
||||
for (int j = 1; j <= 6; j++)
|
||||
{
|
||||
char c = str[i + j];
|
||||
if (!((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')))
|
||||
{
|
||||
isColorCode = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isColorCode)
|
||||
{
|
||||
i += 6; // bỏ qua 6 ký tự hex
|
||||
continue;
|
||||
}
|
||||
}
|
||||
result.Append(str[i]);
|
||||
}
|
||||
return result.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Format thời gian cho task (tương đương CDlgTask::FormatTime trong C++).
|
||||
/// </summary>
|
||||
private static string FormatTime(int nSec, string format, int totalTime)
|
||||
{
|
||||
int hours = nSec / 3600;
|
||||
int minutes = (nSec % 3600) / 60;
|
||||
int seconds = nSec % 60;
|
||||
|
||||
string timeStr;
|
||||
if (hours > 0)
|
||||
timeStr = $"{hours:D2}:{minutes:D2}:{seconds:D2}";
|
||||
else
|
||||
timeStr = $"{minutes:D2}:{seconds:D2}";
|
||||
|
||||
if (!string.IsNullOrEmpty(format))
|
||||
{
|
||||
try { return string.Format(format, timeStr); }
|
||||
catch { return timeStr; }
|
||||
}
|
||||
return timeStr;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Lấy string từ bảng String Table (StringFromTable).
|
||||
/// Tương đương pUIMan->GetStringFromTable(id) trong C++.
|
||||
/// </summary>
|
||||
private static string GetStringFromTable(int id)
|
||||
{
|
||||
// Sử dụng hệ thống StringTable có sẵn trong project
|
||||
var gameUI = CECUIManager.Instance?.GetInGameUIMan();
|
||||
string result = gameUI?.GetStringFromTable(id);
|
||||
return result ?? $"[STR_{id}]";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Lấy tên NPC theo ID từ ElementDataMan.
|
||||
/// </summary>
|
||||
private static string GetNPCName(int npcId)
|
||||
{
|
||||
// TODO: Kết nối với ElementDataMan của bạn khi đã port xong
|
||||
// var pDataMan = EC_Game.GetElementDataMan();
|
||||
// return pDataMan?.GetNPCName(npcId);
|
||||
return $"NPC_{npcId}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Lấy tên Monster theo ID từ ElementDataMan.
|
||||
/// </summary>
|
||||
private static string GetMonsterName(int monsterId)
|
||||
{
|
||||
// TODO: Kết nối với ElementDataMan của bạn khi đã port xong
|
||||
// var pDataMan = EC_Game.GetElementDataMan();
|
||||
// return pDataMan?.GetMonsterName(monsterId);
|
||||
return $"Monster_{monsterId}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Lấy tên Item theo ID từ ElementDataMan.
|
||||
/// </summary>
|
||||
private static string GetItemName(int itemId)
|
||||
{
|
||||
// TODO: Kết nối với ElementDataMan của bạn khi đã port xong
|
||||
// var pDataMan = EC_Game.GetElementDataMan();
|
||||
// return pDataMan?.GetItemName(itemId);
|
||||
return $"Item_{itemId}";
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user