From ae355720abb70f0f27b3dcc7b711c76483ac0d07 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 4 Jan 2013 20:34:39 +0000 Subject: 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 --- .../Shared/Api/Implementation/LSL_Api.cs | 48 ++++++++++++++-------- 1 file changed, 31 insertions(+), 17 deletions(-) (limited to 'OpenSim/Region/ScriptEngine/Shared/Api/Implementation') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 75749a9..f31bbff 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -3738,33 +3738,47 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_String llGetLinkKey(int linknum) { m_host.AddScriptLPS(1); - List keytable = new List(); - // parse for sitting avatare-uuids - World.ForEachRootScenePresence(delegate(ScenePresence presence) - { - if (presence.ParentID != 0 && m_host.ParentGroup.ContainsPart(presence.ParentID)) - keytable.Add(presence.UUID); - }); - int totalprims = m_host.ParentGroup.PrimCount + keytable.Count; - if (linknum > m_host.ParentGroup.PrimCount && linknum <= totalprims) + if (linknum < 0) { - return keytable[totalprims - linknum].ToString(); + if (linknum == ScriptBaseClass.LINK_THIS) + return m_host.UUID.ToString(); + else + return ScriptBaseClass.NULL_KEY; } - if (linknum == 1 && m_host.ParentGroup.PrimCount == 1 && keytable.Count == 1) + int actualPrimCount = m_host.ParentGroup.PrimCount; + List sittingAvatarIds = m_host.ParentGroup.GetSittingAvatars(); + int adjustedPrimCount = actualPrimCount + sittingAvatarIds.Count; + + // Special case for a single prim. In this case the linknum is zero. However, this will not match a single + // prim that has any avatars sat upon it (in which case the root prim is link 1). + if (linknum == 0) { - return m_host.UUID.ToString(); - } + if (actualPrimCount == 1 && sittingAvatarIds.Count == 0) + return m_host.UUID.ToString(); - SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum); - if (part != null) + return ScriptBaseClass.NULL_KEY; + } + // Special case to handle a single prim with sitting avatars. GetLinkPart() would only match zero but + // here we must match 1 (ScriptBaseClass.LINK_ROOT). + else if (linknum == 1 && actualPrimCount == 1) { - return part.UUID.ToString(); + if (sittingAvatarIds.Count > 0) + return m_host.ParentGroup.RootPart.UUID.ToString(); + else + return ScriptBaseClass.NULL_KEY; + } + else if (linknum <= adjustedPrimCount) + { + if (linknum <= actualPrimCount) + return m_host.ParentGroup.GetLinkNumPart(linknum).UUID.ToString(); + else + return sittingAvatarIds[linknum - actualPrimCount - 1].ToString(); } else { - return UUID.Zero.ToString(); + return ScriptBaseClass.NULL_KEY; } } -- cgit v1.1