diff options
Diffstat (limited to 'OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs')
-rw-r--r-- | OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs | 397 |
1 files changed, 303 insertions, 94 deletions
diff --git a/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs b/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs index 8358bc0..2c2c99c 100644 --- a/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs | |||
@@ -28,8 +28,13 @@ | |||
28 | using System; | 28 | using System; |
29 | using System.Collections; | 29 | using System.Collections; |
30 | using System.Collections.Generic; | 30 | using System.Collections.Generic; |
31 | using System.Text.RegularExpressions; | ||
32 | |||
31 | using Nini.Config; | 33 | using Nini.Config; |
34 | using Mono.Addins; | ||
35 | |||
32 | using OpenMetaverse; | 36 | using OpenMetaverse; |
37 | |||
33 | using OpenSim.Framework; | 38 | using OpenSim.Framework; |
34 | using OpenSim.Region.Framework.Interfaces; | 39 | using OpenSim.Region.Framework.Interfaces; |
35 | using OpenSim.Region.Framework.Scenes; | 40 | using OpenSim.Region.Framework.Scenes; |
@@ -85,7 +90,8 @@ using OpenSim.Region.Framework.Scenes; | |||
85 | 90 | ||
86 | namespace OpenSim.Region.CoreModules.Scripting.WorldComm | 91 | namespace OpenSim.Region.CoreModules.Scripting.WorldComm |
87 | { | 92 | { |
88 | public class WorldCommModule : IRegionModule, IWorldComm | 93 | [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "WorldCommModule")] |
94 | public class WorldCommModule : IWorldComm, INonSharedRegionModule | ||
89 | { | 95 | { |
90 | // private static readonly ILog m_log = | 96 | // private static readonly ILog m_log = |
91 | // LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 97 | // LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
@@ -98,9 +104,9 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm | |||
98 | private int m_saydistance = 20; | 104 | private int m_saydistance = 20; |
99 | private int m_shoutdistance = 100; | 105 | private int m_shoutdistance = 100; |
100 | 106 | ||
101 | #region IRegionModule Members | 107 | #region INonSharedRegionModule Members |
102 | 108 | ||
103 | public void Initialise(Scene scene, IConfigSource config) | 109 | public void Initialise(IConfigSource config) |
104 | { | 110 | { |
105 | // wrap this in a try block so that defaults will work if | 111 | // wrap this in a try block so that defaults will work if |
106 | // the config file doesn't specify otherwise. | 112 | // the config file doesn't specify otherwise. |
@@ -108,29 +114,49 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm | |||
108 | int maxhandles = 64; | 114 | int maxhandles = 64; |
109 | try | 115 | try |
110 | { | 116 | { |
111 | m_whisperdistance = config.Configs["Chat"].GetInt("whisper_distance", m_whisperdistance); | 117 | m_whisperdistance = config.Configs["Chat"].GetInt( |
112 | m_saydistance = config.Configs["Chat"].GetInt("say_distance", m_saydistance); | 118 | "whisper_distance", m_whisperdistance); |
113 | m_shoutdistance = config.Configs["Chat"].GetInt("shout_distance", m_shoutdistance); | 119 | m_saydistance = config.Configs["Chat"].GetInt( |
114 | maxlisteners = config.Configs["LL-Functions"].GetInt("max_listens_per_region", maxlisteners); | 120 | "say_distance", m_saydistance); |
115 | maxhandles = config.Configs["LL-Functions"].GetInt("max_listens_per_script", maxhandles); | 121 | m_shoutdistance = config.Configs["Chat"].GetInt( |
122 | "shout_distance", m_shoutdistance); | ||
123 | maxlisteners = config.Configs["LL-Functions"].GetInt( | ||
124 | "max_listens_per_region", maxlisteners); | ||
125 | maxhandles = config.Configs["LL-Functions"].GetInt( | ||
126 | "max_listens_per_script", maxhandles); | ||
116 | } | 127 | } |
117 | catch (Exception) | 128 | catch (Exception) |
118 | { | 129 | { |
119 | } | 130 | } |
120 | if (maxlisteners < 1) maxlisteners = int.MaxValue; | 131 | if (maxlisteners < 1) maxlisteners = int.MaxValue; |
121 | if (maxhandles < 1) maxhandles = int.MaxValue; | 132 | if (maxhandles < 1) maxhandles = int.MaxValue; |
133 | m_listenerManager = new ListenerManager(maxlisteners, maxhandles); | ||
134 | m_pendingQ = new Queue(); | ||
135 | m_pending = Queue.Synchronized(m_pendingQ); | ||
136 | } | ||
122 | 137 | ||
138 | public void PostInitialise() | ||
139 | { | ||
140 | } | ||
141 | |||
142 | public void AddRegion(Scene scene) | ||
143 | { | ||
123 | m_scene = scene; | 144 | m_scene = scene; |
124 | m_scene.RegisterModuleInterface<IWorldComm>(this); | 145 | m_scene.RegisterModuleInterface<IWorldComm>(this); |
125 | m_listenerManager = new ListenerManager(maxlisteners, maxhandles); | ||
126 | m_scene.EventManager.OnChatFromClient += DeliverClientMessage; | 146 | m_scene.EventManager.OnChatFromClient += DeliverClientMessage; |
127 | m_scene.EventManager.OnChatBroadcast += DeliverClientMessage; | 147 | m_scene.EventManager.OnChatBroadcast += DeliverClientMessage; |
128 | m_pendingQ = new Queue(); | ||
129 | m_pending = Queue.Synchronized(m_pendingQ); | ||
130 | } | 148 | } |
131 | 149 | ||
132 | public void PostInitialise() | 150 | public void RegionLoaded(Scene scene) { } |
151 | |||
152 | public void RemoveRegion(Scene scene) | ||
133 | { | 153 | { |
154 | if (scene != m_scene) | ||
155 | return; | ||
156 | |||
157 | m_scene.UnregisterModuleInterface<IWorldComm>(this); | ||
158 | m_scene.EventManager.OnChatBroadcast -= DeliverClientMessage; | ||
159 | m_scene.EventManager.OnChatBroadcast -= DeliverClientMessage; | ||
134 | } | 160 | } |
135 | 161 | ||
136 | public void Close() | 162 | public void Close() |
@@ -142,10 +168,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm | |||
142 | get { return "WorldCommModule"; } | 168 | get { return "WorldCommModule"; } |
143 | } | 169 | } |
144 | 170 | ||
145 | public bool IsSharedModule | 171 | public Type ReplaceableInterface { get { return null; } } |
146 | { | ||
147 | get { return false; } | ||
148 | } | ||
149 | 172 | ||
150 | #endregion | 173 | #endregion |
151 | 174 | ||
@@ -170,12 +193,42 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm | |||
170 | /// <param name="hostID">UUID of the SceneObjectPart</param> | 193 | /// <param name="hostID">UUID of the SceneObjectPart</param> |
171 | /// <param name="channel">channel to listen on</param> | 194 | /// <param name="channel">channel to listen on</param> |
172 | /// <param name="name">name to filter on</param> | 195 | /// <param name="name">name to filter on</param> |
173 | /// <param name="id">key to filter on (user given, could be totally faked)</param> | 196 | /// <param name="id"> |
197 | /// key to filter on (user given, could be totally faked) | ||
198 | /// </param> | ||
174 | /// <param name="msg">msg to filter on</param> | 199 | /// <param name="msg">msg to filter on</param> |
175 | /// <returns>number of the scripts handle</returns> | 200 | /// <returns>number of the scripts handle</returns> |
176 | public int Listen(uint localID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg) | 201 | public int Listen(uint localID, UUID itemID, UUID hostID, int channel, |
202 | string name, UUID id, string msg) | ||
177 | { | 203 | { |
178 | return m_listenerManager.AddListener(localID, itemID, hostID, channel, name, id, msg); | 204 | return m_listenerManager.AddListener(localID, itemID, hostID, |
205 | channel, name, id, msg); | ||
206 | } | ||
207 | |||
208 | /// <summary> | ||
209 | /// Create a listen event callback with the specified filters. | ||
210 | /// The parameters localID,itemID are needed to uniquely identify | ||
211 | /// the script during 'peek' time. Parameter hostID is needed to | ||
212 | /// determine the position of the script. | ||
213 | /// </summary> | ||
214 | /// <param name="localID">localID of the script engine</param> | ||
215 | /// <param name="itemID">UUID of the script engine</param> | ||
216 | /// <param name="hostID">UUID of the SceneObjectPart</param> | ||
217 | /// <param name="channel">channel to listen on</param> | ||
218 | /// <param name="name">name to filter on</param> | ||
219 | /// <param name="id"> | ||
220 | /// key to filter on (user given, could be totally faked) | ||
221 | /// </param> | ||
222 | /// <param name="msg">msg to filter on</param> | ||
223 | /// <param name="regexBitfield"> | ||
224 | /// Bitfield indicating which strings should be processed as regex. | ||
225 | /// </param> | ||
226 | /// <returns>number of the scripts handle</returns> | ||
227 | public int Listen(uint localID, UUID itemID, UUID hostID, int channel, | ||
228 | string name, UUID id, string msg, int regexBitfield) | ||
229 | { | ||
230 | return m_listenerManager.AddListener(localID, itemID, hostID, | ||
231 | channel, name, id, msg, regexBitfield); | ||
179 | } | 232 | } |
180 | 233 | ||
181 | /// <summary> | 234 | /// <summary> |
@@ -224,7 +277,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm | |||
224 | 277 | ||
225 | if ((source = m_scene.GetSceneObjectPart(id)) != null) | 278 | if ((source = m_scene.GetSceneObjectPart(id)) != null) |
226 | position = source.AbsolutePosition; | 279 | position = source.AbsolutePosition; |
227 | else if ((avatar = m_scene.GetScenePresence(id)) != null) | 280 | else if ((avatar = m_scene.GetScenePresence(id)) != null) |
228 | position = avatar.AbsolutePosition; | 281 | position = avatar.AbsolutePosition; |
229 | else if (ChatTypeEnum.Region == type) | 282 | else if (ChatTypeEnum.Region == type) |
230 | position = CenterOfRegion; | 283 | position = CenterOfRegion; |
@@ -247,7 +300,8 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm | |||
247 | /// <param name="name">name of sender (object or avatar)</param> | 300 | /// <param name="name">name of sender (object or avatar)</param> |
248 | /// <param name="id">key of sender (object or avatar)</param> | 301 | /// <param name="id">key of sender (object or avatar)</param> |
249 | /// <param name="msg">msg to sent</param> | 302 | /// <param name="msg">msg to sent</param> |
250 | public void DeliverMessage(ChatTypeEnum type, int channel, string name, UUID id, string msg, Vector3 position) | 303 | public void DeliverMessage(ChatTypeEnum type, int channel, |
304 | string name, UUID id, string msg, Vector3 position) | ||
251 | { | 305 | { |
252 | // m_log.DebugFormat("[WorldComm] got[2] type {0}, channel {1}, name {2}, id {3}, msg {4}", | 306 | // m_log.DebugFormat("[WorldComm] got[2] type {0}, channel {1}, name {2}, id {3}, msg {4}", |
253 | // type, channel, name, id, msg); | 307 | // type, channel, name, id, msg); |
@@ -255,17 +309,21 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm | |||
255 | // Determine which listen event filters match the given set of arguments, this results | 309 | // Determine which listen event filters match the given set of arguments, this results |
256 | // in a limited set of listeners, each belonging a host. If the host is in range, add them | 310 | // in a limited set of listeners, each belonging a host. If the host is in range, add them |
257 | // to the pending queue. | 311 | // to the pending queue. |
258 | foreach (ListenerInfo li in m_listenerManager.GetListeners(UUID.Zero, channel, name, id, msg)) | 312 | foreach (ListenerInfo li |
313 | in m_listenerManager.GetListeners(UUID.Zero, channel, | ||
314 | name, id, msg)) | ||
259 | { | 315 | { |
260 | // Dont process if this message is from yourself! | 316 | // Dont process if this message is from yourself! |
261 | if (li.GetHostID().Equals(id)) | 317 | if (li.GetHostID().Equals(id)) |
262 | continue; | 318 | continue; |
263 | 319 | ||
264 | SceneObjectPart sPart = m_scene.GetSceneObjectPart(li.GetHostID()); | 320 | SceneObjectPart sPart = m_scene.GetSceneObjectPart( |
321 | li.GetHostID()); | ||
265 | if (sPart == null) | 322 | if (sPart == null) |
266 | continue; | 323 | continue; |
267 | 324 | ||
268 | double dis = Util.GetDistanceTo(sPart.AbsolutePosition, position); | 325 | double dis = Util.GetDistanceTo(sPart.AbsolutePosition, |
326 | position); | ||
269 | switch (type) | 327 | switch (type) |
270 | { | 328 | { |
271 | case ChatTypeEnum.Whisper: | 329 | case ChatTypeEnum.Whisper: |
@@ -308,14 +366,16 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm | |||
308 | /// <param name='msg'> | 366 | /// <param name='msg'> |
309 | /// Message. | 367 | /// Message. |
310 | /// </param> | 368 | /// </param> |
311 | public void DeliverMessageTo(UUID target, int channel, Vector3 pos, string name, UUID id, string msg) | 369 | public void DeliverMessageTo(UUID target, int channel, Vector3 pos, |
370 | string name, UUID id, string msg) | ||
312 | { | 371 | { |
313 | // Is id an avatar? | 372 | // Is id an avatar? |
314 | ScenePresence sp = m_scene.GetScenePresence(target); | 373 | ScenePresence sp = m_scene.GetScenePresence(target); |
315 | 374 | ||
316 | if (sp != null) | 375 | if (sp != null) |
317 | { | 376 | { |
318 | // ignore if a child agent this is restricted to inside one region | 377 | // ignore if a child agent this is restricted to inside one |
378 | // region | ||
319 | if (sp.IsChildAgent) | 379 | if (sp.IsChildAgent) |
320 | return; | 380 | return; |
321 | 381 | ||
@@ -324,8 +384,9 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm | |||
324 | // non zero channel messages only go to the attachments | 384 | // non zero channel messages only go to the attachments |
325 | if (channel == 0) | 385 | if (channel == 0) |
326 | { | 386 | { |
327 | m_scene.SimChatToAgent(target, Utils.StringToBytes(msg), pos, name, id, false); | 387 | m_scene.SimChatToAgent(target, Utils.StringToBytes(msg), |
328 | } | 388 | pos, name, id, false); |
389 | } | ||
329 | else | 390 | else |
330 | { | 391 | { |
331 | List<SceneObjectGroup> attachments = sp.GetAttachments(); | 392 | List<SceneObjectGroup> attachments = sp.GetAttachments(); |
@@ -341,13 +402,18 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm | |||
341 | } | 402 | } |
342 | 403 | ||
343 | // Need to check each attachment | 404 | // Need to check each attachment |
344 | foreach (ListenerInfo li in m_listenerManager.GetListeners(UUID.Zero, channel, name, id, msg)) | 405 | foreach (ListenerInfo li |
406 | in m_listenerManager.GetListeners(UUID.Zero, | ||
407 | channel, name, id, msg)) | ||
345 | { | 408 | { |
346 | if (li.GetHostID().Equals(id)) | 409 | if (li.GetHostID().Equals(id)) |
347 | continue; | 410 | continue; |
348 | 411 | ||
349 | if (m_scene.GetSceneObjectPart(li.GetHostID()) == null) | 412 | if (m_scene.GetSceneObjectPart( |
413 | li.GetHostID()) == null) | ||
414 | { | ||
350 | continue; | 415 | continue; |
416 | } | ||
351 | 417 | ||
352 | if (targets.Contains(li.GetHostID())) | 418 | if (targets.Contains(li.GetHostID())) |
353 | QueueMessage(new ListenerInfo(li, name, id, msg)); | 419 | QueueMessage(new ListenerInfo(li, name, id, msg)); |
@@ -358,17 +424,20 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm | |||
358 | } | 424 | } |
359 | 425 | ||
360 | // No avatar found so look for an object | 426 | // No avatar found so look for an object |
361 | foreach (ListenerInfo li in m_listenerManager.GetListeners(UUID.Zero, channel, name, id, msg)) | 427 | foreach (ListenerInfo li |
428 | in m_listenerManager.GetListeners(UUID.Zero, channel, | ||
429 | name, id, msg)) | ||
362 | { | 430 | { |
363 | // Dont process if this message is from yourself! | 431 | // Dont process if this message is from yourself! |
364 | if (li.GetHostID().Equals(id)) | 432 | if (li.GetHostID().Equals(id)) |
365 | continue; | 433 | continue; |
366 | 434 | ||
367 | SceneObjectPart sPart = m_scene.GetSceneObjectPart(li.GetHostID()); | 435 | SceneObjectPart sPart = m_scene.GetSceneObjectPart( |
436 | li.GetHostID()); | ||
368 | if (sPart == null) | 437 | if (sPart == null) |
369 | continue; | 438 | continue; |
370 | 439 | ||
371 | if ( li.GetHostID().Equals(target)) | 440 | if (li.GetHostID().Equals(target)) |
372 | { | 441 | { |
373 | QueueMessage(new ListenerInfo(li, name, id, msg)); | 442 | QueueMessage(new ListenerInfo(li, name, id, msg)); |
374 | break; | 443 | break; |
@@ -422,9 +491,15 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm | |||
422 | private void DeliverClientMessage(Object sender, OSChatMessage e) | 491 | private void DeliverClientMessage(Object sender, OSChatMessage e) |
423 | { | 492 | { |
424 | if (null != e.Sender) | 493 | if (null != e.Sender) |
425 | DeliverMessage(e.Type, e.Channel, e.Sender.Name, e.Sender.AgentId, e.Message, e.Position); | 494 | { |
495 | DeliverMessage(e.Type, e.Channel, e.Sender.Name, | ||
496 | e.Sender.AgentId, e.Message, e.Position); | ||
497 | } | ||
426 | else | 498 | else |
427 | DeliverMessage(e.Type, e.Channel, e.From, UUID.Zero, e.Message, e.Position); | 499 | { |
500 | DeliverMessage(e.Type, e.Channel, e.From, UUID.Zero, | ||
501 | e.Message, e.Position); | ||
502 | } | ||
428 | } | 503 | } |
429 | 504 | ||
430 | public Object[] GetSerializationData(UUID itemID) | 505 | public Object[] GetSerializationData(UUID itemID) |
@@ -441,7 +516,8 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm | |||
441 | 516 | ||
442 | public class ListenerManager | 517 | public class ListenerManager |
443 | { | 518 | { |
444 | private Dictionary<int, List<ListenerInfo>> m_listeners = new Dictionary<int, List<ListenerInfo>>(); | 519 | private Dictionary<int, List<ListenerInfo>> m_listeners = |
520 | new Dictionary<int, List<ListenerInfo>>(); | ||
445 | private int m_maxlisteners; | 521 | private int m_maxlisteners; |
446 | private int m_maxhandles; | 522 | private int m_maxhandles; |
447 | private int m_curlisteners; | 523 | private int m_curlisteners; |
@@ -465,15 +541,25 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm | |||
465 | m_curlisteners = 0; | 541 | m_curlisteners = 0; |
466 | } | 542 | } |
467 | 543 | ||
468 | public int AddListener(uint localID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg) | 544 | public int AddListener(uint localID, UUID itemID, UUID hostID, |
545 | int channel, string name, UUID id, string msg) | ||
546 | { | ||
547 | return AddListener(localID, itemID, hostID, channel, name, id, | ||
548 | msg, 0); | ||
549 | } | ||
550 | |||
551 | public int AddListener(uint localID, UUID itemID, UUID hostID, | ||
552 | int channel, string name, UUID id, string msg, | ||
553 | int regexBitfield) | ||
469 | { | 554 | { |
470 | // do we already have a match on this particular filter event? | 555 | // do we already have a match on this particular filter event? |
471 | List<ListenerInfo> coll = GetListeners(itemID, channel, name, id, msg); | 556 | List<ListenerInfo> coll = GetListeners(itemID, channel, name, id, |
557 | msg); | ||
472 | 558 | ||
473 | if (coll.Count > 0) | 559 | if (coll.Count > 0) |
474 | { | 560 | { |
475 | // special case, called with same filter settings, return same handle | 561 | // special case, called with same filter settings, return same |
476 | // (2008-05-02, tested on 1.21.1 server, still holds) | 562 | // handle (2008-05-02, tested on 1.21.1 server, still holds) |
477 | return coll[0].GetHandle(); | 563 | return coll[0].GetHandle(); |
478 | } | 564 | } |
479 | 565 | ||
@@ -485,16 +571,19 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm | |||
485 | 571 | ||
486 | if (newHandle > 0) | 572 | if (newHandle > 0) |
487 | { | 573 | { |
488 | ListenerInfo li = new ListenerInfo(newHandle, localID, itemID, hostID, channel, name, id, msg); | 574 | ListenerInfo li = new ListenerInfo(newHandle, localID, |
575 | itemID, hostID, channel, name, id, msg, | ||
576 | regexBitfield); | ||
489 | 577 | ||
490 | List<ListenerInfo> listeners; | 578 | List<ListenerInfo> listeners; |
491 | if (!m_listeners.TryGetValue(channel,out listeners)) | 579 | if (!m_listeners.TryGetValue( |
492 | { | 580 | channel, out listeners)) |
493 | listeners = new List<ListenerInfo>(); | 581 | { |
494 | m_listeners.Add(channel, listeners); | 582 | listeners = new List<ListenerInfo>(); |
495 | } | 583 | m_listeners.Add(channel, listeners); |
496 | listeners.Add(li); | 584 | } |
497 | m_curlisteners++; | 585 | listeners.Add(li); |
586 | m_curlisteners++; | ||
498 | 587 | ||
499 | return newHandle; | 588 | return newHandle; |
500 | } | 589 | } |
@@ -507,11 +596,13 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm | |||
507 | { | 596 | { |
508 | lock (m_listeners) | 597 | lock (m_listeners) |
509 | { | 598 | { |
510 | foreach (KeyValuePair<int,List<ListenerInfo>> lis in m_listeners) | 599 | foreach (KeyValuePair<int, List<ListenerInfo>> lis |
600 | in m_listeners) | ||
511 | { | 601 | { |
512 | foreach (ListenerInfo li in lis.Value) | 602 | foreach (ListenerInfo li in lis.Value) |
513 | { | 603 | { |
514 | if (li.GetItemID().Equals(itemID) && li.GetHandle().Equals(handle)) | 604 | if (li.GetItemID().Equals(itemID) && |
605 | li.GetHandle().Equals(handle)) | ||
515 | { | 606 | { |
516 | lis.Value.Remove(li); | 607 | lis.Value.Remove(li); |
517 | if (lis.Value.Count == 0) | 608 | if (lis.Value.Count == 0) |
@@ -534,13 +625,15 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm | |||
534 | 625 | ||
535 | lock (m_listeners) | 626 | lock (m_listeners) |
536 | { | 627 | { |
537 | foreach (KeyValuePair<int,List<ListenerInfo>> lis in m_listeners) | 628 | foreach (KeyValuePair<int, List<ListenerInfo>> lis |
629 | in m_listeners) | ||
538 | { | 630 | { |
539 | foreach (ListenerInfo li in lis.Value) | 631 | foreach (ListenerInfo li in lis.Value) |
540 | { | 632 | { |
541 | if (li.GetItemID().Equals(itemID)) | 633 | if (li.GetItemID().Equals(itemID)) |
542 | { | 634 | { |
543 | // store them first, else the enumerated bails on us | 635 | // store them first, else the enumerated bails on |
636 | // us | ||
544 | removedListeners.Add(li); | 637 | removedListeners.Add(li); |
545 | } | 638 | } |
546 | } | 639 | } |
@@ -567,11 +660,13 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm | |||
567 | { | 660 | { |
568 | lock (m_listeners) | 661 | lock (m_listeners) |
569 | { | 662 | { |
570 | foreach (KeyValuePair<int,List<ListenerInfo>> lis in m_listeners) | 663 | foreach (KeyValuePair<int, List<ListenerInfo>> lis |
664 | in m_listeners) | ||
571 | { | 665 | { |
572 | foreach (ListenerInfo li in lis.Value) | 666 | foreach (ListenerInfo li in lis.Value) |
573 | { | 667 | { |
574 | if (li.GetItemID().Equals(itemID) && li.GetHandle() == handle) | 668 | if (li.GetItemID().Equals(itemID) && |
669 | li.GetHandle() == handle) | ||
575 | { | 670 | { |
576 | li.Activate(); | 671 | li.Activate(); |
577 | // only one, bail out | 672 | // only one, bail out |
@@ -586,11 +681,13 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm | |||
586 | { | 681 | { |
587 | lock (m_listeners) | 682 | lock (m_listeners) |
588 | { | 683 | { |
589 | foreach (KeyValuePair<int,List<ListenerInfo>> lis in m_listeners) | 684 | foreach (KeyValuePair<int, List<ListenerInfo>> lis |
685 | in m_listeners) | ||
590 | { | 686 | { |
591 | foreach (ListenerInfo li in lis.Value) | 687 | foreach (ListenerInfo li in lis.Value) |
592 | { | 688 | { |
593 | if (li.GetItemID().Equals(itemID) && li.GetHandle() == handle) | 689 | if (li.GetItemID().Equals(itemID) && |
690 | li.GetHandle() == handle) | ||
594 | { | 691 | { |
595 | li.Deactivate(); | 692 | li.Deactivate(); |
596 | // only one, bail out | 693 | // only one, bail out |
@@ -601,19 +698,24 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm | |||
601 | } | 698 | } |
602 | } | 699 | } |
603 | 700 | ||
604 | // non-locked access, since its always called in the context of the lock | 701 | /// <summary> |
702 | /// non-locked access, since its always called in the context of the | ||
703 | /// lock | ||
704 | /// </summary> | ||
705 | /// <param name="itemID"></param> | ||
706 | /// <returns></returns> | ||
605 | private int GetNewHandle(UUID itemID) | 707 | private int GetNewHandle(UUID itemID) |
606 | { | 708 | { |
607 | List<int> handles = new List<int>(); | 709 | List<int> handles = new List<int>(); |
608 | 710 | ||
609 | // build a list of used keys for this specific itemID... | 711 | // build a list of used keys for this specific itemID... |
610 | foreach (KeyValuePair<int,List<ListenerInfo>> lis in m_listeners) | 712 | foreach (KeyValuePair<int, List<ListenerInfo>> lis in m_listeners) |
611 | { | 713 | { |
612 | foreach (ListenerInfo li in lis.Value) | 714 | foreach (ListenerInfo li in lis.Value) |
613 | { | 715 | { |
614 | if (li.GetItemID().Equals(itemID)) | 716 | if (li.GetItemID().Equals(itemID)) |
615 | handles.Add(li.GetHandle()); | 717 | handles.Add(li.GetHandle()); |
616 | } | 718 | } |
617 | } | 719 | } |
618 | 720 | ||
619 | // Note: 0 is NOT a valid handle for llListen() to return | 721 | // Note: 0 is NOT a valid handle for llListen() to return |
@@ -626,17 +728,46 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm | |||
626 | return -1; | 728 | return -1; |
627 | } | 729 | } |
628 | 730 | ||
629 | // Theres probably a more clever and efficient way to | 731 | /// These are duplicated from ScriptBaseClass |
630 | // do this, maybe with regex. | 732 | /// http://opensimulator.org/mantis/view.php?id=6106#c21945 |
631 | // PM2008: Ha, one could even be smart and define a specialized Enumerator. | 733 | #region Constants for the bitfield parameter of osListenRegex |
632 | public List<ListenerInfo> GetListeners(UUID itemID, int channel, string name, UUID id, string msg) | 734 | |
735 | /// <summary> | ||
736 | /// process name parameter as regex | ||
737 | /// </summary> | ||
738 | public const int OS_LISTEN_REGEX_NAME = 0x1; | ||
739 | |||
740 | /// <summary> | ||
741 | /// process message parameter as regex | ||
742 | /// </summary> | ||
743 | public const int OS_LISTEN_REGEX_MESSAGE = 0x2; | ||
744 | |||
745 | #endregion | ||
746 | |||
747 | /// <summary> | ||
748 | /// Get listeners matching the input parameters. | ||
749 | /// </summary> | ||
750 | /// <remarks> | ||
751 | /// Theres probably a more clever and efficient way to do this, maybe | ||
752 | /// with regex. | ||
753 | /// PM2008: Ha, one could even be smart and define a specialized | ||
754 | /// Enumerator. | ||
755 | /// </remarks> | ||
756 | /// <param name="itemID"></param> | ||
757 | /// <param name="channel"></param> | ||
758 | /// <param name="name"></param> | ||
759 | /// <param name="id"></param> | ||
760 | /// <param name="msg"></param> | ||
761 | /// <returns></returns> | ||
762 | public List<ListenerInfo> GetListeners(UUID itemID, int channel, | ||
763 | string name, UUID id, string msg) | ||
633 | { | 764 | { |
634 | List<ListenerInfo> collection = new List<ListenerInfo>(); | 765 | List<ListenerInfo> collection = new List<ListenerInfo>(); |
635 | 766 | ||
636 | lock (m_listeners) | 767 | lock (m_listeners) |
637 | { | 768 | { |
638 | List<ListenerInfo> listeners; | 769 | List<ListenerInfo> listeners; |
639 | if (!m_listeners.TryGetValue(channel,out listeners)) | 770 | if (!m_listeners.TryGetValue(channel, out listeners)) |
640 | { | 771 | { |
641 | return collection; | 772 | return collection; |
642 | } | 773 | } |
@@ -647,11 +778,15 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm | |||
647 | { | 778 | { |
648 | continue; | 779 | continue; |
649 | } | 780 | } |
650 | if (!itemID.Equals(UUID.Zero) && !li.GetItemID().Equals(itemID)) | 781 | if (!itemID.Equals(UUID.Zero) && |
782 | !li.GetItemID().Equals(itemID)) | ||
651 | { | 783 | { |
652 | continue; | 784 | continue; |
653 | } | 785 | } |
654 | if (li.GetName().Length > 0 && !li.GetName().Equals(name)) | 786 | if (li.GetName().Length > 0 && ( |
787 | ((li.RegexBitfield & OS_LISTEN_REGEX_NAME) != OS_LISTEN_REGEX_NAME && !li.GetName().Equals(name)) || | ||
788 | ((li.RegexBitfield & OS_LISTEN_REGEX_NAME) == OS_LISTEN_REGEX_NAME && !Regex.IsMatch(name, li.GetName())) | ||
789 | )) | ||
655 | { | 790 | { |
656 | continue; | 791 | continue; |
657 | } | 792 | } |
@@ -659,7 +794,10 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm | |||
659 | { | 794 | { |
660 | continue; | 795 | continue; |
661 | } | 796 | } |
662 | if (li.GetMessage().Length > 0 && !li.GetMessage().Equals(msg)) | 797 | if (li.GetMessage().Length > 0 && ( |
798 | ((li.RegexBitfield & OS_LISTEN_REGEX_MESSAGE) != OS_LISTEN_REGEX_MESSAGE && !li.GetMessage().Equals(msg)) || | ||
799 | ((li.RegexBitfield & OS_LISTEN_REGEX_MESSAGE) == OS_LISTEN_REGEX_MESSAGE && !Regex.IsMatch(msg, li.GetMessage())) | ||
800 | )) | ||
663 | { | 801 | { |
664 | continue; | 802 | continue; |
665 | } | 803 | } |
@@ -692,10 +830,13 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm | |||
692 | { | 830 | { |
693 | int idx = 0; | 831 | int idx = 0; |
694 | Object[] item = new Object[6]; | 832 | Object[] item = new Object[6]; |
833 | int dataItemLength = 6; | ||
695 | 834 | ||
696 | while (idx < data.Length) | 835 | while (idx < data.Length) |
697 | { | 836 | { |
698 | Array.Copy(data, idx, item, 0, 6); | 837 | dataItemLength = (idx + 7 == data.Length || (idx + 7 < data.Length && data[idx + 7] is bool)) ? 7 : 6; |
838 | item = new Object[dataItemLength]; | ||
839 | Array.Copy(data, idx, item, 0, dataItemLength); | ||
699 | 840 | ||
700 | ListenerInfo info = | 841 | ListenerInfo info = |
701 | ListenerInfo.FromData(localID, itemID, hostID, item); | 842 | ListenerInfo.FromData(localID, itemID, hostID, item); |
@@ -703,39 +844,98 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm | |||
703 | lock (m_listeners) | 844 | lock (m_listeners) |
704 | { | 845 | { |
705 | if (!m_listeners.ContainsKey((int)item[2])) | 846 | if (!m_listeners.ContainsKey((int)item[2])) |
706 | m_listeners.Add((int)item[2], new List<ListenerInfo>()); | 847 | { |
848 | m_listeners.Add((int)item[2], | ||
849 | new List<ListenerInfo>()); | ||
850 | } | ||
707 | m_listeners[(int)item[2]].Add(info); | 851 | m_listeners[(int)item[2]].Add(info); |
708 | } | 852 | } |
709 | 853 | ||
710 | idx+=6; | 854 | idx += dataItemLength; |
711 | } | 855 | } |
712 | } | 856 | } |
713 | } | 857 | } |
714 | 858 | ||
715 | public class ListenerInfo: IWorldCommListenerInfo | 859 | public class ListenerInfo : IWorldCommListenerInfo |
716 | { | 860 | { |
717 | private bool m_active; // Listener is active or not | 861 | /// <summary> |
718 | private int m_handle; // Assigned handle of this listener | 862 | /// Listener is active or not |
719 | private uint m_localID; // Local ID from script engine | 863 | /// </summary> |
720 | private UUID m_itemID; // ID of the host script engine | 864 | private bool m_active; |
721 | private UUID m_hostID; // ID of the host/scene part | ||
722 | private int m_channel; // Channel | ||
723 | private UUID m_id; // ID to filter messages from | ||
724 | private string m_name; // Object name to filter messages from | ||
725 | private string m_message; // The message | ||
726 | 865 | ||
727 | public ListenerInfo(int handle, uint localID, UUID ItemID, UUID hostID, int channel, string name, UUID id, string message) | 866 | /// <summary> |
867 | /// Assigned handle of this listener | ||
868 | /// </summary> | ||
869 | private int m_handle; | ||
870 | |||
871 | /// <summary> | ||
872 | /// Local ID from script engine | ||
873 | /// </summary> | ||
874 | private uint m_localID; | ||
875 | |||
876 | /// <summary> | ||
877 | /// ID of the host script engine | ||
878 | /// </summary> | ||
879 | private UUID m_itemID; | ||
880 | |||
881 | /// <summary> | ||
882 | /// ID of the host/scene part | ||
883 | /// </summary> | ||
884 | private UUID m_hostID; | ||
885 | |||
886 | /// <summary> | ||
887 | /// Channel | ||
888 | /// </summary> | ||
889 | private int m_channel; | ||
890 | |||
891 | /// <summary> | ||
892 | /// ID to filter messages from | ||
893 | /// </summary> | ||
894 | private UUID m_id; | ||
895 | |||
896 | /// <summary> | ||
897 | /// Object name to filter messages from | ||
898 | /// </summary> | ||
899 | private string m_name; | ||
900 | |||
901 | /// <summary> | ||
902 | /// The message | ||
903 | /// </summary> | ||
904 | private string m_message; | ||
905 | |||
906 | public ListenerInfo(int handle, uint localID, UUID ItemID, | ||
907 | UUID hostID, int channel, string name, UUID id, | ||
908 | string message) | ||
909 | { | ||
910 | Initialise(handle, localID, ItemID, hostID, channel, name, id, | ||
911 | message, 0); | ||
912 | } | ||
913 | |||
914 | public ListenerInfo(int handle, uint localID, UUID ItemID, | ||
915 | UUID hostID, int channel, string name, UUID id, | ||
916 | string message, int regexBitfield) | ||
728 | { | 917 | { |
729 | Initialise(handle, localID, ItemID, hostID, channel, name, id, message); | 918 | Initialise(handle, localID, ItemID, hostID, channel, name, id, |
919 | message, regexBitfield); | ||
730 | } | 920 | } |
731 | 921 | ||
732 | public ListenerInfo(ListenerInfo li, string name, UUID id, string message) | 922 | public ListenerInfo(ListenerInfo li, string name, UUID id, |
923 | string message) | ||
733 | { | 924 | { |
734 | Initialise(li.m_handle, li.m_localID, li.m_itemID, li.m_hostID, li.m_channel, name, id, message); | 925 | Initialise(li.m_handle, li.m_localID, li.m_itemID, li.m_hostID, |
926 | li.m_channel, name, id, message, 0); | ||
735 | } | 927 | } |
736 | 928 | ||
737 | private void Initialise(int handle, uint localID, UUID ItemID, UUID hostID, int channel, string name, | 929 | public ListenerInfo(ListenerInfo li, string name, UUID id, |
738 | UUID id, string message) | 930 | string message, int regexBitfield) |
931 | { | ||
932 | Initialise(li.m_handle, li.m_localID, li.m_itemID, li.m_hostID, | ||
933 | li.m_channel, name, id, message, regexBitfield); | ||
934 | } | ||
935 | |||
936 | private void Initialise(int handle, uint localID, UUID ItemID, | ||
937 | UUID hostID, int channel, string name, UUID id, | ||
938 | string message, int regexBitfield) | ||
739 | { | 939 | { |
740 | m_active = true; | 940 | m_active = true; |
741 | m_handle = handle; | 941 | m_handle = handle; |
@@ -746,11 +946,12 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm | |||
746 | m_name = name; | 946 | m_name = name; |
747 | m_id = id; | 947 | m_id = id; |
748 | m_message = message; | 948 | m_message = message; |
949 | RegexBitfield = regexBitfield; | ||
749 | } | 950 | } |
750 | 951 | ||
751 | public Object[] GetSerializationData() | 952 | public Object[] GetSerializationData() |
752 | { | 953 | { |
753 | Object[] data = new Object[6]; | 954 | Object[] data = new Object[7]; |
754 | 955 | ||
755 | data[0] = m_active; | 956 | data[0] = m_active; |
756 | data[1] = m_handle; | 957 | data[1] = m_handle; |
@@ -758,16 +959,22 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm | |||
758 | data[3] = m_name; | 959 | data[3] = m_name; |
759 | data[4] = m_id; | 960 | data[4] = m_id; |
760 | data[5] = m_message; | 961 | data[5] = m_message; |
962 | data[6] = RegexBitfield; | ||
761 | 963 | ||
762 | return data; | 964 | return data; |
763 | } | 965 | } |
764 | 966 | ||
765 | public static ListenerInfo FromData(uint localID, UUID ItemID, UUID hostID, Object[] data) | 967 | public static ListenerInfo FromData(uint localID, UUID ItemID, |
968 | UUID hostID, Object[] data) | ||
766 | { | 969 | { |
767 | ListenerInfo linfo = new ListenerInfo((int)data[1], localID, | 970 | ListenerInfo linfo = new ListenerInfo((int)data[1], localID, |
768 | ItemID, hostID, (int)data[2], (string)data[3], | 971 | ItemID, hostID, (int)data[2], (string)data[3], |
769 | (UUID)data[4], (string)data[5]); | 972 | (UUID)data[4], (string)data[5]); |
770 | linfo.m_active=(bool)data[0]; | 973 | linfo.m_active = (bool)data[0]; |
974 | if (data.Length >= 7) | ||
975 | { | ||
976 | linfo.RegexBitfield = (int)data[6]; | ||
977 | } | ||
771 | 978 | ||
772 | return linfo; | 979 | return linfo; |
773 | } | 980 | } |
@@ -826,5 +1033,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm | |||
826 | { | 1033 | { |
827 | return m_id; | 1034 | return m_id; |
828 | } | 1035 | } |
1036 | |||
1037 | public int RegexBitfield { get; private set; } | ||
829 | } | 1038 | } |
830 | } | 1039 | } |