OpenSim
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros
WorldCommModule.cs
Go to the documentation of this file.
1 /*
2  * Copyright (c) Contributors, http://opensimulator.org/
3  * See CONTRIBUTORS.TXT for a full list of copyright holders.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * * Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * * Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * * Neither the name of the OpenSimulator Project nor the
13  * names of its contributors may be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 using System;
29 using System.Collections;
30 using System.Collections.Generic;
31 using System.Text.RegularExpressions;
32 
33 using Nini.Config;
34 using Mono.Addins;
35 
36 using OpenMetaverse;
37 
38 using OpenSim.Framework;
39 using OpenSim.Region.Framework.Interfaces;
40 using OpenSim.Region.Framework.Scenes;
41 
42 // using log4net;
43 // using System.Reflection;
44 
45 
46 /*****************************************************
47  *
48  * WorldCommModule
49  *
50  *
51  * Holding place for world comms - basically llListen
52  * function implementation.
53  *
54  * lLListen(integer channel, string name, key id, string msg)
55  * The name, id, and msg arguments specify the filtering
56  * criteria. You can pass the empty string
57  * (or NULL_KEY for id) for these to set a completely
58  * open filter; this causes the listen() event handler to be
59  * invoked for all chat on the channel. To listen only
60  * for chat spoken by a specific object or avatar,
61  * specify the name and/or id arguments. To listen
62  * only for a specific command, specify the
63  * (case-sensitive) msg argument. If msg is not empty,
64  * listener will only hear strings which are exactly equal
65  * to msg. You can also use all the arguments to establish
66  * the most restrictive filtering criteria.
67  *
68  * It might be useful for each listener to maintain a message
69  * digest, with a list of recent messages by UUID. This can
70  * be used to prevent in-world repeater loops. However, the
71  * linden functions do not have this capability, so for now
72  * thats the way it works.
73  * Instead it blocks messages originating from the same prim.
74  * (not Object!)
75  *
76  * For LSL compliance, note the following:
77  * (Tested again 1.21.1 on May 2, 2008)
78  * 1. 'id' has to be parsed into a UUID. None-UUID keys are
79  * to be replaced by the ZeroID key. (Well, TryParse does
80  * that for us.
81  * 2. Setting up an listen event from the same script, with the
82  * same filter settings (including step 1), returns the same
83  * handle as the original filter.
84  * 3. (TODO) handles should be script-local. Starting from 1.
85  * Might be actually easier to map the global handle into
86  * script-local handle in the ScriptEngine. Not sure if its
87  * worth the effort tho.
88  *
89  * **************************************************/
90 
91 namespace OpenSim.Region.CoreModules.Scripting.WorldComm
92 {
93  [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "WorldCommModule")]
95  {
96  // private static readonly ILog m_log =
97  // LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
98 
99  private const int DEBUG_CHANNEL = 2147483647;
100 
101  private ListenerManager m_listenerManager;
102  private Queue m_pending;
103  private Queue m_pendingQ;
104  private Scene m_scene;
105  private int m_whisperdistance = 10;
106  private int m_saydistance = 20;
107  private int m_shoutdistance = 100;
108 
109  #region INonSharedRegionModule Members
110 
111  public void Initialise(IConfigSource config)
112  {
113  // wrap this in a try block so that defaults will work if
114  // the config file doesn't specify otherwise.
115  int maxlisteners = 1000;
116  int maxhandles = 64;
117  try
118  {
119  m_whisperdistance = config.Configs["Chat"].GetInt(
120  "whisper_distance", m_whisperdistance);
121  m_saydistance = config.Configs["Chat"].GetInt(
122  "say_distance", m_saydistance);
123  m_shoutdistance = config.Configs["Chat"].GetInt(
124  "shout_distance", m_shoutdistance);
125  maxlisteners = config.Configs["LL-Functions"].GetInt(
126  "max_listens_per_region", maxlisteners);
127  maxhandles = config.Configs["LL-Functions"].GetInt(
128  "max_listens_per_script", maxhandles);
129  }
130  catch (Exception)
131  {
132  }
133  if (maxlisteners < 1) maxlisteners = int.MaxValue;
134  if (maxhandles < 1) maxhandles = int.MaxValue;
135  m_listenerManager = new ListenerManager(maxlisteners, maxhandles);
136  m_pendingQ = new Queue();
137  m_pending = Queue.Synchronized(m_pendingQ);
138  }
139 
140  public void PostInitialise()
141  {
142  }
143 
144  public void AddRegion(Scene scene)
145  {
146  m_scene = scene;
147  m_scene.RegisterModuleInterface<IWorldComm>(this);
148  m_scene.EventManager.OnChatFromClient += DeliverClientMessage;
149  m_scene.EventManager.OnChatBroadcast += DeliverClientMessage;
150  }
151 
152  public void RegionLoaded(Scene scene) { }
153 
154  public void RemoveRegion(Scene scene)
155  {
156  if (scene != m_scene)
157  return;
158 
159  m_scene.UnregisterModuleInterface<IWorldComm>(this);
160  m_scene.EventManager.OnChatBroadcast -= DeliverClientMessage;
161  m_scene.EventManager.OnChatBroadcast -= DeliverClientMessage;
162  }
163 
164  public void Close()
165  {
166  }
167 
168  public string Name
169  {
170  get { return "WorldCommModule"; }
171  }
172 
173  public Type ReplaceableInterface { get { return null; } }
174 
175  #endregion
176 
177  #region IWorldComm Members
178 
179  public int ListenerCount
180  {
181  get
182  {
183  return m_listenerManager.ListenerCount;
184  }
185  }
186 
203  public int Listen(uint localID, UUID itemID, UUID hostID, int channel,
204  string name, UUID id, string msg)
205  {
206  return m_listenerManager.AddListener(localID, itemID, hostID,
207  channel, name, id, msg);
208  }
209 
229  public int Listen(uint localID, UUID itemID, UUID hostID, int channel,
230  string name, UUID id, string msg, int regexBitfield)
231  {
232  return m_listenerManager.AddListener(localID, itemID, hostID,
233  channel, name, id, msg, regexBitfield);
234  }
235 
243  public void ListenControl(UUID itemID, int handle, int active)
244  {
245  if (active == 1)
246  m_listenerManager.Activate(itemID, handle);
247  else if (active == 0)
248  m_listenerManager.Dectivate(itemID, handle);
249  }
250 
256  public void ListenRemove(UUID itemID, int handle)
257  {
258  m_listenerManager.Remove(itemID, handle);
259  }
260 
266  public void DeleteListener(UUID itemID)
267  {
268  m_listenerManager.DeleteListener(itemID);
269  }
270 
271 
272  protected static Vector3 CenterOfRegion = new Vector3(128, 128, 20);
273 
274  public void DeliverMessage(ChatTypeEnum type, int channel, string name, UUID id, string msg)
275  {
276  Vector3 position;
277  SceneObjectPart source;
278  ScenePresence avatar;
279 
280  if ((source = m_scene.GetSceneObjectPart(id)) != null)
281  position = source.AbsolutePosition;
282  else if ((avatar = m_scene.GetScenePresence(id)) != null)
283  position = avatar.AbsolutePosition;
284  else if (ChatTypeEnum.Region == type)
285  position = CenterOfRegion;
286  else
287  return;
288 
289  DeliverMessage(type, channel, name, id, msg, position);
290  }
291 
305  public void DeliverMessage(ChatTypeEnum type, int channel,
306  string name, UUID id, string msg, Vector3 position)
307  {
308  // m_log.DebugFormat("[WorldComm] got[2] type {0}, channel {1}, name {2}, id {3}, msg {4}",
309  // type, channel, name, id, msg);
310 
311  // Determine which listen event filters match the given set of arguments, this results
312  // in a limited set of listeners, each belonging a host. If the host is in range, add them
313  // to the pending queue.
314 
315  foreach (ListenerInfo li
316  in m_listenerManager.GetListeners(UUID.Zero, channel,
317  name, id, msg))
318  {
319  // Dont process if this message is from yourself!
320  if (li.GetHostID().Equals(id))
321  continue;
322 
323  SceneObjectPart sPart = m_scene.GetSceneObjectPart(
324  li.GetHostID());
325  if (sPart == null)
326  continue;
327 
328  double dis = Util.GetDistanceTo(sPart.AbsolutePosition,
329  position);
330  switch (type)
331  {
332  case ChatTypeEnum.Whisper:
333  if (dis < m_whisperdistance)
334  QueueMessage(new ListenerInfo(li, name, id, msg));
335  break;
336 
337  case ChatTypeEnum.Say:
338  if (dis < m_saydistance)
339  QueueMessage(new ListenerInfo(li, name, id, msg));
340  break;
341 
342  case ChatTypeEnum.Shout:
343  if (dis < m_shoutdistance)
344  QueueMessage(new ListenerInfo(li, name, id, msg));
345  break;
346 
347  case ChatTypeEnum.Region:
348  QueueMessage(new ListenerInfo(li, name, id, msg));
349  break;
350  }
351  }
352  }
353 
372  public void DeliverMessageTo(UUID target, int channel, Vector3 pos, string name, UUID id, string msg)
373  {
374  if (channel == DEBUG_CHANNEL)
375  return;
376 
377  // Is id an avatar?
378  ScenePresence sp = m_scene.GetScenePresence(target);
379 
380  if (sp != null)
381  {
382  // Send message to avatar
383  if (channel == 0)
384  {
385  // Channel 0 goes to viewer ONLY
386  m_scene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Broadcast, 0, pos, name, id, target, false, false);
387  return;
388  }
389 
390  // for now messages to prims don't cross regions
391  if(sp.IsChildAgent)
392  return;
393 
394  List<SceneObjectGroup> attachments = sp.GetAttachments();
395 
396  if (attachments.Count == 0)
397  return;
398 
399  // Get uuid of attachments
400  List<UUID> targets = new List<UUID>();
401  foreach (SceneObjectGroup sog in attachments)
402  {
403  if (!sog.IsDeleted)
404  targets.Add(sog.UUID);
405  }
406 
407  // Need to check each attachment
408  foreach (ListenerInfo li in m_listenerManager.GetListeners(UUID.Zero, channel, name, id, msg))
409  {
410  if (li.GetHostID().Equals(id))
411  continue;
412 
413  if (m_scene.GetSceneObjectPart(li.GetHostID()) == null)
414  continue;
415 
416  if (targets.Contains(li.GetHostID()))
417  QueueMessage(new ListenerInfo(li, name, id, msg));
418  }
419 
420  return;
421  }
422 
423  SceneObjectPart part = m_scene.GetSceneObjectPart(target);
424  if (part == null) // Not even an object
425  return; // No error
426 
427  foreach (ListenerInfo li in m_listenerManager.GetListeners(UUID.Zero, channel, name, id, msg))
428  {
429  // Dont process if this message is from yourself!
430  if (li.GetHostID().Equals(id))
431  continue;
432 
433  SceneObjectPart sPart = m_scene.GetSceneObjectPart(
434  li.GetHostID());
435  if (sPart == null)
436  continue;
437 
438  if (li.GetHostID().Equals(target))
439  {
440  QueueMessage(new ListenerInfo(li, name, id, msg));
441  break;
442  }
443  }
444  }
445 
446  protected void QueueMessage(ListenerInfo li)
447  {
448  lock (m_pending.SyncRoot)
449  {
450  m_pending.Enqueue(li);
451  }
452  }
453 
458  public bool HasMessages()
459  {
460  return (m_pending.Count > 0);
461  }
462 
468  {
469  ListenerInfo li = null;
470 
471  lock (m_pending.SyncRoot)
472  {
473  li = (ListenerInfo)m_pending.Dequeue();
474  }
475 
476  return li;
477  }
478 
479  #endregion
480 
481  /********************************************************************
482  *
483  * Listener Stuff
484  *
485  * *****************************************************************/
486 
487  private void DeliverClientMessage(Object sender, OSChatMessage e)
488  {
489  if (null != e.Sender)
490  {
491  DeliverMessage(e.Type, e.Channel, e.Sender.Name,
492  e.Sender.AgentId, e.Message, e.Position);
493  }
494  else
495  {
496  DeliverMessage(e.Type, e.Channel, e.From, UUID.Zero,
497  e.Message, e.Position);
498  }
499  }
500 
501  public Object[] GetSerializationData(UUID itemID)
502  {
503  return m_listenerManager.GetSerializationData(itemID);
504  }
505 
506  public void CreateFromData(uint localID, UUID itemID, UUID hostID,
507  Object[] data)
508  {
509  m_listenerManager.AddFromData(localID, itemID, hostID, data);
510  }
511  }
512 
513  public class ListenerManager
514  {
515  private Dictionary<int, List<ListenerInfo>> m_listeners =
516  new Dictionary<int, List<ListenerInfo>>();
517  private int m_maxlisteners;
518  private int m_maxhandles;
519  private int m_curlisteners;
520 
524  public int ListenerCount
525  {
526  get
527  {
528  lock (m_listeners)
529  return m_listeners.Count;
530  }
531  }
532 
533  public ListenerManager(int maxlisteners, int maxhandles)
534  {
535  m_maxlisteners = maxlisteners;
536  m_maxhandles = maxhandles;
537  m_curlisteners = 0;
538  }
539 
540  public int AddListener(uint localID, UUID itemID, UUID hostID,
541  int channel, string name, UUID id, string msg)
542  {
543  return AddListener(localID, itemID, hostID, channel, name, id,
544  msg, 0);
545  }
546 
547  public int AddListener(uint localID, UUID itemID, UUID hostID,
548  int channel, string name, UUID id, string msg,
549  int regexBitfield)
550  {
551  // do we already have a match on this particular filter event?
552  List<ListenerInfo> coll = GetListeners(itemID, channel, name, id,
553  msg);
554 
555  if (coll.Count > 0)
556  {
557  // special case, called with same filter settings, return same
558  // handle (2008-05-02, tested on 1.21.1 server, still holds)
559  return coll[0].GetHandle();
560  }
561 
562  if (m_curlisteners < m_maxlisteners)
563  {
564  lock (m_listeners)
565  {
566  int newHandle = GetNewHandle(itemID);
567 
568  if (newHandle > 0)
569  {
570  ListenerInfo li = new ListenerInfo(newHandle, localID,
571  itemID, hostID, channel, name, id, msg,
572  regexBitfield);
573 
574  List<ListenerInfo> listeners;
575  if (!m_listeners.TryGetValue(
576  channel, out listeners))
577  {
578  listeners = new List<ListenerInfo>();
579  m_listeners.Add(channel, listeners);
580  }
581  listeners.Add(li);
582  m_curlisteners++;
583 
584  return newHandle;
585  }
586  }
587  }
588  return -1;
589  }
590 
591  public void Remove(UUID itemID, int handle)
592  {
593  lock (m_listeners)
594  {
595  foreach (KeyValuePair<int, List<ListenerInfo>> lis
596  in m_listeners)
597  {
598  foreach (ListenerInfo li in lis.Value)
599  {
600  if (li.GetItemID().Equals(itemID) &&
601  li.GetHandle().Equals(handle))
602  {
603  lis.Value.Remove(li);
604  if (lis.Value.Count == 0)
605  {
606  m_listeners.Remove(lis.Key);
607  m_curlisteners--;
608  }
609  // there should be only one, so we bail out early
610  return;
611  }
612  }
613  }
614  }
615  }
616 
617  public void DeleteListener(UUID itemID)
618  {
619  List<int> emptyChannels = new List<int>();
620  List<ListenerInfo> removedListeners = new List<ListenerInfo>();
621 
622  lock (m_listeners)
623  {
624  foreach (KeyValuePair<int, List<ListenerInfo>> lis
625  in m_listeners)
626  {
627  foreach (ListenerInfo li in lis.Value)
628  {
629  if (li.GetItemID().Equals(itemID))
630  {
631  // store them first, else the enumerated bails on
632  // us
633  removedListeners.Add(li);
634  }
635  }
636  foreach (ListenerInfo li in removedListeners)
637  {
638  lis.Value.Remove(li);
639  m_curlisteners--;
640  }
641  removedListeners.Clear();
642  if (lis.Value.Count == 0)
643  {
644  // again, store first, remove later
645  emptyChannels.Add(lis.Key);
646  }
647  }
648  foreach (int channel in emptyChannels)
649  {
650  m_listeners.Remove(channel);
651  }
652  }
653  }
654 
655  public void Activate(UUID itemID, int handle)
656  {
657  lock (m_listeners)
658  {
659  foreach (KeyValuePair<int, List<ListenerInfo>> lis
660  in m_listeners)
661  {
662  foreach (ListenerInfo li in lis.Value)
663  {
664  if (li.GetItemID().Equals(itemID) &&
665  li.GetHandle() == handle)
666  {
667  li.Activate();
668  // only one, bail out
669  return;
670  }
671  }
672  }
673  }
674  }
675 
676  public void Dectivate(UUID itemID, int handle)
677  {
678  lock (m_listeners)
679  {
680  foreach (KeyValuePair<int, List<ListenerInfo>> lis
681  in m_listeners)
682  {
683  foreach (ListenerInfo li in lis.Value)
684  {
685  if (li.GetItemID().Equals(itemID) &&
686  li.GetHandle() == handle)
687  {
688  li.Deactivate();
689  // only one, bail out
690  return;
691  }
692  }
693  }
694  }
695  }
696 
703  private int GetNewHandle(UUID itemID)
704  {
705  List<int> handles = new List<int>();
706 
707  // build a list of used keys for this specific itemID...
708  foreach (KeyValuePair<int, List<ListenerInfo>> lis in m_listeners)
709  {
710  foreach (ListenerInfo li in lis.Value)
711  {
712  if (li.GetItemID().Equals(itemID))
713  handles.Add(li.GetHandle());
714  }
715  }
716 
717  // Note: 0 is NOT a valid handle for llListen() to return
718  for (int i = 1; i <= m_maxhandles; i++)
719  {
720  if (!handles.Contains(i))
721  return i;
722  }
723 
724  return -1;
725  }
726 
729  #region Constants for the bitfield parameter of osListenRegex
730 
734  public const int OS_LISTEN_REGEX_NAME = 0x1;
735 
739  public const int OS_LISTEN_REGEX_MESSAGE = 0x2;
740 
741  #endregion
742 
758  public List<ListenerInfo> GetListeners(UUID itemID, int channel,
759  string name, UUID id, string msg)
760  {
761  List<ListenerInfo> collection = new List<ListenerInfo>();
762 
763  lock (m_listeners)
764  {
765  List<ListenerInfo> listeners;
766  if (!m_listeners.TryGetValue(channel, out listeners))
767  {
768  return collection;
769  }
770 
771  foreach (ListenerInfo li in listeners)
772  {
773  if (!li.IsActive())
774  {
775  continue;
776  }
777  if (!itemID.Equals(UUID.Zero) &&
778  !li.GetItemID().Equals(itemID))
779  {
780  continue;
781  }
782  if (li.GetName().Length > 0 && (
783  ((li.RegexBitfield & OS_LISTEN_REGEX_NAME) != OS_LISTEN_REGEX_NAME && !li.GetName().Equals(name)) ||
784  ((li.RegexBitfield & OS_LISTEN_REGEX_NAME) == OS_LISTEN_REGEX_NAME && !Regex.IsMatch(name, li.GetName()))
785  ))
786  {
787  continue;
788  }
789  if (!li.GetID().Equals(UUID.Zero) && !li.GetID().Equals(id))
790  {
791  continue;
792  }
793  if (li.GetMessage().Length > 0 && (
794  ((li.RegexBitfield & OS_LISTEN_REGEX_MESSAGE) != OS_LISTEN_REGEX_MESSAGE && !li.GetMessage().Equals(msg)) ||
795  ((li.RegexBitfield & OS_LISTEN_REGEX_MESSAGE) == OS_LISTEN_REGEX_MESSAGE && !Regex.IsMatch(msg, li.GetMessage()))
796  ))
797  {
798  continue;
799  }
800  collection.Add(li);
801  }
802  }
803  return collection;
804  }
805 
806  public Object[] GetSerializationData(UUID itemID)
807  {
808  List<Object> data = new List<Object>();
809 
810  lock (m_listeners)
811  {
812  foreach (List<ListenerInfo> list in m_listeners.Values)
813  {
814  foreach (ListenerInfo l in list)
815  {
816  if (l.GetItemID() == itemID)
817  data.AddRange(l.GetSerializationData());
818  }
819  }
820  }
821  return (Object[])data.ToArray();
822  }
823 
824  public void AddFromData(uint localID, UUID itemID, UUID hostID,
825  Object[] data)
826  {
827  int idx = 0;
828  Object[] item = new Object[6];
829  int dataItemLength = 6;
830 
831  while (idx < data.Length)
832  {
833  dataItemLength = (idx + 7 == data.Length || (idx + 7 < data.Length && data[idx + 7] is bool)) ? 7 : 6;
834  item = new Object[dataItemLength];
835  Array.Copy(data, idx, item, 0, dataItemLength);
836 
837  ListenerInfo info =
838  ListenerInfo.FromData(localID, itemID, hostID, item);
839 
840  lock (m_listeners)
841  {
842  if (!m_listeners.ContainsKey((int)item[2]))
843  {
844  m_listeners.Add((int)item[2],
845  new List<ListenerInfo>());
846  }
847  m_listeners[(int)item[2]].Add(info);
848  }
849 
850  idx += dataItemLength;
851  }
852  }
853  }
854 
856  {
860  private bool m_active;
861 
865  private int m_handle;
866 
870  private uint m_localID;
871 
875  private UUID m_itemID;
876 
880  private UUID m_hostID;
881 
885  private int m_channel;
886 
890  private UUID m_id;
891 
895  private string m_name;
896 
900  private string m_message;
901 
902  public ListenerInfo(int handle, uint localID, UUID ItemID,
903  UUID hostID, int channel, string name, UUID id,
904  string message)
905  {
906  Initialise(handle, localID, ItemID, hostID, channel, name, id,
907  message, 0);
908  }
909 
910  public ListenerInfo(int handle, uint localID, UUID ItemID,
911  UUID hostID, int channel, string name, UUID id,
912  string message, int regexBitfield)
913  {
914  Initialise(handle, localID, ItemID, hostID, channel, name, id,
915  message, regexBitfield);
916  }
917 
918  public ListenerInfo(ListenerInfo li, string name, UUID id,
919  string message)
920  {
921  Initialise(li.m_handle, li.m_localID, li.m_itemID, li.m_hostID,
922  li.m_channel, name, id, message, 0);
923  }
924 
925  public ListenerInfo(ListenerInfo li, string name, UUID id,
926  string message, int regexBitfield)
927  {
928  Initialise(li.m_handle, li.m_localID, li.m_itemID, li.m_hostID,
929  li.m_channel, name, id, message, regexBitfield);
930  }
931 
932  private void Initialise(int handle, uint localID, UUID ItemID,
933  UUID hostID, int channel, string name, UUID id,
934  string message, int regexBitfield)
935  {
936  m_active = true;
937  m_handle = handle;
938  m_localID = localID;
939  m_itemID = ItemID;
940  m_hostID = hostID;
941  m_channel = channel;
942  m_name = name;
943  m_id = id;
944  m_message = message;
945  RegexBitfield = regexBitfield;
946  }
947 
949  {
950  Object[] data = new Object[7];
951 
952  data[0] = m_active;
953  data[1] = m_handle;
954  data[2] = m_channel;
955  data[3] = m_name;
956  data[4] = m_id;
957  data[5] = m_message;
958  data[6] = RegexBitfield;
959 
960  return data;
961  }
962 
963  public static ListenerInfo FromData(uint localID, UUID ItemID,
964  UUID hostID, Object[] data)
965  {
966  ListenerInfo linfo = new ListenerInfo((int)data[1], localID,
967  ItemID, hostID, (int)data[2], (string)data[3],
968  (UUID)data[4], (string)data[5]);
969  linfo.m_active = (bool)data[0];
970  if (data.Length >= 7)
971  {
972  linfo.RegexBitfield = (int)data[6];
973  }
974 
975  return linfo;
976  }
977 
978  public UUID GetItemID()
979  {
980  return m_itemID;
981  }
982 
983  public UUID GetHostID()
984  {
985  return m_hostID;
986  }
987 
988  public int GetChannel()
989  {
990  return m_channel;
991  }
992 
993  public uint GetLocalID()
994  {
995  return m_localID;
996  }
997 
998  public int GetHandle()
999  {
1000  return m_handle;
1001  }
1002 
1003  public string GetMessage()
1004  {
1005  return m_message;
1006  }
1007 
1008  public string GetName()
1009  {
1010  return m_name;
1011  }
1012 
1013  public bool IsActive()
1014  {
1015  return m_active;
1016  }
1017 
1018  public void Deactivate()
1019  {
1020  m_active = false;
1021  }
1022 
1023  public void Activate()
1024  {
1025  m_active = true;
1026  }
1027 
1028  public UUID GetID()
1029  {
1030  return m_id;
1031  }
1032 
1033  public int RegexBitfield { get; private set; }
1034  }
1035 }
void AddFromData(uint localID, UUID itemID, UUID hostID, Object[] data)
void Close()
This is the inverse to Initialise. After a Close(), this instance won't be usable anymore...
int Listen(uint localID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg)
Create a listen event callback with the specified filters. The parameters localID,itemID are needed to uniquely identify the script during 'peek' time. Parameter hostID is needed to determine the position of the script.
ListenerInfo(ListenerInfo li, string name, UUID id, string message, int regexBitfield)
void DeliverMessage(ChatTypeEnum type, int channel, string name, UUID id, string msg)
This method scans over the objects which registered an interest in listen callbacks. For everyone it finds, it checks if it fits the given filter. If it does, then enqueue the message for delivery to the objects listen event handler. The enqueued ListenerInfo no longer has filter values, but the actually trigged values. Objects that do an llSay have their messages delivered here and for nearby avatars, the OnChatFromClient event is used.
void DeliverMessageTo(UUID target, int channel, Vector3 pos, string name, UUID id, string msg)
Delivers the message to a scene entity.
ListenerInfo(int handle, uint localID, UUID ItemID, UUID hostID, int channel, string name, UUID id, string message, int regexBitfield)
void RegionLoaded(Scene scene)
This will be called once for every scene loaded. In a shared module this will be multiple times in on...
IClientAPI Sender
The client responsible for sending the message, or null.
ListenerInfo(int handle, uint localID, UUID ItemID, UUID hostID, int channel, string name, UUID id, string message)
string Name
Returns the full name of the agent/avatar represented by this client
Definition: IClientAPI.cs:754
int Listen(uint localID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg, int regexBitfield)
Create a listen event callback with the specified filters. The parameters localID,itemID are needed to uniquely identify the script during 'peek' time. Parameter hostID is needed to determine the position of the script.
void AddRegion(Scene scene)
This is called whenever a Scene is added. For shared modules, this can happen several times...
A scene object group is conceptually an object in the scene. The object is constituted of SceneObject...
void CreateFromData(uint localID, UUID itemID, UUID hostID, Object[] data)
bool HasMessages()
Are there any listen events ready to be dispatched?
string Message
The message sent by the user
List< ListenerInfo > GetListeners(UUID itemID, int channel, string name, UUID id, string msg)
Get listeners matching the input parameters.
void ListenControl(UUID itemID, int handle, int active)
Sets the listen event with handle as active (active = TRUE) or inactive (active = FALSE)...
void ListenRemove(UUID itemID, int handle)
Removes the listen event callback with handle
void DeleteListener(UUID itemID)
Removes all listen event callbacks for the given itemID (script engine)
bool IsDeleted
Signals whether this entity was in a scene but has since been removed from it.
Definition: EntityBase.cs:73
int AddListener(uint localID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg)
string From
The name of the sender (needed for scripts)
int AddListener(uint localID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg, int regexBitfield)
ChatFromViewer Arguments
ChatTypeEnum Type
The type of message, eg say, shout, broadcast.
static ListenerInfo FromData(uint localID, UUID ItemID, UUID hostID, Object[] data)
Interactive OpenSim region server
Definition: OpenSim.cs:55
IWorldCommListenerInfo GetNextMessage()
Pop the first availlable listen event from the queue
ListenerInfo(ListenerInfo li, string name, UUID id, string message)
Vector3 Position
The position of the sender at the time of the message broadcast.
int Channel
Which channel was this message sent on? Different channels may have different listeners. Public chat is on channel zero.
void RemoveRegion(Scene scene)
This is called whenever a Scene is removed. For shared modules, this can happen several times...
void DeliverMessage(ChatTypeEnum type, int channel, string name, UUID id, string msg, Vector3 position)
This method scans over the objects which registered an interest in listen callbacks. For everyone it finds, it checks if it fits the given filter. If it does, then enqueue the message for delivery to the objects listen event handler. The enqueued ListenerInfo no longer has filter values, but the actually trigged values. Objects that do an llSay have their messages delivered here and for nearby avatars, the OnChatFromClient event is used.
void Initialise(IConfigSource config)
This is called to initialize the region module. For shared modules, this is called exactly once...