From bf23e5d66cf091d310c660877380f3727d0b0234 Mon Sep 17 00:00:00 2001 From: Dr Scofield Date: Fri, 23 May 2008 10:24:26 +0000 Subject: i've refactored the ChatModule into two modules: ChatModule and IRCBridgeModule. ChatModule is now only doing in-world chat. IRCBridgeModule is only doing, well, bridging chat to/from IRC. Both modules are now using a new OnChatFromWorld event handler (which Scene.PacketHandler is feeding for chat from in-world instead of going via the Interface method). This refactoring will allow us to easily add other bridge modules (e.g., an XMPP bridge module). there is still a bug in IRCBridgeModule (inherited from the old ChatModule) where FindClientRegion does not really find the client region... --- .../Environment/Modules/Avatar/Chat/ChatModule.cs | 746 +-------------------- 1 file changed, 37 insertions(+), 709 deletions(-) (limited to 'OpenSim/Region/Environment/Modules') diff --git a/OpenSim/Region/Environment/Modules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Chat/ChatModule.cs index 825fb8f..37cf328 100644 --- a/OpenSim/Region/Environment/Modules/Avatar/Chat/ChatModule.cs +++ b/OpenSim/Region/Environment/Modules/Avatar/Chat/ChatModule.cs @@ -43,23 +43,19 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat { public class ChatModule : IRegionModule, ISimChat { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - private string m_defaultzone = null; + private static readonly ILog m_log = + LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - private IRCChatModule m_irc = null; - private Thread m_irc_connector = null; + private const int DEBUG_CHANNEL = 2147483647; - private string m_last_leaving_user = null; - private string m_last_new_user = null; private int m_saydistance = 30; - private List m_scenes = new List(); private int m_shoutdistance = 100; - internal object m_syncInit = new object(); - internal object m_syncLogout = new object(); private int m_whisperdistance = 10; + private List m_scenes = new List(); - #region IRegionModule Members + internal object m_syncInit = new object(); + #region IRegionModule Members public void Initialise(Scene scene, IConfigSource config) { lock (m_syncInit) @@ -68,7 +64,8 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat { m_scenes.Add(scene); scene.EventManager.OnNewClient += NewClient; - scene.RegisterModuleInterface(this); + scene.EventManager.OnChatFromWorld += SimChat; + // scene.RegisterModuleInterface(this); } // wrap this in a try block so that defaults will work if @@ -82,57 +79,17 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat catch (Exception) { } - - try - { - m_defaultzone = config.Configs["IRC"].GetString("nick", "Sim"); - } - catch (Exception) - { - } - - // setup IRC Relay - if (m_irc == null) - { - m_irc = new IRCChatModule(config); - } - if (m_irc_connector == null) - { - m_irc_connector = new Thread(IRCConnectRun); - m_irc_connector.Name = "IRCConnectorThread"; - m_irc_connector.IsBackground = true; - } + m_log.InfoFormat("[CHAT] initialized for {0} w:{1} s:{2} S:{3}", scene.RegionInfo.RegionName, + m_whisperdistance, m_saydistance, m_shoutdistance); } } public void PostInitialise() { - if (m_irc.Enabled) - { - try - { - //m_irc.Connect(m_scenes); - if (m_irc_connector == null) - { - m_irc_connector = new Thread(IRCConnectRun); - m_irc_connector.Name = "IRCConnectorThread"; - m_irc_connector.IsBackground = true; - } - if (!m_irc_connector.IsAlive) - { - m_irc_connector.Start(); - ThreadTracker.Add(m_irc_connector); - } - } - catch (Exception) - { - } - } } public void Close() { - m_irc.Close(); } public string Name @@ -148,11 +105,8 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat #endregion #region ISimChat Members - public void SimChat(Object sender, ChatFromViewerArgs e) { - // FROM: Sim TO: IRC - ScenePresence avatar = null; //TODO: Move ForEachScenePresence and others into IScene. @@ -164,7 +118,8 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat // Filled in since it's easier than rewriting right now. LLVector3 fromPos = e.Position; - LLVector3 regionPos = new LLVector3(scene.RegionInfo.RegionLocX * Constants.RegionSize, scene.RegionInfo.RegionLocY * Constants.RegionSize, 0); + LLVector3 regionPos = new LLVector3(scene.RegionInfo.RegionLocX * Constants.RegionSize, + scene.RegionInfo.RegionLocY * Constants.RegionSize, 0); string fromName = e.From; string message = e.Message; @@ -178,66 +133,37 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat if (avatar != null) { fromPos = avatar.AbsolutePosition; - regionPos = new LLVector3(scene.RegionInfo.RegionLocX * Constants.RegionSize, scene.RegionInfo.RegionLocY * Constants.RegionSize, 0); + regionPos = new LLVector3(scene.RegionInfo.RegionLocX * Constants.RegionSize, + scene.RegionInfo.RegionLocY * Constants.RegionSize, 0); fromName = avatar.Firstname + " " + avatar.Lastname; fromAgentID = e.Sender.AgentId; } - // Try to reconnect to server if not connected - if (m_irc.Enabled && !m_irc.Connected) - { - // In a non-blocking way. Eventually the connector will get it started - try - { - if (m_irc_connector == null) - { - m_irc_connector = new Thread(IRCConnectRun); - m_irc_connector.Name = "IRCConnectorThread"; - m_irc_connector.IsBackground = true; - } - if (!m_irc_connector.IsAlive) - { - m_irc_connector.Start(); - ThreadTracker.Add(m_irc_connector); - } - } - catch (Exception) - { - } - } - - // We only want to relay stuff on channel 0 - if (e.Channel == 0 || e.Channel == 2147483647) + if (e.Channel == 0 || e.Channel == DEBUG_CHANNEL) { - if (e.Channel == 2147483647) + if (e.Channel == DEBUG_CHANNEL) e.Type = ChatTypeEnum.DebugChannel; - // IRC stuff - if (e.Message.Length > 0 && e.Channel == 0) - { - if (m_irc.Connected && (avatar != null)) // this is to keep objects from talking to IRC - { - m_irc.PrivMsg(fromName, scene.RegionInfo.RegionName, e.Message); - } - } - + // chat works by redistributing every incoming chat + // message to each avatar in the scene foreach (Scene s in m_scenes) { s.ForEachScenePresence(delegate(ScenePresence presence) + { + if (e.Channel == DEBUG_CHANNEL) { - if (e.Channel == 2147483647) - { - TrySendChatMessage(presence, fromPos, regionPos, - fromAgentID, fromName, e.Type, message, ChatSourceType.Object); - } - else - { - TrySendChatMessage(presence, fromPos, regionPos, - fromAgentID, fromName, e.Type, message, ChatSourceType.Agent); - - } - }); + TrySendChatMessage(presence, fromPos, regionPos, + fromAgentID, fromName, e.Type, + message, ChatSourceType.Object); + } + else + { + TrySendChatMessage(presence, fromPos, regionPos, + fromAgentID, fromName, e.Type, + message, ChatSourceType.Agent); + } + }); } } } @@ -249,67 +175,23 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat try { client.OnChatFromViewer += SimChat; - - if ((m_irc.Enabled) && (m_irc.Connected)) - { - string clientName = client.Name; - // handles simple case. May not work for hundred connecting in per second. - // and the NewClients calles getting interleved - // but filters out multiple reports - if (clientName != m_last_new_user) - { - m_last_new_user = clientName; - string clientRegion = FindClientRegion(client.FirstName, client.LastName); - m_irc.PrivMsg(m_irc.Nick, "Sim", "notices " + clientName + " in " + clientRegion); - } - } - client.OnLogout += ClientLoggedOut; - client.OnConnectionClosed += ClientLoggedOut; - client.OnLogout += ClientLoggedOut; } catch (Exception ex) { - m_log.Error("[IRC]: NewClient exception trap:" + ex.ToString()); - } - } - - public void ClientLoggedOut(IClientAPI client) - { - lock (m_syncLogout) - { - try - { - if ((m_irc.Enabled) && (m_irc.Connected)) - { - string clientName = client.FirstName + " " + client.LastName; - string clientRegion = FindClientRegion(client.FirstName, client.LastName); - // handles simple case. May not work for hundred connecting in per second. - // and the NewClients calles getting interleved - // but filters out multiple reports - if (clientName != m_last_leaving_user) - { - m_last_leaving_user = clientName; - m_irc.PrivMsg(m_irc.Nick, "Sim", "notices " + clientName + " left " + clientRegion); - m_log.Info("[IRC]: IRC watcher notices " + clientName + " left " + clientRegion); - } - } - } - catch (Exception ex) - { - m_log.Error("[IRC]: ClientLoggedOut exception trap:" + ex.ToString()); - } + m_log.Error("[CHAT]: NewClient exception trap:" + ex.ToString()); } } private void TrySendChatMessage(ScenePresence presence, LLVector3 fromPos, LLVector3 regionPos, - LLUUID fromAgentID, string fromName, ChatTypeEnum type, string message, ChatSourceType src) + LLUUID fromAgentID, string fromName, ChatTypeEnum type, + string message, ChatSourceType src) { if (!presence.IsChildAgent) { LLVector3 fromRegionPos = fromPos + regionPos; LLVector3 toRegionPos = presence.AbsolutePosition + regionPos; int dis = Math.Abs((int) Util.GetDistanceTo(toRegionPos, fromRegionPos)); - + if (type == ChatTypeEnum.Whisper && dis > m_whisperdistance || type == ChatTypeEnum.Say && dis > m_saydistance || type == ChatTypeEnum.Shout && dis > m_shoutdistance) @@ -318,563 +200,9 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat } // TODO: should change so the message is sent through the avatar rather than direct to the ClientView - presence.ControllingClient.SendChatMessage(message, (byte) type, fromPos, fromName, fromAgentID,(byte)src,(byte)ChatAudibleLevel.Fully); - } - } - - // if IRC is enabled then just keep trying using a monitor thread - public void IRCConnectRun() - { - while (true) - { - if ((m_irc.Enabled) && (!m_irc.Connected)) - { - m_irc.Connect(m_scenes); - } - Thread.Sleep(15000); - } - } - - public string FindClientRegion(string client_FirstName, string client_LastName) - { - string sourceRegion = null; - foreach (Scene s in m_scenes) - { - s.ForEachScenePresence(delegate(ScenePresence presence) - { - if ((presence.IsChildAgent == false) - && (presence.Firstname == client_FirstName) - && (presence.Lastname == client_LastName)) - { - sourceRegion = presence.Scene.RegionInfo.RegionName; - //sourceRegion= s.RegionInfo.RegionName; - } - }); - if (sourceRegion != null) return sourceRegion; - } - if (m_defaultzone == null) - { - m_defaultzone = "Sim"; - } - return m_defaultzone; - } - } - - internal class IRCChatModule - { - #region ErrorReplies enum - - public enum ErrorReplies - { - NotRegistered = 451, // ":You have not registered" - NicknameInUse = 433 // " :Nickname is already in use" - } - - #endregion - - #region Replies enum - - public enum Replies - { - MotdStart = 375, // ":- Message of the day - " - Motd = 372, // ":- " - EndOfMotd = 376 // ":End of /MOTD command" - } - - #endregion - - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - private Thread listener; - - private string m_basenick = null; - private string m_channel = null; - private bool m_connected = false; - private bool m_enabled = false; - private List m_last_scenes = null; - private string m_nick = null; - private uint m_port = 6668; - private string m_privmsgformat = "PRIVMSG {0} :<{1} in {2}>: {3}"; - private StreamReader m_reader; - private List m_scenes = null; - private string m_server = null; - - private NetworkStream m_stream; - internal object m_syncConnect = new object(); - private TcpClient m_tcp; - private string m_user = "USER OpenSimBot 8 * :I'm a OpenSim to irc bot"; - private StreamWriter m_writer; - - private Thread pingSender; - - public IRCChatModule(IConfigSource config) - { - m_nick = "OSimBot" + Util.RandomClass.Next(1, 99); - m_tcp = null; - m_writer = null; - m_reader = null; - - // configuration in OpenSim.ini - // [IRC] - // server = chat.freenode.net - // nick = OSimBot_mysim - // ;username = USER OpenSimBot 8 * :I'm a OpenSim to irc bot - // ; username is the IRC command line sent - // ; USER * : - // channel = #opensim-regions - // port = 6667 - // ;MSGformat fields : 0=botnick, 1=user, 2=region, 3=message - // ;for : : - // ;msgformat = "PRIVMSG {0} :<{1} in {2}>: {3}" - // ;for : - : - // ;msgformat = "PRIVMSG {0} : {3} - {1} of {2}" - // ;for : - from : - // ;msgformat = "PRIVMSG {0} : {3} - from {1}" - // Traps I/O disconnects so it does not crash the sim - // Trys to reconnect if disconnected and someone says something - // Tells IRC server "QUIT" when doing a close (just to be nice) - // Default port back to 6667 - - try - { - m_server = config.Configs["IRC"].GetString("server"); - m_nick = config.Configs["IRC"].GetString("nick"); - m_basenick = m_nick; - m_channel = config.Configs["IRC"].GetString("channel"); - m_port = (uint) config.Configs["IRC"].GetInt("port", (int) m_port); - m_user = config.Configs["IRC"].GetString("username", m_user); - m_privmsgformat = config.Configs["IRC"].GetString("msgformat", m_privmsgformat); - if (m_server != null && m_nick != null && m_channel != null) - { - m_nick = m_nick + Util.RandomClass.Next(1, 99); - m_enabled = true; - } - } - catch (Exception) - { - m_log.Info("[CHAT]: No IRC config information, skipping IRC bridge configuration"); - } - } - - public bool Enabled - { - get { return m_enabled; } - } - - public bool Connected - { - get { return m_connected; } - } - - public string Nick - { - get { return m_nick; } - } - - public bool Connect(List scenes) - { - lock (m_syncConnect) - { - try - { - if (m_connected) return true; - m_scenes = scenes; - if (m_last_scenes == null) - { - m_last_scenes = scenes; - } - - m_tcp = new TcpClient(m_server, (int) m_port); - m_log.Info("[IRC]: Connecting..."); - m_stream = m_tcp.GetStream(); - m_log.Info("[IRC]: Connected to " + m_server); - m_reader = new StreamReader(m_stream); - m_writer = new StreamWriter(m_stream); - - pingSender = new Thread(new ThreadStart(PingRun)); - pingSender.Name = "PingSenderThread"; - pingSender.IsBackground = true; - pingSender.Start(); - ThreadTracker.Add(pingSender); - - listener = new Thread(new ThreadStart(ListenerRun)); - listener.Name = "IRCChatModuleListenerThread"; - listener.IsBackground = true; - listener.Start(); - ThreadTracker.Add(listener); - - m_writer.WriteLine(m_user); - m_writer.Flush(); - m_writer.WriteLine("NICK " + m_nick); - m_writer.Flush(); - m_writer.WriteLine("JOIN " + m_channel); - m_writer.Flush(); - m_log.Info("[IRC]: Connection fully established"); - m_connected = true; - } - catch (Exception e) - { - Console.WriteLine(e.ToString()); - } - return m_connected; + presence.ControllingClient.SendChatMessage(message, (byte) type, fromPos, fromName, + fromAgentID,(byte)src,(byte)ChatAudibleLevel.Fully); } } - - public void Reconnect() - { - m_connected = false; - listener.Abort(); - pingSender.Abort(); - m_writer.Close(); - m_reader.Close(); - m_tcp.Close(); - if (m_enabled) - { - Connect(m_last_scenes); - } - } - - public void PrivMsg(string from, string region, string msg) - { - // One message to the IRC server - - try - { - if (m_privmsgformat == null) - { - m_writer.WriteLine("PRIVMSG {0} :<{1} in {2}>: {3}", m_channel, from, region, msg); - } - else - { - m_writer.WriteLine(m_privmsgformat, m_channel, from, region, msg); - } - m_writer.Flush(); - m_log.Info("[IRC]: PrivMsg " + from + " in " + region + " :" + msg); - } - catch (IOException) - { - m_log.Error("[IRC]: Disconnected from IRC server.(PrivMsg)"); - Reconnect(); - } - catch (Exception ex) - { - m_log.Error("[IRC]: PrivMsg exception trap:" + ex.ToString()); - } - } - - private Dictionary ExtractMsg(string input) - { - //examines IRC commands and extracts any private messages - // which will then be reboadcast in the Sim - - m_log.Info("[IRC]: ExtractMsg: " + input); - Dictionary result = null; - //string regex = @":(?\w*)!~(?\S*) PRIVMSG (?\S+) :(?.*)"; - string regex = @":(?\w*)!(?\S*) PRIVMSG (?\S+) :(?.*)"; - Regex RE = new Regex(regex, RegexOptions.Multiline); - MatchCollection matches = RE.Matches(input); - // Get some direct matches $1 $4 is a - if ((matches.Count == 1) && (matches[0].Groups.Count == 5)) - { - result = new Dictionary(); - result.Add("nick", matches[0].Groups[1].Value); - result.Add("user", matches[0].Groups[2].Value); - result.Add("channel", matches[0].Groups[3].Value); - result.Add("msg", matches[0].Groups[4].Value); - } - else - { - m_log.Info("[IRC]: Number of matches: " + matches.Count); - if (matches.Count > 0) - { - m_log.Info("[IRC]: Number of groups: " + matches[0].Groups.Count); - } - } - return result; - } - - public void PingRun() - { - // IRC keep alive thread - // send PING ever 15 seconds - while (true) - { - try - { - if (m_connected == true) - { - m_writer.WriteLine("PING :" + m_server); - m_writer.Flush(); - Thread.Sleep(15000); - } - } - catch (IOException) - { - m_log.Error("[IRC]: Disconnected from IRC server.(PingRun)"); - Reconnect(); - } - catch (Exception ex) - { - m_log.Error("[IRC]: PingRun exception trap:" + ex.ToString() + "\n" + ex.StackTrace); - } - } - } - - public void ListenerRun() - { - string inputLine; - LLVector3 pos = new LLVector3(128, 128, 20); - while (true) - { - try - { - while ((m_connected == true) && ((inputLine = m_reader.ReadLine()) != null)) - { - // Console.WriteLine(inputLine); - if (inputLine.Contains(m_channel)) - { - Dictionary data = ExtractMsg(inputLine); - // Any chat ??? - if (data != null) - { - foreach (Scene m_scene in m_scenes) - { - m_scene.ForEachScenePresence(delegate(ScenePresence avatar) - { - if (!avatar.IsChildAgent) - { - avatar.ControllingClient.SendChatMessage( - Helpers.StringToField(data["msg"]), 255, - pos, data["nick"], - LLUUID.Zero,(byte)ChatSourceType.Agent,(byte)ChatAudibleLevel.Fully); - } - }); - } - } - else - { - // Was an command from the IRC server - ProcessIRCCommand(inputLine); - } - } - else - { - // Was an command from the IRC server - ProcessIRCCommand(inputLine); - } - Thread.Sleep(150); - } - } - catch (IOException) - { - m_log.Error("[IRC]: ListenerRun IOException. Disconnected from IRC server ??? (ListenerRun)"); - Reconnect(); - } - catch (Exception ex) - { - m_log.Error("[IRC]: ListenerRun exception trap:" + ex.ToString() + "\n" + ex.StackTrace); - } - } - } - - public void BroadcastSim(string message, string sender) - { - LLVector3 pos = new LLVector3(128, 128, 20); - try - { - foreach (Scene m_scene in m_scenes) - { - m_scene.ForEachScenePresence(delegate(ScenePresence avatar) - { - if (!avatar.IsChildAgent) - { - avatar.ControllingClient.SendChatMessage( - Helpers.StringToField(message), 255, - pos, sender, - LLUUID.Zero,(byte)ChatSourceType.Object,(byte)ChatAudibleLevel.Fully); - } - }); - } - } - catch (Exception ex) // IRC gate should not crash Sim - { - m_log.Error("[IRC]: BroadcastSim Exception Trap:" + ex.ToString() + "\n" + ex.StackTrace); - } - } - - public void ProcessIRCCommand(string command) - { - //m_log.Info("[IRC]: ProcessIRCCommand:" + command); - - string[] commArgs = new string[command.Split(' ').Length]; - string c_server = m_server; - - commArgs = command.Split(' '); - if (commArgs[0].Substring(0, 1) == ":") - { - commArgs[0] = commArgs[0].Remove(0, 1); - } - - if (commArgs[1] == "002") - { - // fetch the correct servername - // ex: irc.freenode.net -> brown.freenode.net/kornbluth.freenode.net/... - // irc.bluewin.ch -> irc1.bluewin.ch/irc2.bluewin.ch - - c_server = (commArgs[6].Split('['))[0]; - m_server = c_server; - } - - if (commArgs[0] == "ERROR") - { - m_log.Error("[IRC]: IRC SERVER ERROR:" + command); - } - - if (commArgs[0] == "PING") - { - string p_reply = ""; - - for (int i = 1; i < commArgs.Length; i++) - { - p_reply += commArgs[i] + " "; - } - - m_writer.WriteLine("PONG " + p_reply); - m_writer.Flush(); - } - else if (commArgs[0] == c_server) - { - // server message - try - { - Int32 commandCode = Int32.Parse(commArgs[1]); - switch (commandCode) - { - case (int) ErrorReplies.NicknameInUse: - // Gen a new name - m_nick = m_basenick + Util.RandomClass.Next(1, 99); - m_log.Error("[IRC]: IRC SERVER reports NicknameInUse, trying " + m_nick); - // Retry - m_writer.WriteLine("NICK " + m_nick); - m_writer.Flush(); - m_writer.WriteLine("JOIN " + m_channel); - m_writer.Flush(); - break; - case (int) ErrorReplies.NotRegistered: - break; - case (int) Replies.EndOfMotd: - break; - } - } - catch (Exception) - { - } - } - else - { - // Normal message - string commAct = commArgs[1]; - switch (commAct) - { - case "JOIN": - eventIrcJoin(commArgs); - break; - case "PART": - eventIrcPart(commArgs); - break; - case "MODE": - eventIrcMode(commArgs); - break; - case "NICK": - eventIrcNickChange(commArgs); - break; - case "KICK": - eventIrcKick(commArgs); - break; - case "QUIT": - eventIrcQuit(commArgs); - break; - case "PONG": - break; // that's nice - } - } - } - - public void eventIrcJoin(string[] commArgs) - { - string IrcChannel = commArgs[2]; - string IrcUser = commArgs[0].Split('!')[0]; - BroadcastSim(IrcUser + " is joining " + IrcChannel, m_nick); - } - - public void eventIrcPart(string[] commArgs) - { - string IrcChannel = commArgs[2]; - string IrcUser = commArgs[0].Split('!')[0]; - BroadcastSim(IrcUser + " is parting " + IrcChannel, m_nick); - } - - public void eventIrcMode(string[] commArgs) - { - //string IrcChannel = commArgs[2]; - //string IrcUser = commArgs[0].Split('!')[0]; - string UserMode = ""; - for (int i = 3; i < commArgs.Length; i++) - { - UserMode += commArgs[i] + " "; - } - - if (UserMode.Substring(0, 1) == ":") - { - UserMode = UserMode.Remove(0, 1); - } - } - - public void eventIrcNickChange(string[] commArgs) - { - string UserOldNick = commArgs[0].Split('!')[0]; - string UserNewNick = commArgs[2].Remove(0, 1); - BroadcastSim(UserOldNick + " changed their nick to " + UserNewNick, m_nick); - } - - public void eventIrcKick(string[] commArgs) - { - string UserKicker = commArgs[0].Split('!')[0]; - string UserKicked = commArgs[3]; - string IrcChannel = commArgs[2]; - string KickMessage = ""; - for (int i = 4; i < commArgs.Length; i++) - { - KickMessage += commArgs[i] + " "; - } - BroadcastSim(UserKicker + " kicked " + UserKicked + " on " + IrcChannel + " saying " + KickMessage, m_nick); - if (UserKicked == m_nick) - { - BroadcastSim("Hey, that was me!!!", m_nick); - } - } - - public void eventIrcQuit(string[] commArgs) - { - string IrcUser = commArgs[0].Split('!')[0]; - string QuitMessage = ""; - - for (int i = 2; i < commArgs.Length; i++) - { - QuitMessage += commArgs[i] + " "; - } - BroadcastSim(IrcUser + " quits saying " + QuitMessage, m_nick); - } - - public void Close() - { - m_connected = false; - m_writer.WriteLine("QUIT :" + m_nick + " to " + m_channel + " wormhole with " + m_server + " closing"); - m_writer.Flush(); - listener.Abort(); - pingSender.Abort(); - m_writer.Close(); - m_reader.Close(); - m_tcp.Close(); - } } } \ No newline at end of file -- cgit v1.1