Adding OnChatBroadcast event logic to EventManager providing

a clean interface for Sim broadcasts. Added SimBroadcast support to 
ChatModule.

Removing all code from IRCBridgeModule dealing with agent/client directly.

Cleaning up ChatModule.

Polishing IRC messages, adding support for "/me" (both directions).
0.6.0-stable
Dr Scofield 2008-05-26 11:56:04 +00:00
parent bf7c557f57
commit 42cdf3c240
4 changed files with 166 additions and 108 deletions

View File

@ -65,6 +65,7 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat
m_scenes.Add(scene); m_scenes.Add(scene);
scene.EventManager.OnNewClient += NewClient; scene.EventManager.OnNewClient += NewClient;
scene.EventManager.OnChatFromWorld += SimChat; scene.EventManager.OnChatFromWorld += SimChat;
scene.EventManager.OnChatBroadcast += SimBroadcast;
} }
// wrap this in a try block so that defaults will work if // wrap this in a try block so that defaults will work if
@ -104,8 +105,34 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat
#endregion #endregion
#region ISimChat Members #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) 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; ScenePresence avatar = null;
Scene scene = (Scene) e.Scene; Scene scene = (Scene) e.Scene;
@ -136,32 +163,28 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat
fromAgentID = e.Sender.AgentId; fromAgentID = e.Sender.AgentId;
} }
// We only want to relay stuff on channel 0 if (e.Channel == DEBUG_CHANNEL)
if (e.Channel == 0 || e.Channel == DEBUG_CHANNEL) e.Type = ChatTypeEnum.DebugChannel;
{
if (e.Channel == DEBUG_CHANNEL)
e.Type = ChatTypeEnum.DebugChannel;
// chat works by redistributing every incoming chat // chat works by redistributing every incoming chat
// message to each avatar in the scene // message to each avatar in the scene
foreach (Scene s in m_scenes) foreach (Scene s in m_scenes)
{ {
s.ForEachScenePresence(delegate(ScenePresence presence) s.ForEachScenePresence(delegate(ScenePresence presence)
{
if (e.Channel == DEBUG_CHANNEL)
{ {
if (e.Channel == DEBUG_CHANNEL) TrySendChatMessage(presence, fromPos, regionPos,
{ fromAgentID, fromName, e.Type,
TrySendChatMessage(presence, fromPos, regionPos, message, ChatSourceType.Object);
fromAgentID, fromName, e.Type, }
message, ChatSourceType.Object); else
} {
else TrySendChatMessage(presence, fromPos, regionPos,
{ fromAgentID, fromName, e.Type,
TrySendChatMessage(presence, fromPos, regionPos, message, ChatSourceType.Agent);
fromAgentID, fromName, e.Type, }
message, ChatSourceType.Agent); });
}
});
}
} }
} }
@ -183,23 +206,23 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat
LLUUID fromAgentID, string fromName, ChatTypeEnum type, LLUUID fromAgentID, string fromName, ChatTypeEnum type,
string message, ChatSourceType src) 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; return;
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);
} }
// 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);
} }
} }
} }

View File

