From: Michael Osias <mosias@us.ibm.com>
Fixes mantis 771 - multiple uses of llListen cause duplicate events Thanks Michael!0.6.0-stable
parent
9117dfc858
commit
45b9114df7
OpenSim/Region/Environment/Modules
|
@ -26,6 +26,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using libsecondlife;
|
using libsecondlife;
|
||||||
using Nini.Config;
|
using Nini.Config;
|
||||||
|
@ -72,8 +73,8 @@ namespace OpenSim.Region.Environment.Modules
|
||||||
private object ListLock = new object();
|
private object ListLock = new object();
|
||||||
private string m_name = "WorldCommModule";
|
private string m_name = "WorldCommModule";
|
||||||
private ListenerManager m_listenerManager;
|
private ListenerManager m_listenerManager;
|
||||||
private Queue<ListenerInfo> m_pending;
|
private Queue m_pendingQ;
|
||||||
|
private Queue m_pending;
|
||||||
public WorldCommModule()
|
public WorldCommModule()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -84,7 +85,8 @@ namespace OpenSim.Region.Environment.Modules
|
||||||
m_scene.RegisterModuleInterface<IWorldComm>(this);
|
m_scene.RegisterModuleInterface<IWorldComm>(this);
|
||||||
m_listenerManager = new ListenerManager();
|
m_listenerManager = new ListenerManager();
|
||||||
m_scene.EventManager.OnNewClient += NewClient;
|
m_scene.EventManager.OnNewClient += NewClient;
|
||||||
m_pending = new Queue<ListenerInfo>();
|
m_pendingQ = new Queue();
|
||||||
|
m_pending = Queue.Synchronized(m_pendingQ);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PostInitialise()
|
public void PostInitialise()
|
||||||
|
@ -125,27 +127,29 @@ namespace OpenSim.Region.Environment.Modules
|
||||||
|
|
||||||
public void ListenControl(int handle, int active)
|
public void ListenControl(int handle, int active)
|
||||||
{
|
{
|
||||||
if (active == 1)
|
if (m_listenerManager != null)
|
||||||
m_listenerManager.Activate(handle);
|
{
|
||||||
else if (active == 0)
|
if (active == 1)
|
||||||
m_listenerManager.Dectivate(handle);
|
m_listenerManager.Activate(handle);
|
||||||
|
else if (active == 0)
|
||||||
|
m_listenerManager.Dectivate(handle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ListenRemove(int handle)
|
public void ListenRemove(int handle)
|
||||||
{
|
{
|
||||||
m_listenerManager.Remove(handle);
|
if (m_listenerManager != null)
|
||||||
|
{
|
||||||
|
m_listenerManager.Remove(handle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DeleteListener(LLUUID itemID)
|
public void DeleteListener(LLUUID itemID)
|
||||||
{
|
{
|
||||||
if (m_listenerManager != null)
|
if (m_listenerManager != null)
|
||||||
{
|
{
|
||||||
lock (ListLock)
|
m_listenerManager.DeleteListener(itemID);
|
||||||
{
|
|
||||||
m_listenerManager.DeleteListener(itemID);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This method scans nearby objects and determines if they are listeners,
|
// This method scans nearby objects and determines if they are listeners,
|
||||||
|
@ -175,87 +179,99 @@ namespace OpenSim.Region.Environment.Modules
|
||||||
|
|
||||||
m_scene.Entities.TryGetValue(li.GetHostID(), out sPart);
|
m_scene.Entities.TryGetValue(li.GetHostID(), out sPart);
|
||||||
|
|
||||||
// Dont process if this message is from itself!
|
if(sPart != null)
|
||||||
if (li.GetHostID().ToString().Equals(sourceItemID) ||
|
|
||||||
sPart.UUID.ToString().Equals(sourceItemID))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
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:
|
// Dont process if this message is from itself!
|
||||||
|
if (li.GetHostID().ToString().Equals(sourceItemID) ||
|
||||||
|
sPart.UUID.ToString().Equals(sourceItemID))
|
||||||
|
continue;
|
||||||
|
|
||||||
if ((dis < 10) && (dis > -10))
|
double dis = 0;
|
||||||
{
|
|
||||||
ListenerInfo isListener = m_listenerManager.IsListenerMatch(
|
if (source != null)
|
||||||
sourceItemID, sPart.UUID, channel, name, msg
|
dis = Util.GetDistanceTo(sPart.AbsolutePosition, source.AbsolutePosition);
|
||||||
);
|
else
|
||||||
if (isListener != null)
|
dis = Util.GetDistanceTo(sPart.AbsolutePosition, avatar.AbsolutePosition);
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case ChatTypeEnum.Whisper:
|
||||||
|
|
||||||
|
if ((dis < 10) && (dis > -10))
|
||||||
{
|
{
|
||||||
lock (CommListLock)
|
if (li.GetChannel() == channel)
|
||||||
{
|
{
|
||||||
m_pending.Enqueue(isListener);
|
ListenerInfo isListener = m_listenerManager.IsListenerMatch(
|
||||||
|
sourceItemID, sPart.UUID, channel, name, msg
|
||||||
|
);
|
||||||
|
if (isListener != null)
|
||||||
|
{
|
||||||
|
lock (m_pending.SyncRoot)
|
||||||
|
{
|
||||||
|
m_pending.Enqueue(isListener);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
break;
|
|
||||||
|
|
||||||
case ChatTypeEnum.Say:
|
case ChatTypeEnum.Say:
|
||||||
|
|
||||||
if ((dis < 30) && (dis > -30))
|
if ((dis < 30) && (dis > -30))
|
||||||
{
|
|
||||||
ListenerInfo isListener = m_listenerManager.IsListenerMatch(
|
|
||||||
sourceItemID, sPart.UUID, channel, name, msg
|
|
||||||
);
|
|
||||||
if (isListener != null)
|
|
||||||
{
|
{
|
||||||
lock (CommListLock)
|
if (li.GetChannel() == channel)
|
||||||
{
|
{
|
||||||
m_pending.Enqueue(isListener);
|
ListenerInfo isListener = m_listenerManager.IsListenerMatch(
|
||||||
|
sourceItemID, sPart.UUID, channel, name, msg
|
||||||
|
);
|
||||||
|
if (isListener != null)
|
||||||
|
{
|
||||||
|
lock (m_pending.SyncRoot)
|
||||||
|
{
|
||||||
|
m_pending.Enqueue(isListener);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
break;
|
|
||||||
|
|
||||||
case ChatTypeEnum.Shout:
|
case ChatTypeEnum.Shout:
|
||||||
if ((dis < 100) && (dis > -100))
|
if ((dis < 100) && (dis > -100))
|
||||||
{
|
|
||||||
ListenerInfo isListener = m_listenerManager.IsListenerMatch(
|
|
||||||
sourceItemID, sPart.UUID, channel, name, msg
|
|
||||||
);
|
|
||||||
if (isListener != null)
|
|
||||||
{
|
{
|
||||||
lock (CommListLock)
|
if (li.GetChannel() == channel)
|
||||||
{
|
{
|
||||||
m_pending.Enqueue(isListener);
|
ListenerInfo isListener = m_listenerManager.IsListenerMatch(
|
||||||
|
sourceItemID, sPart.UUID, channel, name, msg
|
||||||
|
);
|
||||||
|
if (isListener != null)
|
||||||
|
{
|
||||||
|
lock (m_pending.SyncRoot)
|
||||||
|
{
|
||||||
|
m_pending.Enqueue(isListener);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
break;
|
|
||||||
|
|
||||||
case ChatTypeEnum.Broadcast:
|
case ChatTypeEnum.Broadcast:
|
||||||
ListenerInfo isListen =
|
ListenerInfo isListen =
|
||||||
m_listenerManager.IsListenerMatch(sourceItemID, li.GetItemID(), channel, name, msg);
|
m_listenerManager.IsListenerMatch(sourceItemID, li.GetItemID(), channel, name, msg);
|
||||||
if (isListen != null)
|
if (isListen != null)
|
||||||
{
|
|
||||||
ListenerInfo isListener = m_listenerManager.IsListenerMatch(
|
|
||||||
sourceItemID, sPart.UUID, channel, name, msg
|
|
||||||
);
|
|
||||||
if (isListener != null)
|
|
||||||
{
|
{
|
||||||
lock (CommListLock)
|
ListenerInfo isListener = m_listenerManager.IsListenerMatch(
|
||||||
|
sourceItemID, sPart.UUID, channel, name, msg
|
||||||
|
);
|
||||||
|
if (isListener != null)
|
||||||
{
|
{
|
||||||
m_pending.Enqueue(isListener);
|
lock (m_pending.SyncRoot)
|
||||||
|
{
|
||||||
|
m_pending.Enqueue(isListener);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
break;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -273,9 +289,9 @@ namespace OpenSim.Region.Environment.Modules
|
||||||
{
|
{
|
||||||
ListenerInfo li = null;
|
ListenerInfo li = null;
|
||||||
|
|
||||||
lock (CommListLock)
|
lock (m_pending.SyncRoot)
|
||||||
{
|
{
|
||||||
li = m_pending.Dequeue();
|
li = (ListenerInfo) m_pending.Dequeue();
|
||||||
}
|
}
|
||||||
|
|
||||||
return li;
|
return li;
|
||||||
|
@ -283,12 +299,12 @@ namespace OpenSim.Region.Environment.Modules
|
||||||
|
|
||||||
public uint PeekNextMessageLocalID()
|
public uint PeekNextMessageLocalID()
|
||||||
{
|
{
|
||||||
return m_pending.Peek().GetLocalID();
|
return ((ListenerInfo)m_pending.Peek()).GetLocalID();
|
||||||
}
|
}
|
||||||
|
|
||||||
public LLUUID PeekNextMessageItemID()
|
public LLUUID PeekNextMessageItemID()
|
||||||
{
|
{
|
||||||
return m_pending.Peek().GetItemID();
|
return ((ListenerInfo)m_pending.Peek()).GetItemID();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -298,15 +314,11 @@ namespace OpenSim.Region.Environment.Modules
|
||||||
// localID: local ID of host engine
|
// localID: local ID of host engine
|
||||||
public class ListenerManager
|
public class ListenerManager
|
||||||
{
|
{
|
||||||
private Dictionary<int, ListenerInfo> m_listeners;
|
//private Dictionary<int, ListenerInfo> m_listeners;
|
||||||
|
private Hashtable m_listeners = Hashtable.Synchronized(new Hashtable());
|
||||||
private object ListenersLock = new object();
|
private object ListenersLock = new object();
|
||||||
private int m_MaxListeners = 100;
|
private int m_MaxListeners = 100;
|
||||||
|
|
||||||
public ListenerManager()
|
|
||||||
{
|
|
||||||
m_listeners = new Dictionary<int, ListenerInfo>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public int AddListener(uint localID, LLUUID itemID, LLUUID hostID, int channel, string name, string id, string msg)
|
public int AddListener(uint localID, LLUUID itemID, LLUUID hostID, int channel, string name, string id, string msg)
|
||||||
{
|
{
|
||||||
if (m_listeners.Count < m_MaxListeners)
|
if (m_listeners.Count < m_MaxListeners)
|
||||||
|
@ -321,7 +333,7 @@ namespace OpenSim.Region.Environment.Modules
|
||||||
{
|
{
|
||||||
ListenerInfo li = new ListenerInfo(localID, newHandle, itemID, hostID, channel, name, id, msg);
|
ListenerInfo li = new ListenerInfo(localID, newHandle, itemID, hostID, channel, name, id, msg);
|
||||||
|
|
||||||
lock (ListenersLock)
|
lock (m_listeners.SyncRoot)
|
||||||
{
|
{
|
||||||
m_listeners.Add(newHandle, li);
|
m_listeners.Add(newHandle, li);
|
||||||
}
|
}
|
||||||
|
@ -336,17 +348,30 @@ namespace OpenSim.Region.Environment.Modules
|
||||||
|
|
||||||
public void Remove(int handle)
|
public void Remove(int handle)
|
||||||
{
|
{
|
||||||
m_listeners.Remove(handle);
|
lock (m_listeners.SyncRoot)
|
||||||
|
{
|
||||||
|
m_listeners.Remove(handle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DeleteListener(LLUUID itemID)
|
public void DeleteListener(LLUUID itemID)
|
||||||
{
|
{
|
||||||
foreach (ListenerInfo li in m_listeners.Values)
|
ArrayList removedListeners = new ArrayList();
|
||||||
|
|
||||||
|
lock (m_listeners.SyncRoot)
|
||||||
{
|
{
|
||||||
if (li.GetItemID().Equals(itemID))
|
IDictionaryEnumerator en = m_listeners.GetEnumerator();
|
||||||
|
while (en.MoveNext())
|
||||||
{
|
{
|
||||||
Remove(li.GetHandle());
|
ListenerInfo li = (ListenerInfo)en.Value;
|
||||||
return;
|
if (li.GetItemID().Equals(itemID))
|
||||||
|
{
|
||||||
|
removedListeners.Add(li.GetHandle());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach (int handle in removedListeners)
|
||||||
|
{
|
||||||
|
m_listeners.Remove(handle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -375,20 +400,23 @@ namespace OpenSim.Region.Environment.Modules
|
||||||
|
|
||||||
public void Activate(int handle)
|
public void Activate(int handle)
|
||||||
{
|
{
|
||||||
ListenerInfo li;
|
|
||||||
|
|
||||||
if (m_listeners.TryGetValue(handle, out li))
|
if (m_listeners.ContainsKey(handle))
|
||||||
{
|
{
|
||||||
li.Activate();
|
lock (m_listeners.SyncRoot)
|
||||||
|
{
|
||||||
|
ListenerInfo li = (ListenerInfo)m_listeners[handle];
|
||||||
|
li.Activate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dectivate(int handle)
|
public void Dectivate(int handle)
|
||||||
{
|
{
|
||||||
ListenerInfo li;
|
|
||||||
|
|
||||||
if (m_listeners.TryGetValue(handle, out li))
|
if (m_listeners.ContainsKey(handle))
|
||||||
{
|
{
|
||||||
|
ListenerInfo li = (ListenerInfo)m_listeners[handle];
|
||||||
li.Deactivate();
|
li.Deactivate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -399,36 +427,41 @@ namespace OpenSim.Region.Environment.Modules
|
||||||
string msg)
|
string msg)
|
||||||
{
|
{
|
||||||
bool isMatch = true;
|
bool isMatch = true;
|
||||||
|
lock (m_listeners.SyncRoot)
|
||||||
foreach (ListenerInfo li in m_listeners.Values)
|
|
||||||
{
|
{
|
||||||
if (li.GetHostID().Equals(listenerKey))
|
IDictionaryEnumerator en = m_listeners.GetEnumerator();
|
||||||
|
while (en.MoveNext())
|
||||||
{
|
{
|
||||||
if (li.IsActive())
|
ListenerInfo li = (ListenerInfo)en.Value;
|
||||||
|
|
||||||
|
if (li.GetHostID().Equals(listenerKey))
|
||||||
{
|
{
|
||||||
if (channel == li.GetChannel())
|
if (li.IsActive())
|
||||||
{
|
{
|
||||||
if ((li.GetID().ToString().Length > 0) &&
|
if (channel == li.GetChannel())
|
||||||
(!li.GetID().Equals(LLUUID.Zero)))
|
|
||||||
{
|
{
|
||||||
if (!li.GetID().ToString().Equals(sourceItemID))
|
if ((li.GetID().ToString().Length > 0) &&
|
||||||
|
(!li.GetID().Equals(LLUUID.Zero)))
|
||||||
{
|
{
|
||||||
isMatch = false;
|
if (!li.GetID().ToString().Equals(sourceItemID))
|
||||||
|
{
|
||||||
|
isMatch = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
if (isMatch && (li.GetName().Length > 0))
|
||||||
if (isMatch && (li.GetName().Length > 0))
|
|
||||||
{
|
|
||||||
if (li.GetName().Equals(name))
|
|
||||||
{
|
{
|
||||||
isMatch = false;
|
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)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (isMatch)
|
|
||||||
{
|
|
||||||
return new ListenerInfo(
|
|
||||||
li.GetLocalID(), li.GetHandle(), li.GetItemID(), li.GetHostID(),
|
|
||||||
li.GetChannel(), name, li.GetID(), msg, new LLUUID(sourceItemID)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -437,7 +470,7 @@ namespace OpenSim.Region.Environment.Modules
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Dictionary<int, ListenerInfo>.ValueCollection GetListeners()
|
public ICollection GetListeners()
|
||||||
{
|
{
|
||||||
return m_listeners.Values;
|
return m_listeners.Values;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue