using UnityEngine; using TMPro; using BrewMonster; using BrewMonster.Network; using CSNetwork.GPDataType; using System; using System.Collections.Generic; using System.Text; using BrewMonster.Scripts.Task; namespace BrewMonster.Scripts.ChatUI { /// /// Handles chat input from TMP_InputField and provides task-sharing functionality. /// Converted from CDlgTaskTrace::OnCommand_Chat (DlgTaskTrace.cpp line 888). /// public class ChatInputHandler : MonoBehaviour { [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() { inputField.onSubmit.RemoveListener(OnSubmit); } // ===== Khi nhấn Enter ===== private void OnSubmit(string text) { if (string.IsNullOrWhiteSpace(text)) return; HandleUserInput(text); } // ===== 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, 0, 0 ); // reset input inputField.text = ""; inputField.ActivateInputField(); // focus lại để tiếp tục gõ } public void Send(string text) { if (string.IsNullOrWhiteSpace(text)) return; HandleUserInput(text); } // ================================================================= // SECTION: OnCommand_Chat - Chia sẻ trạng thái nhiệm vụ lên chat // Converted from CDlgTaskTrace::OnCommand_Chat (DlgTaskTrace.cpp) // ================================================================= /// /// 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. /// /// ID của nhiệm vụ cần chia sẻ. 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 // ================================================================= /// /// Cắt chuỗi nếu vượt quá giới hạn ký tự, thêm dấu "..." ở cuối. /// 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); } /// /// Xóa các mã màu "^xxxxxx" ra khỏi chuỗi. /// Tương đương CDlgTaskTrace::DeleteColorStr trong C++. /// 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(); } /// /// Format thời gian cho task (tương đương CDlgTask::FormatTime trong C++). /// 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; } /// /// Lấy string từ bảng String Table (StringFromTable). /// Tương đương pUIMan->GetStringFromTable(id) trong C++. /// 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}]"; } /// /// Lấy tên NPC theo ID từ ElementDataMan. /// 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}"; } /// /// Lấy tên Monster theo ID từ ElementDataMan. /// 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}"; } /// /// Lấy tên Item theo ID từ ElementDataMan. /// 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}"; } } }