29 using System.Collections.Generic;
30 using System.Reflection;
35 using OpenMetaverse.StructuredData;
36 using OpenSim.Framework;
37 using OpenSim.Region.Framework.Interfaces;
38 using OpenSim.Region.Framework.Scenes;
42 [Extension(Path =
"/OpenSim/RegionModules", NodeName =
"RegionModule", Id =
"ChatModule")]
45 private static readonly ILog m_log =
46 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48 private const int DEBUG_CHANNEL = 2147483647;
50 private bool m_enabled =
true;
51 private int m_saydistance = 20;
52 private int m_shoutdistance = 100;
53 private int m_whisperdistance = 10;
54 private List<Scene> m_scenes =
new List<Scene>();
55 private List<string> FreezeCache =
new List<string>();
56 private string m_adminPrefix =
"";
57 internal object m_syncy =
new object();
59 internal IConfig m_config;
61 #region ISharedRegionModule Members
64 m_config = config.Configs[
"Chat"];
68 if (!m_config.GetBoolean(
"enabled",
true))
70 m_log.Info(
"[CHAT]: plugin disabled by configuration");
75 m_whisperdistance = m_config.GetInt(
"whisper_distance", m_whisperdistance);
76 m_saydistance = m_config.GetInt(
"say_distance", m_saydistance);
77 m_shoutdistance = m_config.GetInt(
"shout_distance", m_shoutdistance);
78 m_adminPrefix = m_config.GetString(
"admin_prefix",
"");
84 if (!m_enabled)
return;
88 if (!m_scenes.Contains(scene))
91 scene.EventManager.OnNewClient += OnNewClient;
92 scene.EventManager.OnChatFromWorld += OnChatFromWorld;
93 scene.EventManager.OnChatBroadcast += OnChatBroadcast;
97 m_log.InfoFormat(
"[CHAT]: Initialized for {0} w:{1} s:{2} S:{3}", scene.RegionInfo.RegionName,
98 m_whisperdistance, m_saydistance, m_shoutdistance);
108 if (featuresModule != null)
109 featuresModule.OnSimulatorFeaturesRequest += OnSimulatorFeaturesRequest;
115 if (!m_enabled)
return;
119 if (m_scenes.Contains(scene))
121 scene.EventManager.OnNewClient -= OnNewClient;
122 scene.EventManager.OnChatFromWorld -= OnChatFromWorld;
123 scene.EventManager.OnChatBroadcast -= OnChatBroadcast;
124 m_scenes.Remove(scene);
137 public Type ReplaceableInterface
142 public virtual string Name
144 get {
return "ChatModule"; }
152 client.OnChatFromClient += OnChatFromClient;
160 c.Position = avatar.AbsolutePosition;
167 c = FixPositionOfChatMessage(c);
179 m_log.ErrorFormat(
"[CHAT]: OnChatFromClient from {0} has empty Sender field!", sender);
186 c.Sender.SendAgentAlertMessage(
"You may not talk as you are frozen.",
false);
190 DeliverChatToAvatars(ChatSourceType.Agent, c);
199 DeliverChatToAvatars(ChatSourceType.Object, c);
204 string fromName = c.From;
205 string fromNamePrefix =
"";
206 UUID fromID = UUID.Zero;
207 UUID ownerID = UUID.Zero;
208 string message = c.Message;
210 UUID destination = c.Destination;
211 Vector3 fromPos = c.Position;
214 bool checkParcelHide =
false;
215 UUID sourceParcelID = UUID.Zero;
216 Vector3 hidePos = fromPos;
218 if (c.
Channel == DEBUG_CHANNEL) c.Type = ChatTypeEnum.DebugChannel;
220 if(!m_scenes.Contains(scene))
222 m_log.WarnFormat(
"[CHAT]: message from unkown scene {0} ignored",
223 scene.RegionInfo.RegionName);
229 case ChatSourceType.Agent:
231 fromPos = avatar.AbsolutePosition;
232 fromName = avatar.Name;
233 fromID = c.Sender.AgentId;
236 fromNamePrefix = m_adminPrefix;
237 checkParcelHide =
false;
241 checkParcelHide =
true;
243 destination = UUID.Zero;
244 ownerID = c.Sender.AgentId;
249 case ChatSourceType.Object:
250 fromID = c.SenderUUID;
255 if (((SceneObjectPart)c.SenderObject).ParentGroup.IsAttachment)
257 checkParcelHide =
true;
258 hidePos = ((SceneObjectPart)c.
SenderObject).ParentGroup.AbsolutePosition;
265 if (message.Length >= 1000)
266 message = message.Substring(0, 1000);
272 HashSet<UUID> receiverIDs =
new HashSet<UUID>();
276 checkParcelHide =
false;
279 ILandObject srcland = scene.LandChannel.GetLandObject(hidePos.X, hidePos.Y);
282 sourceParcelID = srcland.LandData.GlobalID;
283 checkParcelHide =
true;
288 scene.ForEachScenePresence(
291 if (destination !=
UUID.Zero && presence.
UUID != destination)
298 if (TrySendChatMessage(presence, fromPos, regionPos, fromID,
299 ownerID, fromNamePrefix + fromName, c.
Type,
300 message, sourceType, (destination !=
UUID.Zero)))
301 receiverIDs.Add(presence.UUID);
305 ILandObject Presencecheck = scene.LandChannel.GetLandObject(presence.AbsolutePosition.X, presence.AbsolutePosition.Y);
306 if (Presencecheck != null)
315 if (TrySendChatMessage(presence, fromPos, regionPos, fromID,
316 ownerID, fromNamePrefix + fromName, c.
Type,
317 message, sourceType, (destination !=
UUID.Zero)))
318 receiverIDs.Add(presence.
UUID);
323 scene.EventManager.TriggerOnChatToClients(
324 fromID, receiverIDs, message, c.Type, fromPos, fromName, sourceType, ChatAudibleLevel.Fully);
327 static private Vector3 CenterOfRegion =
new Vector3(128, 128, 30);
334 if (c.
Channel == DEBUG_CHANNEL)
335 cType = ChatTypeEnum.DebugChannel;
338 cType = ChatTypeEnum.Say;
341 c.Message = c.Message.Substring(0, 1000);
345 string fromName = c.From;
347 UUID fromID = UUID.Zero;
348 UUID ownerID = UUID.Zero;
349 ChatSourceType sourceType = ChatSourceType.Object;
353 fromID = c.Sender.AgentId;
354 fromName = avatar.Name;
355 ownerID = c.Sender.AgentId;
356 sourceType = ChatSourceType.Agent;
360 fromID = c.SenderUUID;
365 HashSet<UUID> receiverIDs =
new HashSet<UUID>();
380 client.SendChatMessage(c.Message, (byte)cType, CenterOfRegion, fromName, fromID, fromID,
381 (byte)sourceType, (byte)ChatAudibleLevel.Fully);
382 receiverIDs.Add(client.AgentId);
386 fromID, receiverIDs, c.
Message, cType, CenterOfRegion, fromName, sourceType, ChatAudibleLevel.Fully);
409 UUID fromAgentID, UUID ownerID,
string fromName,
ChatTypeEnum type,
410 string message, ChatSourceType src,
bool ignoreDistance)
417 Vector3 fromRegionPos = fromPos + regionPos;
418 Vector3 toRegionPos = presence.AbsolutePosition +
421 int dis = (int)Util.GetDistanceTo(toRegionPos, fromRegionPos);
423 if (type ==
ChatTypeEnum.Whisper && dis > m_whisperdistance ||
432 presence.ControllingClient.SendChatMessage(
433 message, (byte) type, fromPos, fromName,
434 fromAgentID, ownerID, (byte)src, (byte)ChatAudibleLevel.Fully);
439 Dictionary<
UUID, System.Threading.Timer> Timers =
new Dictionary<
UUID, System.Threading.Timer>();
442 System.Threading.Timer
Timer;
445 FreezeCache.Add(target.ToString());
446 System.Threading.TimerCallback timeCB =
new System.Threading.TimerCallback(OnEndParcelFrozen);
447 Timer =
new System.Threading.Timer(timeCB, target, 30000, 0);
448 Timers.Add(target,
Timer);
452 FreezeCache.Remove(target.ToString());
453 Timers.TryGetValue(target, out
Timer);
454 Timers.Remove(target);
459 private void OnEndParcelFrozen(
object avatar)
462 FreezeCache.Remove(target.ToString());
463 System.Threading.Timer
Timer;
464 Timers.TryGetValue(target, out
Timer);
465 Timers.Remove(target);
468 #region SimulatorFeaturesRequest
470 static OSDInteger m_SayRange, m_WhisperRange, m_ShoutRange;
472 private void OnSimulatorFeaturesRequest(UUID agentID, ref
OSDMap features)
475 if (features.ContainsKey(
"OpenSimExtras"))
476 extras = features[
"OpenSimExtras"];
478 features[
"OpenSimExtras"] = extras;
480 if (m_SayRange == null)
483 m_SayRange =
new OSDInteger(m_saydistance);
484 m_WhisperRange =
new OSDInteger(m_whisperdistance);
485 m_ShoutRange =
new OSDInteger(m_shoutdistance);
488 ((
OSDMap)extras)[
"say-range"] = m_SayRange;
489 ((
OSDMap)extras)[
"whisper-range"] = m_WhisperRange;
490 ((
OSDMap)extras)[
"shout-range"] = m_ShoutRange;
void ParcelFreezeUser(IClientAPI client, UUID parcelowner, uint flags, UUID target)
virtual void OnNewClient(IClientAPI client)
Scene Scene
The scene to which this entity belongs
virtual void RemoveRegion(Scene scene)
This is called whenever a Scene is removed. For shared modules, this can happen several times...
EventManager EventManager
IClientAPI Sender
The client responsible for sending the message, or null.
OSChatMessage FixPositionOfChatMessage(OSChatMessage c)
ScenePresenceState
The possible states that a scene presence can be in. This is currently orthagonal to whether a scene ...
OpenMetaverse.StructuredData.OSDMap OSDMap
virtual void OnChatBroadcast(Object sender, OSChatMessage c)
Add remove or retrieve Simulator Features that will be given to a viewer via the SimulatorFeatures ca...
string Message
The message sent by the user
bool IsEitherBannedOrRestricted(UUID avatar)
System.Timers.Timer Timer
ScenePresence GetScenePresence(UUID agentID)
Request a scene presence by UUID. Fast, indexed lookup.
UUID GlobalID
Global ID for the parcel. (3rd Party Integration)
virtual void Close()
This is the inverse to Initialise. After a Close(), this instance won't be usable anymore...
object SenderObject
The object responsible for sending the message, or null.
virtual void OnChatFromWorld(Object sender, OSChatMessage c)
ChatTypeEnum Type
The type of message, eg say, shout, broadcast.
OpenMetaverse.StructuredData.OSD OSD
virtual void PostInitialise()
This is called exactly once after all the shared region-modules have been instanciated and IRegionMod...
virtual void DeliverChatToAvatars(ChatSourceType sourceType, OSChatMessage c)
virtual void AddRegion(Scene scene)
This is called whenever a Scene is added. For shared modules, this can happen several times...
Interactive OpenSim region server
A class for triggering remote scene events.
virtual void Initialise(IConfigSource config)
This is called to initialize the region module. For shared modules, this is called exactly once...
int Channel
Which channel was this message sent on? Different channels may have different listeners. Public chat is on channel zero.
void TriggerOnChatFromClient(Object sender, OSChatMessage chat)
virtual bool TrySendChatMessage(ScenePresence presence, Vector3 fromPos, Vector3 regionPos, UUID fromAgentID, UUID ownerID, string fromName, ChatTypeEnum type, string message, ChatSourceType src, bool ignoreDistance)
Try to send a message to the given presence
virtual RegionInfo RegionInfo
void TriggerOnChatToClients(UUID senderID, HashSet< UUID > receiverIDs, string message, ChatTypeEnum type, Vector3 fromPos, string fromName, ChatSourceType src, ChatAudibleLevel level)
ScenePresenceState LifecycleState
The current state of this presence. Governs only the existence lifecycle. See ScenePresenceStateMachi...
virtual void OnChatFromClient(Object sender, OSChatMessage c)
virtual void RegionLoaded(Scene scene)
This will be called once for every scene loaded. In a shared module this will be multiple times in on...