From 19ab4c950880beb3ac88a172b775c3973782ec3d Mon Sep 17 00:00:00 2001
From: meta7
Date: Sat, 7 Aug 2010 16:52:03 -0700
Subject: Fix a rather nasty issue where the Backup() process causes objects
 and avatars sitting on them to be pushed to the corner of the sim.

---
 .../Region/Framework/Scenes/SceneObjectGroup.cs    | 199 +++++++++++----------
 OpenSim/Region/Framework/Scenes/SceneObjectPart.cs |  25 +--
 2 files changed, 120 insertions(+), 104 deletions(-)

diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index a828127..0d15cb4 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -317,8 +317,8 @@ namespace OpenSim.Region.Framework.Scenes
         private bool m_scriptListens_notAtTarget = false;
 
         private bool m_scriptListens_atRotTarget = false;
-        private bool m_scriptListens_notAtRotTarget = false;
-
+        private bool m_scriptListens_notAtRotTarget = false;
+        public bool m_dupeInProgress = false;
         internal Dictionary<UUID, string> m_savedScriptState = null;
 
         #region Properties
@@ -475,16 +475,21 @@ namespace OpenSim.Region.Framework.Scenes
                 {
                     part.IgnoreUndoUpdate = false;
                     part.StoreUndoState(UndoType.STATE_GROUP_POSITION);
-                    part.GroupPosition = val;
-                    part.TriggerScriptChangedEvent(Changed.POSITION);
-                }
-
-                foreach (ScenePresence av in m_linkedAvatars)
-                {
-                    Vector3 offset = m_parts[av.LinkedPrim].GetWorldPosition() - av.ParentPosition;
-                    av.AbsolutePosition += offset;
-                    av.ParentPosition = m_parts[av.LinkedPrim].GetWorldPosition(); //ParentPosition gets cleared by AbsolutePosition
-                    av.SendFullUpdateToAllClients();
+                    part.GroupPosition = val;
+                    if (!m_dupeInProgress)
+                    {
+                        part.TriggerScriptChangedEvent(Changed.POSITION);
+                    }
+                }
+                if (!m_dupeInProgress)
+                {
+                    foreach (ScenePresence av in m_linkedAvatars)
+                    {
+                        Vector3 offset = m_parts[av.LinkedPrim].GetWorldPosition() - av.ParentPosition;
+                        av.AbsolutePosition += offset;
+                        av.ParentPosition = m_parts[av.LinkedPrim].GetWorldPosition(); //ParentPosition gets cleared by AbsolutePosition
+                        av.SendFullUpdateToAllClients();
+                    }
                 }
 
                 //if (m_rootPart.PhysActor != null)
@@ -1800,88 +1805,96 @@ namespace OpenSim.Region.Framework.Scenes
         /// <param name="userExposed">True if the duplicate will immediately be in the scene, false otherwise</param>
         /// <returns></returns>
         public SceneObjectGroup Copy(bool userExposed)
