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.cs208
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}