@ -101,27 +101,27 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat
public void PostInitialise() 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); m_irc_connector = new Thread(IRCConnectRun);
if (m_irc_connector == null) m_irc_connector.Name = "IRCConnectorThread";
{ m_irc_connector.IsBackground = true;
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)
if (!m_irc_connector.IsAlive)
{ {
m_irc_connector.Start();
ThreadTracker.Add(m_irc_connector);
} }
} }
catch (Exception)
{
}
} }
public void Close() public void Close()
@ -145,6 +145,13 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat
public void SimChat(Object sender, ChatFromViewerArgs e) 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; ScenePresence avatar = null;
Scene scene = (Scene) e.Scene; Scene scene = (Scene) e.Scene;
@ -187,21 +194,21 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat
} }
} }
if (e.Message.StartsWith("/me ") && (null != avatar))
// We only want to relay stuff on channel 0 e.Message = String.Format("{0} {1}", fromName, e.Message.Substring(4));
if (e.Channel == 0 || e.Channel == DEBUG_CHANNEL) if (e.Channel == 0 || e.Channel == DEBUG_CHANNEL)
{ {
if (e.Channel == DEBUG_CHANNEL) if (e.Channel == DEBUG_CHANNEL)
e.Type = ChatTypeEnum.DebugChannel; e.Type = ChatTypeEnum.DebugChannel;
// IRC stuff // IRC stuff
if (e.Message.Length > 0 && e.Channel == 0) if (e.Message.Length > 0 && e.Channel == 0)
{ {
if (m_irc.Connected && (avatar != null)) // this is to keep objects from talking to IRC if (m_irc.Connected && (avatar != null)) // this is to keep objects from talking to IRC
{ {
m_irc.PrivMsg(fromName, scene.RegionInfo.RegionName, e.Message); m_irc.PrivMsg(fromName, scene.RegionInfo.RegionName, e.Message);
} }
} }
} }
} }
@ -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)); 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)); m_irc.PrivMsg(m_irc.Nick, "Sim", String.Format("notices {0} left {1}", clientName, regionName));
} }
} }
catch (Exception ex) catch (Exception)
{ {
} }
} }
@ -430,6 +437,7 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat
try try
{ {
if (m_connected) return true; if (m_connected) return true;
m_scenes = scenes; m_scenes = scenes;
if (m_last_scenes == null) if (m_last_scenes == null)
{ {
@ -517,8 +525,9 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat
string regex = @":(?<nick>\w*)!(?<user>\S*) PRIVMSG (?<channel>\S+) :(?<msg>.*)"; string regex = @":(?<nick>\w*)!(?<user>\S*) PRIVMSG (?<channel>\S+) :(?<msg>.*)";
Regex RE = new Regex(regex, RegexOptions.Multiline); Regex RE = new Regex(regex, RegexOptions.Multiline);
MatchCollection matches = RE.Matches(input); MatchCollection matches = RE.Matches(input);
// Get some direct matches $1 $4 is a // 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<string, string>(); result = new Dictionary<string, string>();
result.Add("nick", matches[0].Groups[1].Value); 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); m_log.Info("[IRC]: Number of groups: " + matches[0].Groups.Count);
} }
return null;
} }
result = new Dictionary<string, string>();
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; return result;
} }
@ -581,32 +598,32 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat
// Any chat ??? // Any chat ???
if (data != null) 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) c.Scene = scene;
{ scene.EventManager.TriggerOnChatBroadcast(this, c);
if (!avatar.IsChildAgent)
{
avatar.ControllingClient.SendChatMessage(
Helpers.StringToField(data["msg"]),
1, // 255,
pos, data["nick"],
LLUUID.Zero,(byte)ChatSourceType.Agent,(byte)ChatAudibleLevel.Fully);
}
});
} }
} }
else
{ Thread.Sleep(150);
// Was an command from the IRC server continue;
ProcessIRCCommand(inputLine);
}
}
else
{
// Was an command from the IRC server
ProcessIRCCommand(inputLine);
} }
ProcessIRCCommand(inputLine);
Thread.Sleep(150); Thread.Sleep(150);
} }
} }
@ -627,20 +644,19 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat
LLVector3 pos = new LLVector3(128, 128, 20); LLVector3 pos = new LLVector3(128, 128, 20);
try 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) foreach (Scene m_scene in m_scenes)
{ {
m_scene.ForEachScenePresence(delegate(ScenePresence avatar) c.Scene = m_scene;
{ m_scene.EventManager.TriggerOnChatBroadcast(this, c);
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 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) public void eventIrcJoin(string[] commArgs)
{ {
string IrcChannel = commArgs[2]; string IrcChannel = commArgs[2];
if (IrcChannel.StartsWith(":"))
IrcChannel = IrcChannel.Substring(1);
string IrcUser = commArgs[0].Split('!')[0]; 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) public void eventIrcPart(string[] commArgs)
{ {
string IrcChannel = commArgs[2]; string IrcChannel = commArgs[2];
string IrcUser = commArgs[0].Split('!')[0]; 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) public void eventIrcMode(string[] commArgs)
@ -781,7 +799,7 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat
{ {
string UserOldNick = commArgs[0].Split('!')[0]; string UserOldNick = commArgs[0].Split('!')[0];
string UserNewNick = commArgs[2].Remove(0, 1); 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) public void eventIrcKick(string[] commArgs)
@ -794,7 +812,7 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat
{ {
KickMessage += commArgs[i] + " "; 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) if (UserKicked == m_nick)
{ {
BroadcastSim(m_nick, "Hey, that was me!!!"); BroadcastSim(m_nick, "Hey, that was me!!!");
@ -810,7 +828,7 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat
{ {
QuitMessage += commArgs[i] + " "; QuitMessage += commArgs[i] + " ";
} }
BroadcastSim(m_nick, "{0} quits saying {1}", IrcUser, QuitMessage); BroadcastSim(IrcUser, "/me quits saying \"{0}\"", QuitMessage);
} }
public void Close() public void Close()

View File

@ -217,6 +217,12 @@ namespace OpenSim.Region.Environment.Scenes
/// </summary> /// </summary>
public delegate void ChatFromWorldEvent(Object sender, ChatFromViewerArgs chat); public delegate void ChatFromWorldEvent(Object sender, ChatFromViewerArgs chat);
public event ChatFromWorldEvent OnChatFromWorld; public event ChatFromWorldEvent OnChatFromWorld;
/// <summary>
/// ChatBroadcastEvent is called via Scene when a broadcast chat message
/// from world comes in (chat from viewer is available via client.OnChatFromViewer).
/// </summary>
public delegate void ChatBroadcastEvent(Object sender, ChatFromViewerArgs chat);
public event ChatBroadcastEvent OnChatBroadcast;
public class MoneyTransferArgs : EventArgs public class MoneyTransferArgs : EventArgs
{ {
@ -320,6 +326,7 @@ namespace OpenSim.Region.Environment.Scenes
private RegisterCapsEvent handlerRegisterCaps = null; // OnRegisterCaps; private RegisterCapsEvent handlerRegisterCaps = null; // OnRegisterCaps;
private DeregisterCapsEvent handlerDeregisterCaps = null; // OnDeregisterCaps; private DeregisterCapsEvent handlerDeregisterCaps = null; // OnDeregisterCaps;
private ChatFromWorldEvent handlerChatFromWorld = null; // OnChatFromWorld; private ChatFromWorldEvent handlerChatFromWorld = null; // OnChatFromWorld;
private ChatBroadcastEvent handlerChatBroadcast = null; // OnChatBroadcast;
private NewInventoryItemUploadComplete handlerNewInventoryItemUpdateComplete = null; private NewInventoryItemUploadComplete handlerNewInventoryItemUpdateComplete = null;
private RequestChangeWaterHeight handlerRequestChangeWaterHeight = null; //OnRequestChangeWaterHeight private RequestChangeWaterHeight handlerRequestChangeWaterHeight = null; //OnRequestChangeWaterHeight
private ScriptControlEvent handlerScriptControlEvent = null; 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) internal void TriggerControlEvent(uint p, LLUUID scriptUUID, LLUUID avatarID, uint held, uint _changed)
{ {
handlerScriptControlEvent = OnScriptControlEvent; handlerScriptControlEvent = OnScriptControlEvent;

View File

@ -292,6 +292,7 @@ enabled = false
;nick = OpenSimBotNameProbablyMakeThisShorter ;nick = OpenSimBotNameProbablyMakeThisShorter
;channel = #the_irc_channel_you_want_to_connect_to ;channel = #the_irc_channel_you_want_to_connect_to
;port = 6667 ;port = 6667
;fallback_region = name of "default" region
;MSGformat fields : 0=botnick, 1=user, 2=region, 3=message ;MSGformat fields : 0=botnick, 1=user, 2=region, 3=message
; must start with "PRIVMSG {0} : " or irc server will get upset ; must start with "PRIVMSG {0} : " or irc server will get upset
;for <bot>:<user in region> :<message> ;for <bot>:<user in region> :<message>