mke sending to listeners code a bit more confusing

This commit is contained in:
UbitUmarov
2022-06-19 01:22:03 +01:00
parent 6e1aa77416
commit adf818370a
3 changed files with 265 additions and 117 deletions

View File

@@ -100,11 +100,13 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
private const int DEBUG_CHANNEL = 0x7fffffff;
private ListenerManager m_listenerManager;
private ConcurrentQueue<ListenerInfo> m_pending;
private ConcurrentQueue<ListenerMessage> m_pending;
private Scene m_scene;
private int m_whisperdistance = 10;
private int m_saydistance = 20;
private int m_shoutdistance = 100;
private int m_maxlisteners = 1000;
private int m_maxhandles = 65;
#region INonSharedRegionModule Members
@@ -112,20 +114,13 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
{
// wrap this in a try block so that defaults will work if
// the config file doesn't specify otherwise.
int maxlisteners = 1000;
int maxhandles = 65;
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["LL-Functions"].GetInt(
"max_listens_per_region", maxlisteners);
maxhandles = config.Configs["LL-Functions"].GetInt(
"max_listens_per_script", maxhandles);
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);
m_maxlisteners = config.Configs["LL-Functions"].GetInt("max_listens_per_region", m_maxlisteners);
m_maxhandles = config.Configs["LL-Functions"].GetInt("max_listens_per_script", m_maxhandles);
}
catch (Exception)
{
@@ -135,16 +130,14 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
m_saydistance *= m_saydistance;
m_shoutdistance *= m_shoutdistance;
if (maxlisteners < 1)
maxlisteners = int.MaxValue;
if (maxhandles < 1)
maxhandles = int.MaxValue;
if (m_maxlisteners < 1)
m_maxlisteners = int.MaxValue;
if (m_maxhandles < 1)
m_maxhandles = int.MaxValue;
if (maxlisteners < maxhandles)
maxlisteners = maxhandles;
if (m_maxlisteners < m_maxhandles)
m_maxlisteners = m_maxhandles;
m_listenerManager = new ListenerManager(maxlisteners, maxhandles);
m_pending = new ConcurrentQueue<ListenerInfo>();
}
public void PostInitialise()
@@ -153,7 +146,9 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
public void AddRegion(Scene scene)
{
m_pending = new ConcurrentQueue<ListenerMessage>();
m_scene = scene;
m_listenerManager = new ListenerManager(m_maxlisteners, m_maxhandles, scene, m_pending);
m_scene.RegisterModuleInterface<IWorldComm>(this);
m_scene.EventManager.OnChatFromClient += DeliverClientMessage;
m_scene.EventManager.OnChatBroadcast += DeliverClientMessage;
@@ -278,15 +273,18 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
public void DeliverMessage(ChatTypeEnum type, int channel, string name, UUID id, string msg)
{
if (type == ChatTypeEnum.Region)
{
m_listenerManager.TryEnqueueMessage(channel, name, id, msg);
return;
}
SceneObjectPart source;
ScenePresence avatar;
if ((source = m_scene.GetSceneObjectPart(id)) != null)
DeliverMessage(type, channel, name, id, msg, source.AbsolutePosition);
else if ((avatar = m_scene.GetScenePresence(id)) != null)
DeliverMessage(type, channel, name, id, msg, avatar.AbsolutePosition);
else if (ChatTypeEnum.Region == type)
DeliverMessage(type, channel, name, id, msg, CenterOfRegion);
}
/// <summary>
@@ -307,6 +305,11 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
{
// m_log.DebugFormat("[WorldComm] got[2] type {0}, channel {1}, name {2}, id {3}, msg {4}",
// type, channel, name, id, msg);
if (type == ChatTypeEnum.Region)
{
m_listenerManager.TryEnqueueMessage(channel, name, id, msg);
return;
}
// validate type and set range
float maxDistanceSQ;
@@ -324,37 +327,11 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
maxDistanceSQ = m_shoutdistance;
break;
case ChatTypeEnum.Region:
maxDistanceSQ = -1f;
break;
default:
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(UUID.Zero, channel, name, id, msg))
{
// Dont process if this message is from yourself!
if (id.Equals(li.HostID))
continue;
if(maxDistanceSQ < 0)
{
QueueMessage(new ListenerInfo(li, name, id, msg));
continue;
}
SceneObjectPart sPart = m_scene.GetSceneObjectPart(li.HostID);
if (sPart == null)
continue;
if(maxDistanceSQ > Vector3.DistanceSquared(sPart.AbsolutePosition, position))
QueueMessage(new ListenerInfo(li, name, id, msg));
}
m_listenerManager.TryEnqueueMessage(channel, position, maxDistanceSQ, name, id, msg);
}
/// <summary>
@@ -405,7 +382,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
return;
// Get uuid of attachments
List<UUID> targets = new List<UUID>();
HashSet<UUID> targets = new HashSet<UUID>();
foreach (SceneObjectGroup sog in attachments)
{
if (!sog.IsDeleted)
@@ -416,18 +393,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
}
}
foreach (ListenerInfo li in m_listenerManager.GetListeners(UUID.Zero, channel, name, id, msg))
{
UUID liHostID = li.HostID;
if (li.HostID.Equals(id))
continue;
if (m_scene.GetSceneObjectPart(liHostID) == null)
continue;
if (targets.Contains(liHostID))
QueueMessage(new ListenerInfo(li, name, id, msg));
}
m_listenerManager.TryEnqueueMessage(channel, targets, name, id, msg);
return;
}
@@ -435,24 +401,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
if (part == null) // Not even an object
return; // No error
foreach (ListenerInfo li in m_listenerManager.GetListeners(UUID.Zero, channel, name, id, msg))
{
UUID liHostID = li.HostID;
// Dont process if this message is from yourself!
if (liHostID.Equals(id))
continue;
if (!liHostID.Equals(target))
continue;
if (m_scene.GetSceneObjectPart(liHostID) == null)
continue;
QueueMessage(new ListenerInfo(li, name, id, msg));
}
}
protected void QueueMessage(ListenerInfo li)
{
m_pending.Enqueue(li);
m_listenerManager.TryEnqueueMessage(channel, target, name, id, msg);
}
/// <summary>
@@ -468,9 +417,9 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
/// Pop the first availlable listen event from the queue
/// </summary>
/// <returns>ListenerInfo with filter filled in</returns>
public IWorldCommListenerInfo GetNextMessage()
public IWorldCommListenerMessage GetNextMessage()
{
m_pending.TryDequeue(out ListenerInfo li);
m_pending.TryDequeue(out ListenerMessage li);
return li;
}
@@ -516,6 +465,9 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
private int m_maxhandles;
private int m_curlisteners;
private Scene m_scene;
private ConcurrentQueue<ListenerMessage> m_messagesQueue;
/// <summary>
/// Total number of listeners
/// </summary>
@@ -528,11 +480,13 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
}
}
public ListenerManager(int maxlisteners, int maxhandles)
public ListenerManager(int maxlisteners, int maxhandles, Scene scene, ConcurrentQueue<ListenerMessage> messagesQueue)
{
m_maxlisteners = maxlisteners;
m_maxhandles = maxhandles;
m_curlisteners = 0;
m_scene = scene;
m_messagesQueue = messagesQueue;
}
public int AddListener(UUID itemID, UUID hostID, int channel, string name, UUID id, string msg)
@@ -732,8 +686,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
/// <param name="id"></param>
/// <param name="msg"></param>
/// <returns></returns>
public List<ListenerInfo> GetListeners(UUID itemID, int channel,
string name, UUID id, string msg)
public List<ListenerInfo> GetListeners(UUID itemID, int channel, string name, UUID id, string msg)
{
List<ListenerInfo> collection = new List<ListenerInfo>();
@@ -745,8 +698,6 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
}
bool itemIDNotZero = itemID.IsNotZero();
bool nameNotEmpty = !string.IsNullOrEmpty(name);
bool msgNotEmpty = !string.IsNullOrEmpty(msg);
foreach (ListenerInfo li in listeners)
{
if (!li.IsActive)
@@ -758,7 +709,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
if (li.ID.IsNotZero() && id.NotEqual(li.ID))
continue;
if (nameNotEmpty && li.Name.Length > 0)
if (li.Name.Length > 0)
{
if ((li.RegexBitfield & OS_LISTEN_REGEX_NAME) == OS_LISTEN_REGEX_NAME)
{
@@ -767,12 +718,12 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
}
else
{
if (!li.Name.Equals(name))
if (!name.Equals(li.Name, StringComparison.InvariantCulture))
continue;
}
}
if (msgNotEmpty && li.Message.Length > 0)
if (li.Message.Length > 0)
{
if ((li.RegexBitfield & OS_LISTEN_REGEX_MESSAGE) == OS_LISTEN_REGEX_MESSAGE)
{
@@ -781,7 +732,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
}
else
{
if (!li.Message.Equals(msg))
if (!msg.Equals(li.Message, StringComparison.InvariantCulture))
continue;
}
}
@@ -791,58 +742,246 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
return collection;
}
public List<ListenerInfo> GetListeners(int channel, string name, UUID id, string msg)
public void TryEnqueueMessage(int channel, Vector3 position, float maxDistanceSQ, string name, UUID id, string msg)
{
List<ListenerInfo> collection = new List<ListenerInfo>();
lock (mainLock)
{
if (!m_listenersByChannel.TryGetValue(channel, out List<ListenerInfo> listeners))
{
return collection;
}
return;
bool nameNotEmpty = !string.IsNullOrEmpty(name);
bool msgNotEmpty = !string.IsNullOrEmpty(msg);
foreach (ListenerInfo li in listeners)
{
if (!li.IsActive)
continue;
if (id.Equals(li.HostID))
continue;
if (li.ID.IsNotZero() && id.NotEqual(li.ID))
continue;
if (nameNotEmpty && li.Name.Length > 0)
if (li.Name.Length > 0)
{
if ((li.RegexBitfield & OS_LISTEN_REGEX_NAME) == OS_LISTEN_REGEX_NAME)
if ((li.RegexBitfield & OS_LISTEN_REGEX_NAME) != 0)
{
if (!Regex.IsMatch(name, li.Name))
continue;
}
else
{
if (!li.Name.Equals(name))
if (!name.Equals(li.Name, StringComparison.InvariantCulture))
continue;
}
}
if (msgNotEmpty && li.Message.Length > 0)
if (li.Message.Length > 0)
{
if ((li.RegexBitfield & OS_LISTEN_REGEX_MESSAGE) == OS_LISTEN_REGEX_MESSAGE)
if ((li.RegexBitfield & OS_LISTEN_REGEX_MESSAGE) != 0)
{
if (!Regex.IsMatch(msg, li.Message))
continue;
}
else
{
if (!li.Message.Equals(msg))
if (!msg.Equals(li.Message, StringComparison.InvariantCulture))
continue;
}
}
collection.Add(li);
SceneObjectPart sPart = m_scene.GetSceneObjectPart(li.HostID);
if (sPart == null)
return;
if (maxDistanceSQ > Vector3.DistanceSquared(sPart.AbsolutePosition, position))
{
m_messagesQueue.Enqueue(new ListenerMessage
{
ItemID = li.ItemID,
ID = id,
Channel = channel,
Name = name,
Message = msg
});
}
}
}
}
public void TryEnqueueMessage(int channel, string name, UUID id, string msg)
{
lock (mainLock)
{
if (!m_listenersByChannel.TryGetValue(channel, out List<ListenerInfo> listeners))
return;
foreach (ListenerInfo li in listeners)
{
if (!li.IsActive)
continue;
if (id.Equals(li.HostID))
continue;
if (li.ID.IsNotZero() && id.NotEqual(li.ID))
continue;
if (li.Name.Length > 0)
{
if ((li.RegexBitfield & OS_LISTEN_REGEX_NAME) != 0)
{
if (!Regex.IsMatch(name, li.Name))
continue;
}
else
{
if (!name.Equals(li.Name, StringComparison.InvariantCulture))
continue;
}
}
if (li.Message.Length > 0)
{
if ((li.RegexBitfield & OS_LISTEN_REGEX_MESSAGE) != 0)
{
if (!Regex.IsMatch(msg, li.Message))
continue;
}
else
{
if (!msg.Equals(li.Message, StringComparison.InvariantCulture))
continue;
}
}
m_messagesQueue.Enqueue(new ListenerMessage
{
ItemID = li.ItemID,
ID = id,
Channel = channel,
Name = name,
Message = msg
});
}
}
}
public void TryEnqueueMessage(int channel, UUID target, string name, UUID id, string msg)
{
lock (mainLock)
{
if (!m_listenersByChannel.TryGetValue(channel, out List<ListenerInfo> listeners))
return;
foreach (ListenerInfo li in listeners)
{
if (!li.IsActive)
continue;
if (id.Equals(li.HostID))
continue;
if (target.NotEqual(li.HostID))
continue;
if (li.ID.IsNotZero() && id.NotEqual(li.ID))
continue;
if (li.Name.Length > 0)
{
if ((li.RegexBitfield & OS_LISTEN_REGEX_NAME) != 0)
{
if (!Regex.IsMatch(name, li.Name))
continue;
}
else
{
if (!name.Equals(li.Name, StringComparison.InvariantCulture))
continue;
}
}
if (li.Message.Length > 0)
{
if ((li.RegexBitfield & OS_LISTEN_REGEX_MESSAGE) != 0)
{
if (!Regex.IsMatch(msg, li.Message))
continue;
}
else
{
if (!msg.Equals(li.Message, StringComparison.InvariantCulture))
continue;
}
}
m_messagesQueue.Enqueue(new ListenerMessage
{
ItemID = li.ItemID,
ID = id,
Channel = channel,
Name = name,
Message = msg
});
}
}
}
public void TryEnqueueMessage(int channel, HashSet<UUID> targets, string name, UUID id, string msg)
{
lock (mainLock)
{
if (!m_listenersByChannel.TryGetValue(channel, out List<ListenerInfo> listeners))
return;
foreach (ListenerInfo li in listeners)
{
if (!li.IsActive)
continue;
if (id.Equals(li.HostID))
continue;
if (!targets.Contains(li.HostID))
continue;
if (li.ID.IsNotZero() && id.NotEqual(li.ID))
continue;
if (li.Name.Length > 0)
{
if ((li.RegexBitfield & OS_LISTEN_REGEX_NAME) != 0)
{
if (!Regex.IsMatch(name, li.Name))
continue;
}
else
{
if (!name.Equals(li.Name, StringComparison.InvariantCulture))
continue;
}
}
if (li.Message.Length > 0)
{
if ((li.RegexBitfield & OS_LISTEN_REGEX_MESSAGE) != 0)
{
if (!Regex.IsMatch(msg, li.Message))
continue;
}
else
{
if (!msg.Equals(li.Message, StringComparison.InvariantCulture))
continue;
}
}
m_messagesQueue.Enqueue(new ListenerMessage
{
ItemID = li.ItemID,
ID = id,
Channel = channel,
Name = name,
Message = msg
});
}
}
return collection;
}
public Object[] GetSerializationData(UUID itemID)
@@ -890,6 +1029,14 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
}
}
}
public class ListenerMessage: IWorldCommListenerMessage
{
public UUID ItemID;
public int Channel;
public UUID ID;
public string Name;
public string Message;
}
public class ListenerInfo : IWorldCommListenerInfo
{