aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs')
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs293
1 files changed, 198 insertions, 95 deletions
diff --git a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
index f0b1e67..ea90185 100644
--- a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
@@ -45,17 +45,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
45 private static readonly ILog m_log = 45 private static readonly ILog m_log =
46 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 46 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47 47
48 private const int DEBUG_CHANNEL = 2147483647; 48 protected const int DEBUG_CHANNEL = 2147483647;
49 49
50 private bool m_enabled = true; 50 protected bool m_enabled = true;
51 private int m_saydistance = 20; 51 protected int m_saydistance = 20;
52 private int m_shoutdistance = 100; 52 protected int m_shoutdistance = 100;
53 private int m_whisperdistance = 10; 53 protected int m_whisperdistance = 10;
54 54 protected List<Scene> m_scenes = new List<Scene>();
55 internal object m_syncy = new object(); 55 protected List<string> FreezeCache = new List<string>();
56 56 protected string m_adminPrefix = "";
57 internal IConfig m_config; 57 protected object m_syncy = new object();
58 58 protected IConfig m_config;
59 #region ISharedRegionModule Members 59 #region ISharedRegionModule Members
60 public virtual void Initialise(IConfigSource config) 60 public virtual void Initialise(IConfigSource config)
61 { 61 {
@@ -69,21 +69,28 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
69 m_enabled = false; 69 m_enabled = false;
70 return; 70 return;
71 } 71 }
72 }
73 72
74 m_whisperdistance = config.Configs["Chat"].GetInt("whisper_distance", m_whisperdistance); 73 m_whisperdistance = m_config.GetInt("whisper_distance", m_whisperdistance);
75 m_saydistance = config.Configs["Chat"].GetInt("say_distance", m_saydistance); 74 m_saydistance = m_config.GetInt("say_distance", m_saydistance);
76 m_shoutdistance = config.Configs["Chat"].GetInt("shout_distance", m_shoutdistance); 75 m_shoutdistance = m_config.GetInt("shout_distance", m_shoutdistance);
76 m_adminPrefix = m_config.GetString("admin_prefix", "");
77 }
77 } 78 }
78 79
79 public virtual void AddRegion(Scene scene) 80 public virtual void AddRegion(Scene scene)
80 { 81 {
81 if (!m_enabled) 82 if (!m_enabled) return;
82 return;
83 83
84 scene.EventManager.OnNewClient += OnNewClient; 84 lock (m_syncy)
85 scene.EventManager.OnChatFromWorld += OnChatFromWorld; 85 {
86 scene.EventManager.OnChatBroadcast += OnChatBroadcast; 86 if (!m_scenes.Contains(scene))
87 {
88 m_scenes.Add(scene);
89 scene.EventManager.OnNewClient += OnNewClient;
90 scene.EventManager.OnChatFromWorld += OnChatFromWorld;
91 scene.EventManager.OnChatBroadcast += OnChatBroadcast;
92 }
93 }
87 94
88 m_log.InfoFormat("[CHAT]: Initialized for {0} w:{1} s:{2} S:{3}", scene.RegionInfo.RegionName, 95 m_log.InfoFormat("[CHAT]: Initialized for {0} w:{1} s:{2} S:{3}", scene.RegionInfo.RegionName,
89 m_whisperdistance, m_saydistance, m_shoutdistance); 96 m_whisperdistance, m_saydistance, m_shoutdistance);
@@ -103,14 +110,20 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
103 110
104 public virtual void RemoveRegion(Scene scene) 111 public virtual void RemoveRegion(Scene scene)
105 { 112 {
106 if (!m_enabled) 113 if (!m_enabled) return;
107 return;
108 114
109 scene.EventManager.OnNewClient -= OnNewClient; 115 lock (m_syncy)
110 scene.EventManager.OnChatFromWorld -= OnChatFromWorld; 116 {
111 scene.EventManager.OnChatBroadcast -= OnChatBroadcast; 117 if (m_scenes.Contains(scene))
118 {
119 scene.EventManager.OnNewClient -= OnNewClient;
120 scene.EventManager.OnChatFromWorld -= OnChatFromWorld;
121 scene.EventManager.OnChatBroadcast -= OnChatBroadcast;
122 m_scenes.Remove(scene);
123 }
124 }
112 } 125 }
113 126
114 public virtual void Close() 127 public virtual void Close()
115 { 128 {
116 } 129 }
@@ -119,7 +132,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
119 { 132 {
120 } 133 }
121 134
122 public Type ReplaceableInterface 135 public virtual Type ReplaceableInterface
123 { 136 {
124 get { return null; } 137 get { return null; }
125 } 138 }
@@ -137,7 +150,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
137 client.OnChatFromClient += OnChatFromClient; 150 client.OnChatFromClient += OnChatFromClient;
138 } 151 }
139 152
140 protected OSChatMessage FixPositionOfChatMessage(OSChatMessage c) 153 protected virtual OSChatMessage FixPositionOfChatMessage(OSChatMessage c)
141 { 154 {
142 ScenePresence avatar; 155 ScenePresence avatar;
143 Scene scene = (Scene)c.Scene; 156 Scene scene = (Scene)c.Scene;
@@ -165,7 +178,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
165 return; 178 return;
166 } 179 }
167 180
168 DeliverChatToAvatars(ChatSourceType.Agent, c); 181 if (FreezeCache.Contains(c.Sender.AgentId.ToString()))
182 {
183 if (c.Type != ChatTypeEnum.StartTyping || c.Type != ChatTypeEnum.StopTyping)
184 c.Sender.SendAgentAlertMessage("You may not talk as you are frozen.", false);
185 }
186 else
187 {
188 DeliverChatToAvatars(ChatSourceType.Agent, c);
189 }
169 } 190 }
170 191
171 public virtual void OnChatFromWorld(Object sender, OSChatMessage c) 192 public virtual void OnChatFromWorld(Object sender, OSChatMessage c)
@@ -179,34 +200,63 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
179 protected virtual void DeliverChatToAvatars(ChatSourceType sourceType, OSChatMessage c) 200 protected virtual void DeliverChatToAvatars(ChatSourceType sourceType, OSChatMessage c)
180 { 201 {
181 string fromName = c.From; 202 string fromName = c.From;
203 string fromNamePrefix = "";
182 UUID fromID = UUID.Zero; 204 UUID fromID = UUID.Zero;
183 UUID ownerID = UUID.Zero; 205 UUID ownerID = UUID.Zero;
184 UUID targetID = c.TargetUUID;
185 string message = c.Message; 206 string message = c.Message;
186 Scene scene = (Scene)c.Scene; 207 Scene scene = c.Scene as Scene;
208 UUID destination = c.Destination;
187 Vector3 fromPos = c.Position; 209 Vector3 fromPos = c.Position;
188 Vector3 regionPos = new Vector3(scene.RegionInfo.WorldLocX, scene.RegionInfo.WorldLocY, 0); 210 Vector3 regionPos = new Vector3(scene.RegionInfo.WorldLocX, scene.RegionInfo.WorldLocY, 0);
189 211
212 bool checkParcelHide = false;
213 UUID sourceParcelID = UUID.Zero;
214 Vector3 hidePos = fromPos;
215
190 if (c.Channel == DEBUG_CHANNEL) c.Type = ChatTypeEnum.DebugChannel; 216 if (c.Channel == DEBUG_CHANNEL) c.Type = ChatTypeEnum.DebugChannel;
191 217
192 switch (sourceType) 218 if(!m_scenes.Contains(scene))
193 { 219 {
194 case ChatSourceType.Agent: 220 m_log.WarnFormat("[CHAT]: message from unkown scene {0} ignored",
195 ScenePresence avatar = scene.GetScenePresence(c.Sender.AgentId); 221 scene.RegionInfo.RegionName);
196 fromPos = avatar.AbsolutePosition; 222 return;
197 fromName = avatar.Name; 223 }
198 fromID = c.Sender.AgentId;
199 ownerID = c.Sender.AgentId;
200 224
201 break; 225 switch (sourceType)
226 {
227 case ChatSourceType.Agent:
228 ScenePresence avatar = (scene as Scene).GetScenePresence(c.Sender.AgentId);
229 fromPos = avatar.AbsolutePosition;
230 fromName = avatar.Name;
231 fromID = c.Sender.AgentId;
232 if (avatar.IsViewerUIGod)
233 { // let gods speak to outside or things may get confusing
234 fromNamePrefix = m_adminPrefix;
235 checkParcelHide = false;
236 }
237 else
238 {
239 checkParcelHide = true;
240 }
241 destination = UUID.Zero; // Avatars cant "SayTo"
242 ownerID = c.Sender.AgentId;
202 243
203 case ChatSourceType.Object: 244 hidePos = fromPos;
204 fromID = c.SenderUUID; 245 break;
205 246
206 if (c.SenderObject != null && c.SenderObject is SceneObjectPart) 247 case ChatSourceType.Object:
207 ownerID = ((SceneObjectPart)c.SenderObject).OwnerID; 248 fromID = c.SenderUUID;
208 249
209 break; 250 if (c.SenderObject != null && c.SenderObject is SceneObjectPart)
251 {
252 ownerID = ((SceneObjectPart)c.SenderObject).OwnerID;
253 if (((SceneObjectPart)c.SenderObject).ParentGroup.IsAttachment)
254 {
255 checkParcelHide = true;
256 hidePos = ((SceneObjectPart)c.SenderObject).ParentGroup.AbsolutePosition;
257 }
258 }
259 break;
210 } 260 }
211 261
212 // TODO: iterate over message 262 // TODO: iterate over message
@@ -214,43 +264,66 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
214 message = message.Substring(0, 1000); 264 message = message.Substring(0, 1000);
215 265
216// m_log.DebugFormat( 266// m_log.DebugFormat(
217// "[CHAT]: DCTA: fromID {0} fromName {1}, region{2}, cType {3}, sType {4}, targetID {5}", 267// "[CHAT]: DCTA: fromID {0} fromName {1}, region{2}, cType {3}, sType {4}",
218// fromID, fromName, scene.RegionInfo.RegionName, c.Type, sourceType, targetID); 268// fromID, fromName, scene.RegionInfo.RegionName, c.Type, sourceType);
219 269
220 HashSet<UUID> receiverIDs = new HashSet<UUID>(); 270 HashSet<UUID> receiverIDs = new HashSet<UUID>();
221 271
222 if (targetID == UUID.Zero) 272 if (checkParcelHide)
223 { 273 {
224 // This should use ForEachClient, but clients don't have a position. 274 checkParcelHide = false;
225 // If camera is moved into client, then camera position can be used 275 if (c.Type < ChatTypeEnum.DebugChannel && destination == UUID.Zero)
226 scene.ForEachScenePresence( 276 {
227 delegate(ScenePresence presence) 277 ILandObject srcland = scene.LandChannel.GetLandObject(hidePos.X, hidePos.Y);
278 if (srcland != null && !srcland.LandData.SeeAVs)
228 { 279 {
229 if (TrySendChatMessage( 280 sourceParcelID = srcland.LandData.GlobalID;
230 presence, fromPos, regionPos, fromID, ownerID, fromName, c.Type, message, sourceType, false)) 281 checkParcelHide = true;
231 receiverIDs.Add(presence.UUID);
232 } 282 }
233 );
234 }
235 else
236 {
237 // This is a send to a specific client eg from llRegionSayTo
238 // no need to check distance etc, jand send is as say
239 ScenePresence presence = scene.GetScenePresence(targetID);
240 if (presence != null && !presence.IsChildAgent)
241 {
242 if (TrySendChatMessage(
243 presence, fromPos, regionPos, fromID, ownerID, fromName, ChatTypeEnum.Say, message, sourceType, true))
244 receiverIDs.Add(presence.UUID);
245 } 283 }
246 } 284 }
247 285
286 scene.ForEachScenePresence(
287 delegate(ScenePresence presence)
288 {
289 if (destination != UUID.Zero && presence.UUID != destination)
290 return;
291
292 if(presence.IsChildAgent)
293 {
294 if(checkParcelHide)
295 return;
296 if (TrySendChatMessage(presence, fromPos, regionPos, fromID,
297 ownerID, fromNamePrefix + fromName, c.Type,
298 message, sourceType, (destination != UUID.Zero)))
299 receiverIDs.Add(presence.UUID);
300 return;
301 }
302
303 ILandObject Presencecheck = scene.LandChannel.GetLandObject(presence.AbsolutePosition.X, presence.AbsolutePosition.Y);
304 if (Presencecheck != null)
305 {
306 if (checkParcelHide)
307 {
308 if (sourceParcelID != Presencecheck.LandData.GlobalID && !presence.IsViewerUIGod)
309 return;
310 }
311 if (c.Sender == null || Presencecheck.IsEitherBannedOrRestricted(c.Sender.AgentId) != true)
312 {
313 if (TrySendChatMessage(presence, fromPos, regionPos, fromID,
314 ownerID, fromNamePrefix + fromName, c.Type,
315 message, sourceType, (destination != UUID.Zero)))
316 receiverIDs.Add(presence.UUID);
317 }
318 }
319 });
320
248 scene.EventManager.TriggerOnChatToClients( 321 scene.EventManager.TriggerOnChatToClients(
249 fromID, receiverIDs, message, c.Type, fromPos, fromName, sourceType, ChatAudibleLevel.Fully); 322 fromID, receiverIDs, message, c.Type, fromPos, fromName, sourceType, ChatAudibleLevel.Fully);
250 } 323 }
251 324
252 static private Vector3 CenterOfRegion = new Vector3(128, 128, 30); 325 static protected Vector3 CenterOfRegion = new Vector3(128, 128, 30);
253 326
254 public virtual void OnChatBroadcast(Object sender, OSChatMessage c) 327 public virtual void OnChatBroadcast(Object sender, OSChatMessage c)
255 { 328 {
256 if (c.Channel != 0 && c.Channel != DEBUG_CHANNEL) return; 329 if (c.Channel != 0 && c.Channel != DEBUG_CHANNEL) return;
@@ -268,7 +341,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
268 // broadcast chat works by redistributing every incoming chat 341 // broadcast chat works by redistributing every incoming chat
269 // message to each avatar in the scene. 342 // message to each avatar in the scene.
270 string fromName = c.From; 343 string fromName = c.From;
271 344
272 UUID fromID = UUID.Zero; 345 UUID fromID = UUID.Zero;
273 UUID ownerID = UUID.Zero; 346 UUID ownerID = UUID.Zero;
274 ChatSourceType sourceType = ChatSourceType.Object; 347 ChatSourceType sourceType = ChatSourceType.Object;
@@ -280,35 +353,36 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
280 ownerID = c.Sender.AgentId; 353 ownerID = c.Sender.AgentId;
281 sourceType = ChatSourceType.Agent; 354 sourceType = ChatSourceType.Agent;
282 } 355 }
283 else if (c.SenderUUID != UUID.Zero) 356 else if (c.SenderUUID != UUID.Zero)
284 { 357 {
285 fromID = c.SenderUUID; 358 fromID = c.SenderUUID;
286 ownerID = ((SceneObjectPart)c.SenderObject).OwnerID; 359 ownerID = ((SceneObjectPart)c.SenderObject).OwnerID;
287 } 360 }
288
289 // m_log.DebugFormat("[CHAT] Broadcast: fromID {0} fromName {1}, cType {2}, sType {3}", fromID, fromName, cType, sourceType);
290 361
362 // m_log.DebugFormat("[CHAT] Broadcast: fromID {0} fromName {1}, cType {2}, sType {3}", fromID, fromName, cType, sourceType);
291 HashSet<UUID> receiverIDs = new HashSet<UUID>(); 363 HashSet<UUID> receiverIDs = new HashSet<UUID>();
292
293 ((Scene)c.Scene).ForEachRootClient(
294 delegate(IClientAPI client)
295 {
296 // don't forward SayOwner chat from objects to
297 // non-owner agents
298 if ((c.Type == ChatTypeEnum.Owner) &&
299 (null != c.SenderObject) &&
300 (((SceneObjectPart)c.SenderObject).OwnerID != client.AgentId))
301 return;
302 364
303 client.SendChatMessage( 365 if (c.Scene != null)
304 c.Message, (byte)cType, CenterOfRegion, fromName, fromID, ownerID, 366 {
305 (byte)sourceType, (byte)ChatAudibleLevel.Fully); 367 ((Scene)c.Scene).ForEachRootClient
306 368 (
307 receiverIDs.Add(client.AgentId); 369 delegate(IClientAPI client)
308 }); 370 {
309 371 // don't forward SayOwner chat from objects to
310 (c.Scene as Scene).EventManager.TriggerOnChatToClients( 372 // non-owner agents
311 fromID, receiverIDs, c.Message, cType, CenterOfRegion, fromName, sourceType, ChatAudibleLevel.Fully); 373 if ((c.Type == ChatTypeEnum.Owner) &&
374 (null != c.SenderObject) &&
375 (((SceneObjectPart)c.SenderObject).OwnerID != client.AgentId))
376 return;
377
378 client.SendChatMessage(c.Message, (byte)cType, CenterOfRegion, fromName, fromID, fromID,
379 (byte)sourceType, (byte)ChatAudibleLevel.Fully);
380 receiverIDs.Add(client.AgentId);
381 }
382 );
383 (c.Scene as Scene).EventManager.TriggerOnChatToClients(
384 fromID, receiverIDs, c.Message, cType, CenterOfRegion, fromName, sourceType, ChatAudibleLevel.Fully);
385 }
312 } 386 }
313 387
314 /// <summary> 388 /// <summary>
@@ -326,7 +400,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
326 /// <param name="type"></param> 400 /// <param name="type"></param>
327 /// <param name="message"></param> 401 /// <param name="message"></param>
328 /// <param name="src"></param> 402 /// <param name="src"></param>
329 /// <returns>true if the message was sent to the receiver, false if it was not sent due to failing a 403 /// <returns>true if the message was sent to the receiver, false if it was not sent due to failing a
330 /// precondition</returns> 404 /// precondition</returns>
331 protected virtual bool TrySendChatMessage( 405 protected virtual bool TrySendChatMessage(
332 ScenePresence presence, Vector3 fromPos, Vector3 regionPos, 406 ScenePresence presence, Vector3 fromPos, Vector3 regionPos,
@@ -356,15 +430,44 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
356 presence.ControllingClient.SendChatMessage( 430 presence.ControllingClient.SendChatMessage(
357 message, (byte) type, fromPos, fromName, 431 message, (byte) type, fromPos, fromName,
358 fromAgentID, ownerID, (byte)src, (byte)ChatAudibleLevel.Fully); 432 fromAgentID, ownerID, (byte)src, (byte)ChatAudibleLevel.Fully);
359 433
360 return true; 434 return true;
361 } 435 }
362 436
437 Dictionary<UUID, System.Threading.Timer> Timers = new Dictionary<UUID, System.Threading.Timer>();
438 public virtual void ParcelFreezeUser(IClientAPI client, UUID parcelowner, uint flags, UUID target)
439 {
440 System.Threading.Timer Timer;
441 if (flags == 0)
442 {
443 FreezeCache.Add(target.ToString());
444 System.Threading.TimerCallback timeCB = new System.Threading.TimerCallback(OnEndParcelFrozen);
445 Timer = new System.Threading.Timer(timeCB, target, 30000, 0);
446 Timers.Add(target, Timer);
447 }
448 else
449 {
450 FreezeCache.Remove(target.ToString());
451 Timers.TryGetValue(target, out Timer);
452 Timers.Remove(target);
453 Timer.Dispose();
454 }
455 }
456
457 protected virtual void OnEndParcelFrozen(object avatar)
458 {
459 UUID target = (UUID)avatar;
460 FreezeCache.Remove(target.ToString());
461 System.Threading.Timer Timer;
462 Timers.TryGetValue(target, out Timer);
463 Timers.Remove(target);
464 Timer.Dispose();
465 }
363 #region SimulatorFeaturesRequest 466 #region SimulatorFeaturesRequest
364 467
365 static OSDInteger m_SayRange, m_WhisperRange, m_ShoutRange; 468 protected static OSDInteger m_SayRange, m_WhisperRange, m_ShoutRange;
366 469
367 private void OnSimulatorFeaturesRequest(UUID agentID, ref OSDMap features) 470 protected virtual void OnSimulatorFeaturesRequest(UUID agentID, ref OSDMap features)
368 { 471 {
369 OSD extras = new OSDMap(); 472 OSD extras = new OSDMap();
370 if (features.ContainsKey("OpenSimExtras")) 473 if (features.ContainsKey("OpenSimExtras"))