using System.Collections.Generic; using System.Text; using UnityEngine; using SanAndreasUnity.Net; using SanAndreasUnity.Utilities; namespace SanAndreasUnity.Chat { public class ChatMessage { public ChatMessage (string msg, string sender) { this.msg = msg; this.sender = sender; } public string msg = ""; public string sender = ""; } public class ChatPreprocessorResult { public bool shouldBeDiscarded; public string finalChatMessage; } public class ChatPreprocessor { public System.Func processCallback; } public class ChatManager : MonoBehaviour { public static ChatManager singleton { get ; private set ; } public string serverChatNick = "Server"; public static event System.Action onChatMessage = delegate {}; List m_chatPreprocessors = new List(); static StringBuilder _stringBuilderForMessageProcessing = new StringBuilder(); void Awake () { singleton = this; onChatMessage += (ChatMessage chatMsg) => Debug.Log ("" + chatMsg.sender + " : " + chatMsg.msg); ChatSync.onChatMessageReceivedOnServer += OnChatMessageReceivedOnServer; ChatSync.onChatMessageReceivedOnLocalPlayer += (ChatMessage chatMsg) => F.InvokeEventExceptionSafe(onChatMessage, chatMsg); } void OnSceneChanged( SanAndreasUnity.Behaviours.SceneChangedMessage info ) { if (NetStatus.IsServer) { SendChatMessageToAllPlayersAsServer ("Map changed to " + info.s2.name + "."); } } private void OnChatMessageReceivedOnServer(Player player, string msg) { if (!FilterWithPreprocessors(player, ref msg)) return; SendChatMessageToAllPlayers(msg, "player " + player.netId); } private bool FilterWithPreprocessors(Player player, ref string chatMessageToFilter) { string finalMsg = chatMessageToFilter; foreach (var chatPreprocessor in m_chatPreprocessors) { ChatPreprocessorResult result = null; F.RunExceptionSafe(() => result = chatPreprocessor.processCallback(player, finalMsg)); if (null == result || result.shouldBeDiscarded || null == result.finalChatMessage) return false; finalMsg = result.finalChatMessage; } chatMessageToFilter = finalMsg; return true; } public static string RemoveInvalidCharacters(string chatMessage) { if (chatMessage == null) return string.Empty; if (chatMessage.Length > 2000) return string.Empty; var sb = _stringBuilderForMessageProcessing; sb.Clear(); sb.Append(chatMessage); // Remove tags. sb.Replace ('<', ' '); // the only easy way :D sb.Replace ('>', ' '); // msg = msg.Replace ("", ""); // msg = msg.Replace ("", ""); // msg = msg.Replace (">", "\\>"); sb.Replace('\r', ' '); sb.Replace('\n', ' '); sb.Replace('\t', ' '); return sb.ToString().Trim(); } public static void SendChatMessageToAllPlayersAsServer( string msg ) { if (NetStatus.IsServerStarted) { SendChatMessageToAllPlayers (msg, singleton.serverChatNick); } } public static void SendChatMessageToAllPlayersAsLocalPlayer( string msg ) { if (null == Player.Local) { return; } var chatSync = Player.Local.GetComponent (); if (chatSync != null) { chatSync.SendChatMsgToServer (msg); } } /// Use only on server. public static void SendChatMessageToAllPlayers( string msg, string sender ) { if (!NetStatus.IsServerStarted) return; msg = ChatManager.RemoveInvalidCharacters(msg); if (string.IsNullOrEmpty(msg)) return; foreach (var player in Player.AllPlayers) { SendChatMessageToPlayer ( player, msg, sender ); } if (!NetStatus.IsHost ()) { // running as dedicated server // we should invoke the event here, because there is no local player to receive the chat message F.InvokeEventExceptionSafe(onChatMessage, new ChatMessage(msg, sender)); } } /// Use only on server. public static void SendChatMessageToPlayer( Player player, string msg ) { if (!NetStatus.IsServerStarted) return; msg = ChatManager.RemoveInvalidCharacters(msg); if (string.IsNullOrEmpty(msg)) return; SendChatMessageToPlayer (player, msg, singleton.serverChatNick); } private static void SendChatMessageToPlayer( Player player, string msg, string sender ) { if (!NetStatus.IsServerStarted) return; var chatSync = player.GetComponent (); if (chatSync != null) { chatSync.SendChatMsgToClient (player.connectionToClient, msg, sender); } } public void RegisterChatPreprocessor(ChatPreprocessor chatPreprocessor) { m_chatPreprocessors.Add(chatPreprocessor); } } }