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.cs235
1 files changed, 173 insertions, 62 deletions
diff --git a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
index f0b1e67..d83713b 100644
--- a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
@@ -51,7 +51,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
51 private int m_saydistance = 20; 51 private int m_saydistance = 20;
52 private int m_shoutdistance = 100; 52 private int m_shoutdistance = 100;
53 private int m_whisperdistance = 10; 53 private int m_whisperdistance = 10;
54 54 private List<Scene> m_scenes = new List<Scene>();
55 private List<string> FreezeCache = new List<string>();
56 private string m_adminPrefix = "";
55 internal object m_syncy = new object(); 57 internal object m_syncy = new object();
56 58
57 internal IConfig m_config; 59 internal IConfig m_config;
@@ -69,21 +71,28 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
69 m_enabled = false; 71 m_enabled = false;
70 return; 72 return;
71 } 73 }
74
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", "");
72 } 79 }
73
74 m_whisperdistance = config.Configs["Chat"].GetInt("whisper_distance", m_whisperdistance);
75 m_saydistance = config.Configs["Chat"].GetInt("say_distance", m_saydistance);
76 m_shoutdistance = config.Configs["Chat"].GetInt("shout_distance", m_shoutdistance);
77 } 80 }
78 81
79 public virtual void AddRegion(Scene scene) 82 public virtual void AddRegion(Scene scene)
80 { 83 {
81 if (!m_enabled) 84 if (!m_enabled) return;
82 return;
83 85
84 scene.EventManager.OnNewClient += OnNewClient; 86 lock (m_syncy)
85 scene.EventManager.OnChatFromWorld += OnChatFromWorld; 87 {
86 scene.EventManager.OnChatBroadcast += OnChatBroadcast; 88 if (!m_scenes.Contains(scene))
89 {
90 m_scenes.Add(scene);
91 scene.EventManager.OnNewClient += OnNewClient;
92 scene.EventManager.OnChatFromWorld += OnChatFromWorld;
93 scene.EventManager.OnChatBroadcast += OnChatBroadcast;
94 }
95 }
87 96
88 m_log.InfoFormat("[CHAT]: Initialized for {0} w:{1} s:{2} S:{3}", scene.RegionInfo.RegionName, 97 m_log.InfoFormat("[CHAT]: Initialized for {0} w:{1} s:{2} S:{3}", scene.RegionInfo.RegionName,
89 m_whisperdistance, m_saydistance, m_shoutdistance); 98 m_whisperdistance, m_saydistance, m_shoutdistance);
@@ -103,12 +112,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
103 112
104 public virtual void RemoveRegion(Scene scene) 113 public virtual void RemoveRegion(Scene scene)
105 { 114 {
106 if (!m_enabled) 115 if (!m_enabled) return;
107 return;
108 116
109 scene.EventManager.OnNewClient -= OnNewClient; 117 lock (m_syncy)
110 scene.EventManager.OnChatFromWorld -= OnChatFromWorld; 118 {
111 scene.EventManager.OnChatBroadcast -= OnChatBroadcast; 119 if (m_scenes.Contains(scene))
120 {
121 scene.EventManager.OnNewClient -= OnNewClient;
122 scene.EventManager.OnChatFromWorld -= OnChatFromWorld;
123 scene.EventManager.OnChatBroadcast -= OnChatBroadcast;
124 m_scenes.Remove(scene);
125 }
126 }
112 } 127 }
113 128
114 public virtual void Close() 129 public virtual void Close()
@@ -165,7 +180,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
165 return; 180 return;
166 } 181 }
167 182
168 DeliverChatToAvatars(ChatSourceType.Agent, c); 183 if (FreezeCache.Contains(c.Sender.AgentId.ToString()))
184 {
185 if (c.Type != ChatTypeEnum.StartTyping || c.Type != ChatTypeEnum.StopTyping)
186 c.Sender.SendAgentAlertMessage("You may not talk as you are frozen.", false);
187 }
188 else
189 {
190 DeliverChatToAvatars(ChatSourceType.Agent, c);
191 }
169 } 192 }
170 193
171 public virtual void OnChatFromWorld(Object sender, OSChatMessage c) 194 public virtual void OnChatFromWorld(Object sender, OSChatMessage c)
@@ -179,33 +202,61 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
179 protected virtual void DeliverChatToAvatars(ChatSourceType sourceType, OSChatMessage c) 202 protected virtual void DeliverChatToAvatars(ChatSourceType sourceType, OSChatMessage c)
180 { 203 {
181 string fromName = c.From; 204 string fromName = c.From;
205 string fromNamePrefix = "";
182 UUID fromID = UUID.Zero; 206 UUID fromID = UUID.Zero;
183 UUID ownerID = UUID.Zero; 207 UUID ownerID = UUID.Zero;
184 UUID targetID = c.TargetUUID;
185 string message = c.Message; 208 string message = c.Message;
186 Scene scene = (Scene)c.Scene; 209 IScene scene = c.Scene;
210 UUID destination = c.Destination;
187 Vector3 fromPos = c.Position; 211 Vector3 fromPos = c.Position;
188 Vector3 regionPos = new Vector3(scene.RegionInfo.WorldLocX, scene.RegionInfo.WorldLocY, 0); 212 Vector3 regionPos = new Vector3(scene.RegionInfo.WorldLocX, scene.RegionInfo.WorldLocY, 0);
189 213
214 bool checkParcelHide = false;
215 UUID sourceParcelID = UUID.Zero;
216 Vector3 hidePos = fromPos;
217
190 if (c.Channel == DEBUG_CHANNEL) c.Type = ChatTypeEnum.DebugChannel; 218 if (c.Channel == DEBUG_CHANNEL) c.Type = ChatTypeEnum.DebugChannel;
191 219
192 switch (sourceType) 220 switch (sourceType)
193 { 221 {
194 case ChatSourceType.Agent: 222 case ChatSourceType.Agent:
195 ScenePresence avatar = scene.GetScenePresence(c.Sender.AgentId); 223 if (!(scene is Scene))
224 {
225 m_log.WarnFormat("[CHAT]: scene {0} is not a Scene object, cannot obtain scene presence for {1}",
226 scene.RegionInfo.RegionName, c.Sender.AgentId);
227 return;
228 }
229 ScenePresence avatar = (scene as Scene).GetScenePresence(c.Sender.AgentId);
196 fromPos = avatar.AbsolutePosition; 230 fromPos = avatar.AbsolutePosition;
197 fromName = avatar.Name; 231 fromName = avatar.Name;
198 fromID = c.Sender.AgentId; 232 fromID = c.Sender.AgentId;
233 if (avatar.GodLevel >= 200)
234 { // let gods speak to outside or things may get confusing
235 fromNamePrefix = m_adminPrefix;
236 checkParcelHide = false;
237 }
238 else
239 {
240 checkParcelHide = true;
241 }
242 destination = UUID.Zero; // Avatars cant "SayTo"
199 ownerID = c.Sender.AgentId; 243 ownerID = c.Sender.AgentId;
200 244
245 hidePos = fromPos;
201 break; 246 break;
202 247
203 case ChatSourceType.Object: 248 case ChatSourceType.Object:
204 fromID = c.SenderUUID; 249 fromID = c.SenderUUID;
205 250
206 if (c.SenderObject != null && c.SenderObject is SceneObjectPart) 251 if (c.SenderObject != null && c.SenderObject is SceneObjectPart)
252 {
207 ownerID = ((SceneObjectPart)c.SenderObject).OwnerID; 253 ownerID = ((SceneObjectPart)c.SenderObject).OwnerID;
208 254 if (((SceneObjectPart)c.SenderObject).ParentGroup.IsAttachment)
255 {
256 checkParcelHide = true;
257 hidePos = ((SceneObjectPart)c.SenderObject).ParentGroup.AbsolutePosition;
258 }
259 }
209 break; 260 break;
210 } 261 }
211 262
@@ -214,38 +265,68 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
214 message = message.Substring(0, 1000); 265 message = message.Substring(0, 1000);
215 266
216// m_log.DebugFormat( 267// m_log.DebugFormat(
217// "[CHAT]: DCTA: fromID {0} fromName {1}, region{2}, cType {3}, sType {4}, targetID {5}", 268// "[CHAT]: DCTA: fromID {0} fromName {1}, region{2}, cType {3}, sType {4}",
218// fromID, fromName, scene.RegionInfo.RegionName, c.Type, sourceType, targetID); 269// fromID, fromName, scene.RegionInfo.RegionName, c.Type, sourceType);
219 270
220 HashSet<UUID> receiverIDs = new HashSet<UUID>(); 271 HashSet<UUID> receiverIDs = new HashSet<UUID>();
221 272
222 if (targetID == UUID.Zero) 273 if (checkParcelHide)
274 {
275 checkParcelHide = false;
276 if (c.Type < ChatTypeEnum.DebugChannel && destination == UUID.Zero)
277 {
278 ILandObject srcland = (scene as Scene).LandChannel.GetLandObject(hidePos.X, hidePos.Y);
279 if (srcland != null && !srcland.LandData.SeeAVs)
280 {
281 sourceParcelID = srcland.LandData.GlobalID;
282 checkParcelHide = true;
283 }
284 }
285 }
286
287 foreach (Scene s in m_scenes)
223 { 288 {
224 // This should use ForEachClient, but clients don't have a position. 289 // This should use ForEachClient, but clients don't have a position.
225 // If camera is moved into client, then camera position can be used 290 // If camera is moved into client, then camera position can be used
226 scene.ForEachScenePresence( 291 // MT: No, it can't, as chat is heard from the avatar position, not
292 // the camera position.
293
294 s.ForEachScenePresence(
227 delegate(ScenePresence presence) 295 delegate(ScenePresence presence)
228 { 296 {
229 if (TrySendChatMessage( 297 if (destination != UUID.Zero && presence.UUID != destination)
230 presence, fromPos, regionPos, fromID, ownerID, fromName, c.Type, message, sourceType, false)) 298 return;
231 receiverIDs.Add(presence.UUID); 299 ILandObject Presencecheck = s.LandChannel.GetLandObject(presence.AbsolutePosition.X, presence.AbsolutePosition.Y);
300 if (Presencecheck != null)
301 {
302 // This will pass all chat from objects. Not
303 // perfect, but it will do. For now. Better
304 // than the prior behavior of muting all
305 // objects on a parcel with access restrictions
306 if (checkParcelHide)
307 {
308 if (sourceParcelID != Presencecheck.LandData.GlobalID && presence.GodLevel < 200)
309 return;
310 }
311 if (c.Sender == null || Presencecheck.IsEitherBannedOrRestricted(c.Sender.AgentId) != true)
312 {
313 if (destination != UUID.Zero)
314 {
315 if (TrySendChatMessage(presence, fromPos, regionPos, fromID, ownerID, fromNamePrefix + fromName, c.Type, message, sourceType, true))
316 receiverIDs.Add(presence.UUID);
317 }
318 else
319 {
320 if (TrySendChatMessage(presence, fromPos, regionPos, fromID, ownerID, fromNamePrefix + fromName, c.Type, message, sourceType, false))
321 receiverIDs.Add(presence.UUID);
322 }
323 }
324 }
232 } 325 }
233 ); 326 );
234 } 327 }
235 else 328
236 { 329 (scene as Scene).EventManager.TriggerOnChatToClients(
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 }
246 }
247
248 scene.EventManager.TriggerOnChatToClients(
249 fromID, receiverIDs, message, c.Type, fromPos, fromName, sourceType, ChatAudibleLevel.Fully); 330 fromID, receiverIDs, message, c.Type, fromPos, fromName, sourceType, ChatAudibleLevel.Fully);
250 } 331 }
251 332
@@ -287,28 +368,29 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
287 } 368 }
288 369
289 // m_log.DebugFormat("[CHAT] Broadcast: fromID {0} fromName {1}, cType {2}, sType {3}", fromID, fromName, cType, sourceType); 370 // m_log.DebugFormat("[CHAT] Broadcast: fromID {0} fromName {1}, cType {2}, sType {3}", fromID, fromName, cType, sourceType);
290
291 HashSet<UUID> receiverIDs = new HashSet<UUID>(); 371 HashSet<UUID> receiverIDs = new HashSet<UUID>();
292 372
293 ((Scene)c.Scene).ForEachRootClient( 373 if (c.Scene != null)
294 delegate(IClientAPI client) 374 {
295 { 375 ((Scene)c.Scene).ForEachRootClient
296 // don't forward SayOwner chat from objects to 376 (
297 // non-owner agents 377 delegate(IClientAPI client)
298 if ((c.Type == ChatTypeEnum.Owner) && 378 {
299 (null != c.SenderObject) && 379 // don't forward SayOwner chat from objects to
300 (((SceneObjectPart)c.SenderObject).OwnerID != client.AgentId)) 380 // non-owner agents
301 return; 381 if ((c.Type == ChatTypeEnum.Owner) &&
302 382 (null != c.SenderObject) &&
303 client.SendChatMessage( 383 (((SceneObjectPart)c.SenderObject).OwnerID != client.AgentId))
304 c.Message, (byte)cType, CenterOfRegion, fromName, fromID, ownerID, 384 return;
305 (byte)sourceType, (byte)ChatAudibleLevel.Fully); 385
306 386 client.SendChatMessage(c.Message, (byte)cType, CenterOfRegion, fromName, fromID, fromID,
307 receiverIDs.Add(client.AgentId); 387 (byte)sourceType, (byte)ChatAudibleLevel.Fully);
308 }); 388 receiverIDs.Add(client.AgentId);
309 389 }
310 (c.Scene as Scene).EventManager.TriggerOnChatToClients( 390 );
311 fromID, receiverIDs, c.Message, cType, CenterOfRegion, fromName, sourceType, ChatAudibleLevel.Fully); 391 (c.Scene as Scene).EventManager.TriggerOnChatToClients(
392 fromID, receiverIDs, c.Message, cType, CenterOfRegion, fromName, sourceType, ChatAudibleLevel.Fully);
393 }
312 } 394 }
313 395
314 /// <summary> 396 /// <summary>
@@ -360,6 +442,35 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
360 return true; 442 return true;
361 } 443 }
362 444
445 Dictionary<UUID, System.Threading.Timer> Timers = new Dictionary<UUID, System.Threading.Timer>();
446 public void ParcelFreezeUser(IClientAPI client, UUID parcelowner, uint flags, UUID target)
447 {
448 System.Threading.Timer Timer;
449 if (flags == 0)
450 {
451 FreezeCache.Add(target.ToString());
452 System.Threading.TimerCallback timeCB = new System.Threading.TimerCallback(OnEndParcelFrozen);
453 Timer = new System.Threading.Timer(timeCB, target, 30000, 0);
454 Timers.Add(target, Timer);
455 }
456 else
457 {
458 FreezeCache.Remove(target.ToString());
459 Timers.TryGetValue(target, out Timer);
460 Timers.Remove(target);
461 Timer.Dispose();
462 }
463 }
464
465 private void OnEndParcelFrozen(object avatar)
466 {
467 UUID target = (UUID)avatar;
468 FreezeCache.Remove(target.ToString());
469 System.Threading.Timer Timer;
470 Timers.TryGetValue(target, out Timer);
471 Timers.Remove(target);
472 Timer.Dispose();
473 }
363 #region SimulatorFeaturesRequest 474 #region SimulatorFeaturesRequest
364 475
365 static OSDInteger m_SayRange, m_WhisperRange, m_ShoutRange; 476 static OSDInteger m_SayRange, m_WhisperRange, m_ShoutRange;