diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 93ce29e6a3..c1c4af29b9 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -930,12 +930,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// /// /// - public void SendChatMessage(string message, byte type, LLVector3 fromPos, string fromName, LLUUID fromAgentID, byte source, byte audible) + public void SendChatMessage(string message, byte type, LLVector3 fromPos, string fromName, + LLUUID fromAgentID, byte source, byte audible) { SendChatMessage(Helpers.StringToField(message), type, fromPos, fromName, fromAgentID, source, audible); } - public void SendChatMessage(byte[] message, byte type, LLVector3 fromPos, string fromName, LLUUID fromAgentID, byte source, byte audible) + public void SendChatMessage(byte[] message, byte type, LLVector3 fromPos, string fromName, + LLUUID fromAgentID, byte source, byte audible) { ChatFromSimulatorPacket reply = (ChatFromSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.ChatFromSimulator); reply.ChatData.Audible = audible; diff --git a/OpenSim/Region/Environment/Modules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Chat/ChatModule.cs index 37cf328b84..82162229f3 100644 --- a/OpenSim/Region/Environment/Modules/Avatar/Chat/ChatModule.cs +++ b/OpenSim/Region/Environment/Modules/Avatar/Chat/ChatModule.cs @@ -65,7 +65,6 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat m_scenes.Add(scene); scene.EventManager.OnNewClient += NewClient; scene.EventManager.OnChatFromWorld += SimChat; - // scene.RegisterModuleInterface(this); } // wrap this in a try block so that defaults will work if @@ -108,8 +107,6 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat public void SimChat(Object sender, ChatFromViewerArgs e) { ScenePresence avatar = null; - - //TODO: Move ForEachScenePresence and others into IScene. Scene scene = (Scene) e.Scene; //TODO: Remove the need for this check diff --git a/OpenSim/Region/Environment/Modules/Avatar/Chat/IRCBridgeModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Chat/IRCBridgeModule.cs new file mode 100644 index 0000000000..0b5f1b4f92 --- /dev/null +++ b/OpenSim/Region/Environment/Modules/Avatar/Chat/IRCBridgeModule.cs @@ -0,0 +1,860 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.IO; +using System.Net.Sockets; +using System.Reflection; +using System.Text.RegularExpressions; +using System.Threading; +using libsecondlife; +using log4net; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; + +namespace OpenSim.Region.Environment.Modules.Avatar.Chat +{ + public class IRCBridgeModule : IRegionModule, ISimChat + { + private static readonly ILog m_log = + LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private const int DEBUG_CHANNEL = 2147483647; + + private string m_defaultzone = null; + + private IRCChatModule m_irc = null; + private Thread m_irc_connector = null; + + private string m_last_leaving_user = null; + private string m_last_new_user = null; + private List m_scenes = new List(); + + internal object m_syncInit = new object(); + internal object m_syncLogout = new object(); + + #region IRegionModule Members + + public void Initialise(Scene scene, IConfigSource config) + { + lock (m_syncInit) + { + if (!m_scenes.Contains(scene)) + { + m_scenes.Add(scene); + scene.EventManager.OnNewClient += NewClient; + scene.EventManager.OnChatFromWorld += SimChat; + scene.EventManager.OnMakeRootAgent += OnMakeRootAgent; + scene.EventManager.OnMakeChildAgent += OnMakeChildAgent; + } + + try + { + m_defaultzone = config.Configs["IRC"].GetString("fallback_region", "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("[IRC] initialized for {0}, nick: {1} ", scene.RegionInfo.RegionName, + m_defaultzone); + } + } + + 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 + { + get { return "IRCBridgeModule"; } + } + + public bool IsSharedModule + { + get { return true; } + } + + #endregion + + #region ISimChat Members + + public void SimChat(Object sender, ChatFromViewerArgs e) + { + ScenePresence avatar = null; + Scene scene = (Scene) e.Scene; + + if (scene == null) + scene = m_scenes[0]; + + // Filled in since it's easier than rewriting right now. + string fromName = e.From; + + if (e.Sender != null) + { + avatar = scene.GetScenePresence(e.Sender.AgentId); + } + + if (avatar != null) + { + fromName = avatar.Firstname + " " + avatar.Lastname; + } + + // 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 == DEBUG_CHANNEL) + { + 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); + } + } + } + } + + #endregion + + public void NewClient(IClientAPI client) + { + try + { + string clientName = String.Format("{0} {1}", client.FirstName, client.LastName); + + client.OnChatFromViewer += SimChat; + client.OnLogout += ClientLoggedOut; + client.OnConnectionClosed += ClientLoggedOut; + + if (clientName != m_last_new_user) + { + if ((m_irc.Enabled) && (m_irc.Connected)) + { + m_log.DebugFormat("[IRC] {0} logging on", clientName); + m_irc.PrivMsg(m_irc.Nick, "Sim", + String.Format("notices {0} logging on", clientName)); + } + m_last_new_user = clientName; + } + } + catch (Exception ex) + { + m_log.Error("[IRC]: NewClient exception trap:" + ex.ToString()); + } + } + + public void OnMakeRootAgent(ScenePresence presence) + { + try + { + if ((m_irc.Enabled) && (m_irc.Connected)) + { + string regionName = presence.Scene.RegionInfo.RegionName; + string clientName = String.Format("{0} {1}", presence.Firstname, presence.Lastname); + m_log.DebugFormat("[IRC] noticing {0} in {1}", clientName, regionName); + m_irc.PrivMsg(m_irc.Nick, "Sim", String.Format("notices {0} in {1}", clientName, regionName)); + } + } + catch (Exception ex) + { + } + } + + public void OnMakeChildAgent(ScenePresence presence) + { + try + { + if ((m_irc.Enabled) && (m_irc.Connected)) + { + string regionName = presence.Scene.RegionInfo.RegionName; + string clientName = String.Format("{0} {1}", presence.Firstname, presence.Lastname); + m_log.DebugFormat("[IRC] noticing {0} in {1}", clientName, regionName); + m_irc.PrivMsg(m_irc.Nick, "Sim", String.Format("notices {0} left {1}", clientName, regionName)); + } + } + catch (Exception ex) + { + } + } + + + public void ClientLoggedOut(IClientAPI client) + { + lock (m_syncLogout) + { + try + { + if ((m_irc.Enabled) && (m_irc.Connected)) + { + string clientName = String.Format("{0} {1}", 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", String.Format("notices {0} logging out", clientName)); + m_log.InfoFormat("[IRC]: {0} logging out", clientName); + } + + if (m_last_new_user == clientName) + m_last_new_user = null; + } + } + catch (Exception ex) + { + m_log.Error("[IRC]: ClientLoggedOut exception trap:" + ex.ToString()); + } + } + } + + // 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 firstName, string lastName, bool ignoreChilds) + { + string sourceRegion = null; + foreach (Scene s in m_scenes) + { + s.ForEachScenePresence(delegate(ScenePresence presence) + { + if (ignoreChilds + && (presence.Firstname == firstName) + && (presence.Lastname == lastName)) + { + sourceRegion = presence.Scene.RegionInfo.RegionName; + return; + } + + if (!ignoreChilds && !presence.IsChildAgent + && (presence.Firstname == firstName) + && (presence.Lastname == lastName)) + { + sourceRegion = presence.Scene.RegionInfo.RegionName; + return; + } + }); + 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 an 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(String.Format("NICK {0}", m_nick)); + m_writer.Flush(); + m_writer.WriteLine(String.Format("JOIN {0}", 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; + } + } + + 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 + { + m_writer.WriteLine(m_privmsgformat, m_channel, from, region, msg); + m_writer.Flush(); + m_log.InfoFormat("[IRC]: PrivMsg {0} in {1}: {2}", from, region, msg); + } + catch (IOException) + { + m_log.Error("[IRC]: Disconnected from IRC server.(PrivMsg)"); + Reconnect(); + } + catch (Exception ex) + { + m_log.ErrorFormat("[IRC]: PrivMsg exception trap: {0}", 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(String.Format("PING :{0}", 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.ErrorFormat("[IRC]: PingRun exception trap: {0}\n{1}", ex.ToString(), 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"]), + 1, // 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.ErrorFormat("[IRC]: ListenerRun exception trap: {0}\n{1}", ex.ToString(), ex.StackTrace); + } + } + } + + public void BroadcastSim(string sender, string format, params string[] args) + { + 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(String.Format(format, args)), + 1, //255, + pos, sender, LLUUID.Zero, + (byte)ChatSourceType.Object, + (byte)ChatAudibleLevel.Fully); + } + }); + } + } + catch (Exception ex) // IRC gate should not crash Sim + { + m_log.ErrorFormat("[IRC]: BroadcastSim Exception Trap: {0}\n{1}", ex.ToString(), 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.ErrorFormat("[IRC]: IRC SERVER ERROR: {0}", command); + } + + if (commArgs[0] == "PING") + { + string p_reply = ""; + + for (int i = 1; i < commArgs.Length; i++) + { + p_reply += commArgs[i] + " "; + } + + m_writer.WriteLine(String.Format("PONG {0}", 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.ErrorFormat("[IRC]: IRC SERVER reports NicknameInUse, trying {0}", m_nick); + // Retry + m_writer.WriteLine(String.Format("NICK {0}", m_nick)); + m_writer.Flush(); + m_writer.WriteLine(String.Format("JOIN {0}", 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(m_nick, "{0} is joining {1}", IrcUser, IrcChannel); + } + + public void eventIrcPart(string[] commArgs) + { + string IrcChannel = commArgs[2]; + string IrcUser = commArgs[0].Split('!')[0]; + BroadcastSim(m_nick, "{0} is parting {1}", IrcUser, IrcChannel); + } + + 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(m_nick, "{0} changed their nick to {1}", UserOldNick, UserNewNick); + } + + 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(m_nick, "{0} kicked {1} on {2} saying {3}", UserKicker, UserKicked, IrcChannel, KickMessage); + if (UserKicked == m_nick) + { + BroadcastSim(m_nick, "Hey, that was me!!!"); + } + } + + 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(m_nick, "{0} quits saying {1}", IrcUser, QuitMessage); + } + + public void Close() + { + m_connected = false; + m_writer.WriteLine(String.Format("QUIT :{0} to {1} wormhole with {2} closing", m_nick, m_channel, m_server)); + m_writer.Flush(); + listener.Abort(); + pingSender.Abort(); + m_writer.Close(); + m_reader.Close(); + m_tcp.Close(); + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Scenes/EventManager.cs b/OpenSim/Region/Environment/Scenes/EventManager.cs index f8eef82843..6c714f86d6 100644 --- a/OpenSim/Region/Environment/Scenes/EventManager.cs +++ b/OpenSim/Region/Environment/Scenes/EventManager.cs @@ -156,7 +156,11 @@ namespace OpenSim.Region.Environment.Scenes public event ScriptNotAtTargetEvent OnScriptNotAtTargetEvent; - public event OnNewPresenceDelegate OnMakeChildAgent; + public delegate void OnMakeChildAgentDelegate(ScenePresence presence); + public event OnMakeChildAgentDelegate OnMakeChildAgent; + + public delegate void OnMakeRootAgentDelegate(ScenePresence presence); + public event OnMakeRootAgentDelegate OnMakeRootAgent; public delegate void NewInventoryItemUploadComplete(LLUUID avatarID, LLUUID assetID, string name, int userlevel); @@ -307,7 +311,8 @@ namespace OpenSim.Region.Environment.Scenes private NewGridInstantMessage handlerGridInstantMessageToIM = null; //OnGridInstantMessageToIMModule; private NewGridInstantMessage handlerGridInstantMessageToFriends = null; //OnGridInstantMessageToFriendsModule; private ClientClosed handlerClientClosed = null; //OnClientClosed; - private OnNewPresenceDelegate handlerMakeChildAgent = null; //OnMakeChildAgent; + private OnMakeChildAgentDelegate handlerMakeChildAgent = null; //OnMakeChildAgent; + private OnMakeRootAgentDelegate handlerMakeRootAgent = null; //OnMakeRootAgent; private OnTerrainTickDelegate handlerTerrainTick = null; // OnTerainTick; private RegisterCapsEvent handlerRegisterCaps = null; // OnRegisterCaps; private DeregisterCapsEvent handlerDeregisterCaps = null; // OnDeregisterCaps; @@ -574,6 +579,15 @@ namespace OpenSim.Region.Environment.Scenes } } + public void TriggerOnMakeRootAgent(ScenePresence presence) + { + handlerMakeRootAgent = OnMakeRootAgent; + if (handlerMakeRootAgent != null) + { + handlerMakeRootAgent(presence); + } + } + public void TriggerOnRegisterCaps(LLUUID agentID, Caps caps) { handlerRegisterCaps = OnRegisterCaps; diff --git a/OpenSim/Region/Environment/Scenes/Scene.cs b/OpenSim/Region/Environment/Scenes/Scene.cs index fe8cadad9f..71c5b18b45 100644 --- a/OpenSim/Region/Environment/Scenes/Scene.cs +++ b/OpenSim/Region/Environment/Scenes/Scene.cs @@ -1582,6 +1582,7 @@ namespace OpenSim.Region.Environment.Scenes CommsManager.UserProfileCacheService.AddNewUser(client.AgentId); } + EventManager.TriggerOnNewClient(client); } protected virtual void SubscribeToClientEvents(IClientAPI client) @@ -1660,7 +1661,7 @@ namespace OpenSim.Region.Environment.Scenes client.OnUndo += m_innerScene.HandleUndo; client.OnObjectGroupRequest += m_innerScene.HandleObjectGroupUpdate; - EventManager.TriggerOnNewClient(client); + // EventManager.TriggerOnNewClient(client); } public virtual void TeleportClientHome(LLUUID AgentId, IClientAPI client) diff --git a/OpenSim/Region/Environment/Scenes/ScenePresence.cs b/OpenSim/Region/Environment/Scenes/ScenePresence.cs index 103068ce4e..a692b33217 100644 --- a/OpenSim/Region/Environment/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Environment/Scenes/ScenePresence.cs @@ -590,6 +590,8 @@ namespace OpenSim.Region.Environment.Scenes //{ m_scene.SendAllSceneObjectsToClient(this); + m_scene.EventManager.TriggerOnMakeRootAgent(this); + //m_gotAllObjectsInScene = true; //} }