-        {
-            SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone();
-            dupe.m_isBackedUp = false;
-            dupe.m_parts = new Dictionary<UUID, SceneObjectPart>();
-
-            // Warning, The following code related to previousAttachmentStatus is needed so that clones of 
-            // attachments do not bordercross while they're being duplicated.  This is hacktastic!
-            // Normally, setting AbsolutePosition will bordercross a prim if it's outside the region!
-            // unless IsAttachment is true!, so to prevent border crossing, we save it's attachment state 
-            // (which should be false anyway) set it as an Attachment and then set it's Absolute Position, 
-            // then restore it's attachment state
-
-            // This is only necessary when userExposed is false!
-
-            bool previousAttachmentStatus = dupe.RootPart.IsAttachment;
-            
-            if (!userExposed)
-                dupe.RootPart.IsAttachment = true;
-
-            dupe.AbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z);
-
-            if (!userExposed)
-            {
-                dupe.RootPart.IsAttachment = previousAttachmentStatus;
-            }
-
-            dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed);
-            dupe.m_rootPart.LinkNum = m_rootPart.LinkNum;
-
-            if (userExposed)
-                dupe.m_rootPart.TrimPermissions();
-
-            /// may need to create a new Physics actor.
-            if (dupe.RootPart.PhysActor != null && userExposed)
-            {
-                PrimitiveBaseShape pbs = dupe.RootPart.Shape;
-
-                dupe.RootPart.PhysActor = m_scene.PhysicsScene.AddPrimShape(
-                    dupe.RootPart.Name,
-                    pbs,
-                    dupe.RootPart.AbsolutePosition,
-                    dupe.RootPart.Scale,
-                    dupe.RootPart.RotationOffset,
-                    dupe.RootPart.PhysActor.IsPhysical);
-
-                dupe.RootPart.PhysActor.LocalID = dupe.RootPart.LocalId;
-                dupe.RootPart.DoPhysicsPropertyUpdate(dupe.RootPart.PhysActor.IsPhysical, true);
+        {
+            SceneObjectGroup dupe;
+            try
+            {
+                m_dupeInProgress = true;
+                dupe = (SceneObjectGroup)MemberwiseClone();
+                dupe.m_isBackedUp = false;
+                dupe.m_parts = new Dictionary<UUID, SceneObjectPart>();
+
+                // Warning, The following code related to previousAttachmentStatus is needed so that clones of 
+                // attachments do not bordercross while they're being duplicated.  This is hacktastic!
+                // Normally, setting AbsolutePosition will bordercross a prim if it's outside the region!
+                // unless IsAttachment is true!, so to prevent border crossing, we save it's attachment state 
+                // (which should be false anyway) set it as an Attachment and then set it's Absolute Position, 
+                // then restore it's attachment state
+
+                // This is only necessary when userExposed is false!
+
+                bool previousAttachmentStatus = dupe.RootPart.IsAttachment;
+
+                if (!userExposed)
+                    dupe.RootPart.IsAttachment = true;
+
+                dupe.AbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z);
+
+                if (!userExposed)
+                {
+                    dupe.RootPart.IsAttachment = previousAttachmentStatus;
+                }
+
+                dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed);
+                dupe.m_rootPart.LinkNum = m_rootPart.LinkNum;
+
+                if (userExposed)
+                    dupe.m_rootPart.TrimPermissions();
+
+                /// may need to create a new Physics actor.
+                if (dupe.RootPart.PhysActor != null && userExposed)
+                {
+                    PrimitiveBaseShape pbs = dupe.RootPart.Shape;
+
+                    dupe.RootPart.PhysActor = m_scene.PhysicsScene.AddPrimShape(
+                        dupe.RootPart.Name,
+                        pbs,
+                        dupe.RootPart.AbsolutePosition,
+                        dupe.RootPart.Scale,
+                        dupe.RootPart.RotationOffset,
+                        dupe.RootPart.PhysActor.IsPhysical);
+
+                    dupe.RootPart.PhysActor.LocalID = dupe.RootPart.LocalId;
+                    dupe.RootPart.DoPhysicsPropertyUpdate(dupe.RootPart.PhysActor.IsPhysical, true);
+                }
+
+                List<SceneObjectPart> partList;
+
+                lockPartsForRead(true);
+
+                partList = new List<SceneObjectPart>(m_parts.Values);
+
+                lockPartsForRead(false);
+
+                partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
+                    {
+                        return p1.LinkNum.CompareTo(p2.LinkNum);
+                    }
+                );
+
+                foreach (SceneObjectPart part in partList)
+                {
+                    if (part.UUID != m_rootPart.UUID)
+                    {
+                        SceneObjectPart newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed);
+
+                        newPart.LinkNum = part.LinkNum;
+                    }
+                }
+
+                if (userExposed)
+                {
+                    dupe.UpdateParentIDs();
+                    dupe.HasGroupChanged = true;
+                    dupe.AttachToBackup();
+
+                    ScheduleGroupForFullUpdate();
+                }
+            }
+            finally
+            {
+                m_dupeInProgress = false;
             }
-
-            List<SceneObjectPart> partList;
-
-            lockPartsForRead(true);
-            
-            partList = new List<SceneObjectPart>(m_parts.Values);
-            
-            lockPartsForRead(false);
-            
-            partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
-                {
-                    return p1.LinkNum.CompareTo(p2.LinkNum);
-                }
-            );
-
-            foreach (SceneObjectPart part in partList)
-            {
-                if (part.UUID != m_rootPart.UUID)
-                {
-                    SceneObjectPart newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed);
-
-                    newPart.LinkNum = part.LinkNum;
-                }
-            }
-
-            if (userExposed)
-            {
-                dupe.UpdateParentIDs();
-                dupe.HasGroupChanged = true;
-                dupe.AttachToBackup();
-
-                ScheduleGroupForFullUpdate();
-            }
-
             return dupe;
         }
 
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index b0ce450..77581af 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -718,17 +718,20 @@ namespace OpenSim.Region.Framework.Scenes
 
                         // Tell the physics engines that this prim changed.
                         m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
-                    }
-
-                    List<ScenePresence> avs = ParentGroup.GetLinkedAvatars();
-                    foreach (ScenePresence av in avs)
-                    {
-                        if (av.LinkedPrim == m_uuid)
-                        {
-                            Vector3 offset = (m_offsetPosition - oldpos);
-                            av.OffsetPosition += offset;
-                            av.SendFullUpdateToAllClients();
-                        }
+                    }
+
+                    if (!m_parentGroup.m_dupeInProgress)
+                    {
+                        List<ScenePresence> avs = ParentGroup.GetLinkedAvatars();
+                        foreach (ScenePresence av in avs)
+                        {
+                            if (av.LinkedPrim == m_uuid)
+                            {
+                                Vector3 offset = (m_offsetPosition - oldpos);
+                                av.OffsetPosition += offset;
+                                av.SendFullUpdateToAllClients();
+                            }
+                        }
                     }
                 }
                 TriggerScriptChangedEvent(Changed.POSITION);
-- 
cgit v1.1