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);
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);
}
}
}

View File

@ -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 = @":(?<nick>\w*)!(?<user>\S*) PRIVMSG (?<channel>\S+) :(?<msg>.*)";
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<string, string>();
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<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;
}
@ -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()

View File

@ -217,6 +217,12 @@ namespace OpenSim.Region.Environment.Scenes
/// </summary>
public delegate void ChatFromWorldEvent(Object sender, ChatFromViewerArgs chat);
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
{
@ -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;

View File

@ -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 <bot>:<user in region> :<message>