add handlr input
This commit is contained in:
+308
-208
@@ -1,267 +1,367 @@
|
||||
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;
|
||||
using BrewMonster.Network;
|
||||
using BrewMonster.UI;
|
||||
using CSNetwork;
|
||||
|
||||
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")]
|
||||
public TMP_InputField inputField; // Ô gõ text
|
||||
public TMP_InputField inputField;
|
||||
|
||||
[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;
|
||||
private const int MAX_HISTORY = 10;
|
||||
|
||||
// ===== 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 struct ChatMsg
|
||||
{
|
||||
public ChatChannel channel;
|
||||
public float time;
|
||||
public string msg;
|
||||
public int pack;
|
||||
public int slot;
|
||||
}
|
||||
|
||||
private List<ChatMsg> m_vecHistory = new();
|
||||
private int m_nCurHistory = 0;
|
||||
|
||||
private float m_dwTickFarCry = 0;
|
||||
private float m_dwTickFarCry2 = 0;
|
||||
|
||||
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);
|
||||
OnCommand_speak(text);
|
||||
}
|
||||
|
||||
// ===== Hàm xử lý input (gửi server) =====
|
||||
private void HandleUserInput(string text)
|
||||
// =====================================================
|
||||
// PORT C++: CDlgChat::OnCommand_speak
|
||||
// =====================================================
|
||||
|
||||
private void OnCommand_speak(string text)
|
||||
{
|
||||
// Áp dụng giới hạn ký tự
|
||||
text = TruncateText(text, maxChatLength);
|
||||
string strText = text.Trim();
|
||||
|
||||
// Lọc từ cấm (bad words filter)
|
||||
CECUIManager.Instance?.FilterBadWords(ref text);
|
||||
if (strText.Length <= 0)
|
||||
{
|
||||
ChangeFocus();
|
||||
return;
|
||||
}
|
||||
|
||||
UnityGameSession.SendChatData(
|
||||
(byte)ChatChannel.GP_CHAT_LOCAL,
|
||||
text,
|
||||
0,
|
||||
0
|
||||
);
|
||||
int nPack = -1;
|
||||
int nSlot = -1;
|
||||
|
||||
// reset input
|
||||
inputField.text = "";
|
||||
inputField.ActivateInputField(); // focus lại để tiếp tục gõ
|
||||
}
|
||||
FilterBadWords(ref strText);
|
||||
|
||||
public void Send(string text)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(text))
|
||||
if (HandleDebugCommand(strText))
|
||||
return;
|
||||
|
||||
HandleUserInput(text);
|
||||
float now = Time.time;
|
||||
|
||||
if (!CheckFarCryRequirement(strText, now))
|
||||
return;
|
||||
|
||||
if (!CheckSuperFarCryRequirement(strText, now))
|
||||
return;
|
||||
|
||||
if (!CheckSpamProtection(strText, now))
|
||||
return;
|
||||
|
||||
ParseAndSendMessage(strText, nPack, nSlot);
|
||||
|
||||
SaveHistory(strText, nPack, nSlot, now);
|
||||
|
||||
ChangeFocus();
|
||||
}
|
||||
|
||||
// =================================================================
|
||||
// SECTION: OnCommand_Chat - Chia sẻ trạng thái nhiệm vụ lên chat
|
||||
// Converted from CDlgTaskTrace::OnCommand_Chat (DlgTaskTrace.cpp)
|
||||
// =================================================================
|
||||
// =====================================================
|
||||
// DEBUG COMMAND
|
||||
// =====================================================
|
||||
|
||||
/// <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)
|
||||
private bool HandleDebugCommand(string text)
|
||||
{
|
||||
// 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 (text == "##debug")
|
||||
{
|
||||
if (str[i] == '^' && i + 6 < str.Length)
|
||||
Debug.Log("Toggle debug console");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// FARCRY CHECK (!@)
|
||||
// =====================================================
|
||||
|
||||
private bool CheckFarCryRequirement(string text, float now)
|
||||
{
|
||||
if (text.StartsWith("!@"))
|
||||
{
|
||||
int itemNum = GetPlayerItemCount(12979) + GetPlayerItemCount(36092);
|
||||
|
||||
if (itemNum < 1 || GetPlayerLevel() < 5)
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
AddChatMessage(CECUIManager.Instance.GameUI.GetStringFromTable(731), ChatChannel.GP_CHAT_MISC);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (now - m_dwTickFarCry <= 1f)
|
||||
{
|
||||
AddChatMessage(CECUIManager.Instance.GameUI.GetStringFromTable(730), ChatChannel.GP_CHAT_MISC);
|
||||
return false;
|
||||
}
|
||||
result.Append(str[i]);
|
||||
}
|
||||
return result.ToString();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <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)
|
||||
// =====================================================
|
||||
// SUPER FARCRY (!#)
|
||||
// =====================================================
|
||||
|
||||
private bool CheckSuperFarCryRequirement(string text, float now)
|
||||
{
|
||||
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))
|
||||
if (text.StartsWith("!#"))
|
||||
{
|
||||
try { return string.Format(format, timeStr); }
|
||||
catch { return timeStr; }
|
||||
int itemNum = GetPlayerItemCount(27728) + GetPlayerItemCount(27729);
|
||||
|
||||
if (itemNum < 1)
|
||||
{
|
||||
AddChatMessage(CECUIManager.Instance.GameUI.GetStringFromTable(8531), ChatChannel.GP_CHAT_MISC);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (now - m_dwTickFarCry2 <= 1f)
|
||||
{
|
||||
AddChatMessage(CECUIManager.Instance.GameUI.GetStringFromTable(8530), ChatChannel.GP_CHAT_MISC);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return timeStr;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <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)
|
||||
// =====================================================
|
||||
// SPAM PROTECTION
|
||||
// =====================================================
|
||||
|
||||
private bool CheckSpamProtection(string text, float now)
|
||||
{
|
||||
// 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}]";
|
||||
if (m_vecHistory.Count == 0)
|
||||
return true;
|
||||
|
||||
var last = m_vecHistory[m_vecHistory.Count - 1];
|
||||
|
||||
if (now - last.time <= 1f)
|
||||
{
|
||||
AddChatMessage(CECUIManager.Instance.GameUI.GetStringFromTable(272), ChatChannel.GP_CHAT_MISC);
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (var cm in m_vecHistory)
|
||||
{
|
||||
if (cm.channel != ChatChannel.GP_CHAT_WHISPER &&
|
||||
cm.msg == text &&
|
||||
now - cm.time <= 6f)
|
||||
{
|
||||
AddChatMessage(CECUIManager.Instance.GameUI.GetStringFromTable(273), ChatChannel.GP_CHAT_MISC);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Lấy tên NPC theo ID từ ElementDataMan.
|
||||
/// </summary>
|
||||
private static string GetNPCName(int npcId)
|
||||
// =====================================================
|
||||
// PARSE MESSAGE PREFIX
|
||||
// =====================================================
|
||||
|
||||
private void ParseAndSendMessage(string text, int nPack, int nSlot)
|
||||
{
|
||||
// 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}";
|
||||
ChatChannel channel;
|
||||
string pszMsg;
|
||||
|
||||
if (text.StartsWith("!!"))
|
||||
{
|
||||
channel = ChatChannel.GP_CHAT_TEAM;
|
||||
pszMsg = text.Substring(2);
|
||||
}
|
||||
else if (text.StartsWith("!~"))
|
||||
{
|
||||
channel = ChatChannel.GP_CHAT_FACTION;
|
||||
pszMsg = text.Substring(2);
|
||||
}
|
||||
else if (text.StartsWith("!@"))
|
||||
{
|
||||
channel = ChatChannel.GP_CHAT_FARCRY;
|
||||
pszMsg = text.Substring(2);
|
||||
}
|
||||
else if (text.StartsWith("!#"))
|
||||
{
|
||||
channel = ChatChannel.GP_CHAT_SUPERFARCRY;
|
||||
pszMsg = text.Substring(2);
|
||||
}
|
||||
else if (text.StartsWith("$"))
|
||||
{
|
||||
channel = ChatChannel.GP_CHAT_TRADE;
|
||||
pszMsg = text.Substring(1);
|
||||
}
|
||||
else if (text.StartsWith("/"))
|
||||
{
|
||||
HandleWhisper(text, nPack, nSlot);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
channel = ChatChannel.GP_CHAT_LOCAL;
|
||||
pszMsg = text;
|
||||
}
|
||||
|
||||
SendChat(channel, pszMsg, nPack, nSlot);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Lấy tên Monster theo ID từ ElementDataMan.
|
||||
/// </summary>
|
||||
private static string GetMonsterName(int monsterId)
|
||||
// =====================================================
|
||||
// WHISPER
|
||||
// =====================================================
|
||||
|
||||
private void HandleWhisper(string text, int nPack, int nSlot)
|
||||
{
|
||||
// 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}";
|
||||
string cmd = text.Substring(1);
|
||||
|
||||
int spaceIndex = cmd.IndexOf(' ');
|
||||
|
||||
if (spaceIndex <= 0)
|
||||
{
|
||||
AddChatMessage(CECUIManager.Instance.GameUI.GetStringFromTable(234), ChatChannel.GP_CHAT_MISC);
|
||||
return;
|
||||
}
|
||||
|
||||
string player = cmd.Substring(0, spaceIndex);
|
||||
string msg = cmd.Substring(spaceIndex + 1);
|
||||
|
||||
SendPrivateChat(player, msg, nPack, nSlot);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Lấy tên Item theo ID từ ElementDataMan.
|
||||
/// </summary>
|
||||
private static string GetItemName(int itemId)
|
||||
// =====================================================
|
||||
// SEND CHAT
|
||||
// =====================================================
|
||||
|
||||
private void SendChat(ChatChannel channel, string msg, int pack, int slot)
|
||||
{
|
||||
// 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}";
|
||||
UnityGameSession.SendChatData((byte)channel, msg, pack, slot);
|
||||
}
|
||||
|
||||
private void SendPrivateChat(string target, string msg, int pack, int slot)
|
||||
{
|
||||
Debug.Log($"Whisper to {target}: {msg}");
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// HISTORY
|
||||
// =====================================================
|
||||
|
||||
private void SaveHistory(string msg, int pack, int slot, float now)
|
||||
{
|
||||
if (m_vecHistory.Count >= MAX_HISTORY)
|
||||
m_vecHistory.RemoveAt(0);
|
||||
|
||||
m_vecHistory.Add(new ChatMsg
|
||||
{
|
||||
channel = ChatChannel.GP_CHAT_LOCAL,
|
||||
msg = msg,
|
||||
pack = pack,
|
||||
slot = slot,
|
||||
time = now
|
||||
});
|
||||
|
||||
m_nCurHistory = m_vecHistory.Count;
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// UTILITIES
|
||||
// =====================================================
|
||||
|
||||
private void FilterBadWords(ref string text)
|
||||
{
|
||||
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;
|
||||
|
||||
// 2. Blacklist check (Placeholder for porting)
|
||||
if (IsPlayerBlacklisted(idPlayer))
|
||||
return;
|
||||
|
||||
// 3. Flag handling (Friend chat routing)
|
||||
if (byFlag == 1) // CHANNEL_FRIEND equivalent
|
||||
{
|
||||
// AddFriendMessage(strModified, idPlayer, pszPlayer, ...);
|
||||
// return;
|
||||
}
|
||||
|
||||
// 4. Formatting with Rich Text
|
||||
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);
|
||||
}
|
||||
|
||||
private string GetChannelColorHex(ChatChannel channel)
|
||||
{
|
||||
// Simplified mapping based on common PW colors
|
||||
return channel switch
|
||||
{
|
||||
ChatChannel.GP_CHAT_TEAM => "00FFFF", // Cyan
|
||||
ChatChannel.GP_CHAT_FACTION => "00FF00", // Green
|
||||
ChatChannel.GP_CHAT_FARCRY => "FFFF00", // Yellow
|
||||
ChatChannel.GP_CHAT_WHISPER => "FF00FF", // Magenta
|
||||
_ => "FFFFFF" // White
|
||||
};
|
||||
}
|
||||
|
||||
private string GetChannelPrefix(ChatChannel channel)
|
||||
{
|
||||
return channel switch
|
||||
{
|
||||
ChatChannel.GP_CHAT_TEAM => "[Team] ",
|
||||
ChatChannel.GP_CHAT_FACTION => "[Faction] ",
|
||||
ChatChannel.GP_CHAT_FARCRY => "[World] ",
|
||||
ChatChannel.GP_CHAT_WHISPER => "[Whisper] ",
|
||||
_ => ""
|
||||
};
|
||||
}
|
||||
|
||||
private bool IsPlayerBlacklisted(int idPlayer) => false; // Placeholder
|
||||
|
||||
private void ChangeFocus()
|
||||
{
|
||||
inputField.text = "";
|
||||
inputField.ActivateInputField();
|
||||
}
|
||||
|
||||
private int GetPlayerItemCount(int id) => 0;
|
||||
private int GetPlayerLevel() => 10;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user