diff --git a/OpenSim/Region/Environment/Modules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Chat/ChatModule.cs index 9730b02aa9..e12588cc24 100644 --- a/OpenSim/Region/Environment/Modules/Avatar/Chat/ChatModule.cs +++ b/OpenSim/Region/Environment/Modules/Avatar/Chat/ChatModule.cs @@ -65,6 +65,7 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat m_scenes.Add(scene); scene.EventManager.OnNewClient += NewClient; scene.EventManager.OnChatFromWorld += SimChat; + scene.EventManager.OnChatBroadcast += SimBroadcast; } // wrap this in a try block so that defaults will work if @@ -104,8 +105,34 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat #endregion #region ISimChat Members + public void SimBroadcast(Object sender, ChatFromViewerArgs c) + { + // We only want to relay stuff on channel 0 + if (c.Channel != 0 && c.Channel != DEBUG_CHANNEL) return; + + if (c.Channel == DEBUG_CHANNEL) + c.Type = ChatTypeEnum.DebugChannel; + + // chat works by redistributing every incoming chat + // message to each avatar in the scene + LLVector3 pos = new LLVector3(128, 128, 30); + ((Scene)c.Scene).ForEachScenePresence(delegate(ScenePresence presence) + { + if (!presence.IsChildAgent) return; + + presence.ControllingClient.SendChatMessage(c.Message, + 1, //255, + pos, c.From, LLUUID.Zero, + c.Channel == DEBUG_CHANNEL? (byte)ChatSourceType.Object : (byte)ChatSourceType.Agent, + (byte)ChatAudibleLevel.Fully); + }); + } + public void SimChat(Object sender, ChatFromViewerArgs e) { + // early return if not on public or debug channel + if (e.Channel != 0 && e.Channel != DEBUG_CHANNEL) return; + ScenePresence avatar = null; Scene scene = (Scene) e.Scene; @@ -136,32 +163,28 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat fromAgentID = e.Sender.AgentId; } - // 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; + if (e.Channel == DEBUG_CHANNEL) + e.Type = ChatTypeEnum.DebugChannel; - // 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) + // 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 == DEBUG_CHANNEL) - { - 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); + } + }); } } @@ -183,23 +206,23 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat LLUUID fromAgentID, string fromName, ChatTypeEnum type, string message, ChatSourceType src) { - if (!presence.IsChildAgent) + // don't send stuff to child agents + if (presence.IsChildAgent) return; + + 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) { - 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) - { - return; - } - - // 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); + return; } + + // 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); } } } \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/Avatar/Chat/IRCBridgeModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Chat/IRCBridgeModule.cs index 283551bf23..18106bebcc 100644 --- a/OpenSim/Region/Environment/Modules/Avatar/Chat/IRCBridgeModule.cs +++ b/OpenSim/Region/Environment/Modules/Avatar/Chat/IRCBridgeModule.cs @@ -43,7 +43,7 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat { public class IRCBridgeModule : IRegionModule, ISimChat { - private static readonly ILog m_log = + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private const int DEBUG_CHANNEL = 2147483647; @@ -94,34 +94,34 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat m_irc_connector.Name = "IRCConnectorThread"; m_irc_connector.IsBackground = true; } - m_log.InfoFormat("[IRC] initialized for {0}, nick: {1} ", scene.RegionInfo.RegionName, + m_log.InfoFormat("[IRC] initialized for {0}, nick: {1} ", scene.RegionInfo.RegionName, m_defaultzone); } } public void PostInitialise() { - if (m_irc.Enabled) + if (!m_irc.Enabled) return; + + try { - try + //m_irc.Connect(m_scenes); + if (m_irc_connector == null) { - //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); - } + m_irc_connector = new Thread(IRCConnectRun); + m_irc_connector.Name = "IRCConnectorThread"; + m_irc_connector.IsBackground = true; } - catch (Exception) + + if (!m_irc_connector.IsAlive) { + m_irc_connector.Start(); + ThreadTracker.Add(m_irc_connector); } } + catch (Exception) + { + } } public void Close() @@ -145,6 +145,13 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat public void SimChat(Object sender, ChatFromViewerArgs e) { + // We only want to relay stuff on channel 0 + if (e.Channel != 0) return; + if (e.Message.Length == 0) return; + + // not interested in our own babblings + if (m_irc.Equals(sender)) return; + ScenePresence avatar = null; Scene scene = (Scene) e.Scene; @@ -187,21 +194,21 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat } } - - // We only want to relay stuff on channel 0 + if (e.Message.StartsWith("/me ") && (null != avatar)) + e.Message = String.Format("{0} {1}", fromName, e.Message.Substring(4)); if (e.Channel == 0 || e.Channel == DEBUG_CHANNEL) { if (e.Channel == DEBUG_CHANNEL) e.Type = ChatTypeEnum.DebugChannel; - // IRC stuff + // 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); - } - } + if (m_irc.Connected && (avatar != null)) // this is to keep objects from talking to IRC + { + m_irc.PrivMsg(fromName, scene.RegionInfo.RegionName, e.Message); + } + } } } @@ -222,7 +229,7 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat if ((m_irc.Enabled) && (m_irc.Connected)) { m_log.DebugFormat("[IRC] {0} logging on", clientName); - m_irc.PrivMsg(m_irc.Nick, "Sim", + m_irc.PrivMsg(m_irc.Nick, "Sim", String.Format("notices {0} logging on", clientName)); } m_last_new_user = clientName; @@ -246,7 +253,7 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat m_irc.PrivMsg(m_irc.Nick, "Sim", String.Format("notices {0} in {1}", clientName, regionName)); } } - catch (Exception ex) + catch (Exception) { } } @@ -263,7 +270,7 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat m_irc.PrivMsg(m_irc.Nick, "Sim", String.Format("notices {0} left {1}", clientName, regionName)); } } - catch (Exception ex) + catch (Exception) { } } @@ -288,7 +295,7 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat m_log.InfoFormat("[IRC]: {0} logging out", clientName); } - if (m_last_new_user == clientName) + if (m_last_new_user == clientName) m_last_new_user = null; } } @@ -430,6 +437,7 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat try { if (m_connected) return true; + m_scenes = scenes; if (m_last_scenes == null) { @@ -517,8 +525,9 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat 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)) + if ((matches.Count == 0) || (matches.Count != 1) || (matches[0].Groups.Count != 5)) { result = new Dictionary(); result.Add("nick", matches[0].Groups[1].Value); @@ -533,7 +542,15 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat { m_log.Info("[IRC]: Number of groups: " + matches[0].Groups.Count); } + return null; } + + 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); + return result; } @@ -581,32 +598,32 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat // Any chat ??? if (data != null) { - foreach (Scene m_scene in m_scenes) + ChatFromViewerArgs c = new ChatFromViewerArgs(); + c.Message = data["msg"]; + c.Type = ChatTypeEnum.Say; + c.Channel = 0; + c.Position = pos; + c.From = data["nick"]; + c.Sender = null; + c.SenderUUID = LLUUID.Zero; + + // is message "\001ACTION foo + // bar\001"? -> "/me foo bar" + if ((1 == c.Message[0]) && c.Message.Substring(1).StartsWith("ACTION")) + c.Message = String.Format("/me {0}", c.Message.Substring(8, c.Message.Length - 9)); + + foreach (Scene 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); - } - }); + c.Scene = scene; + scene.EventManager.TriggerOnChatBroadcast(this, c); } } - else - { - // Was an command from the IRC server - ProcessIRCCommand(inputLine); - } - } - else - { - // Was an command from the IRC server - ProcessIRCCommand(inputLine); + + Thread.Sleep(150); + continue; } + + ProcessIRCCommand(inputLine); Thread.Sleep(150); } } @@ -627,20 +644,19 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat LLVector3 pos = new LLVector3(128, 128, 20); try { + ChatFromViewerArgs c = new ChatFromViewerArgs(); + c.From = sender; + c.Message = String.Format(format, args); + c.Type = ChatTypeEnum.Say; + c.Channel = 0; + c.Position = new LLVector3(128, 128, 20); + c.Sender = null; + c.SenderUUID = LLUUID.Zero; + 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); - } - }); + c.Scene = m_scene; + m_scene.EventManager.TriggerOnChatBroadcast(this, c); } } catch (Exception ex) // IRC gate should not crash Sim @@ -750,15 +766,17 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat public void eventIrcJoin(string[] commArgs) { string IrcChannel = commArgs[2]; + if (IrcChannel.StartsWith(":")) + IrcChannel = IrcChannel.Substring(1); string IrcUser = commArgs[0].Split('!')[0]; - BroadcastSim(m_nick, "{0} is joining {1}", IrcUser, IrcChannel); + BroadcastSim(IrcUser, "/me joins {0}", 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); + BroadcastSim(IrcUser, "/me parts {0}", IrcChannel); } public void eventIrcMode(string[] commArgs) @@ -781,7 +799,7 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat { string UserOldNick = commArgs[0].Split('!')[0]; string UserNewNick = commArgs[2].Remove(0, 1); - BroadcastSim(m_nick, "{0} changed their nick to {1}", UserOldNick, UserNewNick); + BroadcastSim(UserOldNick, "/me is now known as {0}", UserNewNick); } public void eventIrcKick(string[] commArgs) @@ -794,7 +812,7 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat { KickMessage += commArgs[i] + " "; } - BroadcastSim(m_nick, "{0} kicked {1} on {2} saying {3}", UserKicker, UserKicked, IrcChannel, KickMessage); + BroadcastSim(UserKicker, "/me kicks kicks {0} off {1} saying \"{2}\"", UserKicked, IrcChannel, KickMessage); if (UserKicked == m_nick) { BroadcastSim(m_nick, "Hey, that was me!!!"); @@ -810,7 +828,7 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat { QuitMessage += commArgs[i] + " "; } - BroadcastSim(m_nick, "{0} quits saying {1}", IrcUser, QuitMessage); + BroadcastSim(IrcUser, "/me quits saying \"{0}\"", QuitMessage); } public void Close() diff --git a/OpenSim/Region/Environment/Scenes/EventManager.cs b/OpenSim/Region/Environment/Scenes/EventManager.cs index 1c345bac6f..6cecb6d151 100644 --- a/OpenSim/Region/Environment/Scenes/EventManager.cs +++ b/OpenSim/Region/Environment/Scenes/EventManager.cs @@ -217,6 +217,12 @@ namespace OpenSim.Region.Environment.Scenes /// public delegate void ChatFromWorldEvent(Object sender, ChatFromViewerArgs chat); public event ChatFromWorldEvent OnChatFromWorld; + /// + /// ChatBroadcastEvent is called via Scene when a broadcast chat message + /// from world comes in (chat from viewer is available via client.OnChatFromViewer). + /// + public delegate void ChatBroadcastEvent(Object sender, ChatFromViewerArgs chat); + public event ChatBroadcastEvent OnChatBroadcast; public class MoneyTransferArgs : EventArgs { @@ -320,6 +326,7 @@ namespace OpenSim.Region.Environment.Scenes private RegisterCapsEvent handlerRegisterCaps = null; // OnRegisterCaps; private DeregisterCapsEvent handlerDeregisterCaps = null; // OnDeregisterCaps; private ChatFromWorldEvent handlerChatFromWorld = null; // OnChatFromWorld; + private ChatBroadcastEvent handlerChatBroadcast = null; // OnChatBroadcast; private NewInventoryItemUploadComplete handlerNewInventoryItemUpdateComplete = null; private RequestChangeWaterHeight handlerRequestChangeWaterHeight = null; //OnRequestChangeWaterHeight private ScriptControlEvent handlerScriptControlEvent = null; @@ -699,6 +706,15 @@ namespace OpenSim.Region.Environment.Scenes } } + public void TriggerOnChatBroadcast(Object sender, ChatFromViewerArgs chat) + { + handlerChatBroadcast = OnChatBroadcast; + if (handlerChatBroadcast != null) + { + handlerChatBroadcast(sender, chat); + } + } + internal void TriggerControlEvent(uint p, LLUUID scriptUUID, LLUUID avatarID, uint held, uint _changed) { handlerScriptControlEvent = OnScriptControlEvent; diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index 9da98b66cc..817441d342 100644 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example @@ -292,6 +292,7 @@ enabled = false ;nick = OpenSimBotNameProbablyMakeThisShorter ;channel = #the_irc_channel_you_want_to_connect_to ;port = 6667 +;fallback_region = name of "default" region ;MSGformat fields : 0=botnick, 1=user, 2=region, 3=message ; must start with "PRIVMSG {0} : " or irc server will get upset ;for : :