Files
test/Assets/Scripts/ChatInputHandler.cs
T
2026-03-19 15:24:13 +07:00

405 lines
12 KiB
C#

using System;
using UnityEngine;
using TMPro;
using CSNetwork.GPDataType;
using System.Collections.Generic;
using BrewMonster.Network;
using CSNetwork;
namespace BrewMonster.Scripts.ChatUI
{
public class ChatInputHandler : MonoBehaviour
{
public TMP_InputField inputField;
public ChatSystemSO chatSystem;
[Serializable]
public struct ChannelButtonMapping
{
public ChatChannel channel;
public UnityEngine.UI.Button button;
}
public List<ChannelButtonMapping> channelButtons = new();
private const int MAX_HISTORY = 10;
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);
foreach (var mapping in channelButtons)
{
if (mapping.button != null)
{
ChatChannel ch = mapping.channel; // Capture variable for closure
mapping.button.onClick.AddListener(() => OnCommand_speakmode(ch));
}
}
}
// =====================================================
// PORT C++: CDlgChat::OnCommand_speakmode
// Sets the chat input prefix based on the selected channel from SO.
// =====================================================
private void OnCommand_speakmode(ChatChannel channel)
{
if (chatSystem == null) return;
var config = chatSystem.channelIcons.Find(c => c.channel == channel);
if (config.prefix != null)
{
inputField.text = config.prefix;
inputField.ActivateInputField();
inputField.MoveTextEnd(false);
}
}
private void OnSubmit(string text)
{
if (string.IsNullOrWhiteSpace(text))
return;
OnCommand_speak(text);
}
// =====================================================
// PORT C++: CDlgChat::OnCommand_speak
// =====================================================
private void OnCommand_speak(string text)
{
string strText = text.Trim();
if (strText.Length <= 0)
{
//ChangeFocus();
return;
}
int nPack = -1;
int nSlot = -1;
FilterBadWords(ref strText);
if (HandleDebugCommand(strText))
return;
float now = Time.time;
if (!CheckFarCryRequirement(strText, now))
return;
if (!CheckSuperFarCryRequirement(strText, now))
return;
if (!CheckSpamProtection(strText, now))
return;
ChatChannel resolvedChannel = ParseAndSendMessage(strText, nPack, nSlot);
SaveHistory(resolvedChannel, strText, nPack, nSlot, now);
//ChangeFocus();
}
// =====================================================
// DEBUG COMMAND
// =====================================================
private bool HandleDebugCommand(string text)
{
if (text == "##debug")
{
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)
{
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;
}
}
return true;
}
// =====================================================
// SUPER FARCRY (!#)
// =====================================================
private bool CheckSuperFarCryRequirement(string text, float now)
{
if (text.StartsWith("!#"))
{
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 true;
}
// =====================================================
// SPAM PROTECTION
// =====================================================
private bool CheckSpamProtection(string text, float now)
{
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;
}
// =====================================================
// PARSE MESSAGE PREFIX
// =====================================================
private ChatChannel ParseAndSendMessage(string text, int nPack, int nSlot)
{
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 ChatChannel.GP_CHAT_WHISPER;
}
else
{
channel = ChatChannel.GP_CHAT_LOCAL;
pszMsg = text;
}
SendChat(channel, pszMsg, nPack, nSlot);
return channel;
}
// =====================================================
// WHISPER
// =====================================================
private void HandleWhisper(string text, int nPack, int nSlot)
{
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);
}
// =====================================================
// SEND CHAT
// =====================================================
private void SendChat(ChatChannel channel, string msg, int pack, int slot)
{
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(ChatChannel channel, string msg, int pack, int slot, float now)
{
if (m_vecHistory.Count >= MAX_HISTORY)
m_vecHistory.RemoveAt(0);
m_vecHistory.Add(new ChatMsg
{
channel = channel,
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("[Cuong] AddChatMessage" + 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;
}
}