aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs164
1 files changed, 89 insertions, 75 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index 67eb0fe..4815922 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -92,8 +92,12 @@ namespace OpenSim.Region.Framework.Scenes
92 protected internal Dictionary<uint, SceneObjectGroup> SceneObjectGroupsByLocalPartID = new Dictionary<uint, SceneObjectGroup>(); 92 protected internal Dictionary<uint, SceneObjectGroup> SceneObjectGroupsByLocalPartID = new Dictionary<uint, SceneObjectGroup>();
93 93
94 /// <summary> 94 /// <summary>
95 /// Lock to prevent object group update, linking and delinking operations from running concurrently. 95 /// Lock to prevent object group update, linking, delinking and duplication operations from running concurrently.
96 /// </summary> 96 /// </summary>
97 /// <remarks>
98 /// These operations rely on the parts composition of the object. If allowed to run concurrently then race
99 /// conditions can occur.
100 /// </remarks>
97 private Object m_updateLock = new Object(); 101 private Object m_updateLock = new Object();
98 102
99 #endregion 103 #endregion
@@ -1844,96 +1848,106 @@ namespace OpenSim.Region.Framework.Scenes
1844 /// <param name="AgentID"></param> 1848 /// <param name="AgentID"></param>
1845 /// <param name="GroupID"></param> 1849 /// <param name="GroupID"></param>
1846 /// <param name="rot"></param> 1850 /// <param name="rot"></param>
1847 public SceneObjectGroup DuplicateObject(uint originalPrimID, Vector3 offset, uint flags, UUID AgentID, UUID GroupID, Quaternion rot) 1851 /// <returns>null if duplication fails, otherwise the duplicated object</returns>
1852 public SceneObjectGroup DuplicateObject(
1853 uint originalPrimID, Vector3 offset, uint flags, UUID AgentID, UUID GroupID, Quaternion rot)
1848 { 1854 {
1849// m_log.DebugFormat( 1855 Monitor.Enter(m_updateLock);
1850// "[SCENE]: Duplication of object {0} at offset {1} requested by agent {2}", 1856
1851// originalPrimID, offset, AgentID); 1857 try
1852
1853 SceneObjectGroup original = GetGroupByPrim(originalPrimID);
1854 if (original != null)
1855 { 1858 {
1856 if (m_parentScene.Permissions.CanDuplicateObject( 1859 // m_log.DebugFormat(
1857 original.PrimCount, original.UUID, AgentID, original.AbsolutePosition)) 1860 // "[SCENE]: Duplication of object {0} at offset {1} requested by agent {2}",
1861 // originalPrimID, offset, AgentID);
1862
1863 SceneObjectGroup original = GetGroupByPrim(originalPrimID);
1864 if (original == null)
1858 { 1865 {
1859 SceneObjectGroup copy = original.Copy(true); 1866 m_log.WarnFormat(
1860 copy.AbsolutePosition = copy.AbsolutePosition + offset; 1867 "[SCENEGRAPH]: Attempt to duplicate nonexistant prim id {0} by {1}", originalPrimID, AgentID);
1861 1868
1862 if (original.OwnerID != AgentID) 1869 return null;
1863 { 1870 }
1864 copy.SetOwnerId(AgentID);
1865 copy.SetRootPartOwner(copy.RootPart, AgentID, GroupID);
1866 1871
1867 SceneObjectPart[] partList = copy.Parts; 1872 if (!m_parentScene.Permissions.CanDuplicateObject(
1873 original.PrimCount, original.UUID, AgentID, original.AbsolutePosition))
1874 return null;
1868 1875
1869 if (m_parentScene.Permissions.PropagatePermissions()) 1876 SceneObjectGroup copy = original.Copy(true);
1870 { 1877 copy.AbsolutePosition = copy.AbsolutePosition + offset;
1871 foreach (SceneObjectPart child in partList)
1872 {
1873 child.Inventory.ChangeInventoryOwner(AgentID);
1874 child.TriggerScriptChangedEvent(Changed.OWNER);
1875 child.ApplyNextOwnerPermissions();
1876 }
1877 }
1878 1878
1879 copy.RootPart.ObjectSaleType = 0; 1879 if (original.OwnerID != AgentID)
1880 copy.RootPart.SalePrice = 10; 1880 {
1881 } 1881 copy.SetOwnerId(AgentID);
1882 copy.SetRootPartOwner(copy.RootPart, AgentID, GroupID);
1882 1883
1883 // FIXME: This section needs to be refactored so that it just calls AddSceneObject() 1884 SceneObjectPart[] partList = copy.Parts;
1884 Entities.Add(copy); 1885
1885 1886 if (m_parentScene.Permissions.PropagatePermissions())
1886 lock (SceneObjectGroupsByFullID)
1887 SceneObjectGroupsByFullID[copy.UUID] = copy;
1888
1889 SceneObjectPart[] children = copy.Parts;
1890
1891 lock (SceneObjectGroupsByFullPartID)
1892 {
1893 SceneObjectGroupsByFullPartID[copy.UUID] = copy;
1894 foreach (SceneObjectPart part in children)
1895 SceneObjectGroupsByFullPartID[part.UUID] = copy;
1896 }
1897
1898 lock (SceneObjectGroupsByLocalPartID)
1899 {
1900 SceneObjectGroupsByLocalPartID[copy.LocalId] = copy;
1901 foreach (SceneObjectPart part in children)
1902 SceneObjectGroupsByLocalPartID[part.LocalId] = copy;
1903 }
1904 // PROBABLE END OF FIXME
1905
1906 // Since we copy from a source group that is in selected
1907 // state, but the copy is shown deselected in the viewer,
1908 // We need to clear the selection flag here, else that
1909 // prim never gets persisted at all. The client doesn't
1910 // think it's selected, so it will never send a deselect...
1911 copy.IsSelected = false;
1912
1913 m_numPrim += copy.Parts.Length;
1914
1915 if (rot != Quaternion.Identity)
1916 { 1887 {
1917 copy.UpdateGroupRotationR(rot); 1888 foreach (SceneObjectPart child in partList)
1889 {
1890 child.Inventory.ChangeInventoryOwner(AgentID);
1891 child.TriggerScriptChangedEvent(Changed.OWNER);
1892 child.ApplyNextOwnerPermissions();
1893 }
1918 } 1894 }
1919 1895
1920 copy.CreateScriptInstances(0, false, m_parentScene.DefaultScriptEngine, 1); 1896 copy.RootPart.ObjectSaleType = 0;
1921 copy.HasGroupChanged = true; 1897 copy.RootPart.SalePrice = 10;
1922 copy.ScheduleGroupForFullUpdate(); 1898 }
1923 copy.ResumeScripts();
1924
1925 // required for physics to update it's position
1926 copy.AbsolutePosition = copy.AbsolutePosition;
1927 1899
1928 return copy; 1900 // FIXME: This section needs to be refactored so that it just calls AddSceneObject()
1901 Entities.Add(copy);
1902
1903 lock (SceneObjectGroupsByFullID)
1904 SceneObjectGroupsByFullID[copy.UUID] = copy;
1905
1906 SceneObjectPart[] children = copy.Parts;
1907
1908 lock (SceneObjectGroupsByFullPartID)
1909 {
1910 SceneObjectGroupsByFullPartID[copy.UUID] = copy;
1911 foreach (SceneObjectPart part in children)
1912 SceneObjectGroupsByFullPartID[part.UUID] = copy;
1913 }
1914
1915 lock (SceneObjectGroupsByLocalPartID)
1916 {
1917 SceneObjectGroupsByLocalPartID[copy.LocalId] = copy;
1918 foreach (SceneObjectPart part in children)
1919 SceneObjectGroupsByLocalPartID[part.LocalId] = copy;
1920 }
1921 // PROBABLE END OF FIXME
1922
1923 // Since we copy from a source group that is in selected
1924 // state, but the copy is shown deselected in the viewer,
1925 // We need to clear the selection flag here, else that
1926 // prim never gets persisted at all. The client doesn't
1927 // think it's selected, so it will never send a deselect...
1928 copy.IsSelected = false;
1929
1930 m_numPrim += copy.Parts.Length;
1931
1932 if (rot != Quaternion.Identity)
1933 {
1934 copy.UpdateGroupRotationR(rot);
1929 } 1935 }
1936
1937 copy.CreateScriptInstances(0, false, m_parentScene.DefaultScriptEngine, 1);
1938 copy.HasGroupChanged = true;
1939 copy.ScheduleGroupForFullUpdate();
1940 copy.ResumeScripts();
1941
1942 // required for physics to update it's position
1943 copy.AbsolutePosition = copy.AbsolutePosition;
1944
1945 return copy;
1930 } 1946 }
1931 else 1947 finally
1932 { 1948 {
1933 m_log.WarnFormat("[SCENE]: Attempted to duplicate nonexistant prim id {0}", GroupID); 1949 Monitor.Exit(m_updateLock);
1934 } 1950 }
1935
1936 return null;
1937 } 1951 }
1938 1952
1939 /// <summary> 1953 /// <summary>