Make SP.Attachments available as sp.GetAttachments() instead.
The approach here, as in other parts of OpenSim, is to return a copy of the list rather than the attachments list itself This prevents callers from forgetting to lock the list when they read it, as was happening in various parts of the codebase. It also improves liveness. This might improve attachment anomolies when performing region crossings.remove-scene-viewer
parent
2acfff9f6d
commit
32444d98cb
|
@ -136,10 +136,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||||
|
|
||||||
public void SaveChangedAttachments(IScenePresence sp)
|
public void SaveChangedAttachments(IScenePresence sp)
|
||||||
{
|
{
|
||||||
// Need to copy this list because DetachToInventoryPrep mods it
|
foreach (SceneObjectGroup grp in sp.GetAttachments())
|
||||||
List<SceneObjectGroup> attachments = new List<SceneObjectGroup>(sp.Attachments);
|
|
||||||
|
|
||||||
foreach (SceneObjectGroup grp in attachments)
|
|
||||||
{
|
{
|
||||||
if (grp.HasGroupChanged) // Resizer scripts?
|
if (grp.HasGroupChanged) // Resizer scripts?
|
||||||
{
|
{
|
||||||
|
@ -273,14 +270,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||||
|
|
||||||
// Remove any previous attachments
|
// Remove any previous attachments
|
||||||
UUID itemID = UUID.Zero;
|
UUID itemID = UUID.Zero;
|
||||||
foreach (SceneObjectGroup grp in sp.Attachments)
|
|
||||||
{
|
List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt);
|
||||||
if (grp.AttachmentPoint == attachmentPt)
|
|
||||||
{
|
// At the moment we can only deal with a single attachment
|
||||||
itemID = grp.GetFromItemID();
|
if (attachments.Count != 0)
|
||||||
break;
|
itemID = attachments[0].GetFromItemID();
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (itemID != UUID.Zero)
|
if (itemID != UUID.Zero)
|
||||||
DetachSingleAttachmentToInv(itemID, sp);
|
DetachSingleAttachmentToInv(itemID, sp);
|
||||||
|
|
|
@ -106,7 +106,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
|
||||||
|
|
||||||
// Check status on scene presence
|
// Check status on scene presence
|
||||||
Assert.That(m_presence.HasAttachments(), Is.True);
|
Assert.That(m_presence.HasAttachments(), Is.True);
|
||||||
List<SceneObjectGroup> attachments = m_presence.Attachments;
|
List<SceneObjectGroup> attachments = m_presence.GetAttachments();
|
||||||
Assert.That(attachments.Count, Is.EqualTo(1));
|
Assert.That(attachments.Count, Is.EqualTo(1));
|
||||||
SceneObjectGroup attSo = attachments[0];
|
SceneObjectGroup attSo = attachments[0];
|
||||||
Assert.That(attSo.Name, Is.EqualTo(attName));
|
Assert.That(attSo.Name, Is.EqualTo(attName));
|
||||||
|
@ -140,7 +140,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
|
||||||
|
|
||||||
// Check scene presence status
|
// Check scene presence status
|
||||||
Assert.That(m_presence.HasAttachments(), Is.True);
|
Assert.That(m_presence.HasAttachments(), Is.True);
|
||||||
List<SceneObjectGroup> attachments = m_presence.Attachments;
|
List<SceneObjectGroup> attachments = m_presence.GetAttachments();
|
||||||
Assert.That(attachments.Count, Is.EqualTo(1));
|
Assert.That(attachments.Count, Is.EqualTo(1));
|
||||||
SceneObjectGroup attSo = attachments[0];
|
SceneObjectGroup attSo = attachments[0];
|
||||||
Assert.That(attSo.Name, Is.EqualTo(attName));
|
Assert.That(attSo.Name, Is.EqualTo(attName));
|
||||||
|
@ -174,7 +174,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
|
||||||
|
|
||||||
// Check scene presence status
|
// Check scene presence status
|
||||||
Assert.That(m_presence.HasAttachments(), Is.False);
|
Assert.That(m_presence.HasAttachments(), Is.False);
|
||||||
List<SceneObjectGroup> attachments = m_presence.Attachments;
|
List<SceneObjectGroup> attachments = m_presence.GetAttachments();
|
||||||
Assert.That(attachments.Count, Is.EqualTo(0));
|
Assert.That(attachments.Count, Is.EqualTo(0));
|
||||||
|
|
||||||
// Check appearance status
|
// Check appearance status
|
||||||
|
@ -208,7 +208,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
|
||||||
|
|
||||||
// Check status on scene presence
|
// Check status on scene presence
|
||||||
Assert.That(m_presence.HasAttachments(), Is.False);
|
Assert.That(m_presence.HasAttachments(), Is.False);
|
||||||
List<SceneObjectGroup> attachments = m_presence.Attachments;
|
List<SceneObjectGroup> attachments = m_presence.GetAttachments();
|
||||||
Assert.That(attachments.Count, Is.EqualTo(0));
|
Assert.That(attachments.Count, Is.EqualTo(0));
|
||||||
|
|
||||||
// Check item status
|
// Check item status
|
||||||
|
@ -237,7 +237,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
|
||||||
ScenePresence presence = SceneHelpers.AddScenePresence(scene, acd);
|
ScenePresence presence = SceneHelpers.AddScenePresence(scene, acd);
|
||||||
|
|
||||||
Assert.That(presence.HasAttachments(), Is.True);
|
Assert.That(presence.HasAttachments(), Is.True);
|
||||||
List<SceneObjectGroup> attachments = presence.Attachments;
|
List<SceneObjectGroup> attachments = presence.GetAttachments();
|
||||||
|
|
||||||
Assert.That(attachments.Count, Is.EqualTo(1));
|
Assert.That(attachments.Count, Is.EqualTo(1));
|
||||||
SceneObjectGroup attSo = attachments[0];
|
SceneObjectGroup attSo = attachments[0];
|
||||||
|
|
|
@ -208,7 +208,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
sp.ControllingClient.SendLocalTeleport(position, lookAt, teleportFlags);
|
sp.ControllingClient.SendLocalTeleport(position, lookAt, teleportFlags);
|
||||||
sp.Teleport(position);
|
sp.Teleport(position);
|
||||||
|
|
||||||
foreach (SceneObjectGroup grp in sp.Attachments)
|
foreach (SceneObjectGroup grp in sp.GetAttachments())
|
||||||
sp.Scene.EventManager.TriggerOnScriptChangedEvent(grp.LocalId, (uint)Changed.TELEPORT);
|
sp.Scene.EventManager.TriggerOnScriptChangedEvent(grp.LocalId, (uint)Changed.TELEPORT);
|
||||||
}
|
}
|
||||||
else // Another region possibly in another simulator
|
else // Another region possibly in another simulator
|
||||||
|
@ -559,11 +559,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
|
|
||||||
protected virtual void AgentHasMovedAway(ScenePresence sp, bool logout)
|
protected virtual void AgentHasMovedAway(ScenePresence sp, bool logout)
|
||||||
{
|
{
|
||||||
foreach (SceneObjectGroup sop in sp.Attachments)
|
foreach (SceneObjectGroup sop in sp.GetAttachments())
|
||||||
{
|
{
|
||||||
sop.Scene.DeleteSceneObject(sop, true);
|
sop.Scene.DeleteSceneObject(sop, true);
|
||||||
}
|
}
|
||||||
sp.Attachments.Clear();
|
sp.ClearAttachments();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void KillEntity(Scene scene, uint localID)
|
protected void KillEntity(Scene scene, uint localID)
|
||||||
|
@ -1764,34 +1764,33 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
|
|
||||||
protected bool CrossAttachmentsIntoNewRegion(GridRegion destination, ScenePresence sp, bool silent)
|
protected bool CrossAttachmentsIntoNewRegion(GridRegion destination, ScenePresence sp, bool silent)
|
||||||
{
|
{
|
||||||
List<SceneObjectGroup> m_attachments = sp.Attachments;
|
List<SceneObjectGroup> m_attachments = sp.GetAttachments();
|
||||||
lock (m_attachments)
|
|
||||||
|
// Validate
|
||||||
|
foreach (SceneObjectGroup gobj in m_attachments)
|
||||||
{
|
{
|
||||||
// Validate
|
if (gobj == null || gobj.IsDeleted)
|
||||||
foreach (SceneObjectGroup gobj in m_attachments)
|
return false;
|
||||||
{
|
|
||||||
if (gobj == null || gobj.IsDeleted)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (SceneObjectGroup gobj in m_attachments)
|
|
||||||
{
|
|
||||||
// If the prim group is null then something must have happened to it!
|
|
||||||
if (gobj != null && gobj.RootPart != null)
|
|
||||||
{
|
|
||||||
// Set the parent localID to 0 so it transfers over properly.
|
|
||||||
gobj.RootPart.SetParentLocalId(0);
|
|
||||||
gobj.AbsolutePosition = gobj.RootPart.AttachedPos;
|
|
||||||
gobj.IsAttachment = false;
|
|
||||||
//gobj.RootPart.LastOwnerID = gobj.GetFromAssetID();
|
|
||||||
m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Sending attachment {0} to region {1}", gobj.UUID, destination.RegionName);
|
|
||||||
CrossPrimGroupIntoNewRegion(destination, gobj, silent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m_attachments.Clear();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach (SceneObjectGroup gobj in m_attachments)
|
||||||
|
{
|
||||||
|
// If the prim group is null then something must have happened to it!
|
||||||
|
if (gobj != null && gobj.RootPart != null)
|
||||||
|
{
|
||||||
|
// Set the parent localID to 0 so it transfers over properly.
|
||||||
|
gobj.RootPart.SetParentLocalId(0);
|
||||||
|
gobj.AbsolutePosition = gobj.RootPart.AttachedPos;
|
||||||
|
gobj.IsAttachment = false;
|
||||||
|
//gobj.RootPart.LastOwnerID = gobj.GetFromAssetID();
|
||||||
|
m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Sending attachment {0} to region {1}", gobj.UUID, destination.RegionName);
|
||||||
|
CrossPrimGroupIntoNewRegion(destination, gobj, silent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sp.ClearAttachments();
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -1840,7 +1839,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
int i = 0;
|
int i = 0;
|
||||||
if (sp.InTransitScriptStates.Count > 0)
|
if (sp.InTransitScriptStates.Count > 0)
|
||||||
{
|
{
|
||||||
sp.Attachments.ForEach(delegate(SceneObjectGroup sog)
|
List<SceneObjectGroup> attachments = sp.GetAttachments();
|
||||||
|
|
||||||
|
foreach (SceneObjectGroup sog in attachments)
|
||||||
{
|
{
|
||||||
if (i < sp.InTransitScriptStates.Count)
|
if (i < sp.InTransitScriptStates.Count)
|
||||||
{
|
{
|
||||||
|
@ -1849,8 +1850,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
sog.ResumeScripts();
|
sog.ResumeScripts();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
m_log.ErrorFormat("[ENTITY TRANSFER MODULE]: InTransitScriptStates.Count={0} smaller than Attachments.Count={1}", sp.InTransitScriptStates.Count, sp.Attachments.Count);
|
m_log.ErrorFormat(
|
||||||
});
|
"[ENTITY TRANSFER MODULE]: InTransitScriptStates.Count={0} smaller than Attachments.Count={1}",
|
||||||
|
sp.InTransitScriptStates.Count, attachments.Count);
|
||||||
|
}
|
||||||
|
|
||||||
sp.InTransitScriptStates.Clear();
|
sp.InTransitScriptStates.Clear();
|
||||||
}
|
}
|
||||||
|
|
|
@ -283,7 +283,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Delivers the message to.
|
/// Delivers the message to a scene entity.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name='target'>
|
/// <param name='target'>
|
||||||
/// Target.
|
/// Target.
|
||||||
|
@ -314,17 +314,19 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
|
||||||
m_scene.SimChatBroadcast(Utils.StringToBytes(msg), ChatTypeEnum.Owner, 0, pos, name, id, false);
|
m_scene.SimChatBroadcast(Utils.StringToBytes(msg), ChatTypeEnum.Owner, 0, pos, name, id, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<SceneObjectGroup> attachments = sp.Attachments;
|
List<SceneObjectGroup> attachments = sp.GetAttachments();
|
||||||
|
|
||||||
// Nothing left to do
|
// Nothing left to do
|
||||||
if (attachments == null)
|
if (attachments == null)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// Get uuid of attachments
|
// Get uuid of attachments
|
||||||
List<UUID> targets = new List<UUID>();
|
List<UUID> targets = new List<UUID>();
|
||||||
foreach ( SceneObjectGroup sog in attachments )
|
foreach (SceneObjectGroup sog in attachments)
|
||||||
{
|
{
|
||||||
targets.Add(sog.UUID);
|
targets.Add(sog.UUID);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Need to check each attachment
|
// Need to check each attachment
|
||||||
foreach (ListenerInfo li in m_listenerManager.GetListeners(UUID.Zero, channel, name, id, msg))
|
foreach (ListenerInfo li in m_listenerManager.GetListeners(UUID.Zero, channel, name, id, msg))
|
||||||
{
|
{
|
||||||
|
@ -334,9 +336,10 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
|
||||||
if (m_scene.GetSceneObjectPart(li.GetHostID()) == null)
|
if (m_scene.GetSceneObjectPart(li.GetHostID()) == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if ( targets.Contains(li.GetHostID()))
|
if (targets.Contains(li.GetHostID()))
|
||||||
QueueMessage(new ListenerInfo(li, name, id, msg));
|
QueueMessage(new ListenerInfo(li, name, id, msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -363,6 +366,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -58,10 +58,13 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The scene objects attached to this avatar.
|
/// The scene objects attached to this avatar.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <returns>
|
||||||
|
/// A copy of the list.
|
||||||
|
/// </returns>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// Do not change this list directly - use methods such as
|
/// Do not change this list directly - use methods such as
|
||||||
/// AddAttachment() and RemoveAttachment(). Lock this list when performing any read operations upon it.
|
/// AddAttachment() and RemoveAttachment().
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
List<SceneObjectGroup> Attachments { get; }
|
List<SceneObjectGroup> GetAttachments();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -114,10 +114,13 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
protected ScenePresenceAnimator m_animator;
|
protected ScenePresenceAnimator m_animator;
|
||||||
|
|
||||||
public List<SceneObjectGroup> Attachments
|
/// <summary>
|
||||||
{
|
/// Attachments recorded on this avatar.
|
||||||
get { return m_attachments; }
|
/// </summary>
|
||||||
}
|
/// <remarks>
|
||||||
|
/// TODO: For some reason, we effectively have a list both here and in Appearance. Need to work out if this is
|
||||||
|
/// necessary.
|
||||||
|
/// </remarks>
|
||||||
protected List<SceneObjectGroup> m_attachments = new List<SceneObjectGroup>();
|
protected List<SceneObjectGroup> m_attachments = new List<SceneObjectGroup>();
|
||||||
|
|
||||||
private Dictionary<UUID, ScriptControllers> scriptedcontrols = new Dictionary<UUID, ScriptControllers>();
|
private Dictionary<UUID, ScriptControllers> scriptedcontrols = new Dictionary<UUID, ScriptControllers>();
|
||||||
|
@ -940,15 +943,18 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
// and it has already rezzed the attachments and started their scripts.
|
// and it has already rezzed the attachments and started their scripts.
|
||||||
// We do the following only for non-login agents, because their scripts
|
// We do the following only for non-login agents, because their scripts
|
||||||
// haven't started yet.
|
// haven't started yet.
|
||||||
if (wasChild && Attachments != null && Attachments.Count > 0)
|
lock (m_attachments)
|
||||||
{
|
{
|
||||||
m_log.DebugFormat("[SCENE PRESENCE]: Restarting scripts in attachments...");
|
if (wasChild && m_attachments != null && m_attachments.Count > 0)
|
||||||
// Resume scripts
|
|
||||||
Attachments.ForEach(delegate(SceneObjectGroup sog)
|
|
||||||
{
|
{
|
||||||
sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource());
|
m_log.DebugFormat("[SCENE PRESENCE]: Restarting scripts in attachments...");
|
||||||
sog.ResumeScripts();
|
// Resume scripts
|
||||||
});
|
foreach (SceneObjectGroup sog in m_attachments)
|
||||||
|
{
|
||||||
|
sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource());
|
||||||
|
sog.ResumeScripts();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// send the animations of the other presences to me
|
// send the animations of the other presences to me
|
||||||
|
@ -3472,9 +3478,19 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
m_attachments.Add(gobj);
|
m_attachments.Add(gobj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get the scene object attached to the given point.
|
/// Get all the presence's attachments.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A copy of the list which contains the attachments.</returns>
|
||||||
|
public List<SceneObjectGroup> GetAttachments()
|
||||||
|
{
|
||||||
|
lock (m_attachments)
|
||||||
|
return new List<SceneObjectGroup>(m_attachments);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the scene objects attached to the given point.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="attachmentPoint"></param>
|
/// <param name="attachmentPoint"></param>
|
||||||
/// <returns>Returns an empty list if there were no attachments at the point.</returns>
|
/// <returns>Returns an empty list if there were no attachments at the point.</returns>
|
||||||
|
@ -3521,6 +3537,15 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
m_attachments.Remove(gobj);
|
m_attachments.Remove(gobj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clear all attachments
|
||||||
|
/// </summary>
|
||||||
|
public void ClearAttachments()
|
||||||
|
{
|
||||||
|
lock (m_attachments)
|
||||||
|
m_attachments.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
public bool ValidateAttachments()
|
public bool ValidateAttachments()
|
||||||
{
|
{
|
||||||
lock (m_attachments)
|
lock (m_attachments)
|
||||||
|
|
|
@ -144,14 +144,10 @@ namespace OpenSim.Region.OptionalModules.World.NPC
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// FIXME: An extremely bad bit of code that reaches directly into the attachments list and manipulates it
|
// FIXME: An extremely bad bit of code that reaches directly into the attachments list and manipulates it
|
||||||
List<SceneObjectGroup> attachments = sp.Attachments;
|
foreach (SceneObjectGroup att in sp.GetAttachments())
|
||||||
lock (attachments)
|
scene.DeleteSceneObject(att, false);
|
||||||
{
|
|
||||||
foreach (SceneObjectGroup att in attachments)
|
|
||||||
scene.DeleteSceneObject(att, false);
|
|
||||||
|
|
||||||
attachments.Clear();
|
sp.ClearAttachments();
|
||||||
}
|
|
||||||
|
|
||||||
AvatarAppearance npcAppearance = new AvatarAppearance(appearance, true);
|
AvatarAppearance npcAppearance = new AvatarAppearance(appearance, true);
|
||||||
sp.Appearance = npcAppearance;
|
sp.Appearance = npcAppearance;
|
||||||
|
|
Loading…
Reference in New Issue