diff options
Diffstat (limited to 'OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs')
-rw-r--r-- | OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs | 216 |
1 files changed, 176 insertions, 40 deletions
diff --git a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs index a9d2de0..2801ef0 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; |
@@ -78,16 +80,23 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat | |||
78 | m_whisperdistance = config.Configs["Chat"].GetInt("whisper_distance", m_whisperdistance); | 80 | m_whisperdistance = config.Configs["Chat"].GetInt("whisper_distance", m_whisperdistance); |
79 | m_saydistance = config.Configs["Chat"].GetInt("say_distance", m_saydistance); | 81 | m_saydistance = config.Configs["Chat"].GetInt("say_distance", m_saydistance); |
80 | m_shoutdistance = config.Configs["Chat"].GetInt("shout_distance", m_shoutdistance); | 82 | m_shoutdistance = config.Configs["Chat"].GetInt("shout_distance", m_shoutdistance); |
83 | m_adminPrefix = config.Configs["Chat"].GetString("admin_prefix", ""); | ||
81 | } | 84 | } |
82 | 85 | ||
83 | public virtual void AddRegion(Scene scene) | 86 | public virtual void AddRegion(Scene scene) |
84 | { | 87 | { |
85 | if (!m_enabled) | 88 | if (!m_enabled) return; |
86 | return; | ||
87 | 89 | ||
88 | scene.EventManager.OnNewClient += OnNewClient; | 90 | lock (m_syncy) |
89 | scene.EventManager.OnChatFromWorld += OnChatFromWorld; | 91 | { |
90 | scene.EventManager.OnChatBroadcast += OnChatBroadcast; | 92 | if (!m_scenes.Contains(scene)) |
93 | { | ||
94 | m_scenes.Add(scene); | ||
95 | scene.EventManager.OnNewClient += OnNewClient; | ||
96 | scene.EventManager.OnChatFromWorld += OnChatFromWorld; | ||
97 | scene.EventManager.OnChatBroadcast += OnChatBroadcast; | ||
98 | } | ||
99 | } | ||
91 | 100 | ||
92 | m_log.InfoFormat("[CHAT]: Initialized for {0} w:{1} s:{2} S:{3}", scene.RegionInfo.RegionName, | 101 | m_log.InfoFormat("[CHAT]: Initialized for {0} w:{1} s:{2} S:{3}", scene.RegionInfo.RegionName, |
93 | m_whisperdistance, m_saydistance, m_shoutdistance); | 102 | m_whisperdistance, m_saydistance, m_shoutdistance); |
@@ -107,12 +116,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat | |||
107 | 116 | ||
108 | public virtual void RemoveRegion(Scene scene) | 117 | public virtual void RemoveRegion(Scene scene) |
109 | { | 118 | { |
110 | if (!m_enabled) | 119 | if (!m_enabled) return; |
111 | return; | ||
112 | 120 | ||
113 | scene.EventManager.OnNewClient -= OnNewClient; | 121 | lock (m_syncy) |
114 | scene.EventManager.OnChatFromWorld -= OnChatFromWorld; | 122 | { |
115 | scene.EventManager.OnChatBroadcast -= OnChatBroadcast; | 123 | if (m_scenes.Contains(scene)) |
124 | { | ||
125 | scene.EventManager.OnNewClient -= OnNewClient; | ||
126 | scene.EventManager.OnChatFromWorld -= OnChatFromWorld; | ||
127 | scene.EventManager.OnChatBroadcast -= OnChatBroadcast; | ||
128 | m_scenes.Remove(scene); | ||
129 | } | ||
130 | } | ||
116 | } | 131 | } |
117 | 132 | ||
118 | public virtual void Close() | 133 | public virtual void Close() |
@@ -169,7 +184,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat | |||
169 | return; | 184 | return; |
170 | } | 185 | } |
171 | 186 | ||
172 | DeliverChatToAvatars(ChatSourceType.Agent, c); | 187 | if (FreezeCache.Contains(c.Sender.AgentId.ToString())) |
188 | { | ||
189 | if (c.Type != ChatTypeEnum.StartTyping || c.Type != ChatTypeEnum.StopTyping) | ||
190 | c.Sender.SendAgentAlertMessage("You may not talk as you are frozen.", false); | ||
191 | } | ||
192 | else | ||
193 | { | ||
194 | DeliverChatToAvatars(ChatSourceType.Agent, c); | ||
195 | } | ||
173 | } | 196 | } |
174 | 197 | ||
175 | public virtual void OnChatFromWorld(Object sender, OSChatMessage c) | 198 | public virtual void OnChatFromWorld(Object sender, OSChatMessage c) |
@@ -183,33 +206,64 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat | |||
183 | protected virtual void DeliverChatToAvatars(ChatSourceType sourceType, OSChatMessage c) | 206 | protected virtual void DeliverChatToAvatars(ChatSourceType sourceType, OSChatMessage c) |
184 | { | 207 | { |
185 | string fromName = c.From; | 208 | string fromName = c.From; |
209 | string fromNamePrefix = ""; | ||
186 | UUID fromID = UUID.Zero; | 210 | UUID fromID = UUID.Zero; |
187 | UUID ownerID = UUID.Zero; | 211 | UUID ownerID = UUID.Zero; |
188 | UUID targetID = c.TargetUUID; | ||
189 | string message = c.Message; | 212 | string message = c.Message; |
190 | Scene scene = (Scene)c.Scene; | 213 | IScene scene = c.Scene; |
214 | UUID destination = c.Destination; | ||
191 | Vector3 fromPos = c.Position; | 215 | Vector3 fromPos = c.Position; |
192 | Vector3 regionPos = new Vector3(scene.RegionInfo.WorldLocX, scene.RegionInfo.WorldLocY, 0); | 216 | Vector3 regionPos = new Vector3(scene.RegionInfo.WorldLocX, scene.RegionInfo.WorldLocY, 0); |
217 | <<<<<<< HEAD | ||
218 | ======= | ||
219 | |||
220 | bool checkParcelHide = false; | ||
221 | UUID sourceParcelID = UUID.Zero; | ||
222 | Vector3 hidePos = fromPos; | ||
223 | >>>>>>> avn/ubitvar | ||
193 | 224 | ||
194 | if (c.Channel == DEBUG_CHANNEL) c.Type = ChatTypeEnum.DebugChannel; | 225 | if (c.Channel == DEBUG_CHANNEL) c.Type = ChatTypeEnum.DebugChannel; |
195 | 226 | ||
196 | switch (sourceType) | 227 | switch (sourceType) |
197 | { | 228 | { |
198 | case ChatSourceType.Agent: | 229 | case ChatSourceType.Agent: |
199 | ScenePresence avatar = scene.GetScenePresence(c.Sender.AgentId); | 230 | if (!(scene is Scene)) |
231 | { | ||
232 | m_log.WarnFormat("[CHAT]: scene {0} is not a Scene object, cannot obtain scene presence for {1}", | ||
233 | scene.RegionInfo.RegionName, c.Sender.AgentId); | ||
234 | return; | ||
235 | } | ||
236 | ScenePresence avatar = (scene as Scene).GetScenePresence(c.Sender.AgentId); | ||
200 | fromPos = avatar.AbsolutePosition; | 237 | fromPos = avatar.AbsolutePosition; |
201 | fromName = avatar.Name; | 238 | fromName = avatar.Name; |
202 | fromID = c.Sender.AgentId; | 239 | fromID = c.Sender.AgentId; |
240 | if (avatar.GodLevel >= 200) | ||
241 | { // let gods speak to outside or things may get confusing | ||
242 | fromNamePrefix = m_adminPrefix; | ||
243 | checkParcelHide = false; | ||
244 | } | ||
245 | else | ||
246 | { | ||
247 | checkParcelHide = true; | ||
248 | } | ||
249 | destination = UUID.Zero; // Avatars cant "SayTo" | ||
203 | ownerID = c.Sender.AgentId; | 250 | ownerID = c.Sender.AgentId; |
204 | 251 | ||
252 | hidePos = fromPos; | ||
205 | break; | 253 | break; |
206 | 254 | ||
207 | case ChatSourceType.Object: | 255 | case ChatSourceType.Object: |
208 | fromID = c.SenderUUID; | 256 | fromID = c.SenderUUID; |
209 | 257 | ||
210 | if (c.SenderObject != null && c.SenderObject is SceneObjectPart) | 258 | if (c.SenderObject != null && c.SenderObject is SceneObjectPart) |
259 | { | ||
211 | ownerID = ((SceneObjectPart)c.SenderObject).OwnerID; | 260 | ownerID = ((SceneObjectPart)c.SenderObject).OwnerID; |
212 | 261 | if (((SceneObjectPart)c.SenderObject).ParentGroup.IsAttachment) | |
262 | { | ||
263 | checkParcelHide = true; | ||
264 | hidePos = ((SceneObjectPart)c.SenderObject).ParentGroup.AbsolutePosition; | ||
265 | } | ||
266 | } | ||
213 | break; | 267 | break; |
214 | } | 268 | } |
215 | 269 | ||
@@ -218,38 +272,68 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat | |||
218 | message = message.Substring(0, 1000); | 272 | message = message.Substring(0, 1000); |
219 | 273 | ||
220 | // m_log.DebugFormat( | 274 | // m_log.DebugFormat( |
221 | // "[CHAT]: DCTA: fromID {0} fromName {1}, region{2}, cType {3}, sType {4}, targetID {5}", | 275 | // "[CHAT]: DCTA: fromID {0} fromName {1}, region{2}, cType {3}, sType {4}", |
222 | // fromID, fromName, scene.RegionInfo.RegionName, c.Type, sourceType, targetID); | 276 | // fromID, fromName, scene.RegionInfo.RegionName, c.Type, sourceType); |
223 | 277 | ||
224 | HashSet<UUID> receiverIDs = new HashSet<UUID>(); | 278 | HashSet<UUID> receiverIDs = new HashSet<UUID>(); |
225 | 279 | ||
226 | if (targetID == UUID.Zero) | 280 | if (checkParcelHide) |
281 | { | ||
282 | checkParcelHide = false; | ||
283 | if (c.Type < ChatTypeEnum.DebugChannel && destination == UUID.Zero) | ||
284 | { | ||
285 | ILandObject srcland = (scene as Scene).LandChannel.GetLandObject(hidePos.X, hidePos.Y); | ||
286 | if (srcland != null && !srcland.LandData.SeeAVs) | ||
287 | { | ||
288 | sourceParcelID = srcland.LandData.GlobalID; | ||
289 | checkParcelHide = true; | ||
290 | } | ||
291 | } | ||
292 | } | ||
293 | |||
294 | foreach (Scene s in m_scenes) | ||
227 | { | 295 | { |
228 | // This should use ForEachClient, but clients don't have a position. | 296 | // This should use ForEachClient, but clients don't have a position. |
229 | // If camera is moved into client, then camera position can be used | 297 | // If camera is moved into client, then camera position can be used |
230 | scene.ForEachScenePresence( | 298 | // MT: No, it can't, as chat is heard from the avatar position, not |
299 | // the camera position. | ||
300 | |||
301 | s.ForEachScenePresence( | ||
231 | delegate(ScenePresence presence) | 302 | delegate(ScenePresence presence) |
232 | { | 303 | { |
233 | if (TrySendChatMessage( | 304 | if (destination != UUID.Zero && presence.UUID != destination) |
234 | presence, fromPos, regionPos, fromID, ownerID, fromName, c.Type, message, sourceType, false)) | 305 | return; |
235 | receiverIDs.Add(presence.UUID); | 306 | ILandObject Presencecheck = s.LandChannel.GetLandObject(presence.AbsolutePosition.X, presence.AbsolutePosition.Y); |
307 | if (Presencecheck != null) | ||
308 | { | ||
309 | // This will pass all chat from objects. Not | ||
310 | // perfect, but it will do. For now. Better | ||
311 | // than the prior behavior of muting all | ||
312 | // objects on a parcel with access restrictions | ||
313 | if (checkParcelHide) | ||
314 | { | ||
315 | if (sourceParcelID != Presencecheck.LandData.GlobalID && presence.GodLevel < 200) | ||
316 | return; | ||
317 | } | ||
318 | if (c.Sender == null || Presencecheck.IsEitherBannedOrRestricted(c.Sender.AgentId) != true) | ||
319 | { | ||
320 | if (destination != UUID.Zero) | ||
321 | { | ||
322 | if (TrySendChatMessage(presence, fromPos, regionPos, fromID, ownerID, fromNamePrefix + fromName, c.Type, message, sourceType, true)) | ||
323 | receiverIDs.Add(presence.UUID); | ||
324 | } | ||
325 | else | ||
326 | { | ||
327 | if (TrySendChatMessage(presence, fromPos, regionPos, fromID, ownerID, fromNamePrefix + fromName, c.Type, message, sourceType, false)) | ||
328 | receiverIDs.Add(presence.UUID); | ||
329 | } | ||
330 | } | ||
331 | } | ||
236 | } | 332 | } |
237 | ); | 333 | ); |
238 | } | 334 | } |
239 | else | 335 | |
240 | { | 336 | (scene as Scene).EventManager.TriggerOnChatToClients( |
241 | // This is a send to a specific client eg from llRegionSayTo | ||
242 | // no need to check distance etc, jand send is as say | ||
243 | ScenePresence presence = scene.GetScenePresence(targetID); | ||
244 | if (presence != null && !presence.IsChildAgent) | ||
245 | { | ||
246 | if (TrySendChatMessage( | ||
247 | presence, fromPos, regionPos, fromID, ownerID, fromName, ChatTypeEnum.Say, message, sourceType, true)) | ||
248 | receiverIDs.Add(presence.UUID); | ||
249 | } | ||
250 | } | ||
251 | |||
252 | scene.EventManager.TriggerOnChatToClients( | ||
253 | fromID, receiverIDs, message, c.Type, fromPos, fromName, sourceType, ChatAudibleLevel.Fully); | 337 | fromID, receiverIDs, message, c.Type, fromPos, fromName, sourceType, ChatAudibleLevel.Fully); |
254 | } | 338 | } |
255 | 339 | ||
@@ -291,9 +375,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat | |||
291 | } | 375 | } |
292 | 376 | ||
293 | // m_log.DebugFormat("[CHAT] Broadcast: fromID {0} fromName {1}, cType {2}, sType {3}", fromID, fromName, cType, sourceType); | 377 | // m_log.DebugFormat("[CHAT] Broadcast: fromID {0} fromName {1}, cType {2}, sType {3}", fromID, fromName, cType, sourceType); |
294 | |||
295 | HashSet<UUID> receiverIDs = new HashSet<UUID>(); | 378 | HashSet<UUID> receiverIDs = new HashSet<UUID>(); |
296 | 379 | ||
380 | <<<<<<< HEAD | ||
297 | ((Scene)c.Scene).ForEachRootClient( | 381 | ((Scene)c.Scene).ForEachRootClient( |
298 | delegate(IClientAPI client) | 382 | delegate(IClientAPI client) |
299 | { | 383 | { |
@@ -313,6 +397,29 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat | |||
313 | 397 | ||
314 | (c.Scene as Scene).EventManager.TriggerOnChatToClients( | 398 | (c.Scene as Scene).EventManager.TriggerOnChatToClients( |
315 | fromID, receiverIDs, c.Message, cType, CenterOfRegion, fromName, sourceType, ChatAudibleLevel.Fully); | 399 | fromID, receiverIDs, c.Message, cType, CenterOfRegion, fromName, sourceType, ChatAudibleLevel.Fully); |
400 | ======= | ||
401 | if (c.Scene != null) | ||
402 | { | ||
403 | ((Scene)c.Scene).ForEachRootClient | ||
404 | ( | ||
405 | delegate(IClientAPI client) | ||
406 | { | ||
407 | // don't forward SayOwner chat from objects to | ||
408 | // non-owner agents | ||
409 | if ((c.Type == ChatTypeEnum.Owner) && | ||
410 | (null != c.SenderObject) && | ||
411 | (((SceneObjectPart)c.SenderObject).OwnerID != client.AgentId)) | ||
412 | return; | ||
413 | |||
414 | client.SendChatMessage(c.Message, (byte)cType, CenterOfRegion, fromName, fromID, fromID, | ||
415 | (byte)sourceType, (byte)ChatAudibleLevel.Fully); | ||
416 | receiverIDs.Add(client.AgentId); | ||
417 | } | ||
418 | ); | ||
419 | (c.Scene as Scene).EventManager.TriggerOnChatToClients( | ||
420 | fromID, receiverIDs, c.Message, cType, CenterOfRegion, fromName, sourceType, ChatAudibleLevel.Fully); | ||
421 | } | ||
422 | >>>>>>> avn/ubitvar | ||
316 | } | 423 | } |
317 | 424 | ||
318 | /// <summary> | 425 | /// <summary> |
@@ -364,6 +471,35 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat | |||
364 | return true; | 471 | return true; |
365 | } | 472 | } |
366 | 473 | ||
474 | Dictionary<UUID, System.Threading.Timer> Timers = new Dictionary<UUID, System.Threading.Timer>(); | ||
475 | public void ParcelFreezeUser(IClientAPI client, UUID parcelowner, uint flags, UUID target) | ||
476 | { | ||
477 | System.Threading.Timer Timer; | ||
478 | if (flags == 0) | ||
479 | { | ||
480 | FreezeCache.Add(target.ToString()); | ||
481 | System.Threading.TimerCallback timeCB = new System.Threading.TimerCallback(OnEndParcelFrozen); | ||
482 | Timer = new System.Threading.Timer(timeCB, target, 30000, 0); | ||
483 | Timers.Add(target, Timer); | ||
484 | } | ||
485 | else | ||
486 | { | ||
487 | FreezeCache.Remove(target.ToString()); | ||
488 | Timers.TryGetValue(target, out Timer); | ||
489 | Timers.Remove(target); | ||
490 | Timer.Dispose(); | ||
491 | } | ||
492 | } | ||
493 | |||
494 | private void OnEndParcelFrozen(object avatar) | ||
495 | { | ||
496 | UUID target = (UUID)avatar; | ||
497 | FreezeCache.Remove(target.ToString()); | ||
498 | System.Threading.Timer Timer; | ||
499 | Timers.TryGetValue(target, out Timer); | ||
500 | Timers.Remove(target); | ||
501 | Timer.Dispose(); | ||
502 | } | ||
367 | #region SimulatorFeaturesRequest | 503 | #region SimulatorFeaturesRequest |
368 | 504 | ||
369 | static OSDInteger m_SayRange, m_WhisperRange, m_ShoutRange; | 505 | static OSDInteger m_SayRange, m_WhisperRange, m_ShoutRange; |
@@ -392,4 +528,4 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat | |||
392 | 528 | ||
393 | #endregion | 529 | #endregion |
394 | } | 530 | } |
395 | } \ No newline at end of file | 531 | } |