diff options
Diffstat (limited to 'OpenSim/Region/CoreModules/Avatar/Chat')
-rw-r--r-- | OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs | 191 |
1 files changed, 133 insertions, 58 deletions
diff --git a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs index 27ace68..5cbfec6 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,11 +206,12 @@ 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.RegionLocX * Constants.RegionSize, | 216 | Vector3 regionPos = new Vector3(scene.RegionInfo.RegionLocX * Constants.RegionSize, |
193 | scene.RegionInfo.RegionLocY * Constants.RegionSize, 0); | 217 | scene.RegionInfo.RegionLocY * Constants.RegionSize, 0); |
@@ -197,10 +221,21 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat | |||
197 | switch (sourceType) | 221 | switch (sourceType) |
198 | { | 222 | { |
199 | case ChatSourceType.Agent: | 223 | case ChatSourceType.Agent: |
200 | ScenePresence avatar = scene.GetScenePresence(c.Sender.AgentId); | 224 | if (!(scene is Scene)) |
225 | { | ||
226 | m_log.WarnFormat("[CHAT]: scene {0} is not a Scene object, cannot obtain scene presence for {1}", | ||
227 | scene.RegionInfo.RegionName, c.Sender.AgentId); | ||
228 | return; | ||
229 | } | ||
230 | ScenePresence avatar = (scene as Scene).GetScenePresence(c.Sender.AgentId); | ||
201 | fromPos = avatar.AbsolutePosition; | 231 | fromPos = avatar.AbsolutePosition; |
202 | fromName = avatar.Name; | 232 | fromName = avatar.Name; |
203 | fromID = c.Sender.AgentId; | 233 | fromID = c.Sender.AgentId; |
234 | if (avatar.GodLevel >= 200) | ||
235 | { | ||
236 | fromNamePrefix = m_adminPrefix; | ||
237 | } | ||
238 | destination = UUID.Zero; // Avatars cant "SayTo" | ||
204 | ownerID = c.Sender.AgentId; | 239 | ownerID = c.Sender.AgentId; |
205 | 240 | ||
206 | break; | 241 | break; |
@@ -219,38 +254,48 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat | |||
219 | message = message.Substring(0, 1000); | 254 | message = message.Substring(0, 1000); |
220 | 255 | ||
221 | // m_log.DebugFormat( | 256 | // m_log.DebugFormat( |
222 | // "[CHAT]: DCTA: fromID {0} fromName {1}, region{2}, cType {3}, sType {4}, targetID {5}", | 257 | // "[CHAT]: DCTA: fromID {0} fromName {1}, region{2}, cType {3}, sType {4}", |
223 | // fromID, fromName, scene.RegionInfo.RegionName, c.Type, sourceType, targetID); | 258 | // fromID, fromName, scene.RegionInfo.RegionName, c.Type, sourceType); |
224 | 259 | ||
225 | HashSet<UUID> receiverIDs = new HashSet<UUID>(); | 260 | HashSet<UUID> receiverIDs = new HashSet<UUID>(); |
226 | 261 | ||
227 | if (targetID == UUID.Zero) | 262 | foreach (Scene s in m_scenes) |
228 | { | 263 | { |
229 | // This should use ForEachClient, but clients don't have a position. | 264 | // This should use ForEachClient, but clients don't have a position. |
230 | // If camera is moved into client, then camera position can be used | 265 | // If camera is moved into client, then camera position can be used |
231 | scene.ForEachScenePresence( | 266 | // MT: No, it can't, as chat is heard from the avatar position, not |
267 | // the camera position. | ||
268 | s.ForEachScenePresence( | ||
232 | delegate(ScenePresence presence) | 269 | delegate(ScenePresence presence) |
233 | { | 270 | { |
234 | if (TrySendChatMessage( | 271 | if (destination != UUID.Zero && presence.UUID != destination) |
235 | presence, fromPos, regionPos, fromID, ownerID, fromName, c.Type, message, sourceType, false)) | 272 | return; |
236 | receiverIDs.Add(presence.UUID); | 273 | ILandObject Presencecheck = s.LandChannel.GetLandObject(presence.AbsolutePosition.X, presence.AbsolutePosition.Y); |
274 | if (Presencecheck != null) | ||
275 | { | ||
276 | // This will pass all chat from objects. Not | ||
277 | // perfect, but it will do. For now. Better | ||
278 | // than the prior behavior of muting all | ||
279 | // objects on a parcel with access restrictions | ||
280 | if (c.Sender == null || Presencecheck.IsEitherBannedOrRestricted(c.Sender.AgentId) != true) | ||
281 | { | ||
282 | if (destination != UUID.Zero) | ||
283 | { | ||
284 | if (TrySendChatMessage(presence, fromPos, regionPos, fromID, ownerID, fromNamePrefix + fromName, c.Type, message, sourceType, true)) | ||
285 | receiverIDs.Add(presence.UUID); | ||
286 | } | ||
287 | else | ||
288 | { | ||
289 | if (TrySendChatMessage(presence, fromPos, regionPos, fromID, ownerID, fromNamePrefix + fromName, c.Type, message, sourceType, false)) | ||
290 | receiverIDs.Add(presence.UUID); | ||
291 | } | ||
292 | } | ||
293 | } | ||
237 | } | 294 | } |
238 | ); | 295 | ); |
239 | } | 296 | } |
240 | else | 297 | |
241 | { | 298 | (scene as Scene).EventManager.TriggerOnChatToClients( |
242 | // This is a send to a specific client eg from llRegionSayTo | ||
243 | // no need to check distance etc, jand send is as say | ||
244 | ScenePresence presence = scene.GetScenePresence(targetID); | ||
245 | if (presence != null && !presence.IsChildAgent) | ||
246 | { | ||
247 | if (TrySendChatMessage( | ||
248 | presence, fromPos, regionPos, fromID, ownerID, fromName, ChatTypeEnum.Say, message, sourceType, true)) | ||
249 | receiverIDs.Add(presence.UUID); | ||
250 | } | ||
251 | } | ||
252 | |||
253 | scene.EventManager.TriggerOnChatToClients( | ||
254 | fromID, receiverIDs, message, c.Type, fromPos, fromName, sourceType, ChatAudibleLevel.Fully); | 299 | fromID, receiverIDs, message, c.Type, fromPos, fromName, sourceType, ChatAudibleLevel.Fully); |
255 | } | 300 | } |
256 | 301 | ||
@@ -289,28 +334,29 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat | |||
289 | } | 334 | } |
290 | 335 | ||
291 | // m_log.DebugFormat("[CHAT] Broadcast: fromID {0} fromName {1}, cType {2}, sType {3}", fromID, fromName, cType, sourceType); | 336 | // m_log.DebugFormat("[CHAT] Broadcast: fromID {0} fromName {1}, cType {2}, sType {3}", fromID, fromName, cType, sourceType); |
292 | |||
293 | HashSet<UUID> receiverIDs = new HashSet<UUID>(); | 337 | HashSet<UUID> receiverIDs = new HashSet<UUID>(); |
294 | 338 | ||
295 | ((Scene)c.Scene).ForEachRootClient( | 339 | if (c.Scene != null) |
296 | delegate(IClientAPI client) | 340 | { |
297 | { | 341 | ((Scene)c.Scene).ForEachRootClient |
298 | // don't forward SayOwner chat from objects to | 342 | ( |
299 | // non-owner agents | 343 | delegate(IClientAPI client) |
300 | if ((c.Type == ChatTypeEnum.Owner) && | 344 | { |
301 | (null != c.SenderObject) && | 345 | // don't forward SayOwner chat from objects to |
302 | (((SceneObjectPart)c.SenderObject).OwnerID != client.AgentId)) | 346 | // non-owner agents |
303 | return; | 347 | if ((c.Type == ChatTypeEnum.Owner) && |
304 | 348 | (null != c.SenderObject) && | |
305 | client.SendChatMessage( | 349 | (((SceneObjectPart)c.SenderObject).OwnerID != client.AgentId)) |
306 | c.Message, (byte)cType, CenterOfRegion, fromName, fromID, fromID, | 350 | return; |
307 | (byte)sourceType, (byte)ChatAudibleLevel.Fully); | 351 | |
308 | 352 | client.SendChatMessage(c.Message, (byte)cType, CenterOfRegion, fromName, fromID, fromID, | |
309 | receiverIDs.Add(client.AgentId); | 353 | (byte)sourceType, (byte)ChatAudibleLevel.Fully); |
310 | }); | 354 | receiverIDs.Add(client.AgentId); |
311 | 355 | } | |
312 | (c.Scene as Scene).EventManager.TriggerOnChatToClients( | 356 | ); |
313 | fromID, receiverIDs, c.Message, cType, CenterOfRegion, fromName, sourceType, ChatAudibleLevel.Fully); | 357 | (c.Scene as Scene).EventManager.TriggerOnChatToClients( |
358 | fromID, receiverIDs, c.Message, cType, CenterOfRegion, fromName, sourceType, ChatAudibleLevel.Fully); | ||
359 | } | ||
314 | } | 360 | } |
315 | 361 | ||
316 | /// <summary> | 362 | /// <summary> |
@@ -363,6 +409,35 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat | |||
363 | return true; | 409 | return true; |
364 | } | 410 | } |
365 | 411 | ||
412 | Dictionary<UUID, System.Threading.Timer> Timers = new Dictionary<UUID, System.Threading.Timer>(); | ||
413 | public void ParcelFreezeUser(IClientAPI client, UUID parcelowner, uint flags, UUID target) | ||
414 | { | ||
415 | System.Threading.Timer Timer; | ||
416 | if (flags == 0) | ||
417 | { | ||
418 | FreezeCache.Add(target.ToString()); | ||
419 | System.Threading.TimerCallback timeCB = new System.Threading.TimerCallback(OnEndParcelFrozen); | ||
420 | Timer = new System.Threading.Timer(timeCB, target, 30000, 0); | ||
421 | Timers.Add(target, Timer); | ||
422 | } | ||
423 | else | ||
424 | { | ||
425 | FreezeCache.Remove(target.ToString()); | ||
426 | Timers.TryGetValue(target, out Timer); | ||
427 | Timers.Remove(target); | ||
428 | Timer.Dispose(); | ||
429 | } | ||
430 | } | ||
431 | |||
432 | private void OnEndParcelFrozen(object avatar) | ||
433 | { | ||
434 | UUID target = (UUID)avatar; | ||
435 | FreezeCache.Remove(target.ToString()); | ||
436 | System.Threading.Timer Timer; | ||
437 | Timers.TryGetValue(target, out Timer); | ||
438 | Timers.Remove(target); | ||
439 | Timer.Dispose(); | ||
440 | } | ||
366 | #region SimulatorFeaturesRequest | 441 | #region SimulatorFeaturesRequest |
367 | 442 | ||
368 | static OSDInteger m_SayRange, m_WhisperRange, m_ShoutRange; | 443 | static OSDInteger m_SayRange, m_WhisperRange, m_ShoutRange; |
@@ -391,4 +466,4 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat | |||
391 | 466 | ||
392 | #endregion | 467 | #endregion |
393 | } | 468 | } |
394 | } \ No newline at end of file | 469 | } |