* Applying patch #1121 - Fixes for llListen() (Thanks Middlelink!)
parent
cf7560d1aa
commit
dc21e8d5e2
|
@ -55,6 +55,8 @@ namespace OpenSim.Framework
|
||||||
StartTyping = 4,
|
StartTyping = 4,
|
||||||
StopTyping = 5,
|
StopTyping = 5,
|
||||||
DebugChannel = 6,
|
DebugChannel = 6,
|
||||||
|
Region = 7,
|
||||||
|
Owner = 8,
|
||||||
Broadcast = 0xFF
|
Broadcast = 0xFF
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,14 +33,12 @@ namespace OpenSim.Region.Environment.Interfaces
|
||||||
{
|
{
|
||||||
public interface IWorldComm
|
public interface IWorldComm
|
||||||
{
|
{
|
||||||
int Listen(uint LocalID, LLUUID itemID, LLUUID hostID, int channel, string name, string id, string msg);
|
int Listen(uint LocalID, LLUUID itemID, LLUUID hostID, int channel, string name, LLUUID id, string msg);
|
||||||
void DeliverMessage(string sourceItemID, ChatTypeEnum type, int channel, string name, string msg);
|
void DeliverMessage(ChatTypeEnum type, int channel, string name, LLUUID id, string msg);
|
||||||
bool HasMessages();
|
bool HasMessages();
|
||||||
ListenerInfo GetNextMessage();
|
ListenerInfo GetNextMessage();
|
||||||
void ListenControl(int handle, int active);
|
void ListenControl(LLUUID itemID, int handle, int active);
|
||||||
void ListenRemove(int handle);
|
void ListenRemove(LLUUID itemID, int handle);
|
||||||
void DeleteListener(LLUUID itemID);
|
void DeleteListener(LLUUID itemID);
|
||||||
uint PeekNextMessageLocalID();
|
|
||||||
LLUUID PeekNextMessageItemID();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
using libsecondlife;
|
using libsecondlife;
|
||||||
using Nini.Config;
|
using Nini.Config;
|
||||||
using OpenSim.Framework;
|
using OpenSim.Framework;
|
||||||
|
@ -60,6 +61,21 @@ using OpenSim.Region.Environment.Scenes;
|
||||||
* be used to prevent in-world repeater loops. However, the
|
* be used to prevent in-world repeater loops. However, the
|
||||||
* linden functions do not have this capability, so for now
|
* linden functions do not have this capability, so for now
|
||||||
* thats the way it works.
|
* thats the way it works.
|
||||||
|
* Instead it blocks messages originating from the same prim.
|
||||||
|
* (not Object!)
|
||||||
|
*
|
||||||
|
* For LSL compliance, note the following:
|
||||||
|
* (Tested again 1.21.1 on May 2, 2008)
|
||||||
|
* 1. 'id' has to be parsed into a LLUUID. None-UUID keys are
|
||||||
|
* to be replaced by the ZeroID key. (Well, TryParse does
|
||||||
|
* that for us.
|
||||||
|
* 2. Setting up an listen event from the same script, with the
|
||||||
|
* same filter settings (including step 1), returns the same
|
||||||
|
* handle as the original filter.
|
||||||
|
* 3. (TODO) handles should be script-local. Starting from 1.
|
||||||
|
* Might be actually easier to map the global handle into
|
||||||
|
* script-local handle in the ScriptEngine. Not sure if its
|
||||||
|
* worth the effort tho.
|
||||||
*
|
*
|
||||||
* **************************************************/
|
* **************************************************/
|
||||||
|
|
||||||
|
@ -67,25 +83,39 @@ namespace OpenSim.Region.Environment.Modules.Scripting.WorldComm
|
||||||
{
|
{
|
||||||
public class WorldCommModule : IRegionModule, IWorldComm
|
public class WorldCommModule : IRegionModule, IWorldComm
|
||||||
{
|
{
|
||||||
private object CommListLock = new object();
|
|
||||||
private object ListLock = new object();
|
|
||||||
private ListenerManager m_listenerManager;
|
private ListenerManager m_listenerManager;
|
||||||
private string m_name = "WorldCommModule";
|
|
||||||
private Queue m_pending;
|
private Queue m_pending;
|
||||||
private Queue m_pendingQ;
|
private Queue m_pendingQ;
|
||||||
private Scene m_scene;
|
private Scene m_scene;
|
||||||
|
private int m_whisperdistance = 10;
|
||||||
public WorldCommModule()
|
private int m_saydistance = 30;
|
||||||
{
|
private int m_shoutdistance = 100;
|
||||||
}
|
|
||||||
|
|
||||||
#region IRegionModule Members
|
#region IRegionModule Members
|
||||||
|
|
||||||
public void Initialise(Scene scene, IConfigSource config)
|
public void Initialise(Scene scene, IConfigSource config)
|
||||||
{
|
{
|
||||||
|
// wrap this in a try block so that defaults will work if
|
||||||
|
// the config file doesn't specify otherwise.
|
||||||
|
int maxlisteners = 1000;
|
||||||
|
int maxhandles = 64;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_whisperdistance = config.Configs["Chat"].GetInt("whisper_distance", m_whisperdistance);
|
||||||
|
m_saydistance = config.Configs["Chat"].GetInt("say_distance", m_saydistance);
|
||||||
|
m_shoutdistance = config.Configs["Chat"].GetInt("shout_distance", m_shoutdistance);
|
||||||
|
maxlisteners = config.Configs["Chat"].GetInt("max_listens_per_region", maxlisteners);
|
||||||
|
maxhandles = config.Configs["Chat"].GetInt("max_listens_per_script", maxhandles);
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
if (maxlisteners < 1) maxlisteners = int.MaxValue;
|
||||||
|
if (maxhandles < 1) maxhandles = int.MaxValue;
|
||||||
|
|
||||||
m_scene = scene;
|
m_scene = scene;
|
||||||
m_scene.RegisterModuleInterface<IWorldComm>(this);
|
m_scene.RegisterModuleInterface<IWorldComm>(this);
|
||||||
m_listenerManager = new ListenerManager();
|
m_listenerManager = new ListenerManager(maxlisteners, maxhandles);
|
||||||
m_scene.EventManager.OnNewClient += NewClient;
|
m_scene.EventManager.OnNewClient += NewClient;
|
||||||
m_pendingQ = new Queue();
|
m_pendingQ = new Queue();
|
||||||
m_pending = Queue.Synchronized(m_pendingQ);
|
m_pending = Queue.Synchronized(m_pendingQ);
|
||||||
|
@ -101,7 +131,7 @@ namespace OpenSim.Region.Environment.Modules.Scripting.WorldComm
|
||||||
|
|
||||||
public string Name
|
public string Name
|
||||||
{
|
{
|
||||||
get { return m_name; }
|
get { return "WorldCommModule"; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsSharedModule
|
public bool IsSharedModule
|
||||||
|
@ -113,170 +143,160 @@ namespace OpenSim.Region.Environment.Modules.Scripting.WorldComm
|
||||||
|
|
||||||
#region IWorldComm Members
|
#region IWorldComm Members
|
||||||
|
|
||||||
public int Listen(uint localID, LLUUID itemID, LLUUID hostID, int channel, string name, string id, string msg)
|
/// <summary>
|
||||||
|
/// 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.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="localID">localID of the script engine</param>
|
||||||
|
/// <param name="itemID">UUID of the script engine</param>
|
||||||
|
/// <param name="hostID">UUID of the SceneObjectPart</param>
|
||||||
|
/// <param name="channel">channel to listen on</param>
|
||||||
|
/// <param name="name">name to filter on</param>
|
||||||
|
/// <param name="id">key to filter on (user given, could be totally faked)</param>
|
||||||
|
/// <param name="msg">msg to filter on</param>
|
||||||
|
/// <returns>number of the scripts handle</returns>
|
||||||
|
public int Listen(uint localID, LLUUID itemID, LLUUID hostID, int channel, string name, LLUUID id, string msg)
|
||||||
{
|
{
|
||||||
return m_listenerManager.AddListener(localID, itemID, hostID, channel, name, id, msg);
|
return m_listenerManager.AddListener(localID, itemID, hostID, channel, name, id, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ListenControl(int handle, int active)
|
/// <summary>
|
||||||
{
|
/// Sets the listen event with handle as active (active = TRUE) or inactive (active = FALSE).
|
||||||
if (m_listenerManager != null)
|
/// The handle used is returned from Listen()
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="itemID">UUID of the script engine</param>
|
||||||
|
/// <param name="handle">handle returned by Listen()</param>
|
||||||
|
/// <param name="active">temp. activate or deactivate the Listen()</param>
|
||||||
|
public void ListenControl(LLUUID itemID, int handle, int active)
|
||||||
{
|
{
|
||||||
if (active == 1)
|
if (active == 1)
|
||||||
m_listenerManager.Activate(handle);
|
m_listenerManager.Activate(itemID, handle);
|
||||||
else if (active == 0)
|
else if (active == 0)
|
||||||
m_listenerManager.Dectivate(handle);
|
m_listenerManager.Dectivate(itemID, handle);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ListenRemove(int handle)
|
/// <summary>
|
||||||
|
/// Removes the listen event callback with handle
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="itemID">UUID of the script engine</param>
|
||||||
|
/// <param name="handle">handle returned by Listen()</param>
|
||||||
|
public void ListenRemove(LLUUID itemID, int handle)
|
||||||
{
|
{
|
||||||
if (m_listenerManager != null)
|
m_listenerManager.Remove(itemID, handle);
|
||||||
{
|
|
||||||
m_listenerManager.Remove(handle);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes all listen event callbacks for the given itemID
|
||||||
|
/// (script engine)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="itemID">UUID of the script engine</param>
|
||||||
public void DeleteListener(LLUUID itemID)
|
public void DeleteListener(LLUUID itemID)
|
||||||
{
|
|
||||||
if (m_listenerManager != null)
|
|
||||||
{
|
{
|
||||||
m_listenerManager.DeleteListener(itemID);
|
m_listenerManager.DeleteListener(itemID);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// This method scans nearby objects and determines if they are listeners,
|
/// <summary>
|
||||||
// and if so if this message fits the filter. If it does, then
|
/// This method scans over the objects which registered an interest in listen callbacks.
|
||||||
// enqueue the message for delivery to the objects listen event handler.
|
/// For everyone it finds, it checks if it fits the given filter. If it does, then
|
||||||
// Objects that do an llSay have their messages delivered here, and for
|
/// enqueue the message for delivery to the objects listen event handler.
|
||||||
// nearby avatars, the SimChat function is used.
|
/// The enqueued ListenerInfo no longer has filter values, but the actually trigged values.
|
||||||
public void DeliverMessage(string sourceItemID, ChatTypeEnum type, int channel, string name, string msg)
|
/// Objects that do an llSay have their messages delivered here and for nearby avatars,
|
||||||
|
/// the OnChatFromViewer event is used.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type">type of delvery (whisper,say,shout or regionwide)</param>
|
||||||
|
/// <param name="channel">channel to sent on</param>
|
||||||
|
/// <param name="name">name of sender (object or avatar)</param>
|
||||||
|
/// <param name="id">key of sender (object or avatar)</param>
|
||||||
|
/// <param name="msg">msg to sent</param>
|
||||||
|
public void DeliverMessage(ChatTypeEnum type, int channel, string name, LLUUID id, string msg)
|
||||||
{
|
{
|
||||||
SceneObjectPart source = null;
|
SceneObjectPart source = null;
|
||||||
ScenePresence avatar = null;
|
ScenePresence avatar = null;
|
||||||
|
LLVector3 position;
|
||||||
|
|
||||||
source = m_scene.GetSceneObjectPart(new LLUUID(sourceItemID));
|
source = m_scene.GetSceneObjectPart(id);
|
||||||
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)
|
if (source != null)
|
||||||
dis = Util.GetDistanceTo(sPart.AbsolutePosition, source.AbsolutePosition);
|
position = source.AbsolutePosition;
|
||||||
|
else {
|
||||||
|
avatar = m_scene.GetScenePresence(id);
|
||||||
|
if (avatar != null)
|
||||||
|
position = avatar.AbsolutePosition;
|
||||||
else
|
else
|
||||||
dis = Util.GetDistanceTo(sPart.AbsolutePosition, avatar.AbsolutePosition);
|
// bail out early, given source could not be found
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine which listen event filters match the given set of arguments, this results
|
||||||
|
// in a limited set of listeners, each belonging a host. If the host is in range, add them
|
||||||
|
// to the pending queue.
|
||||||
|
foreach (ListenerInfo li in m_listenerManager.GetListeners(LLUUID.Zero, channel, name, id, msg))
|
||||||
|
{
|
||||||
|
// Dont process if this message is from yourself!
|
||||||
|
if (li.GetHostID().Equals(id))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
SceneObjectPart sPart = m_scene.GetSceneObjectPart(li.GetHostID());
|
||||||
|
if (sPart == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
double dis = Util.GetDistanceTo(sPart.AbsolutePosition, position);
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case ChatTypeEnum.Whisper:
|
case ChatTypeEnum.Whisper:
|
||||||
|
if (dis < m_whisperdistance)
|
||||||
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)
|
lock (m_pending.SyncRoot)
|
||||||
{
|
{
|
||||||
m_pending.Enqueue(isListener);
|
m_pending.Enqueue(new ListenerInfo(li,name,id,msg));
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ChatTypeEnum.Say:
|
case ChatTypeEnum.Say:
|
||||||
|
if (dis < m_saydistance)
|
||||||
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)
|
lock (m_pending.SyncRoot)
|
||||||
{
|
{
|
||||||
m_pending.Enqueue(isListener);
|
m_pending.Enqueue(new ListenerInfo(li,name,id,msg));
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ChatTypeEnum.Shout:
|
case ChatTypeEnum.Shout:
|
||||||
if ((dis < 100) && (dis > -100))
|
if (dis < m_shoutdistance)
|
||||||
{
|
|
||||||
if (li.GetChannel() == channel)
|
|
||||||
{
|
|
||||||
ListenerInfo isListener = m_listenerManager.IsListenerMatch(
|
|
||||||
sourceItemID, sPart.UUID, channel, name, msg
|
|
||||||
);
|
|
||||||
if (isListener != null)
|
|
||||||
{
|
{
|
||||||
lock (m_pending.SyncRoot)
|
lock (m_pending.SyncRoot)
|
||||||
{
|
{
|
||||||
m_pending.Enqueue(isListener);
|
m_pending.Enqueue(new ListenerInfo(li,name,id,msg));
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ChatTypeEnum.Broadcast:
|
case ChatTypeEnum.Region:
|
||||||
// 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)
|
lock (m_pending.SyncRoot)
|
||||||
{
|
{
|
||||||
m_pending.Enqueue(isListener);
|
m_pending.Enqueue(new ListenerInfo(li,name,id,msg));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Are there any listen events ready to be dispatched?
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>boolean indication</returns>
|
||||||
public bool HasMessages()
|
public bool HasMessages()
|
||||||
{
|
{
|
||||||
if (m_pending != null)
|
|
||||||
return (m_pending.Count > 0);
|
return (m_pending.Count > 0);
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pop the first availlable listen event from the queue
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>ListenerInfo with filter filled in</returns>
|
||||||
public ListenerInfo GetNextMessage()
|
public ListenerInfo GetNextMessage()
|
||||||
{
|
{
|
||||||
ListenerInfo li = null;
|
ListenerInfo li = null;
|
||||||
|
@ -289,19 +309,9 @@ namespace OpenSim.Region.Environment.Modules.Scripting.WorldComm
|
||||||
return li;
|
return li;
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint PeekNextMessageLocalID()
|
|
||||||
{
|
|
||||||
return ((ListenerInfo) m_pending.Peek()).GetLocalID();
|
|
||||||
}
|
|
||||||
|
|
||||||
public LLUUID PeekNextMessageItemID()
|
|
||||||
{
|
|
||||||
return ((ListenerInfo) m_pending.Peek()).GetItemID();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
public void NewClient(IClientAPI client)
|
private void NewClient(IClientAPI client)
|
||||||
{
|
{
|
||||||
client.OnChatFromViewer += DeliverClientMessage;
|
client.OnChatFromViewer += DeliverClientMessage;
|
||||||
}
|
}
|
||||||
|
@ -314,212 +324,267 @@ namespace OpenSim.Region.Environment.Modules.Scripting.WorldComm
|
||||||
|
|
||||||
private void DeliverClientMessage(Object sender, ChatFromViewerArgs e)
|
private void DeliverClientMessage(Object sender, ChatFromViewerArgs e)
|
||||||
{
|
{
|
||||||
DeliverMessage(e.Sender.AgentId.ToString(),
|
DeliverMessage(e.Type,
|
||||||
e.Type, e.Channel,
|
e.Channel,
|
||||||
e.Sender.FirstName + " " + e.Sender.LastName,
|
e.Sender.FirstName + " " + e.Sender.LastName,
|
||||||
|
e.Sender.AgentId,
|
||||||
e.Message);
|
e.Message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ListenerManager
|
public class ListenerManager
|
||||||
{
|
{
|
||||||
//private Dictionary<int, ListenerInfo> m_listeners;
|
private Dictionary<int, List<ListenerInfo>> m_listeners = new Dictionary<int, List<ListenerInfo>>();
|
||||||
private object ListenersLock = new object();
|
private int m_maxlisteners;
|
||||||
private Hashtable m_listeners = Hashtable.Synchronized(new Hashtable());
|
private int m_maxhandles;
|
||||||
private int m_MaxListeners = 100;
|
private int m_curlisteners;
|
||||||
|
|
||||||
public int AddListener(uint localID, LLUUID itemID, LLUUID hostID, int channel, string name, string id, string msg)
|
public ListenerManager(int maxlisteners, int maxhandles)
|
||||||
{
|
{
|
||||||
if (m_listeners.Count < m_MaxListeners)
|
m_maxlisteners = maxlisteners;
|
||||||
{
|
m_maxhandles = maxhandles;
|
||||||
ListenerInfo isListener = IsListenerMatch(LLUUID.Zero.ToString(), itemID, channel, name, msg);
|
m_curlisteners = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (isListener == null)
|
public int AddListener(uint localID, LLUUID itemID, LLUUID hostID, int channel, string name, LLUUID id, string msg)
|
||||||
{
|
{
|
||||||
int newHandle = GetNewHandle();
|
// do we already have a match on this particular filter event?
|
||||||
|
List<ListenerInfo> coll = GetListeners(itemID, channel, name, id, msg);
|
||||||
|
|
||||||
if (newHandle > -1)
|
if (coll.Count > 0)
|
||||||
{
|
{
|
||||||
ListenerInfo li = new ListenerInfo(localID, newHandle, itemID, hostID, channel, name, id, msg);
|
// special case, called with same filter settings, return same handle
|
||||||
|
// (2008-05-02, tested on 1.21.1 server, still holds)
|
||||||
|
return coll[0].GetHandle();
|
||||||
|
}
|
||||||
|
|
||||||
lock (m_listeners.SyncRoot)
|
if (m_curlisteners < m_maxlisteners)
|
||||||
{
|
{
|
||||||
m_listeners.Add(newHandle, li);
|
int newHandle = GetNewHandle(itemID);
|
||||||
|
|
||||||
|
if (newHandle > 0)
|
||||||
|
{
|
||||||
|
ListenerInfo li = new ListenerInfo(newHandle, localID, itemID, hostID, channel, name, id, msg);
|
||||||
|
|
||||||
|
lock (m_listeners)
|
||||||
|
{
|
||||||
|
List<ListenerInfo> listeners;
|
||||||
|
if (!m_listeners.TryGetValue(channel,out listeners))
|
||||||
|
{
|
||||||
|
listeners = new List<ListenerInfo>();
|
||||||
|
m_listeners.Add(channel, listeners);
|
||||||
|
}
|
||||||
|
listeners.Add(li);
|
||||||
|
m_curlisteners++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return newHandle;
|
return newHandle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Remove(int handle)
|
public void Remove(LLUUID itemID, int handle)
|
||||||
{
|
{
|
||||||
lock (m_listeners.SyncRoot)
|
lock (m_listeners)
|
||||||
{
|
{
|
||||||
m_listeners.Remove(handle);
|
foreach (KeyValuePair<int,List<ListenerInfo>> lis in m_listeners)
|
||||||
|
{
|
||||||
|
foreach (ListenerInfo li in lis.Value)
|
||||||
|
{
|
||||||
|
if (li.GetItemID().Equals(itemID) && li.GetHandle().Equals(handle))
|
||||||
|
{
|
||||||
|
lis.Value.Remove(li);
|
||||||
|
if (lis.Value.Count == 0)
|
||||||
|
{
|
||||||
|
m_listeners.Remove(lis.Key);
|
||||||
|
m_curlisteners--;
|
||||||
|
}
|
||||||
|
// there should be only one, so we bail out early
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DeleteListener(LLUUID itemID)
|
public void DeleteListener(LLUUID itemID)
|
||||||
{
|
{
|
||||||
ArrayList removedListeners = new ArrayList();
|
List<int> emptyChannels = new List<int>();
|
||||||
|
List<ListenerInfo> removedListeners = new List<ListenerInfo>();
|
||||||
|
|
||||||
lock (m_listeners.SyncRoot)
|
lock (m_listeners)
|
||||||
{
|
{
|
||||||
IDictionaryEnumerator en = m_listeners.GetEnumerator();
|
foreach (KeyValuePair<int,List<ListenerInfo>> lis in m_listeners)
|
||||||
while (en.MoveNext())
|
{
|
||||||
|
foreach (ListenerInfo li in lis.Value)
|
||||||
{
|
{
|
||||||
ListenerInfo li = (ListenerInfo) en.Value;
|
|
||||||
if (li.GetItemID().Equals(itemID))
|
if (li.GetItemID().Equals(itemID))
|
||||||
{
|
{
|
||||||
removedListeners.Add(li.GetHandle());
|
// store them first, else the enumerated bails on us
|
||||||
|
removedListeners.Add(li);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foreach (int handle in removedListeners)
|
foreach (ListenerInfo li in removedListeners)
|
||||||
{
|
{
|
||||||
m_listeners.Remove(handle);
|
lis.Value.Remove(li);
|
||||||
|
m_curlisteners--;
|
||||||
|
}
|
||||||
|
removedListeners.Clear();
|
||||||
|
if (lis.Value.Count == 0)
|
||||||
|
{
|
||||||
|
// again, store first, remove later
|
||||||
|
emptyChannels.Add(lis.Key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach (int channel in emptyChannels)
|
||||||
|
{
|
||||||
|
m_listeners.Remove(channel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int GetNewHandle()
|
public void Activate(LLUUID itemID, int handle)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < int.MaxValue - 1; i++)
|
lock (m_listeners)
|
||||||
{
|
{
|
||||||
if (!m_listeners.ContainsKey(i))
|
foreach (KeyValuePair<int,List<ListenerInfo>> lis in m_listeners)
|
||||||
|
{
|
||||||
|
foreach (ListenerInfo li in lis.Value)
|
||||||
|
{
|
||||||
|
if (li.GetItemID().Equals(itemID) && li.GetHandle() == handle)
|
||||||
|
{
|
||||||
|
li.Activate();
|
||||||
|
// only one, bail out
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dectivate(LLUUID itemID, int handle)
|
||||||
|
{
|
||||||
|
lock (m_listeners)
|
||||||
|
{
|
||||||
|
foreach (KeyValuePair<int,List<ListenerInfo>> lis in m_listeners)
|
||||||
|
{
|
||||||
|
foreach (ListenerInfo li in lis.Value)
|
||||||
|
{
|
||||||
|
if (li.GetItemID().Equals(itemID) && li.GetHandle() == handle)
|
||||||
|
{
|
||||||
|
li.Deactivate();
|
||||||
|
// only one, bail out
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// non-locked access, since its always called in the context of the lock
|
||||||
|
private int GetNewHandle(LLUUID itemID)
|
||||||
|
{
|
||||||
|
List<int> handles = new List<int>();
|
||||||
|
|
||||||
|
// build a list of used keys for this specific itemID...
|
||||||
|
foreach (KeyValuePair<int,List<ListenerInfo>> lis in m_listeners)
|
||||||
|
{
|
||||||
|
foreach (ListenerInfo li in lis.Value)
|
||||||
|
{
|
||||||
|
if (li.GetItemID().Equals(itemID))
|
||||||
|
handles.Add(li.GetHandle());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: 0 is NOT a valid handle for llListen() to return
|
||||||
|
for (int i = 1; i <= m_maxhandles; i++)
|
||||||
|
{
|
||||||
|
if (!handles.Contains(i))
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
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
|
// Theres probably a more clever and efficient way to
|
||||||
// do this, maybe with regex.
|
// do this, maybe with regex.
|
||||||
public ListenerInfo IsListenerMatch(string sourceItemID, LLUUID listenerKey, int channel, string name,
|
// PM2008: Ha, one could even be smart and define a specialized Enumerator.
|
||||||
string msg)
|
public List<ListenerInfo> GetListeners(LLUUID itemID, int channel, string name, LLUUID id, string msg)
|
||||||
{
|
{
|
||||||
bool isMatch = true;
|
List<ListenerInfo> collection = new List<ListenerInfo>();
|
||||||
lock (m_listeners.SyncRoot)
|
|
||||||
{
|
|
||||||
IDictionaryEnumerator en = m_listeners.GetEnumerator();
|
|
||||||
while (en.MoveNext())
|
|
||||||
{
|
|
||||||
ListenerInfo li = (ListenerInfo) en.Value;
|
|
||||||
|
|
||||||
if (li.IsActive())
|
lock (m_listeners)
|
||||||
{
|
{
|
||||||
if (li.GetHostID().Equals(listenerKey))
|
List<ListenerInfo> listeners;
|
||||||
|
if (!m_listeners.TryGetValue(channel,out listeners))
|
||||||
{
|
{
|
||||||
if (channel == li.GetChannel())
|
return collection;
|
||||||
{
|
|
||||||
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()
|
foreach (ListenerInfo li in listeners)
|
||||||
{
|
{
|
||||||
return m_listeners.Values;
|
if (!li.IsActive())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!itemID.Equals(LLUUID.Zero) && !li.GetItemID().Equals(itemID))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (li.GetName().Length > 0 && !li.GetName().Equals(name))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!li.GetID().Equals(LLUUID.Zero) && !li.GetID().Equals(id))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (li.GetMessage().Length > 0 && !li.GetMessage().Equals(msg))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
collection.Add(li);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return collection;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ListenerInfo
|
public class ListenerInfo
|
||||||
{
|
{
|
||||||
private bool m_active; // Listener is active or not
|
private bool m_active; // Listener is active or not
|
||||||
private int m_channel; // Channel
|
|
||||||
private int m_handle; // Assigned handle of this listener
|
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 uint m_localID; // Local ID from script engine
|
||||||
private string m_message; // The message
|
private LLUUID m_itemID; // ID of the host script engine
|
||||||
|
private LLUUID m_hostID; // ID of the host/scene part
|
||||||
|
private int m_channel; // Channel
|
||||||
|
private LLUUID m_id; // ID to filter messages from
|
||||||
private string m_name; // Object name to filter messages from
|
private string m_name; // Object name to filter messages from
|
||||||
private LLUUID m_sourceItemID; // ID of the scenePart or avatar source of the message
|
private string m_message; // The message
|
||||||
|
|
||||||
public ListenerInfo(uint localID, int handle, LLUUID ItemID, LLUUID hostID, int channel, string name, LLUUID id, string message)
|
public ListenerInfo(int handle, uint localID, LLUUID ItemID, LLUUID hostID, int channel, string name, LLUUID id, string message)
|
||||||
{
|
{
|
||||||
Initialise(localID, handle, ItemID, hostID, channel, name, id, message);
|
Initialise(handle, localID, ItemID, hostID, channel, name, id, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ListenerInfo(uint localID, int handle, LLUUID ItemID, LLUUID hostID, int channel, string name, LLUUID id,
|
public ListenerInfo(ListenerInfo li, string name, LLUUID id, string message)
|
||||||
string message, LLUUID sourceItemID)
|
|
||||||
{
|
{
|
||||||
Initialise(localID, handle, ItemID, hostID, channel, name, id, message);
|
Initialise(li.m_handle, li.m_localID, li.m_itemID, li.m_hostID, li.m_channel, name, id, message);
|
||||||
m_sourceItemID = sourceItemID;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Initialise(uint localID, int handle, LLUUID ItemID, LLUUID hostID, int channel, string name,
|
private void Initialise(int handle, uint localID, LLUUID ItemID, LLUUID hostID, int channel, string name,
|
||||||
LLUUID id, string message)
|
LLUUID id, string message)
|
||||||
{
|
{
|
||||||
|
m_active = true;
|
||||||
m_handle = handle;
|
m_handle = handle;
|
||||||
m_channel = channel;
|
m_localID = localID;
|
||||||
m_itemID = ItemID;
|
m_itemID = ItemID;
|
||||||
m_hostID = hostID;
|
m_hostID = hostID;
|
||||||
|
m_channel = channel;
|
||||||
m_name = name;
|
m_name = name;
|
||||||
m_id = id;
|
m_id = id;
|
||||||
m_message = message;
|
m_message = message;
|
||||||
m_active = true;
|
|
||||||
m_localID = localID;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public LLUUID GetItemID()
|
public LLUUID GetItemID()
|
||||||
|
@ -532,11 +597,6 @@ namespace OpenSim.Region.Environment.Modules.Scripting.WorldComm
|
||||||
return m_hostID;
|
return m_hostID;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LLUUID GetSourceItemID()
|
|
||||||
{
|
|
||||||
return m_sourceItemID;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int GetChannel()
|
public int GetChannel()
|
||||||
{
|
{
|
||||||
return m_channel;
|
return m_channel;
|
||||||
|
|
|
@ -465,7 +465,7 @@ namespace OpenSim.Region.ScriptEngine.Common
|
||||||
ChatTypeEnum.Whisper, channelID, m_host.AbsolutePosition, m_host.Name, m_host.UUID);
|
ChatTypeEnum.Whisper, channelID, m_host.AbsolutePosition, m_host.Name, m_host.UUID);
|
||||||
|
|
||||||
IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
|
IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
|
||||||
wComm.DeliverMessage(m_host.UUID.ToString(), ChatTypeEnum.Whisper, channelID, m_host.Name, text);
|
wComm.DeliverMessage(ChatTypeEnum.Whisper, channelID, m_host.Name, m_host.UUID, text);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void llSay(int channelID, string text)
|
public void llSay(int channelID, string text)
|
||||||
|
@ -475,7 +475,7 @@ namespace OpenSim.Region.ScriptEngine.Common
|
||||||
ChatTypeEnum.Say, channelID, m_host.AbsolutePosition, m_host.Name, m_host.UUID);
|
ChatTypeEnum.Say, channelID, m_host.AbsolutePosition, m_host.Name, m_host.UUID);
|
||||||
|
|
||||||
IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
|
IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
|
||||||
wComm.DeliverMessage(m_host.UUID.ToString(), ChatTypeEnum.Say, channelID, m_host.Name, text);
|
wComm.DeliverMessage(ChatTypeEnum.Say, channelID, m_host.Name, m_host.UUID, text);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void llShout(int channelID, string text)
|
public void llShout(int channelID, string text)
|
||||||
|
@ -485,7 +485,7 @@ namespace OpenSim.Region.ScriptEngine.Common
|
||||||
ChatTypeEnum.Shout, channelID, m_host.AbsolutePosition, m_host.Name, m_host.UUID);
|
ChatTypeEnum.Shout, channelID, m_host.AbsolutePosition, m_host.Name, m_host.UUID);
|
||||||
|
|
||||||
IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
|
IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
|
||||||
wComm.DeliverMessage(m_host.UUID.ToString(), ChatTypeEnum.Shout, channelID, m_host.Name, text);
|
wComm.DeliverMessage(ChatTypeEnum.Shout, channelID, m_host.Name, m_host.UUID, text);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void llRegionSay(int channelID, string text)
|
public void llRegionSay(int channelID, string text)
|
||||||
|
@ -499,32 +499,30 @@ namespace OpenSim.Region.ScriptEngine.Common
|
||||||
m_host.AddScriptLPS(1);
|
m_host.AddScriptLPS(1);
|
||||||
|
|
||||||
IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
|
IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
|
||||||
wComm.DeliverMessage(m_host.UUID.ToString(), ChatTypeEnum.Broadcast, channelID, m_host.Name, text);
|
wComm.DeliverMessage(ChatTypeEnum.Region, channelID, m_host.Name, m_host.UUID, text);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int llListen(int channelID, string name, string ID, string msg)
|
public int llListen(int channelID, string name, string ID, string msg)
|
||||||
{
|
{
|
||||||
m_host.AddScriptLPS(1);
|
m_host.AddScriptLPS(1);
|
||||||
if (ID == String.Empty)
|
LLUUID keyID;
|
||||||
{
|
LLUUID.TryParse(ID, out keyID);
|
||||||
ID = LLUUID.Zero.ToString();
|
|
||||||
}
|
|
||||||
IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
|
IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
|
||||||
return wComm.Listen(m_localID, m_itemID, m_host.UUID, channelID, name, ID, msg);
|
return wComm.Listen(m_localID, m_itemID, m_host.UUID, channelID, name, keyID, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void llListenControl(int number, int active)
|
public void llListenControl(int number, int active)
|
||||||
{
|
{
|
||||||
m_host.AddScriptLPS(1);
|
m_host.AddScriptLPS(1);
|
||||||
IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
|
IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
|
||||||
wComm.ListenControl(number, active);
|
wComm.ListenControl(m_itemID, number, active);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void llListenRemove(int number)
|
public void llListenRemove(int number)
|
||||||
{
|
{
|
||||||
m_host.AddScriptLPS(1);
|
m_host.AddScriptLPS(1);
|
||||||
IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
|
IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
|
||||||
wComm.ListenRemove(number);
|
wComm.ListenRemove(m_itemID, number);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void llSensor(string name, string id, int type, double range, double arc)
|
public void llSensor(string name, string id, int type, double range, double arc)
|
||||||
|
@ -5409,9 +5407,9 @@ namespace OpenSim.Region.ScriptEngine.Common
|
||||||
// llGetOwner ==> m_host.ObjectOwner.ToString()
|
// llGetOwner ==> m_host.ObjectOwner.ToString()
|
||||||
llInstantMessage(m_host.ObjectOwner.ToString(),msg);
|
llInstantMessage(m_host.ObjectOwner.ToString(),msg);
|
||||||
|
|
||||||
//World.SimChat(Helpers.StringToField(msg), ChatTypeEnum.Say, 0, m_host.AbsolutePosition, m_host.Name, m_host.UUID);
|
//World.SimChat(Helpers.StringToField(msg), ChatTypeEnum.Owner, 0, m_host.AbsolutePosition, m_host.Name, m_host.UUID);
|
||||||
//IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
|
//IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
|
||||||
//wComm.DeliverMessage(m_host.UUID.ToString(), ChatTypeEnum.Say, 0, m_host.Name, msg);
|
//wComm.DeliverMessage(ChatTypeEnum.Owner, 0, m_host.Name, m_host.UUID, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void llRequestSimulatorData(string simulator, int data)
|
public void llRequestSimulatorData(string simulator, int data)
|
||||||
|
|
|
@ -32,6 +32,8 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase.AsyncCommandPlugin
|
||||||
{
|
{
|
||||||
public class Listener
|
public class Listener
|
||||||
{
|
{
|
||||||
|
// private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
public AsyncCommandManager m_CmdManager;
|
public AsyncCommandManager m_CmdManager;
|
||||||
|
|
||||||
public Listener(AsyncCommandManager CmdManager)
|
public Listener(AsyncCommandManager CmdManager)
|
||||||
|
@ -48,23 +50,24 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase.AsyncCommandPlugin
|
||||||
if (comms != null)
|
if (comms != null)
|
||||||
{
|
{
|
||||||
while (comms.HasMessages())
|
while (comms.HasMessages())
|
||||||
{
|
|
||||||
if (m_CmdManager.m_ScriptEngine.m_ScriptManager.GetScript(
|
|
||||||
comms.PeekNextMessageLocalID(), comms.PeekNextMessageItemID()) != null)
|
|
||||||
{
|
{
|
||||||
ListenerInfo lInfo = comms.GetNextMessage();
|
ListenerInfo lInfo = comms.GetNextMessage();
|
||||||
|
if (m_CmdManager.m_ScriptEngine.m_ScriptManager.GetScript(
|
||||||
|
lInfo.GetLocalID(), lInfo.GetItemID()) != null)
|
||||||
|
{
|
||||||
//Deliver data to prim's listen handler
|
//Deliver data to prim's listen handler
|
||||||
object[] resobj = new object[]
|
object[] resobj = new object[]
|
||||||
{
|
{
|
||||||
//lInfo.GetChannel(), lInfo.GetName(), lInfo.GetID().ToString(), lInfo.GetMessage()
|
//lInfo.GetChannel(), lInfo.GetName(), lInfo.GetID().ToString(), lInfo.GetMessage()
|
||||||
new LSL_Types.LSLInteger(lInfo.GetChannel()), new LSL_Types.LSLString(lInfo.GetName()), new LSL_Types.LSLString(lInfo.GetSourceItemID().ToString()), new LSL_Types.LSLString(lInfo.GetMessage())
|
new LSL_Types.LSLInteger(lInfo.GetChannel()), new LSL_Types.LSLString(lInfo.GetName()), new LSL_Types.LSLString(lInfo.GetID().ToString()), new LSL_Types.LSLString(lInfo.GetMessage())
|
||||||
};
|
};
|
||||||
|
|
||||||
m_CmdManager.m_ScriptEngine.m_EventQueueManager.AddToScriptQueue(
|
m_CmdManager.m_ScriptEngine.m_EventQueueManager.AddToScriptQueue(
|
||||||
lInfo.GetLocalID(), lInfo.GetItemID(), "listen", EventQueueManager.llDetectNull, resobj
|
lInfo.GetLocalID(), lInfo.GetItemID(), "listen", EventQueueManager.llDetectNull, resobj
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
// else
|
||||||
|
// m_log.Info("[ScriptEngineBase.AsyncCommandPlugins: received a listen event for a (no longer) existing script ("+lInfo.GetLocalID().AsString()+")");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -324,6 +324,14 @@ CleanUpOldScriptsOnStartup=true
|
||||||
; Set the following to true to allow administrator owned scripts to execute console commands
|
; Set the following to true to allow administrator owned scripts to execute console commands
|
||||||
AllowosConsoleCommand=false
|
AllowosConsoleCommand=false
|
||||||
|
|
||||||
|
; Maximum number of llListen events we allow globally in the region
|
||||||
|
; Set this to 0 to have no limit imposed.
|
||||||
|
max_listens_per_region = 1000
|
||||||
|
|
||||||
|
; Maximum number of llListen events we allow per script
|
||||||
|
; Set this to 0 to have no limit imposed.
|
||||||
|
max_listens_per_script = 64
|
||||||
|
|
||||||
[DataSnapshot]
|
[DataSnapshot]
|
||||||
; The following set of configs pertains to search.
|
; The following set of configs pertains to search.
|
||||||
; Set index_sims to true to enable search engines to index your searchable data
|
; Set index_sims to true to enable search engines to index your searchable data
|
||||||
|
|
Loading…
Reference in New Issue