From d51ce47b2d7635b17f3dd429158e8f59b78b83aa Mon Sep 17 00:00:00 2001 From: Jeff Ames Date: Thu, 1 May 2008 14:31:30 +0000 Subject: Update svn properties. Minor formatting cleanup. --- .../Modules/Scripting/WorldComm/WorldCommModule.cs | 1168 ++++++++++---------- 1 file changed, 584 insertions(+), 584 deletions(-) (limited to 'OpenSim/Region/Environment/Modules/Scripting/WorldComm') diff --git a/OpenSim/Region/Environment/Modules/Scripting/WorldComm/WorldCommModule.cs b/OpenSim/Region/Environment/Modules/Scripting/WorldComm/WorldCommModule.cs index ff3b31e..e79b2bd 100644 --- a/OpenSim/Region/Environment/Modules/Scripting/WorldComm/WorldCommModule.cs +++ b/OpenSim/Region/Environment/Modules/Scripting/WorldComm/WorldCommModule.cs @@ -1,585 +1,585 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections; -using libsecondlife; -using Nini.Config; -using OpenSim.Framework; -using OpenSim.Region.Environment.Interfaces; -using OpenSim.Region.Environment.Scenes; - -/***************************************************** - * - * WorldCommModule - * - * - * Holding place for world comms - basically llListen - * function implementation. - * - * lLListen(integer channel, string name, key id, string msg) - * The name, id, and msg arguments specify the filtering - * criteria. You can pass the empty string - * (or NULL_KEY for id) for these to set a completely - * open filter; this causes the listen() event handler to be - * invoked for all chat on the channel. To listen only - * for chat spoken by a specific object or avatar, - * specify the name and/or id arguments. To listen - * only for a specific command, specify the - * (case-sensitive) msg argument. If msg is not empty, - * listener will only hear strings which are exactly equal - * to msg. You can also use all the arguments to establish - * the most restrictive filtering criteria. - * - * It might be useful for each listener to maintain a message - * digest, with a list of recent messages by UUID. This can - * be used to prevent in-world repeater loops. However, the - * linden functions do not have this capability, so for now - * thats the way it works. - * - * **************************************************/ - -namespace OpenSim.Region.Environment.Modules.Scripting.WorldComm -{ - public class WorldCommModule : IRegionModule, IWorldComm - { - private object CommListLock = new object(); - private object ListLock = new object(); - private ListenerManager m_listenerManager; - private string m_name = "WorldCommModule"; - private Queue m_pending; - private Queue m_pendingQ; - private Scene m_scene; - - public WorldCommModule() - { - } - - #region IRegionModule Members - - public void Initialise(Scene scene, IConfigSource config) - { - m_scene = scene; - m_scene.RegisterModuleInterface(this); - m_listenerManager = new ListenerManager(); - m_scene.EventManager.OnNewClient += NewClient; - m_pendingQ = new Queue(); - m_pending = Queue.Synchronized(m_pendingQ); - } - - public void PostInitialise() - { - } - - public void Close() - { - } - - public string Name - { - get { return m_name; } - } - - public bool IsSharedModule - { - get { return false; } - } - - #endregion - - #region IWorldComm Members - - public int Listen(uint localID, LLUUID itemID, LLUUID hostID, int channel, string name, string id, string msg) - { - return m_listenerManager.AddListener(localID, itemID, hostID, channel, name, id, msg); - } - - public void ListenControl(int handle, int active) - { - if (m_listenerManager != null) - { - if (active == 1) - m_listenerManager.Activate(handle); - else if (active == 0) - m_listenerManager.Dectivate(handle); - } - } - - public void ListenRemove(int handle) - { - if (m_listenerManager != null) - { - m_listenerManager.Remove(handle); - } - } - - public void DeleteListener(LLUUID itemID) - { - if (m_listenerManager != null) - { - m_listenerManager.DeleteListener(itemID); - } - } - - // This method scans nearby objects and determines if they are listeners, - // and if so if this message fits the filter. If it does, then - // enqueue the message for delivery to the objects listen event handler. - // Objects that do an llSay have their messages delivered here, and for - // nearby avatars, the SimChat function is used. - public void DeliverMessage(string sourceItemID, ChatTypeEnum type, int channel, string name, string msg) - { - SceneObjectPart source = null; - ScenePresence avatar = null; - - source = m_scene.GetSceneObjectPart(new LLUUID(sourceItemID)); - if (source == null) - { - avatar = m_scene.GetScenePresence(new LLUUID(sourceItemID)); - } - if ((avatar != null) || (source != null)) - { - // Loop through the objects in the scene - // If they are in proximity, then if they are - // listeners, if so add them to the pending queue - - foreach (ListenerInfo li in m_listenerManager.GetListeners()) - { - EntityBase sPart; - - m_scene.Entities.TryGetValue(li.GetHostID(), out sPart); - - if (sPart != null) - { - double dis = 0; - - if (source != null) - dis = Util.GetDistanceTo(sPart.AbsolutePosition, source.AbsolutePosition); - else - dis = Util.GetDistanceTo(sPart.AbsolutePosition, avatar.AbsolutePosition); - - switch (type) - { - case ChatTypeEnum.Whisper: - - if ((dis < 10) && (dis > -10)) - { - if (li.GetChannel() == channel) - { - ListenerInfo isListener = m_listenerManager.IsListenerMatch( - sourceItemID, sPart.UUID, channel, name, msg - ); - if (isListener != null) - { - lock (m_pending.SyncRoot) - { - m_pending.Enqueue(isListener); - } - } - } - } - break; - - case ChatTypeEnum.Say: - - if ((dis < 30) && (dis > -30)) - { - if (li.GetChannel() == channel) - { - ListenerInfo isListener = m_listenerManager.IsListenerMatch( - sourceItemID, sPart.UUID, channel, name, msg - ); - if (isListener != null) - { - lock (m_pending.SyncRoot) - { - m_pending.Enqueue(isListener); - } - } - } - } - break; - - case ChatTypeEnum.Shout: - if ((dis < 100) && (dis > -100)) - { - if (li.GetChannel() == channel) - { - ListenerInfo isListener = m_listenerManager.IsListenerMatch( - sourceItemID, sPart.UUID, channel, name, msg - ); - if (isListener != null) - { - lock (m_pending.SyncRoot) - { - m_pending.Enqueue(isListener); - } - } - } - } - break; - - case ChatTypeEnum.Broadcast: - // Dont process if this message is from itself! - if (li.GetHostID().ToString().Equals(sourceItemID) || - sPart.UUID.ToString().Equals(sourceItemID)) - continue; - - if (li.GetChannel() == channel) - { - ListenerInfo isListener = m_listenerManager.IsListenerMatch( - sourceItemID, sPart.UUID, channel, name, msg - ); - if (isListener != null) - { - lock (m_pending.SyncRoot) - { - m_pending.Enqueue(isListener); - } - } - } - - break; - } - } - } - } - } - - public bool HasMessages() - { - if (m_pending != null) - return (m_pending.Count > 0); - else - return false; - } - - public ListenerInfo GetNextMessage() - { - ListenerInfo li = null; - - lock (m_pending.SyncRoot) - { - li = (ListenerInfo) m_pending.Dequeue(); - } - - return li; - } - - public uint PeekNextMessageLocalID() - { - return ((ListenerInfo) m_pending.Peek()).GetLocalID(); - } - - public LLUUID PeekNextMessageItemID() - { - return ((ListenerInfo) m_pending.Peek()).GetItemID(); - } - - #endregion - - public void NewClient(IClientAPI client) - { - client.OnChatFromViewer += DeliverClientMessage; - } - - /******************************************************************** - * - * Listener Stuff - * - * *****************************************************************/ - - private void DeliverClientMessage(Object sender, ChatFromViewerArgs e) - { - DeliverMessage(e.Sender.AgentId.ToString(), - e.Type, e.Channel, - e.Sender.FirstName + " " + e.Sender.LastName, - e.Message); - } - } - - public class ListenerManager - { - //private Dictionary m_listeners; - private object ListenersLock = new object(); - private Hashtable m_listeners = Hashtable.Synchronized(new Hashtable()); - private int m_MaxListeners = 100; - - public int AddListener(uint localID, LLUUID itemID, LLUUID hostID, int channel, string name, string id, string msg) - { - if (m_listeners.Count < m_MaxListeners) - { - ListenerInfo isListener = IsListenerMatch(LLUUID.Zero.ToString(), itemID, channel, name, msg); - - if (isListener == null) - { - int newHandle = GetNewHandle(); - - if (newHandle > -1) - { - ListenerInfo li = new ListenerInfo(localID, newHandle, itemID, hostID, channel, name, id, msg); - - lock (m_listeners.SyncRoot) - { - m_listeners.Add(newHandle, li); - } - - return newHandle; - } - } - } - - return -1; - } - - public void Remove(int handle) - { - lock (m_listeners.SyncRoot) - { - m_listeners.Remove(handle); - } - } - - public void DeleteListener(LLUUID itemID) - { - ArrayList removedListeners = new ArrayList(); - - lock (m_listeners.SyncRoot) - { - IDictionaryEnumerator en = m_listeners.GetEnumerator(); - while (en.MoveNext()) - { - ListenerInfo li = (ListenerInfo) en.Value; - if (li.GetItemID().Equals(itemID)) - { - removedListeners.Add(li.GetHandle()); - } - } - foreach (int handle in removedListeners) - { - m_listeners.Remove(handle); - } - } - } - - private int GetNewHandle() - { - for (int i = 0; i < int.MaxValue - 1; i++) - { - if (!m_listeners.ContainsKey(i)) - return i; - } - - return -1; - } - - public bool IsListener(LLUUID hostID) - { - foreach (ListenerInfo li in m_listeners.Values) - { - if (li.GetHostID().Equals(hostID)) - return true; - } - - return false; - } - - public void Activate(int handle) - { - if (m_listeners.ContainsKey(handle)) - { - lock (m_listeners.SyncRoot) - { - ListenerInfo li = (ListenerInfo) m_listeners[handle]; - li.Activate(); - } - } - } - - public void Dectivate(int handle) - { - if (m_listeners.ContainsKey(handle)) - { - ListenerInfo li = (ListenerInfo) m_listeners[handle]; - li.Deactivate(); - } - } - - // Theres probably a more clever and efficient way to - // do this, maybe with regex. - public ListenerInfo IsListenerMatch(string sourceItemID, LLUUID listenerKey, int channel, string name, - string msg) - { - bool isMatch = true; - lock (m_listeners.SyncRoot) - { - IDictionaryEnumerator en = m_listeners.GetEnumerator(); - while (en.MoveNext()) - { - ListenerInfo li = (ListenerInfo) en.Value; - - if (li.IsActive()) - { - if (li.GetHostID().Equals(listenerKey)) - { - if (channel == li.GetChannel()) - { - if ((li.GetID().ToString().Length > 0) && - (!li.GetID().Equals(LLUUID.Zero))) - { - if (!li.GetID().ToString().Equals(sourceItemID)) - { - isMatch = false; - } - } - if (isMatch && (li.GetName().Length > 0)) - { - if (li.GetName().Equals(name)) - { - isMatch = false; - } - } - if (isMatch) - { - return new ListenerInfo( - li.GetLocalID(), li.GetHandle(), li.GetItemID(), li.GetHostID(), - li.GetChannel(), name, li.GetID(), msg, new LLUUID(sourceItemID) - ); - } - } - } - } - } - } - return null; - } - - public ICollection GetListeners() - { - return m_listeners.Values; - } - } - - public class ListenerInfo - { - private bool m_active; // Listener is active or not - private int m_channel; // Channel - private int m_handle; // Assigned handle of this listener - private LLUUID m_hostID; // ID of the host/scene part - private LLUUID m_id; // ID to filter messages from - private LLUUID m_itemID; // ID of the host script engine - private uint m_localID; // Local ID from script engine - private string m_message; // The message - private string m_name; // Object name to filter messages from - private LLUUID m_sourceItemID; // ID of the scenePart or avatar source of the message - - public ListenerInfo(uint localID, int handle, LLUUID ItemID, LLUUID hostID, int channel, string name, LLUUID id, string message) - { - Initialise(localID, handle, ItemID, hostID, channel, name, id, message); - } - - public ListenerInfo(uint localID, int handle, LLUUID ItemID, LLUUID hostID, int channel, string name, LLUUID id, - string message, LLUUID sourceItemID) - { - Initialise(localID, handle, ItemID, hostID, channel, name, id, message); - m_sourceItemID = sourceItemID; - } - - private void Initialise(uint localID, int handle, LLUUID ItemID, LLUUID hostID, int channel, string name, - LLUUID id, string message) - { - m_handle = handle; - m_channel = channel; - m_itemID = ItemID; - m_hostID = hostID; - m_name = name; - m_id = id; - m_message = message; - m_active = true; - m_localID = localID; - } - - public LLUUID GetItemID() - { - return m_itemID; - } - - public LLUUID GetHostID() - { - return m_hostID; - } - - public LLUUID GetSourceItemID() - { - return m_sourceItemID; - } - - public int GetChannel() - { - return m_channel; - } - - public uint GetLocalID() - { - return m_localID; - } - - public int GetHandle() - { - return m_handle; - } - - public string GetMessage() - { - return m_message; - } - - public string GetName() - { - return m_name; - } - - public bool IsActive() - { - return m_active; - } - - public void Deactivate() - { - m_active = false; - } - - public void Activate() - { - m_active = true; - } - - public LLUUID GetID() - { - return m_id; - } - } +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using libsecondlife; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; + +/***************************************************** + * + * WorldCommModule + * + * + * Holding place for world comms - basically llListen + * function implementation. + * + * lLListen(integer channel, string name, key id, string msg) + * The name, id, and msg arguments specify the filtering + * criteria. You can pass the empty string + * (or NULL_KEY for id) for these to set a completely + * open filter; this causes the listen() event handler to be + * invoked for all chat on the channel. To listen only + * for chat spoken by a specific object or avatar, + * specify the name and/or id arguments. To listen + * only for a specific command, specify the + * (case-sensitive) msg argument. If msg is not empty, + * listener will only hear strings which are exactly equal + * to msg. You can also use all the arguments to establish + * the most restrictive filtering criteria. + * + * It might be useful for each listener to maintain a message + * digest, with a list of recent messages by UUID. This can + * be used to prevent in-world repeater loops. However, the + * linden functions do not have this capability, so for now + * thats the way it works. + * + * **************************************************/ + +namespace OpenSim.Region.Environment.Modules.Scripting.WorldComm +{ + public class WorldCommModule : IRegionModule, IWorldComm + { + private object CommListLock = new object(); + private object ListLock = new object(); + private ListenerManager m_listenerManager; + private string m_name = "WorldCommModule"; + private Queue m_pending; + private Queue m_pendingQ; + private Scene m_scene; + + public WorldCommModule() + { + } + + #region IRegionModule Members + + public void Initialise(Scene scene, IConfigSource config) + { + m_scene = scene; + m_scene.RegisterModuleInterface(this); + m_listenerManager = new ListenerManager(); + m_scene.EventManager.OnNewClient += NewClient; + m_pendingQ = new Queue(); + m_pending = Queue.Synchronized(m_pendingQ); + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return m_name; } + } + + public bool IsSharedModule + { + get { return false; } + } + + #endregion + + #region IWorldComm Members + + public int Listen(uint localID, LLUUID itemID, LLUUID hostID, int channel, string name, string id, string msg) + { + return m_listenerManager.AddListener(localID, itemID, hostID, channel, name, id, msg); + } + + public void ListenControl(int handle, int active) + { + if (m_listenerManager != null) + { + if (active == 1) + m_listenerManager.Activate(handle); + else if (active == 0) + m_listenerManager.Dectivate(handle); + } + } + + public void ListenRemove(int handle) + { + if (m_listenerManager != null) + { + m_listenerManager.Remove(handle); + } + } + + public void DeleteListener(LLUUID itemID) + { + if (m_listenerManager != null) + { + m_listenerManager.DeleteListener(itemID); + } + } + + // This method scans nearby objects and determines if they are listeners, + // and if so if this message fits the filter. If it does, then + // enqueue the message for delivery to the objects listen event handler. + // Objects that do an llSay have their messages delivered here, and for + // nearby avatars, the SimChat function is used. + public void DeliverMessage(string sourceItemID, ChatTypeEnum type, int channel, string name, string msg) + { + SceneObjectPart source = null; + ScenePresence avatar = null; + + source = m_scene.GetSceneObjectPart(new LLUUID(sourceItemID)); + if (source == null) + { + avatar = m_scene.GetScenePresence(new LLUUID(sourceItemID)); + } + if ((avatar != null) || (source != null)) + { + // Loop through the objects in the scene + // If they are in proximity, then if they are + // listeners, if so add them to the pending queue + + foreach (ListenerInfo li in m_listenerManager.GetListeners()) + { + EntityBase sPart; + + m_scene.Entities.TryGetValue(li.GetHostID(), out sPart); + + if (sPart != null) + { + double dis = 0; + + if (source != null) + dis = Util.GetDistanceTo(sPart.AbsolutePosition, source.AbsolutePosition); + else + dis = Util.GetDistanceTo(sPart.AbsolutePosition, avatar.AbsolutePosition); + + switch (type) + { + case ChatTypeEnum.Whisper: + + if ((dis < 10) && (dis > -10)) + { + if (li.GetChannel() == channel) + { + ListenerInfo isListener = m_listenerManager.IsListenerMatch( + sourceItemID, sPart.UUID, channel, name, msg + ); + if (isListener != null) + { + lock (m_pending.SyncRoot) + { + m_pending.Enqueue(isListener); + } + } + } + } + break; + + case ChatTypeEnum.Say: + + if ((dis < 30) && (dis > -30)) + { + if (li.GetChannel() == channel) + { + ListenerInfo isListener = m_listenerManager.IsListenerMatch( + sourceItemID, sPart.UUID, channel, name, msg + ); + if (isListener != null) + { + lock (m_pending.SyncRoot) + { + m_pending.Enqueue(isListener); + } + } + } + } + break; + + case ChatTypeEnum.Shout: + if ((dis < 100) && (dis > -100)) + { + if (li.GetChannel() == channel) + { + ListenerInfo isListener = m_listenerManager.IsListenerMatch( + sourceItemID, sPart.UUID, channel, name, msg + ); + if (isListener != null) + { + lock (m_pending.SyncRoot) + { + m_pending.Enqueue(isListener); + } + } + } + } + break; + + case ChatTypeEnum.Broadcast: + // Dont process if this message is from itself! + if (li.GetHostID().ToString().Equals(sourceItemID) || + sPart.UUID.ToString().Equals(sourceItemID)) + continue; + + if (li.GetChannel() == channel) + { + ListenerInfo isListener = m_listenerManager.IsListenerMatch( + sourceItemID, sPart.UUID, channel, name, msg + ); + if (isListener != null) + { + lock (m_pending.SyncRoot) + { + m_pending.Enqueue(isListener); + } + } + } + + break; + } + } + } + } + } + + public bool HasMessages() + { + if (m_pending != null) + return (m_pending.Count > 0); + else + return false; + } + + public ListenerInfo GetNextMessage() + { + ListenerInfo li = null; + + lock (m_pending.SyncRoot) + { + li = (ListenerInfo) m_pending.Dequeue(); + } + + return li; + } + + public uint PeekNextMessageLocalID() + { + return ((ListenerInfo) m_pending.Peek()).GetLocalID(); + } + + public LLUUID PeekNextMessageItemID() + { + return ((ListenerInfo) m_pending.Peek()).GetItemID(); + } + + #endregion + + public void NewClient(IClientAPI client) + { + client.OnChatFromViewer += DeliverClientMessage; + } + + /******************************************************************** + * + * Listener Stuff + * + * *****************************************************************/ + + private void DeliverClientMessage(Object sender, ChatFromViewerArgs e) + { + DeliverMessage(e.Sender.AgentId.ToString(), + e.Type, e.Channel, + e.Sender.FirstName + " " + e.Sender.LastName, + e.Message); + } + } + + public class ListenerManager + { + //private Dictionary m_listeners; + private object ListenersLock = new object(); + private Hashtable m_listeners = Hashtable.Synchronized(new Hashtable()); + private int m_MaxListeners = 100; + + public int AddListener(uint localID, LLUUID itemID, LLUUID hostID, int channel, string name, string id, string msg) + { + if (m_listeners.Count < m_MaxListeners) + { + ListenerInfo isListener = IsListenerMatch(LLUUID.Zero.ToString(), itemID, channel, name, msg); + + if (isListener == null) + { + int newHandle = GetNewHandle(); + + if (newHandle > -1) + { + ListenerInfo li = new ListenerInfo(localID, newHandle, itemID, hostID, channel, name, id, msg); + + lock (m_listeners.SyncRoot) + { + m_listeners.Add(newHandle, li); + } + + return newHandle; + } + } + } + + return -1; + } + + public void Remove(int handle) + { + lock (m_listeners.SyncRoot) + { + m_listeners.Remove(handle); + } + } + + public void DeleteListener(LLUUID itemID) + { + ArrayList removedListeners = new ArrayList(); + + lock (m_listeners.SyncRoot) + { + IDictionaryEnumerator en = m_listeners.GetEnumerator(); + while (en.MoveNext()) + { + ListenerInfo li = (ListenerInfo) en.Value; + if (li.GetItemID().Equals(itemID)) + { + removedListeners.Add(li.GetHandle()); + } + } + foreach (int handle in removedListeners) + { + m_listeners.Remove(handle); + } + } + } + + private int GetNewHandle() + { + for (int i = 0; i < int.MaxValue - 1; i++) + { + if (!m_listeners.ContainsKey(i)) + return i; + } + + return -1; + } + + public bool IsListener(LLUUID hostID) + { + foreach (ListenerInfo li in m_listeners.Values) + { + if (li.GetHostID().Equals(hostID)) + return true; + } + + return false; + } + + public void Activate(int handle) + { + if (m_listeners.ContainsKey(handle)) + { + lock (m_listeners.SyncRoot) + { + ListenerInfo li = (ListenerInfo) m_listeners[handle]; + li.Activate(); + } + } + } + + public void Dectivate(int handle) + { + if (m_listeners.ContainsKey(handle)) + { + ListenerInfo li = (ListenerInfo) m_listeners[handle]; + li.Deactivate(); + } + } + + // Theres probably a more clever and efficient way to + // do this, maybe with regex. + public ListenerInfo IsListenerMatch(string sourceItemID, LLUUID listenerKey, int channel, string name, + string msg) + { + bool isMatch = true; + lock (m_listeners.SyncRoot) + { + IDictionaryEnumerator en = m_listeners.GetEnumerator(); + while (en.MoveNext()) + { + ListenerInfo li = (ListenerInfo) en.Value; + + if (li.IsActive()) + { + if (li.GetHostID().Equals(listenerKey)) + { + if (channel == li.GetChannel()) + { + if ((li.GetID().ToString().Length > 0) && + (!li.GetID().Equals(LLUUID.Zero))) + { + if (!li.GetID().ToString().Equals(sourceItemID)) + { + isMatch = false; + } + } + if (isMatch && (li.GetName().Length > 0)) + { + if (li.GetName().Equals(name)) + { + isMatch = false; + } + } + if (isMatch) + { + return new ListenerInfo( + li.GetLocalID(), li.GetHandle(), li.GetItemID(), li.GetHostID(), + li.GetChannel(), name, li.GetID(), msg, new LLUUID(sourceItemID) + ); + } + } + } + } + } + } + return null; + } + + public ICollection GetListeners() + { + return m_listeners.Values; + } + } + + public class ListenerInfo + { + private bool m_active; // Listener is active or not + private int m_channel; // Channel + private int m_handle; // Assigned handle of this listener + private LLUUID m_hostID; // ID of the host/scene part + private LLUUID m_id; // ID to filter messages from + private LLUUID m_itemID; // ID of the host script engine + private uint m_localID; // Local ID from script engine + private string m_message; // The message + private string m_name; // Object name to filter messages from + private LLUUID m_sourceItemID; // ID of the scenePart or avatar source of the message + + public ListenerInfo(uint localID, int handle, LLUUID ItemID, LLUUID hostID, int channel, string name, LLUUID id, string message) + { + Initialise(localID, handle, ItemID, hostID, channel, name, id, message); + } + + public ListenerInfo(uint localID, int handle, LLUUID ItemID, LLUUID hostID, int channel, string name, LLUUID id, + string message, LLUUID sourceItemID) + { + Initialise(localID, handle, ItemID, hostID, channel, name, id, message); + m_sourceItemID = sourceItemID; + } + + private void Initialise(uint localID, int handle, LLUUID ItemID, LLUUID hostID, int channel, string name, + LLUUID id, string message) + { + m_handle = handle; + m_channel = channel; + m_itemID = ItemID; + m_hostID = hostID; + m_name = name; + m_id = id; + m_message = message; + m_active = true; + m_localID = localID; + } + + public LLUUID GetItemID() + { + return m_itemID; + } + + public LLUUID GetHostID() + { + return m_hostID; + } + + public LLUUID GetSourceItemID() + { + return m_sourceItemID; + } + + public int GetChannel() + { + return m_channel; + } + + public uint GetLocalID() + { + return m_localID; + } + + public int GetHandle() + { + return m_handle; + } + + public string GetMessage() + { + return m_message; + } + + public string GetName() + { + return m_name; + } + + public bool IsActive() + { + return m_active; + } + + public void Deactivate() + { + m_active = false; + } + + public void Activate() + { + m_active = true; + } + + public LLUUID GetID() + { + return m_id; + } + } } \ No newline at end of file -- cgit v1.1