mirror of
https://github.com/opensim/opensim.git
synced 2026-08-08 18:25:33 +08:00
Fix llGetLinkKey() to return the last sat avatar as the last link number.
As per http://wiki.secondlife.com/wiki/LlGetLinkKey This is done by keeping a scene-object wide list of sitters. This also fixes bugs in this function where linknums 0 and 1 weren't treated properly if there were sitting avatars on a single prim. This also fixes a minor race condition for multiple concurrent sitters on a prim with no current sitters by locking on the object-wide list rather than individual sop lists Addresses http://opensimulator.org/mantis/view.php?id=6477
This commit is contained in:
@@ -647,6 +647,18 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
/// </remarks>
|
||||
public UUID FromFolderID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// IDs of all avatars sat on this scene object.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// We need this so that we can maintain a linkset wide ordering of avatars sat on different parts.
|
||||
/// This must be locked before it is read or written.
|
||||
/// SceneObjectPart sitting avatar add/remove code also locks on this object to avoid race conditions.
|
||||
/// No avatar should appear more than once in this list.
|
||||
/// Do not manipulate this list directly - use the Add/Remove sitting avatar methods on SceneObjectPart.
|
||||
/// </remarks>
|
||||
protected internal List<UUID> m_sittingAvatars = new List<UUID>();
|
||||
|
||||
#endregion
|
||||
|
||||
// ~SceneObjectGroup()
|
||||
@@ -3563,6 +3575,20 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
return count;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a copy of the list of sitting avatars on all prims of this object.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is sorted by the order in which avatars sat down. If an avatar stands up then all avatars that sat
|
||||
/// down after it move one place down the list.
|
||||
/// </remarks>
|
||||
/// <returns>A list of the sitting avatars. Returns an empty list if there are no sitting avatars.</returns>
|
||||
public List<UUID> GetSittingAvatars()
|
||||
{
|
||||
lock (m_sittingAvatars)
|
||||
return new List<UUID>(m_sittingAvatars);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of sitting avatars.
|
||||
/// </summary>
|
||||
@@ -3570,11 +3596,8 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
/// <returns></returns>
|
||||
public int GetSittingAvatarsCount()
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
Array.ForEach<SceneObjectPart>(m_parts.GetArray(), p => count += p.GetSittingAvatarsCount());
|
||||
|
||||
return count;
|
||||
lock (m_sittingAvatars)
|
||||
return m_sittingAvatars.Count;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
@@ -3583,7 +3606,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
}
|
||||
|
||||
#region ISceneObject
|
||||
|
||||
|
||||
public virtual ISceneObject CloneForNewScene()
|
||||
{
|
||||
SceneObjectGroup sog = Copy(false);
|
||||
|
||||
@@ -1256,7 +1256,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
public UUID SitTargetAvatar { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// IDs of all avatars start on this object part.
|
||||
/// IDs of all avatars sat on this part.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// We need to track this so that we can stop sat upon prims from being attached.
|
||||
@@ -4504,18 +4504,22 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
/// <param name='avatarId'></param>
|
||||
protected internal bool AddSittingAvatar(UUID avatarId)
|
||||
{
|
||||
if (IsSitTargetSet && SitTargetAvatar == UUID.Zero)
|
||||
SitTargetAvatar = avatarId;
|
||||
|
||||
HashSet<UUID> sittingAvatars = m_sittingAvatars;
|
||||
|
||||
if (sittingAvatars == null)
|
||||
sittingAvatars = new HashSet<UUID>();
|
||||
|
||||
lock (sittingAvatars)
|
||||
lock (ParentGroup.m_sittingAvatars)
|
||||
{
|
||||
m_sittingAvatars = sittingAvatars;
|
||||
return m_sittingAvatars.Add(avatarId);
|
||||
if (IsSitTargetSet && SitTargetAvatar == UUID.Zero)
|
||||
SitTargetAvatar = avatarId;
|
||||
|
||||
if (m_sittingAvatars == null)
|
||||
m_sittingAvatars = new HashSet<UUID>();
|
||||
|
||||
if (m_sittingAvatars.Add(avatarId))
|
||||
{
|
||||
ParentGroup.m_sittingAvatars.Add(avatarId);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4529,27 +4533,26 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
/// <param name='avatarId'></param>
|
||||
protected internal bool RemoveSittingAvatar(UUID avatarId)
|
||||
{
|
||||
if (SitTargetAvatar == avatarId)
|
||||
SitTargetAvatar = UUID.Zero;
|
||||
|
||||
HashSet<UUID> sittingAvatars = m_sittingAvatars;
|
||||
|
||||
// This can occur under a race condition where another thread
|
||||
if (sittingAvatars == null)
|
||||
return false;
|
||||
|
||||
lock (sittingAvatars)
|
||||
lock (ParentGroup.m_sittingAvatars)
|
||||
{
|
||||
if (sittingAvatars.Remove(avatarId))
|
||||
if (SitTargetAvatar == avatarId)
|
||||
SitTargetAvatar = UUID.Zero;
|
||||
|
||||
if (m_sittingAvatars == null)
|
||||
return false;
|
||||
|
||||
if (m_sittingAvatars.Remove(avatarId))
|
||||
{
|
||||
if (sittingAvatars.Count == 0)
|
||||
if (m_sittingAvatars.Count == 0)
|
||||
m_sittingAvatars = null;
|
||||
|
||||
ParentGroup.m_sittingAvatars.Remove(avatarId);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -4559,16 +4562,12 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
/// <returns>A hashset of the sitting avatars. Returns null if there are no sitting avatars.</returns>
|
||||
public HashSet<UUID> GetSittingAvatars()
|
||||
{
|
||||
HashSet<UUID> sittingAvatars = m_sittingAvatars;
|
||||
|
||||
if (sittingAvatars == null)
|
||||
lock (ParentGroup.m_sittingAvatars)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
lock (sittingAvatars)
|
||||
return new HashSet<UUID>(sittingAvatars);
|
||||
if (m_sittingAvatars == null)
|
||||
return null;
|
||||
else
|
||||
return new HashSet<UUID>(m_sittingAvatars);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4579,13 +4578,13 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
/// <returns></returns>
|
||||
public int GetSittingAvatarsCount()
|
||||
{
|
||||
HashSet<UUID> sittingAvatars = m_sittingAvatars;
|
||||
|
||||
if (sittingAvatars == null)
|
||||
return 0;
|
||||
|
||||
lock (sittingAvatars)
|
||||
return sittingAvatars.Count;
|
||||
lock (ParentGroup.m_sittingAvatars)
|
||||
{
|
||||
if (m_sittingAvatars == null)
|
||||
return 0;
|
||||
else
|
||||
return m_sittingAvatars.Count;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user