diff options
Diffstat (limited to 'OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs')
-rw-r--r-- | OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs | 208 |
1 files changed, 142 insertions, 66 deletions
diff --git a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs index 58f747b..174642d 100644 --- a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs | |||
@@ -50,7 +50,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat | |||
50 | private int m_saydistance = 20; | 50 | private int m_saydistance = 20; |
51 | private int m_shoutdistance = 100; | 51 | private int m_shoutdistance = 100; |
52 | private int m_whisperdistance = 10; | 52 | private int m_whisperdistance = 10; |
53 | 53 | private List<Scene> m_scenes = new List<Scene>(); | |
54 | private List<string> FreezeCache = new List<string>(); | ||
55 | private string m_adminPrefix = ""; | ||
54 | internal object m_syncy = new object(); | 56 | internal object m_syncy = new object(); |
55 | 57 | ||
56 | internal IConfig m_config; | 58 | internal IConfig m_config; |
@@ -77,16 +79,23 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat | |||
77 | m_whisperdistance = config.Configs["Chat"].GetInt("whisper_distance", m_whisperdistance); | 79 | m_whisperdistance = config.Configs["Chat"].GetInt("whisper_distance", m_whisperdistance); |
78 | m_saydistance = config.Configs["Chat"].GetInt("say_distance", m_saydistance); | 80 | m_saydistance = config.Configs["Chat"].GetInt("say_distance", m_saydistance); |
79 | m_shoutdistance = config.Configs["Chat"].GetInt("shout_distance", m_shoutdistance); | 81 | m_shoutdistance = config.Configs["Chat"].GetInt("shout_distance", m_shoutdistance); |
82 | m_adminPrefix = config.Configs["Chat"].GetString("admin_prefix", ""); | ||
80 | } | 83 | } |
81 | 84 | ||
82 | public virtual void AddRegion(Scene scene) | 85 | public virtual void AddRegion(Scene scene) |
83 | { | 86 | { |
84 | if (!m_enabled) | 87 | if (!m_enabled) return; |
85 | return; | ||
86 | 88 | ||
87 | scene.EventManager.OnNewClient += OnNewClient; | 89 | lock (m_syncy) |
88 | scene.EventManager.OnChatFromWorld += OnChatFromWorld; | 90 | { |
89 | scene.EventManager.OnChatBroadcast += OnChatBroadcast; | 91 | if (!m_scenes.Contains(scene)) |
92 | { | ||
93 | m_scenes.Add(scene); | ||
94 | scene.EventManager.OnNewClient += OnNewClient; | ||
95 | scene.EventManager.OnChatFromWorld += OnChatFromWorld; | ||
96 | scene.EventManager.OnChatBroadcast += OnChatBroadcast; | ||
97 | } | ||
98 | } | ||
90 | 99 | ||
91 | m_log.InfoFormat("[CHAT]: Initialized for {0} w:{1} s:{2} S:{3}", scene.RegionInfo.RegionName, | 100 | m_log.InfoFormat("[CHAT]: Initialized for {0} w:{1} s:{2} S:{3}", scene.RegionInfo.RegionName, |
92 | m_whisperdistance, m_saydistance, m_shoutdistance); | 101 | m_whisperdistance, m_saydistance, m_shoutdistance); |
@@ -98,12 +107,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat | |||
98 | 107 | ||
99 | public virtual void RemoveRegion(Scene scene) | 108 | public virtual void RemoveRegion(Scene scene) |
100 | { | 109 | { |
101 | if (!m_enabled) | 110 | if (!m_enabled) return; |
102 | return; | ||
103 | 111 | ||
104 | scene.EventManager.OnNewClient -= OnNewClient; | 112 | lock (m_syncy) |
105 | scene.EventManager.OnChatFromWorld -= OnChatFromWorld; | 113 | { |
106 | scene.EventManager.OnChatBroadcast -= OnChatBroadcast; | 114 | if (m_scenes.Contains(scene)) |
115 | { | ||
116 | scene.EventManager.OnNewClient -= OnNewClient; | ||
117 | scene.EventManager.OnChatFromWorld -= OnChatFromWorld; | ||
118 | scene.EventManager.OnChatBroadcast -= OnChatBroadcast; | ||
119 | m_scenes.Remove(scene); | ||
120 | } | ||
121 | } | ||
107 | } | 122 | } |
108 | 123 | ||
109 | public virtual void Close() | 124 | public virtual void Close() |
@@ -160,7 +175,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat | |||
160 | return; | 175 | return; |
161 | } | 176 | } |
162 | 177 | ||
163 | DeliverChatToAvatars(ChatSourceType.Agent, c); | 178 | if (FreezeCache.Contains(c.Sender.AgentId.ToString())) |
179 | { | ||
180 | if (c.Type != ChatTypeEnum.StartTyping || c.Type != ChatTypeEnum.StopTyping) | ||
181 | c.Sender.SendAgentAlertMessage("You may not talk as you are frozen.", false); | ||
182 | } | ||
183 | else | ||
184 | { | ||
185 | DeliverChatToAvatars(ChatSourceType.Agent, c); | ||
186 | } | ||
164 | } | 187 | } |
165 | 188 | ||
166 | public virtual void OnChatFromWorld(Object sender, OSChatMessage c) | 189 | public virtual void OnChatFromWorld(Object sender, OSChatMessage c) |
@@ -174,11 +197,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat | |||
174 | protected virtual void DeliverChatToAvatars(ChatSourceType sourceType, OSChatMessage c) | 197 | protected virtual void DeliverChatToAvatars(ChatSourceType sourceType, OSChatMessage c) |
175 | { | 198 | { |
176 | string fromName = c.From; | 199 | string fromName = c.From; |
200 | string fromNamePrefix = ""; | ||
177 | UUID fromID = UUID.Zero; | 201 | UUID fromID = UUID.Zero; |
178 | UUID ownerID = UUID.Zero; | 202 | UUID ownerID = UUID.Zero; |
179 | UUID targetID = c.TargetUUID; | ||
180 | string message = c.Message; | 203 | string message = c.Message; |
181 | Scene scene = (Scene)c.Scene; | 204 | IScene scene = c.Scene; |
205 | UUID destination = c.Destination; | ||
182 | Vector3 fromPos = c.Position; | 206 | Vector3 fromPos = c.Position; |
183 | Vector3 regionPos = new Vector3(scene.RegionInfo.RegionLocX * Constants.RegionSize, | 207 | Vector3 regionPos = new Vector3(scene.RegionInfo.RegionLocX * Constants.RegionSize, |
184 | scene.RegionInfo.RegionLocY * Constants.RegionSize, 0); | 208 | scene.RegionInfo.RegionLocY * Constants.RegionSize, 0); |
@@ -188,10 +212,21 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat | |||
188 | switch (sourceType) | 212 | switch (sourceType) |
189 | { | 213 | { |
190 | case ChatSourceType.Agent: | 214 | case ChatSourceType.Agent: |
191 | ScenePresence avatar = scene.GetScenePresence(c.Sender.AgentId); | 215 | if (!(scene is Scene)) |
216 | { | ||
217 | m_log.WarnFormat("[CHAT]: scene {0} is not a Scene object, cannot obtain scene presence for {1}", | ||
218 | scene.RegionInfo.RegionName, c.Sender.AgentId); | ||
219 | return; | ||
220 | } | ||
221 | ScenePresence avatar = (scene as Scene).GetScenePresence(c.Sender.AgentId); | ||
192 | fromPos = avatar.AbsolutePosition; | 222 | fromPos = avatar.AbsolutePosition; |
193 | fromName = avatar.Name; | 223 | fromName = avatar.Name; |
194 | fromID = c.Sender.AgentId; | 224 | fromID = c.Sender.AgentId; |
225 | if (avatar.GodLevel >= 200) | ||
226 | { | ||
227 | fromNamePrefix = m_adminPrefix; | ||
228 | } | ||
229 | destination = UUID.Zero; // Avatars cant "SayTo" | ||
195 | ownerID = c.Sender.AgentId; | 230 | ownerID = c.Sender.AgentId; |
196 | 231 | ||
197 | break; | 232 | break; |
@@ -210,38 +245,48 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat | |||
210 | message = message.Substring(0, 1000); | 245 | message = message.Substring(0, 1000); |
211 | 246 | ||
212 | // m_log.DebugFormat( | 247 | // m_log.DebugFormat( |
213 | // "[CHAT]: DCTA: fromID {0} fromName {1}, region{2}, cType {3}, sType {4}, targetID {5}", | 248 | // "[CHAT]: DCTA: fromID {0} fromName {1}, region{2}, cType {3}, sType {4}", |
214 | // fromID, fromName, scene.RegionInfo.RegionName, c.Type, sourceType, targetID); | 249 | // fromID, fromName, scene.RegionInfo.RegionName, c.Type, sourceType); |
215 | 250 | ||
216 | HashSet<UUID> receiverIDs = new HashSet<UUID>(); | 251 | HashSet<UUID> receiverIDs = new HashSet<UUID>(); |
217 | 252 | ||
218 | if (targetID == UUID.Zero) | 253 | foreach (Scene s in m_scenes) |
219 | { | 254 | { |
220 | // This should use ForEachClient, but clients don't have a position. | 255 | // This should use ForEachClient, but clients don't have a position. |
221 | // If camera is moved into client, then camera position can be used | 256 | // If camera is moved into client, then camera position can be used |
222 | scene.ForEachScenePresence( | 257 | // MT: No, it can't, as chat is heard from the avatar position, not |
258 | // the camera position. | ||
259 | s.ForEachScenePresence( | ||
223 | delegate(ScenePresence presence) | 260 | delegate(ScenePresence presence) |
224 | { | 261 | { |
225 | if (TrySendChatMessage( | 262 | if (destination != UUID.Zero && presence.UUID != destination) |
226 | presence, fromPos, regionPos, fromID, ownerID, fromName, c.Type, message, sourceType, false)) | 263 | return; |
227 | receiverIDs.Add(presence.UUID); | 264 | ILandObject Presencecheck = s.LandChannel.GetLandObject(presence.AbsolutePosition.X, presence.AbsolutePosition.Y); |
265 | if (Presencecheck != null) | ||
266 | { | ||
267 | // This will pass all chat from objects. Not | ||
268 | // perfect, but it will do. For now. Better | ||
269 | // than the prior behavior of muting all | ||
270 | // objects on a parcel with access restrictions | ||
271 | if (c.Sender == null || Presencecheck.IsEitherBannedOrRestricted(c.Sender.AgentId) != true) | ||
272 | { | ||
273 | if (destination != UUID.Zero) | ||
274 | { | ||
275 | if (TrySendChatMessage(presence, fromPos, regionPos, fromID, ownerID, fromNamePrefix + fromName, c.Type, message, sourceType, true)) | ||
276 | receiverIDs.Add(presence.UUID); | ||
277 | } | ||
278 | else | ||
279 | { | ||
280 | if (TrySendChatMessage(presence, fromPos, regionPos, fromID, ownerID, fromNamePrefix + fromName, c.Type, message, sourceType, false)) | ||
281 | receiverIDs.Add(presence.UUID); | ||
282 | } | ||
283 | } | ||
284 | } | ||
228 | } | 285 | } |
229 | ); | 286 | ); |
230 | } | 287 | } |
231 | else | 288 | |
232 | { | 289 | (scene as Scene).EventManager.TriggerOnChatToClients( |
233 | // This is a send to a specific client eg from llRegionSayTo | ||
234 | // no need to check distance etc, jand send is as say | ||
235 | ScenePresence presence = scene.GetScenePresence(targetID); | ||
236 | if (presence != null && !presence.IsChildAgent) | ||
237 | { | ||
238 | if (TrySendChatMessage( | ||
239 | presence, fromPos, regionPos, fromID, ownerID, fromName, ChatTypeEnum.Say, message, sourceType, true)) | ||
240 | receiverIDs.Add(presence.UUID); | ||
241 | } | ||
242 | } | ||
243 | |||
244 | scene.EventManager.TriggerOnChatToClients( | ||
245 | fromID, receiverIDs, message, c.Type, fromPos, fromName, sourceType, ChatAudibleLevel.Fully); | 290 | fromID, receiverIDs, message, c.Type, fromPos, fromName, sourceType, ChatAudibleLevel.Fully); |
246 | } | 291 | } |
247 | 292 | ||
@@ -280,28 +325,29 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat | |||
280 | } | 325 | } |
281 | 326 | ||
282 | // m_log.DebugFormat("[CHAT] Broadcast: fromID {0} fromName {1}, cType {2}, sType {3}", fromID, fromName, cType, sourceType); | 327 | // m_log.DebugFormat("[CHAT] Broadcast: fromID {0} fromName {1}, cType {2}, sType {3}", fromID, fromName, cType, sourceType); |
283 | |||
284 | HashSet<UUID> receiverIDs = new HashSet<UUID>(); | 328 | HashSet<UUID> receiverIDs = new HashSet<UUID>(); |
285 | 329 | ||
286 | ((Scene)c.Scene).ForEachRootClient( | 330 | if (c.Scene != null) |
287 | delegate(IClientAPI client) | 331 | { |
288 | { | 332 | ((Scene)c.Scene).ForEachRootClient |
289 | // don't forward SayOwner chat from objects to | 333 | ( |
290 | // non-owner agents | 334 | delegate(IClientAPI client) |
291 | if ((c.Type == ChatTypeEnum.Owner) && | 335 | { |
292 | (null != c.SenderObject) && | 336 | // don't forward SayOwner chat from objects to |
293 | (((SceneObjectPart)c.SenderObject).OwnerID != client.AgentId)) | 337 | // non-owner agents |
294 | return; | 338 | if ((c.Type == ChatTypeEnum.Owner) && |
295 | 339 | (null != c.SenderObject) && | |
296 | client.SendChatMessage( | 340 | (((SceneObjectPart)c.SenderObject).OwnerID != client.AgentId)) |
297 | c.Message, (byte)cType, CenterOfRegion, fromName, fromID, fromID, | 341 | return; |
298 | (byte)sourceType, (byte)ChatAudibleLevel.Fully); | 342 | |
299 | 343 | client.SendChatMessage(c.Message, (byte)cType, CenterOfRegion, fromName, fromID, fromID, | |
300 | receiverIDs.Add(client.AgentId); | 344 | (byte)sourceType, (byte)ChatAudibleLevel.Fully); |
301 | }); | 345 | receiverIDs.Add(client.AgentId); |
302 | 346 | } | |
303 | (c.Scene as Scene).EventManager.TriggerOnChatToClients( | 347 | ); |
304 | fromID, receiverIDs, c.Message, cType, CenterOfRegion, fromName, sourceType, ChatAudibleLevel.Fully); | 348 | (c.Scene as Scene).EventManager.TriggerOnChatToClients( |
349 | fromID, receiverIDs, c.Message, cType, CenterOfRegion, fromName, sourceType, ChatAudibleLevel.Fully); | ||
350 | } | ||
305 | } | 351 | } |
306 | 352 | ||
307 | /// <summary> | 353 | /// <summary> |
@@ -326,21 +372,21 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat | |||
326 | UUID fromAgentID, UUID ownerID, string fromName, ChatTypeEnum type, | 372 | UUID fromAgentID, UUID ownerID, string fromName, ChatTypeEnum type, |
327 | string message, ChatSourceType src, bool ignoreDistance) | 373 | string message, ChatSourceType src, bool ignoreDistance) |
328 | { | 374 | { |
375 | // don't send chat to child agents | ||
376 | if (presence.IsChildAgent) return false; | ||
377 | |||
329 | Vector3 fromRegionPos = fromPos + regionPos; | 378 | Vector3 fromRegionPos = fromPos + regionPos; |
330 | Vector3 toRegionPos = presence.AbsolutePosition + | 379 | Vector3 toRegionPos = presence.AbsolutePosition + |
331 | new Vector3(presence.Scene.RegionInfo.RegionLocX * Constants.RegionSize, | 380 | new Vector3(presence.Scene.RegionInfo.RegionLocX * Constants.RegionSize, |
332 | presence.Scene.RegionInfo.RegionLocY * Constants.RegionSize, 0); | 381 | presence.Scene.RegionInfo.RegionLocY * Constants.RegionSize, 0); |
333 | 382 | ||
334 | int dis = (int)Util.GetDistanceTo(toRegionPos, fromRegionPos); | 383 | int dis = (int)Util.GetDistanceTo(toRegionPos, fromRegionPos); |
335 | 384 | ||
336 | if (!ignoreDistance) | 385 | if (type == ChatTypeEnum.Whisper && dis > m_whisperdistance || |
386 | type == ChatTypeEnum.Say && dis > m_saydistance || | ||
387 | type == ChatTypeEnum.Shout && dis > m_shoutdistance) | ||
337 | { | 388 | { |
338 | if (type == ChatTypeEnum.Whisper && dis > m_whisperdistance || | 389 | return false; |
339 | type == ChatTypeEnum.Say && dis > m_saydistance || | ||
340 | type == ChatTypeEnum.Shout && dis > m_shoutdistance) | ||
341 | { | ||
342 | return false; | ||
343 | } | ||
344 | } | 390 | } |
345 | 391 | ||
346 | // TODO: should change so the message is sent through the avatar rather than direct to the ClientView | 392 | // TODO: should change so the message is sent through the avatar rather than direct to the ClientView |
@@ -350,5 +396,35 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat | |||
350 | 396 | ||
351 | return true; | 397 | return true; |
352 | } | 398 | } |
399 | |||
400 | Dictionary<UUID, System.Threading.Timer> Timers = new Dictionary<UUID, System.Threading.Timer>(); | ||
401 | public void ParcelFreezeUser(IClientAPI client, UUID parcelowner, uint flags, UUID target) | ||
402 | { | ||
403 | System.Threading.Timer Timer; | ||
404 | if (flags == 0) | ||
405 | { | ||
406 | FreezeCache.Add(target.ToString()); | ||
407 | System.Threading.TimerCallback timeCB = new System.Threading.TimerCallback(OnEndParcelFrozen); | ||
408 | Timer = new System.Threading.Timer(timeCB, target, 30000, 0); | ||
409 | Timers.Add(target, Timer); | ||
410 | } | ||
411 | else | ||
412 | { | ||
413 | FreezeCache.Remove(target.ToString()); | ||
414 | Timers.TryGetValue(target, out Timer); | ||
415 | Timers.Remove(target); | ||
416 | Timer.Dispose(); | ||
417 | } | ||
418 | } | ||
419 | |||
420 | private void OnEndParcelFrozen(object avatar) | ||
421 | { | ||
422 | UUID target = (UUID)avatar; | ||
423 | FreezeCache.Remove(target.ToString()); | ||
424 | System.Threading.Timer Timer; | ||
425 | Timers.TryGetValue(target, out Timer); | ||
426 | Timers.Remove(target); | ||
427 | Timer.Dispose(); | ||
428 | } | ||
353 | } | 429 | } |
354 | } \ No newline at end of file | 430 | } |