aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework/Scenes')
-rw-r--r--OpenSim/Region/Framework/Scenes/EventManager.cs24
-rw-r--r--OpenSim/Region/Framework/Scenes/Prioritizer.cs4
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs328
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs3
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs505
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneBase.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs37
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs230
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneManager.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs17
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs589
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs199
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs808
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs188
-rw-r--r--OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs28
-rw-r--r--OpenSim/Region/Framework/Scenes/UndoState.cs87
-rw-r--r--OpenSim/Region/Framework/Scenes/UuidGatherer.cs4
17 files changed, 2321 insertions, 734 deletions
diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs
index d31d380..57db4d6 100644
--- a/OpenSim/Region/Framework/Scenes/EventManager.cs
+++ b/OpenSim/Region/Framework/Scenes/EventManager.cs
@@ -55,8 +55,12 @@ namespace OpenSim.Region.Framework.Scenes
55 55
56 public delegate void OnTerrainTickDelegate(); 56 public delegate void OnTerrainTickDelegate();
57 57
58 public delegate void OnTerrainUpdateDelegate();
59
58 public event OnTerrainTickDelegate OnTerrainTick; 60 public event OnTerrainTickDelegate OnTerrainTick;
59 61
62 public event OnTerrainUpdateDelegate OnTerrainUpdate;
63
60 public delegate void OnBackupDelegate(ISimulationDataService datastore, bool forceBackup); 64 public delegate void OnBackupDelegate(ISimulationDataService datastore, bool forceBackup);
61 65
62 public event OnBackupDelegate OnBackup; 66 public event OnBackupDelegate OnBackup;
@@ -797,6 +801,26 @@ namespace OpenSim.Region.Framework.Scenes
797 } 801 }
798 } 802 }
799 } 803 }
804 public void TriggerTerrainUpdate()
805 {
806 OnTerrainUpdateDelegate handlerTerrainUpdate = OnTerrainUpdate;
807 if (handlerTerrainUpdate != null)
808 {
809 foreach (OnTerrainUpdateDelegate d in handlerTerrainUpdate.GetInvocationList())
810 {
811 try
812 {
813 d();
814 }
815 catch (Exception e)
816 {
817 m_log.ErrorFormat(
818 "[EVENT MANAGER]: Delegate for TriggerTerrainUpdate failed - continuing. {0} {1}",
819 e.Message, e.StackTrace);
820 }
821 }
822 }
823 }
800 824
801 public void TriggerTerrainTick() 825 public void TriggerTerrainTick()
802 { 826 {
diff --git a/OpenSim/Region/Framework/Scenes/Prioritizer.cs b/OpenSim/Region/Framework/Scenes/Prioritizer.cs
index 1b10e3c..0a34a4c 100644
--- a/OpenSim/Region/Framework/Scenes/Prioritizer.cs
+++ b/OpenSim/Region/Framework/Scenes/Prioritizer.cs
@@ -157,7 +157,7 @@ namespace OpenSim.Region.Framework.Scenes
157 157
158 private uint GetPriorityByBestAvatarResponsiveness(IClientAPI client, ISceneEntity entity) 158 private uint GetPriorityByBestAvatarResponsiveness(IClientAPI client, ISceneEntity entity)
159 { 159 {
160 uint pqueue = ComputeDistancePriority(client,entity,true); 160 uint pqueue = ComputeDistancePriority(client,entity,false);
161 161
162 ScenePresence presence = m_scene.GetScenePresence(client.AgentId); 162 ScenePresence presence = m_scene.GetScenePresence(client.AgentId);
163 if (presence != null) 163 if (presence != null)
@@ -226,7 +226,7 @@ namespace OpenSim.Region.Framework.Scenes
226 226
227 for (int i = 0; i < queues - 1; i++) 227 for (int i = 0; i < queues - 1; i++)
228 { 228 {
229 if (distance < 10 * Math.Pow(2.0,i)) 229 if (distance < 30 * Math.Pow(2.0,i))
230 break; 230 break;
231 pqueue++; 231 pqueue++;
232 } 232 }
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index 6d7559e..58de44e 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -117,34 +117,22 @@ namespace OpenSim.Region.Framework.Scenes
117 /// <param name="item"></param> 117 /// <param name="item"></param>
118 public bool AddInventoryItem(InventoryItemBase item) 118 public bool AddInventoryItem(InventoryItemBase item)
119 { 119 {
120 if (UUID.Zero == item.Folder) 120 InventoryFolderBase folder;
121
122 if (item.Folder == UUID.Zero)
121 { 123 {
122 InventoryFolderBase f = InventoryService.GetFolderForType(item.Owner, (AssetType)item.AssetType); 124 folder = InventoryService.GetFolderForType(item.Owner, (AssetType)item.AssetType);
123 if (f != null) 125 if (folder == null)
124 { 126 {
125// m_log.DebugFormat( 127 folder = InventoryService.GetRootFolder(item.Owner);
126// "[LOCAL INVENTORY SERVICES CONNECTOR]: Found folder {0} type {1} for item {2}", 128
127// f.Name, (AssetType)f.Type, item.Name); 129 if (folder == null)
128
129 item.Folder = f.ID;
130 }
131 else
132 {
133 f = InventoryService.GetRootFolder(item.Owner);
134 if (f != null)
135 {
136 item.Folder = f.ID;
137 }
138 else
139 {
140 m_log.WarnFormat(
141 "[AGENT INVENTORY]: Could not find root folder for {0} when trying to add item {1} with no parent folder specified",
142 item.Owner, item.Name);
143 return false; 130 return false;
144 }
145 } 131 }
132
133 item.Folder = folder.ID;
146 } 134 }
147 135
148 if (InventoryService.AddItem(item)) 136 if (InventoryService.AddItem(item))
149 { 137 {
150 int userlevel = 0; 138 int userlevel = 0;
@@ -264,8 +252,7 @@ namespace OpenSim.Region.Framework.Scenes
264 252
265 // Update item with new asset 253 // Update item with new asset
266 item.AssetID = asset.FullID; 254 item.AssetID = asset.FullID;
267 if (group.UpdateInventoryItem(item)) 255 group.UpdateInventoryItem(item);
268 remoteClient.SendAgentAlertMessage("Script saved", false);
269 256
270 part.SendPropertiesToClient(remoteClient); 257 part.SendPropertiesToClient(remoteClient);
271 258
@@ -276,12 +263,7 @@ namespace OpenSim.Region.Framework.Scenes
276 { 263 {
277 // Needs to determine which engine was running it and use that 264 // Needs to determine which engine was running it and use that
278 // 265 //
279 part.Inventory.CreateScriptInstance(item.ItemID, 0, false, DefaultScriptEngine, 0); 266 errors = part.Inventory.CreateScriptInstanceEr(item.ItemID, 0, false, DefaultScriptEngine, 0);
280 errors = part.Inventory.GetScriptErrors(item.ItemID);
281 }
282 else
283 {
284 remoteClient.SendAgentAlertMessage("Script saved", false);
285 } 267 }
286 part.ParentGroup.ResumeScripts(); 268 part.ParentGroup.ResumeScripts();
287 return errors; 269 return errors;
@@ -345,6 +327,7 @@ namespace OpenSim.Region.Framework.Scenes
345 327
346 if (UUID.Zero == transactionID) 328 if (UUID.Zero == transactionID)
347 { 329 {
330 item.Flags = (item.Flags & ~(uint)255) | (itemUpd.Flags & (uint)255);
348 item.Name = itemUpd.Name; 331 item.Name = itemUpd.Name;
349 item.Description = itemUpd.Description; 332 item.Description = itemUpd.Description;
350 if (item.NextPermissions != (itemUpd.NextPermissions & item.BasePermissions)) 333 if (item.NextPermissions != (itemUpd.NextPermissions & item.BasePermissions))
@@ -723,6 +706,8 @@ namespace OpenSim.Region.Framework.Scenes
723 return; 706 return;
724 } 707 }
725 708
709 if (newName == null) newName = item.Name;
710
726 AssetBase asset = AssetService.Get(item.AssetID.ToString()); 711 AssetBase asset = AssetService.Get(item.AssetID.ToString());
727 712
728 if (asset != null) 713 if (asset != null)
@@ -779,6 +764,24 @@ namespace OpenSim.Region.Framework.Scenes
779 } 764 }
780 765
781 /// <summary> 766 /// <summary>
767 /// Move an item within the agent's inventory, and leave a copy (used in making a new outfit)
768 /// </summary>
769 public void MoveInventoryItemsLeaveCopy(IClientAPI remoteClient, List<InventoryItemBase> items, UUID destfolder)
770 {
771 List<InventoryItemBase> moveitems = new List<InventoryItemBase>();
772 foreach (InventoryItemBase b in items)
773 {
774 CopyInventoryItem(remoteClient, 0, remoteClient.AgentId, b.ID, b.Folder, null);
775 InventoryItemBase n = InventoryService.GetItem(b);
776 n.Folder = destfolder;
777 moveitems.Add(n);
778 remoteClient.SendInventoryItemCreateUpdate(n, 0);
779 }
780
781 MoveInventoryItem(remoteClient, moveitems);
782 }
783
784 /// <summary>
782 /// Move an item within the agent's inventory. 785 /// Move an item within the agent's inventory.
783 /// </summary> 786 /// </summary>
784 /// <param name="remoteClient"></param> 787 /// <param name="remoteClient"></param>
@@ -1121,6 +1124,10 @@ namespace OpenSim.Region.Framework.Scenes
1121 { 1124 {
1122 SceneObjectPart part = GetSceneObjectPart(primLocalId); 1125 SceneObjectPart part = GetSceneObjectPart(primLocalId);
1123 1126
1127 // Can't move a null item
1128 if (itemId == UUID.Zero)
1129 return;
1130
1124 if (null == part) 1131 if (null == part)
1125 { 1132 {
1126 m_log.WarnFormat( 1133 m_log.WarnFormat(
@@ -1231,6 +1238,10 @@ namespace OpenSim.Region.Framework.Scenes
1231 if ((part.OwnerID != destPart.OwnerID) && ((srcTaskItem.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)) 1238 if ((part.OwnerID != destPart.OwnerID) && ((srcTaskItem.CurrentPermissions & (uint)PermissionMask.Transfer) == 0))
1232 return; 1239 return;
1233 1240
1241 bool overrideNoMod = false;
1242 if ((part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) != 0)
1243 overrideNoMod = true;
1244
1234 if (part.OwnerID != destPart.OwnerID && (part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) == 0) 1245 if (part.OwnerID != destPart.OwnerID && (part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) == 0)
1235 { 1246 {
1236 // object cannot copy items to an object owned by a different owner 1247 // object cannot copy items to an object owned by a different owner
@@ -1240,7 +1251,7 @@ namespace OpenSim.Region.Framework.Scenes
1240 } 1251 }
1241 1252
1242 // must have both move and modify permission to put an item in an object 1253 // must have both move and modify permission to put an item in an object
1243 if ((part.OwnerMask & ((uint)PermissionMask.Move | (uint)PermissionMask.Modify)) == 0) 1254 if (((part.OwnerMask & (uint)PermissionMask.Modify) == 0) && (!overrideNoMod))
1244 { 1255 {
1245 return; 1256 return;
1246 } 1257 }
@@ -1299,6 +1310,14 @@ namespace OpenSim.Region.Framework.Scenes
1299 1310
1300 public UUID MoveTaskInventoryItems(UUID destID, string category, SceneObjectPart host, List<UUID> items) 1311 public UUID MoveTaskInventoryItems(UUID destID, string category, SceneObjectPart host, List<UUID> items)
1301 { 1312 {
1313 SceneObjectPart destPart = GetSceneObjectPart(destID);
1314 if (destPart != null) // Move into a prim
1315 {
1316 foreach(UUID itemID in items)
1317 MoveTaskInventoryItem(destID, host, itemID);
1318 return destID; // Prim folder ID == prim ID
1319 }
1320
1302 InventoryFolderBase rootFolder = InventoryService.GetRootFolder(destID); 1321 InventoryFolderBase rootFolder = InventoryService.GetRootFolder(destID);
1303 1322
1304 UUID newFolderID = UUID.Random(); 1323 UUID newFolderID = UUID.Random();
@@ -1484,12 +1503,12 @@ namespace OpenSim.Region.Framework.Scenes
1484 agentTransactions.HandleTaskItemUpdateFromTransaction( 1503 agentTransactions.HandleTaskItemUpdateFromTransaction(
1485 remoteClient, part, transactionID, currentItem); 1504 remoteClient, part, transactionID, currentItem);
1486 1505
1487 if ((InventoryType)itemInfo.InvType == InventoryType.Notecard) 1506// if ((InventoryType)itemInfo.InvType == InventoryType.Notecard)
1488 remoteClient.SendAgentAlertMessage("Notecard saved", false); 1507// remoteClient.SendAgentAlertMessage("Notecard saved", false);
1489 else if ((InventoryType)itemInfo.InvType == InventoryType.LSL) 1508// else if ((InventoryType)itemInfo.InvType == InventoryType.LSL)
1490 remoteClient.SendAgentAlertMessage("Script saved", false); 1509// remoteClient.SendAgentAlertMessage("Script saved", false);
1491 else 1510// else
1492 remoteClient.SendAgentAlertMessage("Item saved", false); 1511// remoteClient.SendAgentAlertMessage("Item saved", false);
1493 } 1512 }
1494 } 1513 }
1495 1514
@@ -1669,7 +1688,7 @@ namespace OpenSim.Region.Framework.Scenes
1669 } 1688 }
1670 1689
1671 AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType, 1690 AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType,
1672 Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n}"), 1691 Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n\n touch_start(integer num)\n {\n }\n}"),
1673 agentID); 1692 agentID);
1674 AssetService.Store(asset); 1693 AssetService.Store(asset);
1675 1694
@@ -1821,23 +1840,32 @@ namespace OpenSim.Region.Framework.Scenes
1821 // build a list of eligible objects 1840 // build a list of eligible objects
1822 List<uint> deleteIDs = new List<uint>(); 1841 List<uint> deleteIDs = new List<uint>();
1823 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>(); 1842 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>();
1824 1843 List<SceneObjectGroup> takeGroups = new List<SceneObjectGroup>();
1825 // Start with true for both, then remove the flags if objects
1826 // that we can't derez are part of the selection
1827 bool permissionToTake = true;
1828 bool permissionToTakeCopy = true;
1829 bool permissionToDelete = true;
1830 1844
1831 foreach (uint localID in localIDs) 1845 foreach (uint localID in localIDs)
1832 { 1846 {
1847 // Start with true for both, then remove the flags if objects
1848 // that we can't derez are part of the selection
1849 bool permissionToTake = true;
1850 bool permissionToTakeCopy = true;
1851 bool permissionToDelete = true;
1852
1833 // Invalid id 1853 // Invalid id
1834 SceneObjectPart part = GetSceneObjectPart(localID); 1854 SceneObjectPart part = GetSceneObjectPart(localID);
1835 if (part == null) 1855 if (part == null)
1856 {
1857 //Client still thinks the object exists, kill it
1858 deleteIDs.Add(localID);
1836 continue; 1859 continue;
1860 }
1837 1861
1838 // Already deleted by someone else 1862 // Already deleted by someone else
1839 if (part.ParentGroup.IsDeleted) 1863 if (part.ParentGroup.IsDeleted)
1864 {
1865 //Client still thinks the object exists, kill it
1866 deleteIDs.Add(localID);
1840 continue; 1867 continue;
1868 }
1841 1869
1842 // Can't delete child prims 1870 // Can't delete child prims
1843 if (part != part.ParentGroup.RootPart) 1871 if (part != part.ParentGroup.RootPart)
@@ -1845,9 +1873,6 @@ namespace OpenSim.Region.Framework.Scenes
1845 1873
1846 SceneObjectGroup grp = part.ParentGroup; 1874 SceneObjectGroup grp = part.ParentGroup;
1847 1875
1848 deleteIDs.Add(localID);
1849 deleteGroups.Add(grp);
1850
1851 if (remoteClient == null) 1876 if (remoteClient == null)
1852 { 1877 {
1853 // Autoreturn has a null client. Nothing else does. So 1878 // Autoreturn has a null client. Nothing else does. So
@@ -1864,83 +1889,195 @@ namespace OpenSim.Region.Framework.Scenes
1864 } 1889 }
1865 else 1890 else
1866 { 1891 {
1867 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId)) 1892 if (action == DeRezAction.TakeCopy)
1893 {
1894 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId))
1895 permissionToTakeCopy = false;
1896 }
1897 else
1898 {
1868 permissionToTakeCopy = false; 1899 permissionToTakeCopy = false;
1869 1900 }
1870 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId)) 1901 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId))
1871 permissionToTake = false; 1902 permissionToTake = false;
1872 1903
1873 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId)) 1904 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId))
1874 permissionToDelete = false; 1905 permissionToDelete = false;
1875 } 1906 }
1876 }
1877 1907
1878 // Handle god perms 1908 // Handle god perms
1879 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId)) 1909 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId))
1880 { 1910 {
1881 permissionToTake = true; 1911 permissionToTake = true;
1882 permissionToTakeCopy = true; 1912 permissionToTakeCopy = true;
1883 permissionToDelete = true; 1913 permissionToDelete = true;
1884 } 1914 }
1885 1915
1886 // If we're re-saving, we don't even want to delete 1916 // If we're re-saving, we don't even want to delete
1887 if (action == DeRezAction.SaveToExistingUserInventoryItem) 1917 if (action == DeRezAction.SaveToExistingUserInventoryItem)
1888 permissionToDelete = false; 1918 permissionToDelete = false;
1889 1919
1890 // if we want to take a copy, we also don't want to delete 1920 // if we want to take a copy, we also don't want to delete
1891 // Note: after this point, the permissionToTakeCopy flag 1921 // Note: after this point, the permissionToTakeCopy flag
1892 // becomes irrelevant. It already includes the permissionToTake 1922 // becomes irrelevant. It already includes the permissionToTake
1893 // permission and after excluding no copy items here, we can 1923 // permission and after excluding no copy items here, we can
1894 // just use that. 1924 // just use that.
1895 if (action == DeRezAction.TakeCopy) 1925 if (action == DeRezAction.TakeCopy)
1896 { 1926 {
1897 // If we don't have permission, stop right here 1927 // If we don't have permission, stop right here
1898 if (!permissionToTakeCopy) 1928 if (!permissionToTakeCopy)
1899 return; 1929 return;
1900 1930
1901 permissionToTake = true; 1931 permissionToTake = true;
1902 // Don't delete 1932 // Don't delete
1903 permissionToDelete = false; 1933 permissionToDelete = false;
1904 } 1934 }
1905 1935
1906 if (action == DeRezAction.Return) 1936 if (action == DeRezAction.Return)
1907 {
1908 if (remoteClient != null)
1909 { 1937 {
1910 if (Permissions.CanReturnObjects( 1938 if (remoteClient != null)
1911 null,
1912 remoteClient.AgentId,
1913 deleteGroups))
1914 { 1939 {
1915 permissionToTake = true; 1940 if (Permissions.CanReturnObjects(
1916 permissionToDelete = true; 1941 null,
1917 1942 remoteClient.AgentId,
1918 foreach (SceneObjectGroup g in deleteGroups) 1943 deleteGroups))
1919 { 1944 {
1920 AddReturn(g.OwnerID, g.Name, g.AbsolutePosition, "parcel owner return"); 1945 permissionToTake = true;
1946 permissionToDelete = true;
1947
1948 AddReturn(grp.OwnerID, grp.Name, grp.AbsolutePosition, "parcel owner return");
1921 } 1949 }
1922 } 1950 }
1951 else // Auto return passes through here with null agent
1952 {
1953 permissionToTake = true;
1954 permissionToDelete = true;
1955 }
1923 } 1956 }
1924 else // Auto return passes through here with null agent 1957
1958 if (permissionToTake && (!permissionToDelete))
1959 takeGroups.Add(grp);
1960
1961 if (permissionToDelete)
1925 { 1962 {
1926 permissionToTake = true; 1963 if (permissionToTake)
1927 permissionToDelete = true; 1964 deleteGroups.Add(grp);
1965 deleteIDs.Add(grp.LocalId);
1928 } 1966 }
1929 } 1967 }
1930 1968
1931 if (permissionToTake) 1969 SendKillObject(deleteIDs);
1970
1971 if (deleteGroups.Count > 0)
1932 { 1972 {
1973 foreach (SceneObjectGroup g in deleteGroups)
1974 deleteIDs.Remove(g.LocalId);
1975
1933 m_asyncSceneObjectDeleter.DeleteToInventory( 1976 m_asyncSceneObjectDeleter.DeleteToInventory(
1934 action, destinationID, deleteGroups, remoteClient, 1977 action, destinationID, deleteGroups, remoteClient,
1935 permissionToDelete); 1978 true);
1979 }
1980 if (takeGroups.Count > 0)
1981 {
1982 m_asyncSceneObjectDeleter.DeleteToInventory(
1983 action, destinationID, takeGroups, remoteClient,
1984 false);
1936 } 1985 }
1937 else if (permissionToDelete) 1986 if (deleteIDs.Count > 0)
1938 { 1987 {
1939 foreach (SceneObjectGroup g in deleteGroups) 1988 foreach (SceneObjectGroup g in deleteGroups)
1940 DeleteSceneObject(g, false); 1989 DeleteSceneObject(g, true);
1941 } 1990 }
1942 } 1991 }
1943 1992
1993 public UUID attachObjectAssetStore(IClientAPI remoteClient, SceneObjectGroup grp, UUID AgentId, out UUID itemID)
1994 {
1995 itemID = UUID.Zero;
1996 if (grp != null)
1997 {
1998 Vector3 inventoryStoredPosition = new Vector3
1999 (((grp.AbsolutePosition.X > (int)Constants.RegionSize)
2000 ? 250
2001 : grp.AbsolutePosition.X)
2002 ,
2003 (grp.AbsolutePosition.X > (int)Constants.RegionSize)
2004 ? 250
2005 : grp.AbsolutePosition.X,
2006 grp.AbsolutePosition.Z);
2007
2008 Vector3 originalPosition = grp.AbsolutePosition;
2009
2010 grp.AbsolutePosition = inventoryStoredPosition;
2011
2012 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp);
2013
2014 grp.AbsolutePosition = originalPosition;
2015
2016 AssetBase asset = CreateAsset(
2017 grp.GetPartName(grp.LocalId),
2018 grp.GetPartDescription(grp.LocalId),
2019 (sbyte)AssetType.Object,
2020 Utils.StringToBytes(sceneObjectXml),
2021 remoteClient.AgentId);
2022 AssetService.Store(asset);
2023
2024 InventoryItemBase item = new InventoryItemBase();
2025 item.CreatorId = grp.RootPart.CreatorID.ToString();
2026 item.CreatorData = grp.RootPart.CreatorData;
2027 item.Owner = remoteClient.AgentId;
2028 item.ID = UUID.Random();
2029 item.AssetID = asset.FullID;
2030 item.Description = asset.Description;
2031 item.Name = asset.Name;
2032 item.AssetType = asset.Type;
2033 item.InvType = (int)InventoryType.Object;
2034
2035 InventoryFolderBase folder = InventoryService.GetFolderForType(remoteClient.AgentId, AssetType.Object);
2036 if (folder != null)
2037 item.Folder = folder.ID;
2038 else // oopsies
2039 item.Folder = UUID.Zero;
2040
2041 // Set up base perms properly
2042 uint permsBase = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify);
2043 permsBase &= grp.RootPart.BaseMask;
2044 permsBase |= (uint)PermissionMask.Move;
2045
2046 // Make sure we don't lock it
2047 grp.RootPart.NextOwnerMask |= (uint)PermissionMask.Move;
2048
2049 if ((remoteClient.AgentId != grp.RootPart.OwnerID) && Permissions.PropagatePermissions())
2050 {
2051 item.BasePermissions = permsBase & grp.RootPart.NextOwnerMask;
2052 item.CurrentPermissions = permsBase & grp.RootPart.NextOwnerMask;
2053 item.NextPermissions = permsBase & grp.RootPart.NextOwnerMask;
2054 item.EveryOnePermissions = permsBase & grp.RootPart.EveryoneMask & grp.RootPart.NextOwnerMask;
2055 item.GroupPermissions = permsBase & grp.RootPart.GroupMask & grp.RootPart.NextOwnerMask;
2056 }
2057 else
2058 {
2059 item.BasePermissions = permsBase;
2060 item.CurrentPermissions = permsBase & grp.RootPart.OwnerMask;
2061 item.NextPermissions = permsBase & grp.RootPart.NextOwnerMask;
2062 item.EveryOnePermissions = permsBase & grp.RootPart.EveryoneMask;
2063 item.GroupPermissions = permsBase & grp.RootPart.GroupMask;
2064 }
2065 item.CreationDate = Util.UnixTimeSinceEpoch();
2066
2067 // sets itemID so client can show item as 'attached' in inventory
2068 grp.SetFromItemID(item.ID);
2069
2070 if (AddInventoryItem(item))
2071 remoteClient.SendInventoryItemCreateUpdate(item, 0);
2072 else
2073 m_dialogModule.SendAlertToUser(remoteClient, "Operation failed");
2074
2075 itemID = item.ID;
2076 return item.AssetID;
2077 }
2078 return UUID.Zero;
2079 }
2080
1944 /// <summary> 2081 /// <summary>
1945 /// Event Handler Rez an object into a scene 2082 /// Event Handler Rez an object into a scene
1946 /// Calls the non-void event handler 2083 /// Calls the non-void event handler
@@ -2067,6 +2204,9 @@ namespace OpenSim.Region.Framework.Scenes
2067 2204
2068 public void SetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID, bool running) 2205 public void SetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID, bool running)
2069 { 2206 {
2207 if (!Permissions.CanEditScript(itemID, objectID, controllingClient.AgentId))
2208 return;
2209
2070 SceneObjectPart part = GetSceneObjectPart(objectID); 2210 SceneObjectPart part = GetSceneObjectPart(objectID);
2071 if (part == null) 2211 if (part == null)
2072 return; 2212 return;
diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
index 3355ebe..bf2e775 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
@@ -346,7 +346,10 @@ namespace OpenSim.Region.Framework.Scenes
346 List<UserAccount> accounts = UserAccountService.GetUserAccounts(RegionInfo.ScopeID, query); 346 List<UserAccount> accounts = UserAccountService.GetUserAccounts(RegionInfo.ScopeID, query);
347 347
348 if (accounts == null) 348 if (accounts == null)
349 {
350 m_log.DebugFormat("[LLCIENT]: ProcessAvatarPickerRequest: returned null result");
349 return; 351 return;
352 }
350 353
351 AvatarPickerReplyPacket replyPacket = (AvatarPickerReplyPacket) PacketPool.Instance.GetPacket(PacketType.AvatarPickerReply); 354 AvatarPickerReplyPacket replyPacket = (AvatarPickerReplyPacket) PacketPool.Instance.GetPacket(PacketType.AvatarPickerReply);
352 // TODO: don't create new blocks if recycling an old packet 355 // TODO: don't create new blocks if recycling an old packet
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 186e01c..03ddbc5 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -104,6 +104,7 @@ namespace OpenSim.Region.Framework.Scenes
104 // TODO: need to figure out how allow client agents but deny 104 // TODO: need to figure out how allow client agents but deny
105 // root agents when ACL denies access to root agent 105 // root agents when ACL denies access to root agent
106 public bool m_strictAccessControl = true; 106 public bool m_strictAccessControl = true;
107 public bool m_seeIntoBannedRegion = false;
107 public int MaxUndoCount = 5; 108 public int MaxUndoCount = 5;
108 // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet; 109 // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet;
109 public bool LoginLock = false; 110 public bool LoginLock = false;
@@ -119,12 +120,14 @@ namespace OpenSim.Region.Framework.Scenes
119 120
120 protected int m_splitRegionID; 121 protected int m_splitRegionID;
121 protected Timer m_restartWaitTimer = new Timer(); 122 protected Timer m_restartWaitTimer = new Timer();
123 protected Timer m_timerWatchdog = new Timer();
122 protected List<RegionInfo> m_regionRestartNotifyList = new List<RegionInfo>(); 124 protected List<RegionInfo> m_regionRestartNotifyList = new List<RegionInfo>();
123 protected List<RegionInfo> m_neighbours = new List<RegionInfo>(); 125 protected List<RegionInfo> m_neighbours = new List<RegionInfo>();
124 protected string m_simulatorVersion = "OpenSimulator Server"; 126 protected string m_simulatorVersion = "OpenSimulator Server";
125 protected ModuleLoader m_moduleLoader; 127 protected ModuleLoader m_moduleLoader;
126 protected AgentCircuitManager m_authenticateHandler; 128 protected AgentCircuitManager m_authenticateHandler;
127 protected SceneCommunicationService m_sceneGridService; 129 protected SceneCommunicationService m_sceneGridService;
130 protected ISnmpModule m_snmpService = null;
128 131
129 protected ISimulationDataService m_SimulationDataService; 132 protected ISimulationDataService m_SimulationDataService;
130 protected IEstateDataService m_EstateDataService; 133 protected IEstateDataService m_EstateDataService;
@@ -177,7 +180,7 @@ namespace OpenSim.Region.Framework.Scenes
177 private int m_update_events = 1; 180 private int m_update_events = 1;
178 private int m_update_backup = 200; 181 private int m_update_backup = 200;
179 private int m_update_terrain = 50; 182 private int m_update_terrain = 50;
180// private int m_update_land = 1; 183 private int m_update_land = 10;
181 private int m_update_coarse_locations = 50; 184 private int m_update_coarse_locations = 50;
182 185
183 private int agentMS; 186 private int agentMS;
@@ -192,6 +195,7 @@ namespace OpenSim.Region.Framework.Scenes
192 private int landMS; 195 private int landMS;
193 private int lastCompletedFrame; 196 private int lastCompletedFrame;
194 197
198 public bool CombineRegions = false;
195 /// <summary> 199 /// <summary>
196 /// Signals whether temporary objects are currently being cleaned up. Needed because this is launched 200 /// Signals whether temporary objects are currently being cleaned up. Needed because this is launched
197 /// asynchronously from the update loop. 201 /// asynchronously from the update loop.
@@ -214,11 +218,14 @@ namespace OpenSim.Region.Framework.Scenes
214 private bool m_scripts_enabled = true; 218 private bool m_scripts_enabled = true;
215 private string m_defaultScriptEngine; 219 private string m_defaultScriptEngine;
216 private int m_LastLogin; 220 private int m_LastLogin;
217 private Thread HeartbeatThread; 221 private Thread HeartbeatThread = null;
218 private volatile bool shuttingdown; 222 private volatile bool shuttingdown;
219 223
220 private int m_lastUpdate; 224 private int m_lastUpdate;
225 private int m_lastIncoming;
226 private int m_lastOutgoing;
221 private bool m_firstHeartbeat = true; 227 private bool m_firstHeartbeat = true;
228 private int m_hbRestarts = 0;
222 229
223 private object m_deleting_scene_object = new object(); 230 private object m_deleting_scene_object = new object();
224 231
@@ -265,6 +272,19 @@ namespace OpenSim.Region.Framework.Scenes
265 get { return m_sceneGridService; } 272 get { return m_sceneGridService; }
266 } 273 }
267 274
275 public ISnmpModule SnmpService
276 {
277 get
278 {
279 if (m_snmpService == null)
280 {
281 m_snmpService = RequestModuleInterface<ISnmpModule>();
282 }
283
284 return m_snmpService;
285 }
286 }
287
268 public ISimulationDataService SimulationDataService 288 public ISimulationDataService SimulationDataService
269 { 289 {
270 get 290 get
@@ -546,6 +566,9 @@ namespace OpenSim.Region.Framework.Scenes
546 m_EstateDataService = estateDataService; 566 m_EstateDataService = estateDataService;
547 m_regionHandle = m_regInfo.RegionHandle; 567 m_regionHandle = m_regInfo.RegionHandle;
548 m_regionName = m_regInfo.RegionName; 568 m_regionName = m_regInfo.RegionName;
569 m_lastUpdate = Util.EnvironmentTickCount();
570 m_lastIncoming = 0;
571 m_lastOutgoing = 0;
549 572
550 m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this); 573 m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this);
551 m_asyncSceneObjectDeleter.Enabled = true; 574 m_asyncSceneObjectDeleter.Enabled = true;
@@ -646,6 +669,7 @@ namespace OpenSim.Region.Framework.Scenes
646 CollidablePrims = startupConfig.GetBoolean("collidable_prim", true); 669 CollidablePrims = startupConfig.GetBoolean("collidable_prim", true);
647 670
648 m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys); 671 m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys);
672
649 if (RegionInfo.NonphysPrimMax > 0) 673 if (RegionInfo.NonphysPrimMax > 0)
650 { 674 {
651 m_maxNonphys = RegionInfo.NonphysPrimMax; 675 m_maxNonphys = RegionInfo.NonphysPrimMax;
@@ -677,6 +701,7 @@ namespace OpenSim.Region.Framework.Scenes
677 m_persistAfter *= 10000000; 701 m_persistAfter *= 10000000;
678 702
679 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine"); 703 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine");
704 m_log.InfoFormat("[SCENE]: Default script engine {0}", m_defaultScriptEngine);
680 705
681 IConfig packetConfig = m_config.Configs["PacketPool"]; 706 IConfig packetConfig = m_config.Configs["PacketPool"];
682 if (packetConfig != null) 707 if (packetConfig != null)
@@ -686,6 +711,8 @@ namespace OpenSim.Region.Framework.Scenes
686 } 711 }
687 712
688 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl); 713 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl);
714 m_seeIntoBannedRegion = startupConfig.GetBoolean("SeeIntoBannedRegion", m_seeIntoBannedRegion);
715 CombineRegions = startupConfig.GetBoolean("CombineContiguousRegions", false);
689 716
690 m_generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", true); 717 m_generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", true);
691 if (m_generateMaptiles) 718 if (m_generateMaptiles)
@@ -721,9 +748,9 @@ namespace OpenSim.Region.Framework.Scenes
721 m_update_terrain = startupConfig.GetInt( "UpdateTerrainEveryNFrames", m_update_terrain); 748 m_update_terrain = startupConfig.GetInt( "UpdateTerrainEveryNFrames", m_update_terrain);
722 m_update_temp_cleaning = startupConfig.GetInt( "UpdateTempCleaningEveryNFrames", m_update_temp_cleaning); 749 m_update_temp_cleaning = startupConfig.GetInt( "UpdateTempCleaningEveryNFrames", m_update_temp_cleaning);
723 } 750 }
724 catch 751 catch (Exception e)
725 { 752 {
726 m_log.Warn("[SCENE]: Failed to load StartupConfig"); 753 m_log.Error("[SCENE]: Failed to load StartupConfig: " + e.ToString());
727 } 754 }
728 755
729 #endregion Region Config 756 #endregion Region Config
@@ -1134,7 +1161,22 @@ namespace OpenSim.Region.Framework.Scenes
1134 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat); 1161 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat);
1135 if (HeartbeatThread != null) 1162 if (HeartbeatThread != null)
1136 { 1163 {
1164 m_hbRestarts++;
1165 if(m_hbRestarts > 10)
1166 Environment.Exit(1);
1167 m_log.ErrorFormat("[SCENE]: Restarting heartbeat thread because it hasn't reported in in region {0}", RegionInfo.RegionName);
1168
1169//int pid = System.Diagnostics.Process.GetCurrentProcess().Id;
1170//System.Diagnostics.Process proc = new System.Diagnostics.Process();
1171//proc.EnableRaisingEvents=false;
1172//proc.StartInfo.FileName = "/bin/kill";
1173//proc.StartInfo.Arguments = "-QUIT " + pid.ToString();
1174//proc.Start();
1175//proc.WaitForExit();
1176//Thread.Sleep(1000);
1177//Environment.Exit(1);
1137 HeartbeatThread.Abort(); 1178 HeartbeatThread.Abort();
1179 Watchdog.AbortThread(HeartbeatThread.ManagedThreadId);
1138 HeartbeatThread = null; 1180 HeartbeatThread = null;
1139 } 1181 }
1140 m_lastUpdate = Util.EnvironmentTickCount(); 1182 m_lastUpdate = Util.EnvironmentTickCount();
@@ -1181,9 +1223,6 @@ namespace OpenSim.Region.Framework.Scenes
1181 m_eventManager.TriggerOnRegionStarted(this); 1223 m_eventManager.TriggerOnRegionStarted(this);
1182 while (!shuttingdown) 1224 while (!shuttingdown)
1183 Update(); 1225 Update();
1184
1185 m_lastUpdate = Util.EnvironmentTickCount();
1186 m_firstHeartbeat = false;
1187 } 1226 }
1188 catch (ThreadAbortException) 1227 catch (ThreadAbortException)
1189 { 1228 {
@@ -1281,6 +1320,13 @@ namespace OpenSim.Region.Framework.Scenes
1281 eventMS = Util.EnvironmentTickCountSubtract(evMS); ; 1320 eventMS = Util.EnvironmentTickCountSubtract(evMS); ;
1282 } 1321 }
1283 1322
1323 // if (Frame % m_update_land == 0)
1324 // {
1325 // int ldMS = Util.EnvironmentTickCount();
1326 // UpdateLand();
1327 // landMS = Util.EnvironmentTickCountSubtract(ldMS);
1328 // }
1329
1284 if (Frame % m_update_backup == 0) 1330 if (Frame % m_update_backup == 0)
1285 { 1331 {
1286 int backMS = Util.EnvironmentTickCount(); 1332 int backMS = Util.EnvironmentTickCount();
@@ -1390,12 +1436,16 @@ namespace OpenSim.Region.Framework.Scenes
1390 maintc = Util.EnvironmentTickCountSubtract(maintc); 1436 maintc = Util.EnvironmentTickCountSubtract(maintc);
1391 maintc = (int)(MinFrameTime * 1000) - maintc; 1437 maintc = (int)(MinFrameTime * 1000) - maintc;
1392 1438
1439
1440 m_lastUpdate = Util.EnvironmentTickCount();
1441 m_firstHeartbeat = false;
1442
1393 if (maintc > 0) 1443 if (maintc > 0)
1394 Thread.Sleep(maintc); 1444 Thread.Sleep(maintc);
1395 1445
1396 // Tell the watchdog that this thread is still alive 1446 // Tell the watchdog that this thread is still alive
1397 Watchdog.UpdateThread(); 1447 Watchdog.UpdateThread();
1398 } 1448 }
1399 1449
1400 public void AddGroupTarget(SceneObjectGroup grp) 1450 public void AddGroupTarget(SceneObjectGroup grp)
1401 { 1451 {
@@ -1411,9 +1461,9 @@ namespace OpenSim.Region.Framework.Scenes
1411 1461
1412 private void CheckAtTargets() 1462 private void CheckAtTargets()
1413 { 1463 {
1414 Dictionary<UUID, SceneObjectGroup>.ValueCollection objs; 1464 List<SceneObjectGroup> objs = new List<SceneObjectGroup>();
1415 lock (m_groupsWithTargets) 1465 lock (m_groupsWithTargets)
1416 objs = m_groupsWithTargets.Values; 1466 objs = new List<SceneObjectGroup>(m_groupsWithTargets.Values);
1417 1467
1418 foreach (SceneObjectGroup entry in objs) 1468 foreach (SceneObjectGroup entry in objs)
1419 entry.checkAtTargets(); 1469 entry.checkAtTargets();
@@ -1495,7 +1545,7 @@ namespace OpenSim.Region.Framework.Scenes
1495 msg.fromAgentName = "Server"; 1545 msg.fromAgentName = "Server";
1496 msg.dialog = (byte)19; // Object msg 1546 msg.dialog = (byte)19; // Object msg
1497 msg.fromGroup = false; 1547 msg.fromGroup = false;
1498 msg.offline = (byte)0; 1548 msg.offline = (byte)1;
1499 msg.ParentEstateID = RegionInfo.EstateSettings.ParentEstateID; 1549 msg.ParentEstateID = RegionInfo.EstateSettings.ParentEstateID;
1500 msg.Position = Vector3.Zero; 1550 msg.Position = Vector3.Zero;
1501 msg.RegionID = RegionInfo.RegionID.Guid; 1551 msg.RegionID = RegionInfo.RegionID.Guid;
@@ -1726,14 +1776,24 @@ namespace OpenSim.Region.Framework.Scenes
1726 /// <returns></returns> 1776 /// <returns></returns>
1727 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter) 1777 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter)
1728 { 1778 {
1779
1780 float wheight = (float)RegionInfo.RegionSettings.WaterHeight;
1781 Vector3 wpos = Vector3.Zero;
1782 // Check for water surface intersection from above
1783 if ( (RayStart.Z > wheight) && (RayEnd.Z < wheight) )
1784 {
1785 float ratio = (RayStart.Z - wheight) / (RayStart.Z - RayEnd.Z);
1786 wpos.X = RayStart.X - (ratio * (RayStart.X - RayEnd.X));
1787 wpos.Y = RayStart.Y - (ratio * (RayStart.Y - RayEnd.Y));
1788 wpos.Z = wheight;
1789 }
1790
1729 Vector3 pos = Vector3.Zero; 1791 Vector3 pos = Vector3.Zero;
1730 if (RayEndIsIntersection == (byte)1) 1792 if (RayEndIsIntersection == (byte)1)
1731 { 1793 {
1732 pos = RayEnd; 1794 pos = RayEnd;
1733 return pos;
1734 } 1795 }
1735 1796 else if (RayTargetID != UUID.Zero)
1736 if (RayTargetID != UUID.Zero)
1737 { 1797 {
1738 SceneObjectPart target = GetSceneObjectPart(RayTargetID); 1798 SceneObjectPart target = GetSceneObjectPart(RayTargetID);
1739 1799
@@ -1755,7 +1815,7 @@ namespace OpenSim.Region.Framework.Scenes
1755 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter); 1815 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter);
1756 1816
1757 // Un-comment out the following line to Get Raytrace results printed to the console. 1817 // Un-comment out the following line to Get Raytrace results printed to the console.
1758 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString()); 1818 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
1759 float ScaleOffset = 0.5f; 1819 float ScaleOffset = 0.5f;
1760 1820
1761 // If we hit something 1821 // If we hit something
@@ -1778,13 +1838,10 @@ namespace OpenSim.Region.Framework.Scenes
1778 //pos.Z -= 0.25F; 1838 //pos.Z -= 0.25F;
1779 1839
1780 } 1840 }
1781
1782 return pos;
1783 } 1841 }
1784 else 1842 else
1785 { 1843 {
1786 // We don't have a target here, so we're going to raytrace all the objects in the scene. 1844 // We don't have a target here, so we're going to raytrace all the objects in the scene.
1787
1788 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false); 1845 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false);
1789 1846
1790 // Un-comment the following line to print the raytrace results to the console. 1847 // Un-comment the following line to print the raytrace results to the console.
@@ -1793,13 +1850,12 @@ namespace OpenSim.Region.Framework.Scenes
1793 if (ei.HitTF) 1850 if (ei.HitTF)
1794 { 1851 {
1795 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z); 1852 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z);
1796 } else 1853 }
1854 else
1797 { 1855 {
1798 // fall back to our stupid functionality 1856 // fall back to our stupid functionality
1799 pos = RayEnd; 1857 pos = RayEnd;
1800 } 1858 }
1801
1802 return pos;
1803 } 1859 }
1804 } 1860 }
1805 else 1861 else
@@ -1810,8 +1866,12 @@ namespace OpenSim.Region.Framework.Scenes
1810 //increase height so its above the ground. 1866 //increase height so its above the ground.
1811 //should be getting the normal of the ground at the rez point and using that? 1867 //should be getting the normal of the ground at the rez point and using that?
1812 pos.Z += scale.Z / 2f; 1868 pos.Z += scale.Z / 2f;
1813 return pos; 1869// return pos;
1814 } 1870 }
1871
1872 // check against posible water intercept
1873 if (wpos.Z > pos.Z) pos = wpos;
1874 return pos;
1815 } 1875 }
1816 1876
1817 1877
@@ -1895,7 +1955,10 @@ namespace OpenSim.Region.Framework.Scenes
1895 public bool AddRestoredSceneObject( 1955 public bool AddRestoredSceneObject(
1896 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 1956 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
1897 { 1957 {
1898 return m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates); 1958 bool result = m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates);
1959 if (result)
1960 sceneObject.IsDeleted = false;
1961 return result;
1899 } 1962 }
1900 1963
1901 /// <summary> 1964 /// <summary>
@@ -1987,6 +2050,15 @@ namespace OpenSim.Region.Framework.Scenes
1987 /// </summary> 2050 /// </summary>
1988 public void DeleteAllSceneObjects() 2051 public void DeleteAllSceneObjects()
1989 { 2052 {
2053 DeleteAllSceneObjects(false);
2054 }
2055
2056 /// <summary>
2057 /// Delete every object from the scene. This does not include attachments worn by avatars.
2058 /// </summary>
2059 public void DeleteAllSceneObjects(bool exceptNoCopy)
2060 {
2061 List<SceneObjectGroup> toReturn = new List<SceneObjectGroup>();
1990 lock (Entities) 2062 lock (Entities)
1991 { 2063 {
1992 EntityBase[] entities = Entities.GetEntities(); 2064 EntityBase[] entities = Entities.GetEntities();
@@ -1995,11 +2067,24 @@ namespace OpenSim.Region.Framework.Scenes
1995 if (e is SceneObjectGroup) 2067 if (e is SceneObjectGroup)
1996 { 2068 {
1997 SceneObjectGroup sog = (SceneObjectGroup)e; 2069 SceneObjectGroup sog = (SceneObjectGroup)e;
1998 if (!sog.IsAttachment) 2070 if (sog != null && !sog.IsAttachment)
1999 DeleteSceneObject((SceneObjectGroup)e, false); 2071 {
2072 if (!exceptNoCopy || ((sog.GetEffectivePermissions() & (uint)PermissionMask.Copy) != 0))
2073 {
2074 DeleteSceneObject((SceneObjectGroup)e, false);
2075 }
2076 else
2077 {
2078 toReturn.Add((SceneObjectGroup)e);
2079 }
2080 }
2000 } 2081 }
2001 } 2082 }
2002 } 2083 }
2084 if (toReturn.Count > 0)
2085 {
2086 returnObjects(toReturn.ToArray(), UUID.Zero);
2087 }
2003 } 2088 }
2004 2089
2005 /// <summary> 2090 /// <summary>
@@ -2047,6 +2132,8 @@ namespace OpenSim.Region.Framework.Scenes
2047 } 2132 }
2048 2133
2049 group.DeleteGroupFromScene(silent); 2134 group.DeleteGroupFromScene(silent);
2135 if (!silent)
2136 SendKillObject(new List<uint>() { group.LocalId });
2050 2137
2051// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID); 2138// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID);
2052 } 2139 }
@@ -2401,10 +2488,17 @@ namespace OpenSim.Region.Framework.Scenes
2401 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns> 2488 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns>
2402 public bool AddSceneObject(SceneObjectGroup sceneObject) 2489 public bool AddSceneObject(SceneObjectGroup sceneObject)
2403 { 2490 {
2491 if (sceneObject.OwnerID == UUID.Zero)
2492 {
2493 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero", sceneObject.UUID);
2494 return false;
2495 }
2496
2404 // If the user is banned, we won't let any of their objects 2497 // If the user is banned, we won't let any of their objects
2405 // enter. Period. 2498 // enter. Period.
2406 // 2499 //
2407 if (m_regInfo.EstateSettings.IsBanned(sceneObject.OwnerID)) 2500 int flags = GetUserFlags(sceneObject.OwnerID);
2501 if (m_regInfo.EstateSettings.IsBanned(sceneObject.OwnerID, flags))
2408 { 2502 {
2409 m_log.InfoFormat("[INTERREGION]: Denied prim crossing for banned avatar {0}", sceneObject.OwnerID); 2503 m_log.InfoFormat("[INTERREGION]: Denied prim crossing for banned avatar {0}", sceneObject.OwnerID);
2410 2504
@@ -2450,12 +2544,23 @@ namespace OpenSim.Region.Framework.Scenes
2450 } 2544 }
2451 else 2545 else
2452 { 2546 {
2547 m_log.DebugFormat("[SCENE]: Attachment {0} arrived and scene presence was not found, setting to temp", sceneObject.UUID);
2453 RootPrim.RemFlag(PrimFlags.TemporaryOnRez); 2548 RootPrim.RemFlag(PrimFlags.TemporaryOnRez);
2454 RootPrim.AddFlag(PrimFlags.TemporaryOnRez); 2549 RootPrim.AddFlag(PrimFlags.TemporaryOnRez);
2455 } 2550 }
2551 if (sceneObject.OwnerID == UUID.Zero)
2552 {
2553 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero after attachment processing. BUG!", sceneObject.UUID);
2554 return false;
2555 }
2456 } 2556 }
2457 else 2557 else
2458 { 2558 {
2559 if (sceneObject.OwnerID == UUID.Zero)
2560 {
2561 m_log.ErrorFormat("[SCENE]: Owner ID for non-attachment {0} was zero", sceneObject.UUID);
2562 return false;
2563 }
2459 AddRestoredSceneObject(sceneObject, true, false); 2564 AddRestoredSceneObject(sceneObject, true, false);
2460 2565
2461 if (!Permissions.CanObjectEntry(sceneObject.UUID, 2566 if (!Permissions.CanObjectEntry(sceneObject.UUID,
@@ -2484,6 +2589,24 @@ namespace OpenSim.Region.Framework.Scenes
2484 return 2; // StateSource.PrimCrossing 2589 return 2; // StateSource.PrimCrossing
2485 } 2590 }
2486 2591
2592 public int GetUserFlags(UUID user)
2593 {
2594 //Unfortunately the SP approach means that the value is cached until region is restarted
2595 /*
2596 ScenePresence sp;
2597 if (TryGetScenePresence(user, out sp))
2598 {
2599 return sp.UserFlags;
2600 }
2601 else
2602 {
2603 */
2604 UserAccount uac = UserAccountService.GetUserAccount(RegionInfo.ScopeID, user);
2605 if (uac == null)
2606 return 0;
2607 return uac.UserFlags;
2608 //}
2609 }
2487 #endregion 2610 #endregion
2488 2611
2489 #region Add/Remove Avatar Methods 2612 #region Add/Remove Avatar Methods
@@ -2498,6 +2621,7 @@ namespace OpenSim.Region.Framework.Scenes
2498 || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; 2621 || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0;
2499 2622
2500 CheckHeartbeat(); 2623 CheckHeartbeat();
2624 ScenePresence presence;
2501 2625
2502 ScenePresence sp = GetScenePresence(client.AgentId); 2626 ScenePresence sp = GetScenePresence(client.AgentId);
2503 2627
@@ -2546,7 +2670,13 @@ namespace OpenSim.Region.Framework.Scenes
2546 2670
2547 EventManager.TriggerOnNewClient(client); 2671 EventManager.TriggerOnNewClient(client);
2548 if (vialogin) 2672 if (vialogin)
2673 {
2549 EventManager.TriggerOnClientLogin(client); 2674 EventManager.TriggerOnClientLogin(client);
2675 // Send initial parcel data
2676 Vector3 pos = sp.AbsolutePosition;
2677 ILandObject land = LandChannel.GetLandObject(pos.X, pos.Y);
2678 land.SendLandUpdateToClient(client);
2679 }
2550 2680
2551 return sp; 2681 return sp;
2552 } 2682 }
@@ -2636,19 +2766,12 @@ namespace OpenSim.Region.Framework.Scenes
2636 // and the scene presence and the client, if they exist 2766 // and the scene presence and the client, if they exist
2637 try 2767 try
2638 { 2768 {
2639 // We need to wait for the client to make UDP contact first. 2769 ScenePresence sp = GetScenePresence(agentID);
2640 // It's the UDP contact that creates the scene presence 2770 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
2641 ScenePresence sp = WaitGetScenePresence(agentID); 2771
2642 if (sp != null) 2772 if (sp != null)
2643 {
2644 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
2645
2646 sp.ControllingClient.Close(); 2773 sp.ControllingClient.Close();
2647 } 2774
2648 else
2649 {
2650 m_log.WarnFormat("[SCENE]: Could not find scene presence for {0}", agentID);
2651 }
2652 // BANG! SLASH! 2775 // BANG! SLASH!
2653 m_authenticateHandler.RemoveCircuit(agentID); 2776 m_authenticateHandler.RemoveCircuit(agentID);
2654 2777
@@ -2749,6 +2872,7 @@ namespace OpenSim.Region.Framework.Scenes
2749 client.OnFetchInventory += m_asyncInventorySender.HandleFetchInventory; 2872 client.OnFetchInventory += m_asyncInventorySender.HandleFetchInventory;
2750 client.OnUpdateInventoryItem += UpdateInventoryItemAsset; 2873 client.OnUpdateInventoryItem += UpdateInventoryItemAsset;
2751 client.OnCopyInventoryItem += CopyInventoryItem; 2874 client.OnCopyInventoryItem += CopyInventoryItem;
2875 client.OnMoveItemsAndLeaveCopy += MoveInventoryItemsLeaveCopy;
2752 client.OnMoveInventoryItem += MoveInventoryItem; 2876 client.OnMoveInventoryItem += MoveInventoryItem;
2753 client.OnRemoveInventoryItem += RemoveInventoryItem; 2877 client.OnRemoveInventoryItem += RemoveInventoryItem;
2754 client.OnRemoveInventoryFolder += RemoveInventoryFolder; 2878 client.OnRemoveInventoryFolder += RemoveInventoryFolder;
@@ -2924,15 +3048,16 @@ namespace OpenSim.Region.Framework.Scenes
2924 /// </summary> 3048 /// </summary>
2925 /// <param name="agentId">The avatar's Unique ID</param> 3049 /// <param name="agentId">The avatar's Unique ID</param>
2926 /// <param name="client">The IClientAPI for the client</param> 3050 /// <param name="client">The IClientAPI for the client</param>
2927 public virtual void TeleportClientHome(UUID agentId, IClientAPI client) 3051 public virtual bool TeleportClientHome(UUID agentId, IClientAPI client)
2928 { 3052 {
2929 if (m_teleportModule != null) 3053 if (m_teleportModule != null)
2930 m_teleportModule.TeleportHome(agentId, client); 3054 return m_teleportModule.TeleportHome(agentId, client);
2931 else 3055 else
2932 { 3056 {
2933 m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active"); 3057 m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active");
2934 client.SendTeleportFailed("Unable to perform teleports on this simulator."); 3058 client.SendTeleportFailed("Unable to perform teleports on this simulator.");
2935 } 3059 }
3060 return false;
2936 } 3061 }
2937 3062
2938 /// <summary> 3063 /// <summary>
@@ -3042,6 +3167,16 @@ namespace OpenSim.Region.Framework.Scenes
3042 /// <param name="flags"></param> 3167 /// <param name="flags"></param>
3043 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags) 3168 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags)
3044 { 3169 {
3170 //Add half the avatar's height so that the user doesn't fall through prims
3171 ScenePresence presence;
3172 if (TryGetScenePresence(remoteClient.AgentId, out presence))
3173 {
3174 if (presence.Appearance != null)
3175 {
3176 position.Z = position.Z + (presence.Appearance.AvatarHeight / 2);
3177 }
3178 }
3179
3045 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt)) 3180 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt))
3046 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot. 3181 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot.
3047 m_dialogModule.SendAlertToUser(remoteClient, "Home position set."); 3182 m_dialogModule.SendAlertToUser(remoteClient, "Home position set.");
@@ -3110,8 +3245,9 @@ namespace OpenSim.Region.Framework.Scenes
3110 regions.Remove(RegionInfo.RegionHandle); 3245 regions.Remove(RegionInfo.RegionHandle);
3111 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); 3246 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions);
3112 } 3247 }
3113 3248 m_log.Debug("[Scene] Beginning ClientClosed");
3114 m_eventManager.TriggerClientClosed(agentID, this); 3249 m_eventManager.TriggerClientClosed(agentID, this);
3250 m_log.Debug("[Scene] Finished ClientClosed");
3115 } 3251 }
3116 catch (NullReferenceException) 3252 catch (NullReferenceException)
3117 { 3253 {
@@ -3173,9 +3309,10 @@ namespace OpenSim.Region.Framework.Scenes
3173 { 3309 {
3174 m_log.ErrorFormat("[SCENE] Scene.cs:RemoveClient exception {0}{1}", e.Message, e.StackTrace); 3310 m_log.ErrorFormat("[SCENE] Scene.cs:RemoveClient exception {0}{1}", e.Message, e.StackTrace);
3175 } 3311 }
3176 3312 m_log.Debug("[Scene] Done. Firing RemoveCircuit");
3177 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode); 3313 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode);
3178// CleanDroppedAttachments(); 3314// CleanDroppedAttachments();
3315 m_log.Debug("[Scene] The avatar has left the building");
3179 //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false)); 3316 //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false));
3180 //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true)); 3317 //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true));
3181 } 3318 }
@@ -3294,13 +3431,16 @@ namespace OpenSim.Region.Framework.Scenes
3294 sp = null; 3431 sp = null;
3295 } 3432 }
3296 3433
3297 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3298 3434
3299 //On login test land permisions 3435 //On login test land permisions
3300 if (vialogin) 3436 if (vialogin)
3301 { 3437 {
3302 if (land != null && !TestLandRestrictions(agent, land, out reason)) 3438 IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>();
3439 if (cache != null)
3440 cache.Remove(agent.firstname + " " + agent.lastname);
3441 if (!TestLandRestrictions(agent.AgentID, out reason, ref agent.startpos.X, ref agent.startpos.Y))
3303 { 3442 {
3443 m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString());
3304 return false; 3444 return false;
3305 } 3445 }
3306 } 3446 }
@@ -3324,8 +3464,13 @@ namespace OpenSim.Region.Framework.Scenes
3324 3464
3325 try 3465 try
3326 { 3466 {
3327 if (!AuthorizeUser(agent, out reason)) 3467 // Always check estate if this is a login. Always
3328 return false; 3468 // check if banned regions are to be blacked out.
3469 if (vialogin || (!m_seeIntoBannedRegion))
3470 {
3471 if (!AuthorizeUser(agent, out reason))
3472 return false;
3473 }
3329 } 3474 }
3330 catch (Exception e) 3475 catch (Exception e)
3331 { 3476 {
@@ -3428,6 +3573,8 @@ namespace OpenSim.Region.Framework.Scenes
3428 } 3573 }
3429 } 3574 }
3430 // Honor parcel landing type and position. 3575 // Honor parcel landing type and position.
3576 /*
3577 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3431 if (land != null) 3578 if (land != null)
3432 { 3579 {
3433 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) 3580 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero)
@@ -3435,26 +3582,34 @@ namespace OpenSim.Region.Framework.Scenes
3435 agent.startpos = land.LandData.UserLocation; 3582 agent.startpos = land.LandData.UserLocation;
3436 } 3583 }
3437 } 3584 }
3585 */// This is now handled properly in ScenePresence.MakeRootAgent
3438 } 3586 }
3439 3587
3440 return true; 3588 return true;
3441 } 3589 }
3442 3590
3443 private bool TestLandRestrictions(AgentCircuitData agent, ILandObject land, out string reason) 3591 public bool TestLandRestrictions(UUID agentID, out string reason, ref float posX, ref float posY)
3444 { 3592 {
3445 3593 reason = String.Empty;
3446 bool banned = land.IsBannedFromLand(agent.AgentID); 3594 if (Permissions.IsGod(agentID))
3447 bool restricted = land.IsRestrictedFromLand(agent.AgentID); 3595 return true;
3596
3597 ILandObject land = LandChannel.GetLandObject(posX, posY);
3598 if (land == null)
3599 return false;
3600
3601 bool banned = land.IsBannedFromLand(agentID);
3602 bool restricted = land.IsRestrictedFromLand(agentID);
3448 3603
3449 if (banned || restricted) 3604 if (banned || restricted)
3450 { 3605 {
3451 ILandObject nearestParcel = GetNearestAllowedParcel(agent.AgentID, agent.startpos.X, agent.startpos.Y); 3606 ILandObject nearestParcel = GetNearestAllowedParcel(agentID, posX, posY);
3452 if (nearestParcel != null) 3607 if (nearestParcel != null)
3453 { 3608 {
3454 //Move agent to nearest allowed 3609 //Move agent to nearest allowed
3455 Vector3 newPosition = GetParcelCenterAtGround(nearestParcel); 3610 Vector3 newPosition = GetParcelCenterAtGround(nearestParcel);
3456 agent.startpos.X = newPosition.X; 3611 posX = newPosition.X;
3457 agent.startpos.Y = newPosition.Y; 3612 posY = newPosition.Y;
3458 } 3613 }
3459 else 3614 else
3460 { 3615 {
@@ -3516,7 +3671,7 @@ namespace OpenSim.Region.Framework.Scenes
3516 3671
3517 if (!m_strictAccessControl) return true; 3672 if (!m_strictAccessControl) return true;
3518 if (Permissions.IsGod(agent.AgentID)) return true; 3673 if (Permissions.IsGod(agent.AgentID)) return true;
3519 3674
3520 if (AuthorizationService != null) 3675 if (AuthorizationService != null)
3521 { 3676 {
3522 if (!AuthorizationService.IsAuthorizedForRegion( 3677 if (!AuthorizationService.IsAuthorizedForRegion(
@@ -3524,14 +3679,14 @@ namespace OpenSim.Region.Framework.Scenes
3524 { 3679 {
3525 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the region", 3680 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the region",
3526 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 3681 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
3527 3682
3528 return false; 3683 return false;
3529 } 3684 }
3530 } 3685 }
3531 3686
3532 if (m_regInfo.EstateSettings != null) 3687 if (m_regInfo.EstateSettings != null)
3533 { 3688 {
3534 if (m_regInfo.EstateSettings.IsBanned(agent.AgentID)) 3689 if (m_regInfo.EstateSettings.IsBanned(agent.AgentID,0))
3535 { 3690 {
3536 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist", 3691 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist",
3537 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 3692 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
@@ -3723,6 +3878,13 @@ namespace OpenSim.Region.Framework.Scenes
3723 3878
3724 // We have to wait until the viewer contacts this region after receiving EAC. 3879 // We have to wait until the viewer contacts this region after receiving EAC.
3725 // That calls AddNewClient, which finally creates the ScenePresence 3880 // That calls AddNewClient, which finally creates the ScenePresence
3881 int flags = GetUserFlags(cAgentData.AgentID);
3882 if (m_regInfo.EstateSettings.IsBanned(cAgentData.AgentID, flags))
3883 {
3884 m_log.DebugFormat("[SCENE]: Denying root agent entry to {0}: banned", cAgentData.AgentID);
3885 return false;
3886 }
3887
3726 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2); 3888 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2);
3727 if (nearestParcel == null) 3889 if (nearestParcel == null)
3728 { 3890 {
@@ -3804,12 +3966,22 @@ namespace OpenSim.Region.Framework.Scenes
3804 return false; 3966 return false;
3805 } 3967 }
3806 3968
3969 public bool IncomingCloseAgent(UUID agentID)
3970 {
3971 return IncomingCloseAgent(agentID, false);
3972 }
3973
3974 public bool IncomingCloseChildAgent(UUID agentID)
3975 {
3976 return IncomingCloseAgent(agentID, true);
3977 }
3978
3807 /// <summary> 3979 /// <summary>
3808 /// Tell a single agent to disconnect from the region. 3980 /// Tell a single agent to disconnect from the region.
3809 /// </summary> 3981 /// </summary>
3810 /// <param name="regionHandle"></param>
3811 /// <param name="agentID"></param> 3982 /// <param name="agentID"></param>
3812 public bool IncomingCloseAgent(UUID agentID) 3983 /// <param name="childOnly"></param>
3984 public bool IncomingCloseAgent(UUID agentID, bool childOnly)
3813 { 3985 {
3814 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); 3986 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID);
3815 3987
@@ -3821,7 +3993,7 @@ namespace OpenSim.Region.Framework.Scenes
3821 { 3993 {
3822 m_sceneGraph.removeUserCount(false); 3994 m_sceneGraph.removeUserCount(false);
3823 } 3995 }
3824 else 3996 else if (!childOnly)
3825 { 3997 {
3826 m_sceneGraph.removeUserCount(true); 3998 m_sceneGraph.removeUserCount(true);
3827 } 3999 }
@@ -3837,9 +4009,12 @@ namespace OpenSim.Region.Framework.Scenes
3837 } 4009 }
3838 else 4010 else
3839 presence.ControllingClient.SendShutdownConnectionNotice(); 4011 presence.ControllingClient.SendShutdownConnectionNotice();
4012 presence.ControllingClient.Close(false);
4013 }
4014 else if (!childOnly)
4015 {
4016 presence.ControllingClient.Close(true);
3840 } 4017 }
3841
3842 presence.ControllingClient.Close();
3843 return true; 4018 return true;
3844 } 4019 }
3845 4020
@@ -4432,34 +4607,78 @@ namespace OpenSim.Region.Framework.Scenes
4432 SimulationDataService.RemoveObject(uuid, m_regInfo.RegionID); 4607 SimulationDataService.RemoveObject(uuid, m_regInfo.RegionID);
4433 } 4608 }
4434 4609
4435 public int GetHealth() 4610 public int GetHealth(out int flags, out string message)
4436 { 4611 {
4437 // Returns: 4612 // Returns:
4438 // 1 = sim is up and accepting http requests. The heartbeat has 4613 // 1 = sim is up and accepting http requests. The heartbeat has
4439 // stopped and the sim is probably locked up, but a remote 4614 // stopped and the sim is probably locked up, but a remote
4440 // admin restart may succeed 4615 // admin restart may succeed
4441 // 4616 //
4442 // 2 = Sim is up and the heartbeat is running. The sim is likely 4617 // 2 = Sim is up and the heartbeat is running. The sim is likely
4443 // usable for people within and logins _may_ work 4618 // usable for people within
4619 //
4620 // 3 = Sim is up and one packet thread is running. Sim is
4621 // unstable and will not accept new logins
4622 //
4623 // 4 = Sim is up and both packet threads are running. Sim is
4624 // likely usable
4444 // 4625 //
4445 // 3 = We have seen a new user enter within the past 4 minutes 4626 // 5 = We have seen a new user enter within the past 4 minutes
4446 // which can be seen as positive confirmation of sim health 4627 // which can be seen as positive confirmation of sim health
4447 // 4628 //
4629
4630 flags = 0;
4631 message = String.Empty;
4632
4633 CheckHeartbeat();
4634
4635 if (m_firstHeartbeat || (m_lastIncoming == 0 && m_lastOutgoing == 0))
4636 {
4637 // We're still starting
4638 // 0 means "in startup", it can't happen another way, since
4639 // to get here, we must be able to accept http connections
4640 return 0;
4641 }
4642
4448 int health=1; // Start at 1, means we're up 4643 int health=1; // Start at 1, means we're up
4449 4644
4450 if ((Util.EnvironmentTickCountSubtract(m_lastUpdate)) < 1000) 4645 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) < 1000)
4646 {
4647 health+=1;
4648 flags |= 1;
4649 }
4650
4651 if (Util.EnvironmentTickCountSubtract(m_lastIncoming) < 1000)
4652 {
4451 health+=1; 4653 health+=1;
4654 flags |= 2;
4655 }
4656
4657 if (Util.EnvironmentTickCountSubtract(m_lastOutgoing) < 1000)
4658 {
4659 health+=1;
4660 flags |= 4;
4661 }
4452 else 4662 else
4663 {
4664int pid = System.Diagnostics.Process.GetCurrentProcess().Id;
4665System.Diagnostics.Process proc = new System.Diagnostics.Process();
4666proc.EnableRaisingEvents=false;
4667proc.StartInfo.FileName = "/bin/kill";
4668proc.StartInfo.Arguments = "-QUIT " + pid.ToString();
4669proc.Start();
4670proc.WaitForExit();
4671Thread.Sleep(1000);
4672Environment.Exit(1);
4673 }
4674
4675 if (flags != 7)
4453 return health; 4676 return health;
4454 4677
4455 // A login in the last 4 mins? We can't be doing too badly 4678 // A login in the last 4 mins? We can't be doing too badly
4456 // 4679 //
4457 if ((Util.EnvironmentTickCountSubtract(m_LastLogin)) < 240000) 4680 if (Util.EnvironmentTickCountSubtract(m_LastLogin) < 240000)
4458 health++; 4681 health++;
4459 else
4460 return health;
4461
4462 CheckHeartbeat();
4463 4682
4464 return health; 4683 return health;
4465 } 4684 }
@@ -4652,7 +4871,7 @@ namespace OpenSim.Region.Framework.Scenes
4652 if (m_firstHeartbeat) 4871 if (m_firstHeartbeat)
4653 return; 4872 return;
4654 4873
4655 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) > 2000) 4874 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) > 5000)
4656 StartTimer(); 4875 StartTimer();
4657 } 4876 }
4658 4877
@@ -4666,9 +4885,14 @@ namespace OpenSim.Region.Framework.Scenes
4666 get { return m_allowScriptCrossings; } 4885 get { return m_allowScriptCrossings; }
4667 } 4886 }
4668 4887
4669 public Vector3? GetNearestAllowedPosition(ScenePresence avatar) 4888 public Vector3 GetNearestAllowedPosition(ScenePresence avatar)
4889 {
4890 return GetNearestAllowedPosition(avatar, null);
4891 }
4892
4893 public Vector3 GetNearestAllowedPosition(ScenePresence avatar, ILandObject excludeParcel)
4670 { 4894 {
4671 ILandObject nearestParcel = GetNearestAllowedParcel(avatar.UUID, avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); 4895 ILandObject nearestParcel = GetNearestAllowedParcel(avatar.UUID, avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y, excludeParcel);
4672 4896
4673 if (nearestParcel != null) 4897 if (nearestParcel != null)
4674 { 4898 {
@@ -4727,13 +4951,18 @@ namespace OpenSim.Region.Framework.Scenes
4727 4951
4728 public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y) 4952 public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y)
4729 { 4953 {
4954 return GetNearestAllowedParcel(avatarId, x, y, null);
4955 }
4956
4957 public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y, ILandObject excludeParcel)
4958 {
4730 List<ILandObject> all = AllParcels(); 4959 List<ILandObject> all = AllParcels();
4731 float minParcelDistance = float.MaxValue; 4960 float minParcelDistance = float.MaxValue;
4732 ILandObject nearestParcel = null; 4961 ILandObject nearestParcel = null;
4733 4962
4734 foreach (var parcel in all) 4963 foreach (var parcel in all)
4735 { 4964 {
4736 if (!parcel.IsEitherBannedOrRestricted(avatarId)) 4965 if (!parcel.IsEitherBannedOrRestricted(avatarId) && parcel != excludeParcel)
4737 { 4966 {
4738 float parcelDistance = GetParcelDistancefromPoint(parcel, x, y); 4967 float parcelDistance = GetParcelDistancefromPoint(parcel, x, y);
4739 if (parcelDistance < minParcelDistance) 4968 if (parcelDistance < minParcelDistance)
@@ -4975,7 +5204,55 @@ namespace OpenSim.Region.Framework.Scenes
4975 mapModule.GenerateMaptile(); 5204 mapModule.GenerateMaptile();
4976 } 5205 }
4977 5206
4978 private void RegenerateMaptileAndReregister(object sender, ElapsedEventArgs e) 5207// public void CleanDroppedAttachments()
5208// {
5209// List<SceneObjectGroup> objectsToDelete =
5210// new List<SceneObjectGroup>();
5211//
5212// lock (m_cleaningAttachments)
5213// {
5214// ForEachSOG(delegate (SceneObjectGroup grp)
5215// {
5216// if (grp.RootPart.Shape.PCode == 0 && grp.RootPart.Shape.State != 0 && (!objectsToDelete.Contains(grp)))
5217// {
5218// UUID agentID = grp.OwnerID;
5219// if (agentID == UUID.Zero)
5220// {
5221// objectsToDelete.Add(grp);
5222// return;
5223// }
5224//
5225// ScenePresence sp = GetScenePresence(agentID);
5226// if (sp == null)
5227// {
5228// objectsToDelete.Add(grp);
5229// return;
5230// }
5231// }
5232// });
5233// }
5234//
5235// foreach (SceneObjectGroup grp in objectsToDelete)
5236// {
5237// m_log.InfoFormat("[SCENE]: Deleting dropped attachment {0} of user {1}", grp.UUID, grp.OwnerID);
5238// DeleteSceneObject(grp, true);
5239// }
5240// }
5241
5242 public void ThreadAlive(int threadCode)
5243 {
5244 switch(threadCode)
5245 {
5246 case 1: // Incoming
5247 m_lastIncoming = Util.EnvironmentTickCount();
5248 break;
5249 case 2: // Incoming
5250 m_lastOutgoing = Util.EnvironmentTickCount();
5251 break;
5252 }
5253 }
5254
5255 public void RegenerateMaptileAndReregister(object sender, ElapsedEventArgs e)
4979 { 5256 {
4980 RegenerateMaptile(); 5257 RegenerateMaptile();
4981 5258
@@ -4994,6 +5271,14 @@ namespace OpenSim.Region.Framework.Scenes
4994 // child agent creation, thereby emulating the SL behavior. 5271 // child agent creation, thereby emulating the SL behavior.
4995 public bool QueryAccess(UUID agentID, Vector3 position, out string reason) 5272 public bool QueryAccess(UUID agentID, Vector3 position, out string reason)
4996 { 5273 {
5274 reason = "You are banned from the region";
5275
5276 if (Permissions.IsGod(agentID))
5277 {
5278 reason = String.Empty;
5279 return true;
5280 }
5281
4997 int num = m_sceneGraph.GetNumberOfScenePresences(); 5282 int num = m_sceneGraph.GetNumberOfScenePresences();
4998 5283
4999 if (num >= RegionInfo.RegionSettings.AgentLimit) 5284 if (num >= RegionInfo.RegionSettings.AgentLimit)
@@ -5005,6 +5290,41 @@ namespace OpenSim.Region.Framework.Scenes
5005 } 5290 }
5006 } 5291 }
5007 5292
5293 ScenePresence presence = GetScenePresence(agentID);
5294 IClientAPI client = null;
5295 AgentCircuitData aCircuit = null;
5296
5297 if (presence != null)
5298 {
5299 client = presence.ControllingClient;
5300 if (client != null)
5301 aCircuit = client.RequestClientInfo();
5302 }
5303
5304 // We may be called before there is a presence or a client.
5305 // Fake AgentCircuitData to keep IAuthorizationModule smiling
5306 if (client == null)
5307 {
5308 aCircuit = new AgentCircuitData();
5309 aCircuit.AgentID = agentID;
5310 aCircuit.firstname = String.Empty;
5311 aCircuit.lastname = String.Empty;
5312 }
5313
5314 try
5315 {
5316 if (!AuthorizeUser(aCircuit, out reason))
5317 {
5318 // m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID);
5319 return false;
5320 }
5321 }
5322 catch (Exception e)
5323 {
5324 m_log.DebugFormat("[SCENE]: Exception authorizing agent: {0} "+ e.StackTrace, e.Message);
5325 return false;
5326 }
5327
5008 if (position == Vector3.Zero) // Teleport 5328 if (position == Vector3.Zero) // Teleport
5009 { 5329 {
5010 if (!RegionInfo.EstateSettings.AllowDirectTeleport) 5330 if (!RegionInfo.EstateSettings.AllowDirectTeleport)
@@ -5033,13 +5353,46 @@ namespace OpenSim.Region.Framework.Scenes
5033 } 5353 }
5034 } 5354 }
5035 } 5355 }
5356
5357 float posX = 128.0f;
5358 float posY = 128.0f;
5359
5360 if (!TestLandRestrictions(agentID, out reason, ref posX, ref posY))
5361 {
5362 // m_log.DebugFormat("[SCENE]: Denying {0} because they are banned on all parcels", agentID);
5363 return false;
5364 }
5365 }
5366 else // Walking
5367 {
5368 ILandObject land = LandChannel.GetLandObject(position.X, position.Y);
5369 if (land == null)
5370 return false;
5371
5372 bool banned = land.IsBannedFromLand(agentID);
5373 bool restricted = land.IsRestrictedFromLand(agentID);
5374
5375 if (banned || restricted)
5376 return false;
5036 } 5377 }
5037 5378
5038 reason = String.Empty; 5379 reason = String.Empty;
5039 return true; 5380 return true;
5040 } 5381 }
5041 5382
5042 /// <summary> 5383 public void StartTimerWatchdog()
5384 {
5385 m_timerWatchdog.Interval = 1000;
5386 m_timerWatchdog.Elapsed += TimerWatchdog;
5387 m_timerWatchdog.AutoReset = true;
5388 m_timerWatchdog.Start();
5389 }
5390
5391 public void TimerWatchdog(object sender, ElapsedEventArgs e)
5392 {
5393 CheckHeartbeat();
5394 }
5395
5043 /// This method deals with movement when an avatar is automatically moving (but this is distinct from the 5396 /// This method deals with movement when an avatar is automatically moving (but this is distinct from the
5044 /// autopilot that moves an avatar to a sit target!. 5397 /// autopilot that moves an avatar to a sit target!.
5045 /// </summary> 5398 /// </summary>
diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs
index 712e094..da3b4dd 100644
--- a/OpenSim/Region/Framework/Scenes/SceneBase.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneBase.cs
@@ -136,6 +136,8 @@ namespace OpenSim.Region.Framework.Scenes
136 get { return m_permissions; } 136 get { return m_permissions; }
137 } 137 }
138 138
139 protected string m_datastore;
140
139 /* Used by the loadbalancer plugin on GForge */ 141 /* Used by the loadbalancer plugin on GForge */
140 protected RegionStatus m_regStatus; 142 protected RegionStatus m_regStatus;
141 public RegionStatus RegionStatus 143 public RegionStatus RegionStatus
diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
index 58a7b20..27833e8 100644
--- a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
@@ -88,7 +88,7 @@ namespace OpenSim.Region.Framework.Scenes
88 88
89 if (neighbour != null) 89 if (neighbour != null)
90 { 90 {
91 m_log.DebugFormat("[INTERGRID]: Successfully informed neighbour {0}-{1} that I'm here", x / Constants.RegionSize, y / Constants.RegionSize); 91 // m_log.DebugFormat("[INTERGRID]: Successfully informed neighbour {0}-{1} that I'm here", x / Constants.RegionSize, y / Constants.RegionSize);
92 m_scene.EventManager.TriggerOnRegionUp(neighbour); 92 m_scene.EventManager.TriggerOnRegionUp(neighbour);
93 } 93 }
94 else 94 else
@@ -102,7 +102,7 @@ namespace OpenSim.Region.Framework.Scenes
102 //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: Sending InterRegion Notification that region is up " + region.RegionName); 102 //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: Sending InterRegion Notification that region is up " + region.RegionName);
103 103
104 List<GridRegion> neighbours = m_scene.GridService.GetNeighbours(m_scene.RegionInfo.ScopeID, m_scene.RegionInfo.RegionID); 104 List<GridRegion> neighbours = m_scene.GridService.GetNeighbours(m_scene.RegionInfo.ScopeID, m_scene.RegionInfo.RegionID);
105 m_log.DebugFormat("[INTERGRID]: Informing {0} neighbours that this region is up", neighbours.Count); 105 //m_log.DebugFormat("[INTERGRID]: Informing {0} neighbours that this region is up", neighbours.Count);
106 foreach (GridRegion n in neighbours) 106 foreach (GridRegion n in neighbours)
107 { 107 {
108 InformNeighbourThatRegionUpDelegate d = InformNeighboursThatRegionIsUpAsync; 108 InformNeighbourThatRegionUpDelegate d = InformNeighboursThatRegionIsUpAsync;
@@ -176,10 +176,13 @@ namespace OpenSim.Region.Framework.Scenes
176 } 176 }
177 } 177 }
178 178
179 public delegate void SendCloseChildAgentDelegate(UUID agentID, ulong regionHandle);
180
179 /// <summary> 181 /// <summary>
180 /// Closes a child agent on a given region 182 /// This Closes child agents on neighboring regions
183 /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
181 /// </summary> 184 /// </summary>
182 protected void SendCloseChildAgent(UUID agentID, ulong regionHandle) 185 protected void SendCloseChildAgentAsync(UUID agentID, ulong regionHandle)
183 { 186 {
184 // let's do our best, but there's not much we can do if the neighbour doesn't accept. 187 // let's do our best, but there's not much we can do if the neighbour doesn't accept.
185 188
@@ -188,31 +191,29 @@ namespace OpenSim.Region.Framework.Scenes
188 Utils.LongToUInts(regionHandle, out x, out y); 191 Utils.LongToUInts(regionHandle, out x, out y);
189 192
190 GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y); 193 GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y);
194 m_scene.SimulationService.CloseChildAgent(destination, agentID);
195 }
191 196
192 m_log.DebugFormat( 197 private void SendCloseChildAgentCompleted(IAsyncResult iar)
193 "[INTERGRID]: Sending close agent {0} to region at {1}-{2}", 198 {
194 agentID, destination.RegionCoordX, destination.RegionCoordY); 199 SendCloseChildAgentDelegate icon = (SendCloseChildAgentDelegate)iar.AsyncState;
195 200 icon.EndInvoke(iar);
196 m_scene.SimulationService.CloseAgent(destination, agentID);
197 } 201 }
198 202
199 /// <summary>
200 /// Closes a child agents in a collection of regions. Does so asynchronously
201 /// so that the caller doesn't wait.
202 /// </summary>
203 /// <param name="agentID"></param>
204 /// <param name="regionslst"></param>
205 public void SendCloseChildAgentConnections(UUID agentID, List<ulong> regionslst) 203 public void SendCloseChildAgentConnections(UUID agentID, List<ulong> regionslst)
206 { 204 {
207 foreach (ulong handle in regionslst) 205 foreach (ulong handle in regionslst)
208 { 206 {
209 SendCloseChildAgent(agentID, handle); 207 SendCloseChildAgentDelegate d = SendCloseChildAgentAsync;
208 d.BeginInvoke(agentID, handle,
209 SendCloseChildAgentCompleted,
210 d);
210 } 211 }
211 } 212 }
212 213
213 public List<GridRegion> RequestNamedRegions(string name, int maxNumber) 214 public List<GridRegion> RequestNamedRegions(string name, int maxNumber)
214 { 215 {
215 return m_scene.GridService.GetRegionsByName(UUID.Zero, name, maxNumber); 216 return m_scene.GridService.GetRegionsByName(UUID.Zero, name, maxNumber);
216 } 217 }
217 } 218 }
218} \ No newline at end of file 219}
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index 7d801b5..17563bd 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -41,6 +41,12 @@ namespace OpenSim.Region.Framework.Scenes
41{ 41{
42 public delegate void PhysicsCrash(); 42 public delegate void PhysicsCrash();
43 43
44 public delegate void AttachToBackupDelegate(SceneObjectGroup sog);
45
46 public delegate void DetachFromBackupDelegate(SceneObjectGroup sog);
47
48 public delegate void ChangedBackupDelegate(SceneObjectGroup sog);
49
44 /// <summary> 50 /// <summary>
45 /// This class used to be called InnerScene and may not yet truly be a SceneGraph. The non scene graph components 51 /// This class used to be called InnerScene and may not yet truly be a SceneGraph. The non scene graph components
46 /// should be migrated out over time. 52 /// should be migrated out over time.
@@ -54,11 +60,15 @@ namespace OpenSim.Region.Framework.Scenes
54 protected internal event PhysicsCrash UnRecoverableError; 60 protected internal event PhysicsCrash UnRecoverableError;
55 private PhysicsCrash handlerPhysicsCrash = null; 61 private PhysicsCrash handlerPhysicsCrash = null;
56 62
63 public event AttachToBackupDelegate OnAttachToBackup;
64 public event DetachFromBackupDelegate OnDetachFromBackup;
65 public event ChangedBackupDelegate OnChangeBackup;
66
57 #endregion 67 #endregion
58 68
59 #region Fields 69 #region Fields
60 70
61 protected object m_presenceLock = new object(); 71 protected OpenMetaverse.ReaderWriterLockSlim m_scenePresencesLock = new OpenMetaverse.ReaderWriterLockSlim();
62 protected Dictionary<UUID, ScenePresence> m_scenePresenceMap = new Dictionary<UUID, ScenePresence>(); 72 protected Dictionary<UUID, ScenePresence> m_scenePresenceMap = new Dictionary<UUID, ScenePresence>();
63 protected List<ScenePresence> m_scenePresenceArray = new List<ScenePresence>(); 73 protected List<ScenePresence> m_scenePresenceArray = new List<ScenePresence>();
64 74
@@ -120,13 +130,18 @@ namespace OpenSim.Region.Framework.Scenes
120 130
121 protected internal void Close() 131 protected internal void Close()
122 { 132 {
123 lock (m_presenceLock) 133 m_scenePresencesLock.EnterWriteLock();
134 try
124 { 135 {
125 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(); 136 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>();
126 List<ScenePresence> newlist = new List<ScenePresence>(); 137 List<ScenePresence> newlist = new List<ScenePresence>();
127 m_scenePresenceMap = newmap; 138 m_scenePresenceMap = newmap;
128 m_scenePresenceArray = newlist; 139 m_scenePresenceArray = newlist;
129 } 140 }
141 finally
142 {
143 m_scenePresencesLock.ExitWriteLock();
144 }
130 145
131 lock (SceneObjectGroupsByFullID) 146 lock (SceneObjectGroupsByFullID)
132 SceneObjectGroupsByFullID.Clear(); 147 SceneObjectGroupsByFullID.Clear();
@@ -265,6 +280,33 @@ namespace OpenSim.Region.Framework.Scenes
265 protected internal bool AddRestoredSceneObject( 280 protected internal bool AddRestoredSceneObject(
266 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 281 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
267 { 282 {
283 if (!m_parentScene.CombineRegions)
284 {
285 // KF: Check for out-of-region, move inside and make static.
286 Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X,
287 sceneObject.RootPart.GroupPosition.Y,
288 sceneObject.RootPart.GroupPosition.Z);
289 if (!(((sceneObject.RootPart.Shape.PCode == (byte)PCode.Prim) && (sceneObject.RootPart.Shape.State != 0))) && (npos.X < 0.0 || npos.Y < 0.0 || npos.Z < 0.0 ||
290 npos.X > Constants.RegionSize ||
291 npos.Y > Constants.RegionSize))
292 {
293 if (npos.X < 0.0) npos.X = 1.0f;
294 if (npos.Y < 0.0) npos.Y = 1.0f;
295 if (npos.Z < 0.0) npos.Z = 0.0f;
296 if (npos.X > Constants.RegionSize) npos.X = Constants.RegionSize - 1.0f;
297 if (npos.Y > Constants.RegionSize) npos.Y = Constants.RegionSize - 1.0f;
298
299 foreach (SceneObjectPart part in sceneObject.Parts)
300 {
301 part.GroupPosition = npos;
302 }
303 sceneObject.RootPart.Velocity = Vector3.Zero;
304 sceneObject.RootPart.AngularVelocity = Vector3.Zero;
305 sceneObject.RootPart.Acceleration = Vector3.Zero;
306 sceneObject.RootPart.Velocity = Vector3.Zero;
307 }
308 }
309
268 if (attachToBackup && (!alreadyPersisted)) 310 if (attachToBackup && (!alreadyPersisted))
269 { 311 {
270 sceneObject.ForceInventoryPersistence(); 312 sceneObject.ForceInventoryPersistence();
@@ -354,6 +396,11 @@ namespace OpenSim.Region.Framework.Scenes
354 /// </returns> 396 /// </returns>
355 protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) 397 protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates)
356 { 398 {
399 if (sceneObject == null)
400 {
401 m_log.ErrorFormat("[SCENEGRAPH]: Tried to add null scene object");
402 return false;
403 }
357 if (sceneObject.UUID == UUID.Zero) 404 if (sceneObject.UUID == UUID.Zero)
358 { 405 {
359 m_log.ErrorFormat( 406 m_log.ErrorFormat(
@@ -488,6 +535,30 @@ namespace OpenSim.Region.Framework.Scenes
488 m_updateList[obj.UUID] = obj; 535 m_updateList[obj.UUID] = obj;
489 } 536 }
490 537
538 public void FireAttachToBackup(SceneObjectGroup obj)
539 {
540 if (OnAttachToBackup != null)
541 {
542 OnAttachToBackup(obj);
543 }
544 }
545
546 public void FireDetachFromBackup(SceneObjectGroup obj)
547 {
548 if (OnDetachFromBackup != null)
549 {
550 OnDetachFromBackup(obj);
551 }
552 }
553
554 public void FireChangeBackup(SceneObjectGroup obj)
555 {
556 if (OnChangeBackup != null)
557 {
558 OnChangeBackup(obj);
559 }
560 }
561
491 /// <summary> 562 /// <summary>
492 /// Process all pending updates 563 /// Process all pending updates
493 /// </summary> 564 /// </summary>
@@ -605,7 +676,8 @@ namespace OpenSim.Region.Framework.Scenes
605 676
606 Entities[presence.UUID] = presence; 677 Entities[presence.UUID] = presence;
607 678
608 lock (m_presenceLock) 679 m_scenePresencesLock.EnterWriteLock();
680 try
609 { 681 {
610 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 682 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
611 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 683 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -629,6 +701,10 @@ namespace OpenSim.Region.Framework.Scenes
629 m_scenePresenceMap = newmap; 701 m_scenePresenceMap = newmap;
630 m_scenePresenceArray = newlist; 702 m_scenePresenceArray = newlist;
631 } 703 }
704 finally
705 {
706 m_scenePresencesLock.ExitWriteLock();
707 }
632 } 708 }
633 709
634 /// <summary> 710 /// <summary>
@@ -643,7 +719,8 @@ namespace OpenSim.Region.Framework.Scenes
643 agentID); 719 agentID);
644 } 720 }
645 721
646 lock (m_presenceLock) 722 m_scenePresencesLock.EnterWriteLock();
723 try
647 { 724 {
648 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 725 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
649 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 726 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -665,6 +742,10 @@ namespace OpenSim.Region.Framework.Scenes
665 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); 742 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID);
666 } 743 }
667 } 744 }
745 finally
746 {
747 m_scenePresencesLock.ExitWriteLock();
748 }
668 } 749 }
669 750
670 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) 751 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F)
@@ -1380,8 +1461,13 @@ namespace OpenSim.Region.Framework.Scenes
1380 { 1461 {
1381 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) 1462 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0))
1382 { 1463 {
1383 if (m_parentScene.AttachmentsModule != null) 1464 // Set the new attachment point data in the object
1384 m_parentScene.AttachmentsModule.UpdateAttachmentPosition(group, pos); 1465 byte attachmentPoint = group.GetAttachmentPoint();
1466 group.UpdateGroupPosition(pos);
1467 group.IsAttachment = false;
1468 group.AbsolutePosition = group.RootPart.AttachedPos;
1469 group.AttachmentPoint = attachmentPoint;
1470 group.HasGroupChanged = true;
1385 } 1471 }
1386 else 1472 else
1387 { 1473 {
@@ -1653,8 +1739,11 @@ namespace OpenSim.Region.Framework.Scenes
1653 return; 1739 return;
1654 1740
1655 Monitor.Enter(m_updateLock); 1741 Monitor.Enter(m_updateLock);
1742
1656 try 1743 try
1657 { 1744 {
1745 parentGroup.areUpdatesSuspended = true;
1746
1658 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); 1747 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
1659 1748
1660 // We do this in reverse to get the link order of the prims correct 1749 // We do this in reverse to get the link order of the prims correct
@@ -1665,9 +1754,13 @@ namespace OpenSim.Region.Framework.Scenes
1665 // Make sure no child prim is set for sale 1754 // Make sure no child prim is set for sale
1666 // So that, on delink, no prims are unwittingly 1755 // So that, on delink, no prims are unwittingly
1667 // left for sale and sold off 1756 // left for sale and sold off
1668 child.RootPart.ObjectSaleType = 0; 1757
1669 child.RootPart.SalePrice = 10; 1758 if (child != null)
1670 childGroups.Add(child); 1759 {
1760 child.RootPart.ObjectSaleType = 0;
1761 child.RootPart.SalePrice = 10;
1762 childGroups.Add(child);
1763 }
1671 } 1764 }
1672 1765
1673 foreach (SceneObjectGroup child in childGroups) 1766 foreach (SceneObjectGroup child in childGroups)
@@ -1686,12 +1779,19 @@ namespace OpenSim.Region.Framework.Scenes
1686 // occur on link to invoke this elsewhere (such as object selection) 1779 // occur on link to invoke this elsewhere (such as object selection)
1687 parentGroup.RootPart.CreateSelected = true; 1780 parentGroup.RootPart.CreateSelected = true;
1688 parentGroup.TriggerScriptChangedEvent(Changed.LINK); 1781 parentGroup.TriggerScriptChangedEvent(Changed.LINK);
1689 parentGroup.HasGroupChanged = true;
1690 parentGroup.ScheduleGroupForFullUpdate();
1691
1692 } 1782 }
1693 finally 1783 finally
1694 { 1784 {
1785 lock (SceneObjectGroupsByLocalPartID)
1786 {
1787 foreach (SceneObjectPart part in parentGroup.Parts)
1788 SceneObjectGroupsByLocalPartID[part.LocalId] = parentGroup;
1789 }
1790
1791 parentGroup.areUpdatesSuspended = false;
1792 parentGroup.HasGroupChanged = true;
1793 parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true);
1794 parentGroup.ScheduleGroupForFullUpdate();
1695 Monitor.Exit(m_updateLock); 1795 Monitor.Exit(m_updateLock);
1696 } 1796 }
1697 } 1797 }
@@ -1728,21 +1828,24 @@ namespace OpenSim.Region.Framework.Scenes
1728 1828
1729 SceneObjectGroup group = part.ParentGroup; 1829 SceneObjectGroup group = part.ParentGroup;
1730 if (!affectedGroups.Contains(group)) 1830 if (!affectedGroups.Contains(group))
1831 {
1832 group.areUpdatesSuspended = true;
1731 affectedGroups.Add(group); 1833 affectedGroups.Add(group);
1834 }
1732 } 1835 }
1733 } 1836 }
1734 } 1837 }
1735 1838
1736 foreach (SceneObjectPart child in childParts) 1839 if (childParts.Count > 0)
1737 { 1840 {
1738 // Unlink all child parts from their groups 1841 foreach (SceneObjectPart child in childParts)
1739 // 1842 {
1740 child.ParentGroup.DelinkFromGroup(child, true); 1843 // Unlink all child parts from their groups
1741 1844 //
1742 // These are not in affected groups and will not be 1845 child.ParentGroup.DelinkFromGroup(child, true);
1743 // handled further. Do the honors here. 1846 child.ParentGroup.HasGroupChanged = true;
1744 child.ParentGroup.HasGroupChanged = true; 1847 child.ParentGroup.ScheduleGroupForFullUpdate();
1745 child.ParentGroup.ScheduleGroupForFullUpdate(); 1848 }
1746 } 1849 }
1747 1850
1748 foreach (SceneObjectPart root in rootParts) 1851 foreach (SceneObjectPart root in rootParts)
@@ -1752,56 +1855,68 @@ namespace OpenSim.Region.Framework.Scenes
1752 // However, editing linked parts and unlinking may be different 1855 // However, editing linked parts and unlinking may be different
1753 // 1856 //
1754 SceneObjectGroup group = root.ParentGroup; 1857 SceneObjectGroup group = root.ParentGroup;
1858 group.areUpdatesSuspended = true;
1755 1859
1756 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); 1860 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts);
1757 int numChildren = newSet.Count; 1861 int numChildren = newSet.Count;
1758 1862
1863 if (numChildren == 1)
1864 break;
1865
1759 // If there are prims left in a link set, but the root is 1866 // If there are prims left in a link set, but the root is
1760 // slated for unlink, we need to do this 1867 // slated for unlink, we need to do this
1868 // Unlink the remaining set
1761 // 1869 //
1762 if (numChildren != 1) 1870 bool sendEventsToRemainder = true;
1763 { 1871 if (numChildren > 1)
1764 // Unlink the remaining set 1872 sendEventsToRemainder = false;
1765 //
1766 bool sendEventsToRemainder = true;
1767 if (numChildren > 1)
1768 sendEventsToRemainder = false;
1769 1873
1770 foreach (SceneObjectPart p in newSet) 1874 foreach (SceneObjectPart p in newSet)
1875 {
1876 if (p != group.RootPart)
1771 { 1877 {
1772 if (p != group.RootPart) 1878 group.DelinkFromGroup(p, sendEventsToRemainder);
1773 group.DelinkFromGroup(p, sendEventsToRemainder); 1879 if (numChildren > 2)
1880 {
1881 p.ParentGroup.areUpdatesSuspended = true;
1882 }
1883 else
1884 {
1885 p.ParentGroup.HasGroupChanged = true;
1886 p.ParentGroup.ScheduleGroupForFullUpdate();
1887 }
1774 } 1888 }
1889 }
1890
1891 // If there is more than one prim remaining, we
1892 // need to re-link
1893 //
1894 if (numChildren > 2)
1895 {
1896 // Remove old root
1897 //
1898 if (newSet.Contains(root))
1899 newSet.Remove(root);
1775 1900
1776 // If there is more than one prim remaining, we 1901 // Preserve link ordering
1777 // need to re-link
1778 // 1902 //
1779 if (numChildren > 2) 1903 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1780 { 1904 {
1781 // Remove old root 1905 return a.LinkNum.CompareTo(b.LinkNum);
1782 // 1906 });
1783 if (newSet.Contains(root))
1784 newSet.Remove(root);
1785
1786 // Preserve link ordering
1787 //
1788 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1789 {
1790 return a.LinkNum.CompareTo(b.LinkNum);
1791 });
1792 1907
1793 // Determine new root 1908 // Determine new root
1794 // 1909 //
1795 SceneObjectPart newRoot = newSet[0]; 1910 SceneObjectPart newRoot = newSet[0];
1796 newSet.RemoveAt(0); 1911 newSet.RemoveAt(0);
1797 1912
1798 foreach (SceneObjectPart newChild in newSet) 1913 foreach (SceneObjectPart newChild in newSet)
1799 newChild.ClearUpdateSchedule(); 1914 newChild.ClearUpdateSchedule();
1800 1915
1801 LinkObjects(newRoot, newSet); 1916 newRoot.ParentGroup.areUpdatesSuspended = true;
1802 if (!affectedGroups.Contains(newRoot.ParentGroup)) 1917 LinkObjects(newRoot, newSet);
1803 affectedGroups.Add(newRoot.ParentGroup); 1918 if (!affectedGroups.Contains(newRoot.ParentGroup))
1804 } 1919 affectedGroups.Add(newRoot.ParentGroup);
1805 } 1920 }
1806 } 1921 }
1807 1922
@@ -1809,8 +1924,14 @@ namespace OpenSim.Region.Framework.Scenes
1809 // 1924 //
1810 foreach (SceneObjectGroup g in affectedGroups) 1925 foreach (SceneObjectGroup g in affectedGroups)
1811 { 1926 {
1927 // Child prims that have been unlinked and deleted will
1928 // return unless the root is deleted. This will remove them
1929 // from the database. They will be rewritten immediately,
1930 // minus the rows for the unlinked child prims.
1931 m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID);
1812 g.TriggerScriptChangedEvent(Changed.LINK); 1932 g.TriggerScriptChangedEvent(Changed.LINK);
1813 g.HasGroupChanged = true; // Persist 1933 g.HasGroupChanged = true; // Persist
1934 g.areUpdatesSuspended = false;
1814 g.ScheduleGroupForFullUpdate(); 1935 g.ScheduleGroupForFullUpdate();
1815 } 1936 }
1816 } 1937 }
@@ -1912,9 +2033,6 @@ namespace OpenSim.Region.Framework.Scenes
1912 child.ApplyNextOwnerPermissions(); 2033 child.ApplyNextOwnerPermissions();
1913 } 2034 }
1914 } 2035 }
1915
1916 copy.RootPart.ObjectSaleType = 0;
1917 copy.RootPart.SalePrice = 10;
1918 } 2036 }
1919 2037
1920 // FIXME: This section needs to be refactored so that it just calls AddSceneObject() 2038 // FIXME: This section needs to be refactored so that it just calls AddSceneObject()
diff --git a/OpenSim/Region/Framework/Scenes/SceneManager.cs b/OpenSim/Region/Framework/Scenes/SceneManager.cs
index d73a959..e4eaf3a 100644
--- a/OpenSim/Region/Framework/Scenes/SceneManager.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneManager.cs
@@ -356,7 +356,7 @@ namespace OpenSim.Region.Framework.Scenes
356 356
357 public bool TrySetCurrentScene(UUID regionID) 357 public bool TrySetCurrentScene(UUID regionID)
358 { 358 {
359 m_log.Debug("Searching for Region: '" + regionID + "'"); 359// m_log.Debug("Searching for Region: '" + regionID + "'");
360 360
361 lock (m_localScenes) 361 lock (m_localScenes)
362 { 362 {
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
index f173c95..b56d3fc 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
@@ -69,10 +69,6 @@ namespace OpenSim.Region.Framework.Scenes
69 /// <summary> 69 /// <summary>
70 /// Stop the scripts contained in all the prims in this group 70 /// Stop the scripts contained in all the prims in this group
71 /// </summary> 71 /// </summary>
72 /// <param name="sceneObjectBeingDeleted">
73 /// Should be true if these scripts are being removed because the scene
74 /// object is being deleted. This will prevent spurious updates to the client.
75 /// </param>
76 public void RemoveScriptInstances(bool sceneObjectBeingDeleted) 72 public void RemoveScriptInstances(bool sceneObjectBeingDeleted)
77 { 73 {
78 SceneObjectPart[] parts = m_parts.GetArray(); 74 SceneObjectPart[] parts = m_parts.GetArray();
@@ -227,6 +223,11 @@ namespace OpenSim.Region.Framework.Scenes
227 223
228 public uint GetEffectivePermissions() 224 public uint GetEffectivePermissions()
229 { 225 {
226 return GetEffectivePermissions(false);
227 }
228
229 public uint GetEffectivePermissions(bool useBase)
230 {
230 uint perms=(uint)(PermissionMask.Modify | 231 uint perms=(uint)(PermissionMask.Modify |
231 PermissionMask.Copy | 232 PermissionMask.Copy |
232 PermissionMask.Move | 233 PermissionMask.Move |
@@ -238,7 +239,10 @@ namespace OpenSim.Region.Framework.Scenes
238 for (int i = 0; i < parts.Length; i++) 239 for (int i = 0; i < parts.Length; i++)
239 { 240 {
240 SceneObjectPart part = parts[i]; 241 SceneObjectPart part = parts[i];
241 ownerMask &= part.OwnerMask; 242 if (useBase)
243 ownerMask &= part.BaseMask;
244 else
245 ownerMask &= part.OwnerMask;
242 perms &= part.Inventory.MaskEffectivePermissions(); 246 perms &= part.Inventory.MaskEffectivePermissions();
243 } 247 }
244 248
@@ -378,6 +382,9 @@ namespace OpenSim.Region.Framework.Scenes
378 382
379 public void ResumeScripts() 383 public void ResumeScripts()
380 { 384 {
385 if (m_scene.RegionInfo.RegionSettings.DisableScripts)
386 return;
387
381 SceneObjectPart[] parts = m_parts.GetArray(); 388 SceneObjectPart[] parts = m_parts.GetArray();
382 for (int i = 0; i < parts.Length; i++) 389 for (int i = 0; i < parts.Length; i++)
383 parts[i].Inventory.ResumeScripts(); 390 parts[i].Inventory.ResumeScripts();
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index e7f2fdb..6485710 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -24,11 +24,12 @@
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Drawing; 30using System.Drawing;
31using System.IO; 31using System.IO;
32using System.Diagnostics;
32using System.Linq; 33using System.Linq;
33using System.Threading; 34using System.Threading;
34using System.Xml; 35using System.Xml;
@@ -105,8 +106,29 @@ namespace OpenSim.Region.Framework.Scenes
105 /// since the group's last persistent backup 106 /// since the group's last persistent backup
106 /// </summary> 107 /// </summary>
107 private bool m_hasGroupChanged = false; 108 private bool m_hasGroupChanged = false;
108 private long timeFirstChanged; 109 private long timeFirstChanged = 0;
109 private long timeLastChanged; 110 private long timeLastChanged = 0;
111 private long m_maxPersistTime = 0;
112 private long m_minPersistTime = 0;
113 private Random m_rand;
114 private bool m_suspendUpdates;
115 private List<ScenePresence> m_linkedAvatars = new List<ScenePresence>();
116
117 public bool areUpdatesSuspended
118 {
119 get
120 {
121 return m_suspendUpdates;
122 }
123 set
124 {
125 m_suspendUpdates = value;
126 if (!value)
127 {
128 QueueForUpdateCheck();
129 }
130 }
131 }
110 132
111 public bool HasGroupChanged 133 public bool HasGroupChanged
112 { 134 {
@@ -114,9 +136,39 @@ namespace OpenSim.Region.Framework.Scenes
114 { 136 {
115 if (value) 137 if (value)
116 { 138 {
139 if (m_isBackedUp)
140 {
141 m_scene.SceneGraph.FireChangeBackup(this);
142 }
117 timeLastChanged = DateTime.Now.Ticks; 143 timeLastChanged = DateTime.Now.Ticks;
118 if (!m_hasGroupChanged) 144 if (!m_hasGroupChanged)
119 timeFirstChanged = DateTime.Now.Ticks; 145 timeFirstChanged = DateTime.Now.Ticks;
146 if (m_rootPart != null && m_rootPart.UUID != null && m_scene != null)
147 {
148 if (m_rand == null)
149 {
150 byte[] val = new byte[16];
151 m_rootPart.UUID.ToBytes(val, 0);
152 m_rand = new Random(BitConverter.ToInt32(val, 0));
153 }
154
155 if (m_scene.GetRootAgentCount() == 0)
156 {
157 //If the region is empty, this change has been made by an automated process
158 //and thus we delay the persist time by a random amount between 1.5 and 2.5.
159
160 float factor = 1.5f + (float)(m_rand.NextDouble());
161 m_maxPersistTime = (long)((float)m_scene.m_persistAfter * factor);
162 m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * factor);
163 }
164 else
165 {
166 //If the region is not empty, we want to obey the minimum and maximum persist times
167 //but add a random factor so we stagger the object persistance a little
168 m_maxPersistTime = (long)((float)m_scene.m_persistAfter * (1.0d - (m_rand.NextDouble() / 5.0d))); //Multiply by 1.0-1.5
169 m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * (1.0d + (m_rand.NextDouble() / 2.0d))); //Multiply by 0.8-1.0
170 }
171 }
120 } 172 }
121 m_hasGroupChanged = value; 173 m_hasGroupChanged = value;
122 174
@@ -131,7 +183,7 @@ namespace OpenSim.Region.Framework.Scenes
131 /// Has the group changed due to an unlink operation? We record this in order to optimize deletion, since 183 /// Has the group changed due to an unlink operation? We record this in order to optimize deletion, since
132 /// an unlinked group currently has to be persisted to the database before we can perform an unlink operation. 184 /// an unlinked group currently has to be persisted to the database before we can perform an unlink operation.
133 /// </summary> 185 /// </summary>
134 public bool HasGroupChangedDueToDelink { get; private set; } 186 public bool HasGroupChangedDueToDelink { get; set; }
135 187
136 private bool isTimeToPersist() 188 private bool isTimeToPersist()
137 { 189 {
@@ -141,8 +193,19 @@ namespace OpenSim.Region.Framework.Scenes
141 return false; 193 return false;
142 if (m_scene.ShuttingDown) 194 if (m_scene.ShuttingDown)
143 return true; 195 return true;
196
197 if (m_minPersistTime == 0 || m_maxPersistTime == 0)
198 {
199 m_maxPersistTime = m_scene.m_persistAfter;
200 m_minPersistTime = m_scene.m_dontPersistBefore;
201 }
202
144 long currentTime = DateTime.Now.Ticks; 203 long currentTime = DateTime.Now.Ticks;
145 if (currentTime - timeLastChanged > m_scene.m_dontPersistBefore || currentTime - timeFirstChanged > m_scene.m_persistAfter) 204
205 if (timeLastChanged == 0) timeLastChanged = currentTime;
206 if (timeFirstChanged == 0) timeFirstChanged = currentTime;
207
208 if (currentTime - timeLastChanged > m_minPersistTime || currentTime - timeFirstChanged > m_maxPersistTime)
146 return true; 209 return true;
147 return false; 210 return false;
148 } 211 }
@@ -247,10 +310,10 @@ namespace OpenSim.Region.Framework.Scenes
247 310
248 private bool m_scriptListens_atTarget; 311 private bool m_scriptListens_atTarget;
249 private bool m_scriptListens_notAtTarget; 312 private bool m_scriptListens_notAtTarget;
250
251 private bool m_scriptListens_atRotTarget; 313 private bool m_scriptListens_atRotTarget;
252 private bool m_scriptListens_notAtRotTarget; 314 private bool m_scriptListens_notAtRotTarget;
253 315
316 public bool m_dupeInProgress = false;
254 internal Dictionary<UUID, string> m_savedScriptState; 317 internal Dictionary<UUID, string> m_savedScriptState;
255 318
256 #region Properties 319 #region Properties
@@ -287,6 +350,16 @@ namespace OpenSim.Region.Framework.Scenes
287 get { return m_parts.Count; } 350 get { return m_parts.Count; }
288 } 351 }
289 352
353// protected Quaternion m_rotation = Quaternion.Identity;
354//
355// public virtual Quaternion Rotation
356// {
357// get { return m_rotation; }
358// set {
359// m_rotation = value;
360// }
361// }
362
290 public Quaternion GroupRotation 363 public Quaternion GroupRotation
291 { 364 {
292 get { return m_rootPart.RotationOffset; } 365 get { return m_rootPart.RotationOffset; }
@@ -395,7 +468,11 @@ namespace OpenSim.Region.Framework.Scenes
395 m_scene.CrossPrimGroupIntoNewRegion(val, this, true); 468 m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
396 } 469 }
397 } 470 }
398 471
472 foreach (SceneObjectPart part in m_parts.GetArray())
473 {
474 part.IgnoreUndoUpdate = true;
475 }
399 if (RootPart.GetStatusSandbox()) 476 if (RootPart.GetStatusSandbox())
400 { 477 {
401 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) 478 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10)
@@ -409,10 +486,30 @@ namespace OpenSim.Region.Framework.Scenes
409 return; 486 return;
410 } 487 }
411 } 488 }
412
413 SceneObjectPart[] parts = m_parts.GetArray(); 489 SceneObjectPart[] parts = m_parts.GetArray();
414 for (int i = 0; i < parts.Length; i++) 490 bool triggerScriptEvent = m_rootPart.GroupPosition != val;
415 parts[i].GroupPosition = val; 491 if (m_dupeInProgress)
492 triggerScriptEvent = false;
493 foreach (SceneObjectPart part in parts)
494 {
495 part.GroupPosition = val;
496 if (triggerScriptEvent)
497 part.TriggerScriptChangedEvent(Changed.POSITION);
498 }
499 if (!m_dupeInProgress)
500 {
501 foreach (ScenePresence av in m_linkedAvatars)
502 {
503 SceneObjectPart p = m_scene.GetSceneObjectPart(av.ParentID);
504 if (m_parts.TryGetValue(p.UUID, out p))
505 {
506 Vector3 offset = p.GetWorldPosition() - av.ParentPosition;
507 av.AbsolutePosition += offset;
508 av.ParentPosition = p.GetWorldPosition(); //ParentPosition gets cleared by AbsolutePosition
509 av.SendAvatarDataToAllAgents();
510 }
511 }
512 }
416 513
417 //if (m_rootPart.PhysActor != null) 514 //if (m_rootPart.PhysActor != null)
418 //{ 515 //{
@@ -577,6 +674,7 @@ namespace OpenSim.Region.Framework.Scenes
577 /// </summary> 674 /// </summary>
578 public SceneObjectGroup() 675 public SceneObjectGroup()
579 { 676 {
677
580 } 678 }
581 679
582 /// <summary> 680 /// <summary>
@@ -593,7 +691,7 @@ namespace OpenSim.Region.Framework.Scenes
593 /// Constructor. This object is added to the scene later via AttachToScene() 691 /// Constructor. This object is added to the scene later via AttachToScene()
594 /// </summary> 692 /// </summary>
595 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) 693 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape)
596 { 694 {
597 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero)); 695 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero));
598 } 696 }
599 697
@@ -641,6 +739,9 @@ namespace OpenSim.Region.Framework.Scenes
641 /// </summary> 739 /// </summary>
642 public virtual void AttachToBackup() 740 public virtual void AttachToBackup()
643 { 741 {
742 if (IsAttachment) return;
743 m_scene.SceneGraph.FireAttachToBackup(this);
744
644 if (InSceneBackup) 745 if (InSceneBackup)
645 { 746 {
646 //m_log.DebugFormat( 747 //m_log.DebugFormat(
@@ -683,6 +784,9 @@ namespace OpenSim.Region.Framework.Scenes
683 784
684 ApplyPhysics(); 785 ApplyPhysics();
685 786
787 if (RootPart.PhysActor != null)
788 RootPart.Buoyancy = RootPart.Buoyancy;
789
686 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled 790 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled
687 // for the same object with very different properties. The caller must schedule the update. 791 // for the same object with very different properties. The caller must schedule the update.
688 //ScheduleGroupForFullUpdate(); 792 //ScheduleGroupForFullUpdate();
@@ -698,6 +802,10 @@ namespace OpenSim.Region.Framework.Scenes
698 EntityIntersection result = new EntityIntersection(); 802 EntityIntersection result = new EntityIntersection();
699 803
700 SceneObjectPart[] parts = m_parts.GetArray(); 804 SceneObjectPart[] parts = m_parts.GetArray();
805
806 // Find closest hit here
807 float idist = float.MaxValue;
808
701 for (int i = 0; i < parts.Length; i++) 809 for (int i = 0; i < parts.Length; i++)
702 { 810 {
703 SceneObjectPart part = parts[i]; 811 SceneObjectPart part = parts[i];
@@ -712,11 +820,6 @@ namespace OpenSim.Region.Framework.Scenes
712 820
713 EntityIntersection inter = part.TestIntersectionOBB(hRay, parentrotation, frontFacesOnly, faceCenters); 821 EntityIntersection inter = part.TestIntersectionOBB(hRay, parentrotation, frontFacesOnly, faceCenters);
714 822
715 // This may need to be updated to the maximum draw distance possible..
716 // We might (and probably will) be checking for prim creation from other sims
717 // when the camera crosses the border.
718 float idist = Constants.RegionSize;
719
720 if (inter.HitTF) 823 if (inter.HitTF)
721 { 824 {
722 // We need to find the closest prim to return to the testcaller along the ray 825 // We need to find the closest prim to return to the testcaller along the ray
@@ -727,10 +830,11 @@ namespace OpenSim.Region.Framework.Scenes
727 result.obj = part; 830 result.obj = part;
728 result.normal = inter.normal; 831 result.normal = inter.normal;
729 result.distance = inter.distance; 832 result.distance = inter.distance;
833
834 idist = inter.distance;
730 } 835 }
731 } 836 }
732 } 837 }
733
734 return result; 838 return result;
735 } 839 }
736 840
@@ -750,17 +854,19 @@ namespace OpenSim.Region.Framework.Scenes
750 minZ = 8192f; 854 minZ = 8192f;
751 855
752 SceneObjectPart[] parts = m_parts.GetArray(); 856 SceneObjectPart[] parts = m_parts.GetArray();
753 for (int i = 0; i < parts.Length; i++) 857 foreach (SceneObjectPart part in parts)
754 { 858 {
755 SceneObjectPart part = parts[i];
756
757 Vector3 worldPos = part.GetWorldPosition(); 859 Vector3 worldPos = part.GetWorldPosition();
758 Vector3 offset = worldPos - AbsolutePosition; 860 Vector3 offset = worldPos - AbsolutePosition;
759 Quaternion worldRot; 861 Quaternion worldRot;
760 if (part.ParentID == 0) 862 if (part.ParentID == 0)
863 {
761 worldRot = part.RotationOffset; 864 worldRot = part.RotationOffset;
865 }
762 else 866 else
867 {
763 worldRot = part.GetWorldRotation(); 868 worldRot = part.GetWorldRotation();
869 }
764 870
765 Vector3 frontTopLeft; 871 Vector3 frontTopLeft;
766 Vector3 frontTopRight; 872 Vector3 frontTopRight;
@@ -772,6 +878,8 @@ namespace OpenSim.Region.Framework.Scenes
772 Vector3 backBottomLeft; 878 Vector3 backBottomLeft;
773 Vector3 backBottomRight; 879 Vector3 backBottomRight;
774 880
881 // Vector3[] corners = new Vector3[8];
882
775 Vector3 orig = Vector3.Zero; 883 Vector3 orig = Vector3.Zero;
776 884
777 frontTopLeft.X = orig.X - (part.Scale.X / 2); 885 frontTopLeft.X = orig.X - (part.Scale.X / 2);
@@ -806,6 +914,38 @@ namespace OpenSim.Region.Framework.Scenes
806 backBottomRight.Y = orig.Y + (part.Scale.Y / 2); 914 backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
807 backBottomRight.Z = orig.Z - (part.Scale.Z / 2); 915 backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
808 916
917
918
919 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
920 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
921 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
922 //m_log.InfoFormat("pre corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
923 //m_log.InfoFormat("pre corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
924 //m_log.InfoFormat("pre corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
925 //m_log.InfoFormat("pre corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
926 //m_log.InfoFormat("pre corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
927
928 //for (int i = 0; i < 8; i++)
929 //{
930 // corners[i] = corners[i] * worldRot;
931 // corners[i] += offset;
932
933 // if (corners[i].X > maxX)
934 // maxX = corners[i].X;
935 // if (corners[i].X < minX)
936 // minX = corners[i].X;
937
938 // if (corners[i].Y > maxY)
939 // maxY = corners[i].Y;
940 // if (corners[i].Y < minY)
941 // minY = corners[i].Y;
942
943 // if (corners[i].Z > maxZ)
944 // maxZ = corners[i].Y;
945 // if (corners[i].Z < minZ)
946 // minZ = corners[i].Z;
947 //}
948
809 frontTopLeft = frontTopLeft * worldRot; 949 frontTopLeft = frontTopLeft * worldRot;
810 frontTopRight = frontTopRight * worldRot; 950 frontTopRight = frontTopRight * worldRot;
811 frontBottomLeft = frontBottomLeft * worldRot; 951 frontBottomLeft = frontBottomLeft * worldRot;
@@ -827,6 +967,15 @@ namespace OpenSim.Region.Framework.Scenes
827 backTopLeft += offset; 967 backTopLeft += offset;
828 backTopRight += offset; 968 backTopRight += offset;
829 969
970 //m_log.InfoFormat("corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
971 //m_log.InfoFormat("corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
972 //m_log.InfoFormat("corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
973 //m_log.InfoFormat("corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
974 //m_log.InfoFormat("corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
975 //m_log.InfoFormat("corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
976 //m_log.InfoFormat("corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
977 //m_log.InfoFormat("corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
978
830 if (frontTopRight.X > maxX) 979 if (frontTopRight.X > maxX)
831 maxX = frontTopRight.X; 980 maxX = frontTopRight.X;
832 if (frontTopLeft.X > maxX) 981 if (frontTopLeft.X > maxX)
@@ -972,15 +1121,20 @@ namespace OpenSim.Region.Framework.Scenes
972 1121
973 public void SaveScriptedState(XmlTextWriter writer) 1122 public void SaveScriptedState(XmlTextWriter writer)
974 { 1123 {
1124 SaveScriptedState(writer, false);
1125 }
1126
1127 public void SaveScriptedState(XmlTextWriter writer, bool oldIDs)
1128 {
975 XmlDocument doc = new XmlDocument(); 1129 XmlDocument doc = new XmlDocument();
976 Dictionary<UUID,string> states = new Dictionary<UUID,string>(); 1130 Dictionary<UUID,string> states = new Dictionary<UUID,string>();
977 1131
978 SceneObjectPart[] parts = m_parts.GetArray(); 1132 SceneObjectPart[] parts = m_parts.GetArray();
979 for (int i = 0; i < parts.Length; i++) 1133 for (int i = 0; i < parts.Length; i++)
980 { 1134 {
981 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(); 1135 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(oldIDs);
982 foreach (KeyValuePair<UUID, string> kvp in pstates) 1136 foreach (KeyValuePair<UUID, string> kvp in pstates)
983 states.Add(kvp.Key, kvp.Value); 1137 states[kvp.Key] = kvp.Value;
984 } 1138 }
985 1139
986 if (states.Count > 0) 1140 if (states.Count > 0)
@@ -1000,6 +1154,168 @@ namespace OpenSim.Region.Framework.Scenes
1000 } 1154 }
1001 1155
1002 /// <summary> 1156 /// <summary>
1157 /// Add the avatar to this linkset (avatar is sat).
1158 /// </summary>
1159 /// <param name="agentID"></param>
1160 public void AddAvatar(UUID agentID)
1161 {
1162 ScenePresence presence;
1163 if (m_scene.TryGetScenePresence(agentID, out presence))
1164 {
1165 if (!m_linkedAvatars.Contains(presence))
1166 {
1167 m_linkedAvatars.Add(presence);
1168 }
1169 }
1170 }
1171
1172 /// <summary>
1173 /// Delete the avatar from this linkset (avatar is unsat).
1174 /// </summary>
1175 /// <param name="agentID"></param>
1176 public void DeleteAvatar(UUID agentID)
1177 {
1178 ScenePresence presence;
1179 if (m_scene.TryGetScenePresence(agentID, out presence))
1180 {
1181 if (m_linkedAvatars.Contains(presence))
1182 {
1183 m_linkedAvatars.Remove(presence);
1184 }
1185 }
1186 }
1187
1188 /// <summary>
1189 /// Returns the list of linked presences (avatars sat on this group)
1190 /// </summary>
1191 /// <param name="agentID"></param>
1192 public List<ScenePresence> GetLinkedAvatars()
1193 {
1194 return m_linkedAvatars;
1195 }
1196
1197 /// <summary>
1198 /// Attach this scene object to the given avatar.
1199 /// </summary>
1200 /// <param name="agentID"></param>
1201 /// <param name="attachmentpoint"></param>
1202 /// <param name="AttachOffset"></param>
1203 private void AttachToAgent(
1204 ScenePresence avatar, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent)
1205 {
1206 if (avatar != null)
1207 {
1208 // don't attach attachments to child agents
1209 if (avatar.IsChildAgent) return;
1210
1211 // Remove from database and parcel prim count
1212 m_scene.DeleteFromStorage(so.UUID);
1213 m_scene.EventManager.TriggerParcelPrimCountTainted();
1214
1215 so.AttachedAvatar = avatar.UUID;
1216
1217 if (so.RootPart.PhysActor != null)
1218 {
1219 m_scene.PhysicsScene.RemovePrim(so.RootPart.PhysActor);
1220 so.RootPart.PhysActor = null;
1221 }
1222
1223 so.AbsolutePosition = attachOffset;
1224 so.RootPart.AttachedPos = attachOffset;
1225 so.IsAttachment = true;
1226 so.RootPart.SetParentLocalId(avatar.LocalId);
1227 so.AttachmentPoint = attachmentpoint;
1228
1229 avatar.AddAttachment(this);
1230
1231 if (!silent)
1232 {
1233 // Killing it here will cause the client to deselect it
1234 // It then reappears on the avatar, deselected
1235 // through the full update below
1236 //
1237 if (IsSelected)
1238 {
1239 m_scene.SendKillObject(new List<uint> { m_rootPart.LocalId });
1240 }
1241
1242 IsSelected = false; // fudge....
1243 ScheduleGroupForFullUpdate();
1244 }
1245 }
1246 else
1247 {
1248 m_log.WarnFormat(
1249 "[SOG]: Tried to add attachment {0} to avatar with UUID {1} in region {2} but the avatar is not present",
1250 UUID, avatar.ControllingClient.AgentId, Scene.RegionInfo.RegionName);
1251 }
1252 }
1253
1254 public byte GetAttachmentPoint()
1255 {
1256 return m_rootPart.Shape.State;
1257 }
1258
1259 public void DetachToGround()
1260 {
1261 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
1262 if (avatar == null)
1263 return;
1264
1265 avatar.RemoveAttachment(this);
1266
1267 Vector3 detachedpos = new Vector3(127f,127f,127f);
1268 if (avatar == null)
1269 return;
1270
1271 detachedpos = avatar.AbsolutePosition;
1272 RootPart.FromItemID = UUID.Zero;
1273
1274 AbsolutePosition = detachedpos;
1275 AttachedAvatar = UUID.Zero;
1276
1277 //SceneObjectPart[] parts = m_parts.GetArray();
1278 //for (int i = 0; i < parts.Length; i++)
1279 // parts[i].AttachedAvatar = UUID.Zero;
1280
1281 m_rootPart.SetParentLocalId(0);
1282 AttachmentPoint = (byte)0;
1283 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive);
1284 HasGroupChanged = true;
1285 RootPart.Rezzed = DateTime.Now;
1286 RootPart.RemFlag(PrimFlags.TemporaryOnRez);
1287 AttachToBackup();
1288 m_scene.EventManager.TriggerParcelPrimCountTainted();
1289 m_rootPart.ScheduleFullUpdate();
1290 m_rootPart.ClearUndoState();
1291 }
1292
1293 public void DetachToInventoryPrep()
1294 {
1295 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
1296 //Vector3 detachedpos = new Vector3(127f, 127f, 127f);
1297 if (avatar != null)
1298 {
1299 //detachedpos = avatar.AbsolutePosition;
1300 avatar.RemoveAttachment(this);
1301 }
1302
1303 AttachedAvatar = UUID.Zero;
1304
1305 /*SceneObjectPart[] parts = m_parts.GetArray();
1306 for (int i = 0; i < parts.Length; i++)
1307 parts[i].AttachedAvatar = UUID.Zero;*/
1308
1309 m_rootPart.SetParentLocalId(0);
1310 //m_rootPart.SetAttachmentPoint((byte)0);
1311 IsAttachment = false;
1312 AbsolutePosition = m_rootPart.AttachedPos;
1313 //m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_scene.m_physicalPrim);
1314 //AttachToBackup();
1315 //m_rootPart.ScheduleFullUpdate();
1316 }
1317
1318 /// <summary>
1003 /// 1319 ///
1004 /// </summary> 1320 /// </summary>
1005 /// <param name="part"></param> 1321 /// <param name="part"></param>
@@ -1049,7 +1365,10 @@ namespace OpenSim.Region.Framework.Scenes
1049 public void AddPart(SceneObjectPart part) 1365 public void AddPart(SceneObjectPart part)
1050 { 1366 {
1051 part.SetParent(this); 1367 part.SetParent(this);
1052 part.LinkNum = m_parts.Add(part.UUID, part); 1368 m_parts.Add(part.UUID, part);
1369
1370 part.LinkNum = m_parts.Count;
1371
1053 if (part.LinkNum == 2) 1372 if (part.LinkNum == 2)
1054 RootPart.LinkNum = 1; 1373 RootPart.LinkNum = 1;
1055 } 1374 }
@@ -1157,6 +1476,11 @@ namespace OpenSim.Region.Framework.Scenes
1157 /// <param name="silent">If true then deletion is not broadcast to clients</param> 1476 /// <param name="silent">If true then deletion is not broadcast to clients</param>
1158 public void DeleteGroupFromScene(bool silent) 1477 public void DeleteGroupFromScene(bool silent)
1159 { 1478 {
1479 // We need to keep track of this state in case this group is still queued for backup.
1480 IsDeleted = true;
1481
1482 DetachFromBackup();
1483
1160 SceneObjectPart[] parts = m_parts.GetArray(); 1484 SceneObjectPart[] parts = m_parts.GetArray();
1161 for (int i = 0; i < parts.Length; i++) 1485 for (int i = 0; i < parts.Length; i++)
1162 { 1486 {
@@ -1179,6 +1503,8 @@ namespace OpenSim.Region.Framework.Scenes
1179 } 1503 }
1180 }); 1504 });
1181 } 1505 }
1506
1507
1182 } 1508 }
1183 1509
1184 public void AddScriptLPS(int count) 1510 public void AddScriptLPS(int count)
@@ -1274,7 +1600,12 @@ namespace OpenSim.Region.Framework.Scenes
1274 1600
1275 public void SetOwnerId(UUID userId) 1601 public void SetOwnerId(UUID userId)
1276 { 1602 {
1277 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); 1603 ForEachPart(delegate(SceneObjectPart part)
1604 {
1605
1606 part.OwnerID = userId;
1607
1608 });
1278 } 1609 }
1279 1610
1280 public void ForEachPart(Action<SceneObjectPart> whatToDo) 1611 public void ForEachPart(Action<SceneObjectPart> whatToDo)
@@ -1306,11 +1637,17 @@ namespace OpenSim.Region.Framework.Scenes
1306 return; 1637 return;
1307 } 1638 }
1308 1639
1640 if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
1641 return;
1642
1309 // Since this is the top of the section of call stack for backing up a particular scene object, don't let 1643 // Since this is the top of the section of call stack for backing up a particular scene object, don't let
1310 // any exception propogate upwards. 1644 // any exception propogate upwards.
1311 try 1645 try
1312 { 1646 {
1313 if (!m_scene.ShuttingDown) // if shutting down then there will be nothing to handle the return so leave till next restart 1647 if (!m_scene.ShuttingDown || // if shutting down then there will be nothing to handle the return so leave till next restart
1648 m_scene.LoginsDisabled || // We're starting up or doing maintenance, don't mess with things
1649 m_scene.LoadingPrims) // Land may not be valid yet
1650
1314 { 1651 {
1315 ILandObject parcel = m_scene.LandChannel.GetLandObject( 1652 ILandObject parcel = m_scene.LandChannel.GetLandObject(
1316 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y); 1653 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y);
@@ -1337,6 +1674,7 @@ namespace OpenSim.Region.Framework.Scenes
1337 } 1674 }
1338 } 1675 }
1339 } 1676 }
1677
1340 } 1678 }
1341 1679
1342 if (m_scene.UseBackup && HasGroupChanged) 1680 if (m_scene.UseBackup && HasGroupChanged)
@@ -1344,6 +1682,20 @@ namespace OpenSim.Region.Framework.Scenes
1344 // don't backup while it's selected or you're asking for changes mid stream. 1682 // don't backup while it's selected or you're asking for changes mid stream.
1345 if (isTimeToPersist() || forcedBackup) 1683 if (isTimeToPersist() || forcedBackup)
1346 { 1684 {
1685 if (m_rootPart.PhysActor != null &&
1686 (!m_rootPart.PhysActor.IsPhysical))
1687 {
1688 // Possible ghost prim
1689 if (m_rootPart.PhysActor.Position != m_rootPart.GroupPosition)
1690 {
1691 foreach (SceneObjectPart part in m_parts.GetArray())
1692 {
1693 // Re-set physics actor positions and
1694 // orientations
1695 part.GroupPosition = m_rootPart.GroupPosition;
1696 }
1697 }
1698 }
1347// m_log.DebugFormat( 1699// m_log.DebugFormat(
1348// "[SCENE]: Storing {0}, {1} in {2}", 1700// "[SCENE]: Storing {0}, {1} in {2}",
1349// Name, UUID, m_scene.RegionInfo.RegionName); 1701// Name, UUID, m_scene.RegionInfo.RegionName);
@@ -1427,7 +1779,7 @@ namespace OpenSim.Region.Framework.Scenes
1427 // This is only necessary when userExposed is false! 1779 // This is only necessary when userExposed is false!
1428 1780
1429 bool previousAttachmentStatus = dupe.IsAttachment; 1781 bool previousAttachmentStatus = dupe.IsAttachment;
1430 1782
1431 if (!userExposed) 1783 if (!userExposed)
1432 dupe.IsAttachment = true; 1784 dupe.IsAttachment = true;
1433 1785
@@ -1445,11 +1797,11 @@ namespace OpenSim.Region.Framework.Scenes
1445 dupe.m_rootPart.TrimPermissions(); 1797 dupe.m_rootPart.TrimPermissions();
1446 1798
1447 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray()); 1799 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray());
1448 1800
1449 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) 1801 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1450 { 1802 {
1451 return p1.LinkNum.CompareTo(p2.LinkNum); 1803 return p1.LinkNum.CompareTo(p2.LinkNum);
1452 } 1804 }
1453 ); 1805 );
1454 1806
1455 foreach (SceneObjectPart part in partList) 1807 foreach (SceneObjectPart part in partList)
@@ -1469,7 +1821,7 @@ namespace OpenSim.Region.Framework.Scenes
1469 if (part.PhysActor != null && userExposed) 1821 if (part.PhysActor != null && userExposed)
1470 { 1822 {
1471 PrimitiveBaseShape pbs = newPart.Shape; 1823 PrimitiveBaseShape pbs = newPart.Shape;
1472 1824
1473 newPart.PhysActor 1825 newPart.PhysActor
1474 = m_scene.PhysicsScene.AddPrimShape( 1826 = m_scene.PhysicsScene.AddPrimShape(
1475 string.Format("{0}/{1}", newPart.Name, newPart.UUID), 1827 string.Format("{0}/{1}", newPart.Name, newPart.UUID),
@@ -1479,11 +1831,11 @@ namespace OpenSim.Region.Framework.Scenes
1479 newPart.RotationOffset, 1831 newPart.RotationOffset,
1480 part.PhysActor.IsPhysical, 1832 part.PhysActor.IsPhysical,
1481 newPart.LocalId); 1833 newPart.LocalId);
1482 1834
1483 newPart.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true); 1835 newPart.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true);
1484 } 1836 }
1485 } 1837 }
1486 1838
1487 if (userExposed) 1839 if (userExposed)
1488 { 1840 {
1489 dupe.UpdateParentIDs(); 1841 dupe.UpdateParentIDs();
@@ -1598,6 +1950,7 @@ namespace OpenSim.Region.Framework.Scenes
1598 return Vector3.Zero; 1950 return Vector3.Zero;
1599 } 1951 }
1600 1952
1953 // This is used by both Double-Click Auto-Pilot and llMoveToTarget() in an attached object
1601 public void moveToTarget(Vector3 target, float tau) 1954 public void moveToTarget(Vector3 target, float tau)
1602 { 1955 {
1603 if (IsAttachment) 1956 if (IsAttachment)
@@ -1625,6 +1978,46 @@ namespace OpenSim.Region.Framework.Scenes
1625 RootPart.PhysActor.PIDActive = false; 1978 RootPart.PhysActor.PIDActive = false;
1626 } 1979 }
1627 1980
1981 public void rotLookAt(Quaternion target, float strength, float damping)
1982 {
1983 SceneObjectPart rootpart = m_rootPart;
1984 if (rootpart != null)
1985 {
1986 if (IsAttachment)
1987 {
1988 /*
1989 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
1990 if (avatar != null)
1991 {
1992 Rotate the Av?
1993 } */
1994 }
1995 else
1996 {
1997 if (rootpart.PhysActor != null)
1998 { // APID must be implemented in your physics system for this to function.
1999 rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W);
2000 rootpart.PhysActor.APIDStrength = strength;
2001 rootpart.PhysActor.APIDDamping = damping;
2002 rootpart.PhysActor.APIDActive = true;
2003 }
2004 }
2005 }
2006 }
2007
2008 public void stopLookAt()
2009 {
2010 SceneObjectPart rootpart = m_rootPart;
2011 if (rootpart != null)
2012 {
2013 if (rootpart.PhysActor != null)
2014 { // APID must be implemented in your physics system for this to function.
2015 rootpart.PhysActor.APIDActive = false;
2016 }
2017 }
2018
2019 }
2020
1628 /// <summary> 2021 /// <summary>
1629 /// Uses a PID to attempt to clamp the object on the Z axis at the given height over tau seconds. 2022 /// Uses a PID to attempt to clamp the object on the Z axis at the given height over tau seconds.
1630 /// </summary> 2023 /// </summary>
@@ -1680,6 +2073,8 @@ namespace OpenSim.Region.Framework.Scenes
1680 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) 2073 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
1681 { 2074 {
1682 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 2075 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
2076 newPart.SetParent(this);
2077
1683 AddPart(newPart); 2078 AddPart(newPart);
1684 2079
1685 SetPartAsNonRoot(newPart); 2080 SetPartAsNonRoot(newPart);
@@ -1808,11 +2203,11 @@ namespace OpenSim.Region.Framework.Scenes
1808 /// Immediately send a full update for this scene object. 2203 /// Immediately send a full update for this scene object.
1809 /// </summary> 2204 /// </summary>
1810 public void SendGroupFullUpdate() 2205 public void SendGroupFullUpdate()
1811 { 2206 {
1812 if (IsDeleted) 2207 if (IsDeleted)
1813 return; 2208 return;
1814 2209
1815// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); 2210// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID);
1816 2211
1817 RootPart.SendFullUpdateToAllClients(); 2212 RootPart.SendFullUpdateToAllClients();
1818 2213
@@ -1956,6 +2351,11 @@ namespace OpenSim.Region.Framework.Scenes
1956 /// <param name="objectGroup">The group of prims which should be linked to this group</param> 2351 /// <param name="objectGroup">The group of prims which should be linked to this group</param>
1957 public void LinkToGroup(SceneObjectGroup objectGroup) 2352 public void LinkToGroup(SceneObjectGroup objectGroup)
1958 { 2353 {
2354 LinkToGroup(objectGroup, false);
2355 }
2356
2357 public void LinkToGroup(SceneObjectGroup objectGroup, bool insert)
2358 {
1959// m_log.DebugFormat( 2359// m_log.DebugFormat(
1960// "[SCENE OBJECT GROUP]: Linking group with root part {0}, {1} to group with root part {2}, {3}", 2360// "[SCENE OBJECT GROUP]: Linking group with root part {0}, {1} to group with root part {2}, {3}",
1961// objectGroup.RootPart.Name, objectGroup.RootPart.UUID, RootPart.Name, RootPart.UUID); 2361// objectGroup.RootPart.Name, objectGroup.RootPart.UUID, RootPart.Name, RootPart.UUID);
@@ -1985,7 +2385,20 @@ namespace OpenSim.Region.Framework.Scenes
1985 2385
1986 lock (m_parts.SyncRoot) 2386 lock (m_parts.SyncRoot)
1987 { 2387 {
1988 int linkNum = PrimCount + 1; 2388 int linkNum;
2389 if (insert)
2390 {
2391 linkNum = 2;
2392 foreach (SceneObjectPart part in Parts)
2393 {
2394 if (part.LinkNum > 1)
2395 part.LinkNum++;
2396 }
2397 }
2398 else
2399 {
2400 linkNum = PrimCount + 1;
2401 }
1989 2402
1990 m_parts.Add(linkPart.UUID, linkPart); 2403 m_parts.Add(linkPart.UUID, linkPart);
1991 2404
@@ -2013,7 +2426,7 @@ namespace OpenSim.Region.Framework.Scenes
2013 objectGroup.IsDeleted = true; 2426 objectGroup.IsDeleted = true;
2014 2427
2015 objectGroup.m_parts.Clear(); 2428 objectGroup.m_parts.Clear();
2016 2429
2017 // Can't do this yet since backup still makes use of the root part without any synchronization 2430 // Can't do this yet since backup still makes use of the root part without any synchronization
2018// objectGroup.m_rootPart = null; 2431// objectGroup.m_rootPart = null;
2019 2432
@@ -2147,6 +2560,7 @@ namespace OpenSim.Region.Framework.Scenes
2147 /// <param name="objectGroup"></param> 2560 /// <param name="objectGroup"></param>
2148 public virtual void DetachFromBackup() 2561 public virtual void DetachFromBackup()
2149 { 2562 {
2563 m_scene.SceneGraph.FireDetachFromBackup(this);
2150 if (m_isBackedUp && Scene != null) 2564 if (m_isBackedUp && Scene != null)
2151 m_scene.EventManager.OnBackup -= ProcessBackup; 2565 m_scene.EventManager.OnBackup -= ProcessBackup;
2152 2566
@@ -2165,7 +2579,8 @@ namespace OpenSim.Region.Framework.Scenes
2165 2579
2166 axPos *= parentRot; 2580 axPos *= parentRot;
2167 part.OffsetPosition = axPos; 2581 part.OffsetPosition = axPos;
2168 part.GroupPosition = oldGroupPosition + part.OffsetPosition; 2582 Vector3 newPos = oldGroupPosition + part.OffsetPosition;
2583 part.GroupPosition = newPos;
2169 part.OffsetPosition = Vector3.Zero; 2584 part.OffsetPosition = Vector3.Zero;
2170 part.RotationOffset = worldRot; 2585 part.RotationOffset = worldRot;
2171 2586
@@ -2176,7 +2591,7 @@ namespace OpenSim.Region.Framework.Scenes
2176 2591
2177 part.LinkNum = linkNum; 2592 part.LinkNum = linkNum;
2178 2593
2179 part.OffsetPosition = part.GroupPosition - AbsolutePosition; 2594 part.OffsetPosition = newPos - AbsolutePosition;
2180 2595
2181 Quaternion rootRotation = m_rootPart.RotationOffset; 2596 Quaternion rootRotation = m_rootPart.RotationOffset;
2182 2597
@@ -2186,7 +2601,7 @@ namespace OpenSim.Region.Framework.Scenes
2186 2601
2187 parentRot = m_rootPart.RotationOffset; 2602 parentRot = m_rootPart.RotationOffset;
2188 oldRot = part.RotationOffset; 2603 oldRot = part.RotationOffset;
2189 Quaternion newRot = Quaternion.Inverse(parentRot) * oldRot; 2604 Quaternion newRot = Quaternion.Inverse(parentRot) * worldRot;
2190 part.RotationOffset = newRot; 2605 part.RotationOffset = newRot;
2191 } 2606 }
2192 2607
@@ -2433,8 +2848,12 @@ namespace OpenSim.Region.Framework.Scenes
2433 } 2848 }
2434 } 2849 }
2435 2850
2851 RootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect);
2436 for (int i = 0; i < parts.Length; i++) 2852 for (int i = 0; i < parts.Length; i++)
2437 parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect); 2853 {
2854 if (parts[i] != RootPart)
2855 parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect);
2856 }
2438 } 2857 }
2439 } 2858 }
2440 2859
@@ -2447,6 +2866,17 @@ namespace OpenSim.Region.Framework.Scenes
2447 } 2866 }
2448 } 2867 }
2449 2868
2869
2870
2871 /// <summary>
2872 /// Gets the number of parts
2873 /// </summary>
2874 /// <returns></returns>
2875 public int GetPartCount()
2876 {
2877 return Parts.Count();
2878 }
2879
2450 /// <summary> 2880 /// <summary>
2451 /// Update the texture entry for this part 2881 /// Update the texture entry for this part
2452 /// </summary> 2882 /// </summary>
@@ -2508,7 +2938,6 @@ namespace OpenSim.Region.Framework.Scenes
2508 { 2938 {
2509// m_log.DebugFormat( 2939// m_log.DebugFormat(
2510// "[SCENE OBJECT GROUP]: Group resizing {0} {1} from {2} to {3}", Name, LocalId, RootPart.Scale, scale); 2940// "[SCENE OBJECT GROUP]: Group resizing {0} {1} from {2} to {3}", Name, LocalId, RootPart.Scale, scale);
2511
2512 RootPart.StoreUndoState(true); 2941 RootPart.StoreUndoState(true);
2513 2942
2514 scale.X = Math.Min(scale.X, Scene.m_maxNonphys); 2943 scale.X = Math.Min(scale.X, Scene.m_maxNonphys);
@@ -2609,7 +3038,6 @@ namespace OpenSim.Region.Framework.Scenes
2609 prevScale.X *= x; 3038 prevScale.X *= x;
2610 prevScale.Y *= y; 3039 prevScale.Y *= y;
2611 prevScale.Z *= z; 3040 prevScale.Z *= z;
2612
2613// RootPart.IgnoreUndoUpdate = true; 3041// RootPart.IgnoreUndoUpdate = true;
2614 RootPart.Resize(prevScale); 3042 RootPart.Resize(prevScale);
2615// RootPart.IgnoreUndoUpdate = false; 3043// RootPart.IgnoreUndoUpdate = false;
@@ -2640,7 +3068,9 @@ namespace OpenSim.Region.Framework.Scenes
2640 } 3068 }
2641 3069
2642// obPart.IgnoreUndoUpdate = false; 3070// obPart.IgnoreUndoUpdate = false;
2643// obPart.StoreUndoState(); 3071 HasGroupChanged = true;
3072 m_rootPart.TriggerScriptChangedEvent(Changed.SCALE);
3073 ScheduleGroupForTerseUpdate();
2644 } 3074 }
2645 3075
2646// m_log.DebugFormat( 3076// m_log.DebugFormat(
@@ -2700,9 +3130,9 @@ namespace OpenSim.Region.Framework.Scenes
2700 { 3130 {
2701 SceneObjectPart part = GetChildPart(localID); 3131 SceneObjectPart part = GetChildPart(localID);
2702 3132
2703// SceneObjectPart[] parts = m_parts.GetArray(); 3133 SceneObjectPart[] parts = m_parts.GetArray();
2704// for (int i = 0; i < parts.Length; i++) 3134 for (int i = 0; i < parts.Length; i++)
2705// parts[i].StoreUndoState(); 3135 parts[i].StoreUndoState();
2706 3136
2707 if (part != null) 3137 if (part != null)
2708 { 3138 {
@@ -2758,10 +3188,27 @@ namespace OpenSim.Region.Framework.Scenes
2758 obPart.OffsetPosition = obPart.OffsetPosition + diff; 3188 obPart.OffsetPosition = obPart.OffsetPosition + diff;
2759 } 3189 }
2760 3190
2761 AbsolutePosition = newPos; 3191 //We have to set undoing here because otherwise an undo state will be saved
3192 if (!m_rootPart.Undoing)
3193 {
3194 m_rootPart.Undoing = true;
3195 AbsolutePosition = newPos;
3196 m_rootPart.Undoing = false;
3197 }
3198 else
3199 {
3200 AbsolutePosition = newPos;
3201 }
2762 3202
2763 HasGroupChanged = true; 3203 HasGroupChanged = true;
2764 ScheduleGroupForTerseUpdate(); 3204 if (m_rootPart.Undoing)
3205 {
3206 ScheduleGroupForFullUpdate();
3207 }
3208 else
3209 {
3210 ScheduleGroupForTerseUpdate();
3211 }
2765 } 3212 }
2766 3213
2767 #endregion 3214 #endregion
@@ -2838,10 +3285,7 @@ namespace OpenSim.Region.Framework.Scenes
2838 public void UpdateSingleRotation(Quaternion rot, uint localID) 3285 public void UpdateSingleRotation(Quaternion rot, uint localID)
2839 { 3286 {
2840 SceneObjectPart part = GetChildPart(localID); 3287 SceneObjectPart part = GetChildPart(localID);
2841
2842 SceneObjectPart[] parts = m_parts.GetArray(); 3288 SceneObjectPart[] parts = m_parts.GetArray();
2843 for (int i = 0; i < parts.Length; i++)
2844 parts[i].StoreUndoState();
2845 3289
2846 if (part != null) 3290 if (part != null)
2847 { 3291 {
@@ -2879,7 +3323,16 @@ namespace OpenSim.Region.Framework.Scenes
2879 if (part.UUID == m_rootPart.UUID) 3323 if (part.UUID == m_rootPart.UUID)
2880 { 3324 {
2881 UpdateRootRotation(rot); 3325 UpdateRootRotation(rot);
2882 AbsolutePosition = pos; 3326 if (!m_rootPart.Undoing)
3327 {
3328 m_rootPart.Undoing = true;
3329 AbsolutePosition = pos;
3330 m_rootPart.Undoing = false;
3331 }
3332 else
3333 {
3334 AbsolutePosition = pos;
3335 }
2883 } 3336 }
2884 else 3337 else
2885 { 3338 {
@@ -2903,9 +3356,10 @@ namespace OpenSim.Region.Framework.Scenes
2903 3356
2904 Quaternion axRot = rot; 3357 Quaternion axRot = rot;
2905 Quaternion oldParentRot = m_rootPart.RotationOffset; 3358 Quaternion oldParentRot = m_rootPart.RotationOffset;
2906
2907 m_rootPart.StoreUndoState(); 3359 m_rootPart.StoreUndoState();
2908 m_rootPart.UpdateRotation(rot); 3360
3361 //Don't use UpdateRotation because it schedules an update prematurely
3362 m_rootPart.RotationOffset = rot;
2909 if (m_rootPart.PhysActor != null) 3363 if (m_rootPart.PhysActor != null)
2910 { 3364 {
2911 m_rootPart.PhysActor.Orientation = m_rootPart.RotationOffset; 3365 m_rootPart.PhysActor.Orientation = m_rootPart.RotationOffset;
@@ -2919,15 +3373,17 @@ namespace OpenSim.Region.Framework.Scenes
2919 if (prim.UUID != m_rootPart.UUID) 3373 if (prim.UUID != m_rootPart.UUID)
2920 { 3374 {
2921 prim.IgnoreUndoUpdate = true; 3375 prim.IgnoreUndoUpdate = true;
3376
3377 Quaternion NewRot = oldParentRot * prim.RotationOffset;
3378 NewRot = Quaternion.Inverse(axRot) * NewRot;
3379 prim.RotationOffset = NewRot;
3380
2922 Vector3 axPos = prim.OffsetPosition; 3381 Vector3 axPos = prim.OffsetPosition;
3382
2923 axPos *= oldParentRot; 3383 axPos *= oldParentRot;
2924 axPos *= Quaternion.Inverse(axRot); 3384 axPos *= Quaternion.Inverse(axRot);
2925 prim.OffsetPosition = axPos; 3385 prim.OffsetPosition = axPos;
2926 Quaternion primsRot = prim.RotationOffset; 3386
2927 Quaternion newRot = oldParentRot * primsRot;
2928 newRot = Quaternion.Inverse(axRot) * newRot;
2929 prim.RotationOffset = newRot;
2930 prim.ScheduleTerseUpdate();
2931 prim.IgnoreUndoUpdate = false; 3387 prim.IgnoreUndoUpdate = false;
2932 } 3388 }
2933 } 3389 }
@@ -2941,8 +3397,8 @@ namespace OpenSim.Region.Framework.Scenes
2941//// childpart.StoreUndoState(); 3397//// childpart.StoreUndoState();
2942// } 3398// }
2943// } 3399// }
2944 3400 HasGroupChanged = true;
2945 m_rootPart.ScheduleTerseUpdate(); 3401 ScheduleGroupForFullUpdate();
2946 3402
2947// m_log.DebugFormat( 3403// m_log.DebugFormat(
2948// "[SCENE OBJECT GROUP]: Updated root rotation of {0} {1} to {2}", 3404// "[SCENE OBJECT GROUP]: Updated root rotation of {0} {1} to {2}",
@@ -3170,7 +3626,6 @@ namespace OpenSim.Region.Framework.Scenes
3170 public float GetMass() 3626 public float GetMass()
3171 { 3627 {
3172 float retmass = 0f; 3628 float retmass = 0f;
3173
3174 SceneObjectPart[] parts = m_parts.GetArray(); 3629 SceneObjectPart[] parts = m_parts.GetArray();
3175 for (int i = 0; i < parts.Length; i++) 3630 for (int i = 0; i < parts.Length; i++)
3176 retmass += parts[i].GetMass(); 3631 retmass += parts[i].GetMass();
@@ -3266,6 +3721,14 @@ namespace OpenSim.Region.Framework.Scenes
3266 SetFromItemID(uuid); 3721 SetFromItemID(uuid);
3267 } 3722 }
3268 3723
3724 public void ResetOwnerChangeFlag()
3725 {
3726 ForEachPart(delegate(SceneObjectPart part)
3727 {
3728 part.ResetOwnerChangeFlag();
3729 });
3730 }
3731
3269 #endregion 3732 #endregion
3270 } 3733 }
3271} 3734}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 0e899ca..a6c234e 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -62,7 +62,8 @@ namespace OpenSim.Region.Framework.Scenes
62 TELEPORT = 512, 62 TELEPORT = 512,
63 REGION_RESTART = 1024, 63 REGION_RESTART = 1024,
64 MEDIA = 2048, 64 MEDIA = 2048,
65 ANIMATION = 16384 65 ANIMATION = 16384,
66 POSITION = 32768
66 } 67 }
67 68
68 // I don't really know where to put this except here. 69 // I don't really know where to put this except here.
@@ -184,6 +185,15 @@ namespace OpenSim.Region.Framework.Scenes
184 185
185 public UUID FromFolderID; 186 public UUID FromFolderID;
186 187
188 // The following two are to hold the attachment data
189 // while an object is inworld
190 [XmlIgnore]
191 public byte AttachPoint = 0;
192
193 [XmlIgnore]
194 public Vector3 AttachOffset = Vector3.Zero;
195
196 [XmlIgnore]
187 public int STATUS_ROTATE_X; 197 public int STATUS_ROTATE_X;
188 198
189 public int STATUS_ROTATE_Y; 199 public int STATUS_ROTATE_Y;
@@ -210,8 +220,7 @@ namespace OpenSim.Region.Framework.Scenes
210 220
211 public Vector3 RotationAxis = Vector3.One; 221 public Vector3 RotationAxis = Vector3.One;
212 222
213 public bool VolumeDetectActive; // XmlIgnore set to avoid problems with persistance until I come to care for this 223 public bool VolumeDetectActive;
214 // Certainly this must be a persistant setting finally
215 224
216 public bool IsWaitingForFirstSpinUpdatePacket; 225 public bool IsWaitingForFirstSpinUpdatePacket;
217 226
@@ -251,6 +260,7 @@ namespace OpenSim.Region.Framework.Scenes
251 private Quaternion m_sitTargetOrientation = Quaternion.Identity; 260 private Quaternion m_sitTargetOrientation = Quaternion.Identity;
252 private Vector3 m_sitTargetPosition; 261 private Vector3 m_sitTargetPosition;
253 private string m_sitAnimation = "SIT"; 262 private string m_sitAnimation = "SIT";
263 private bool m_occupied; // KF if any av is sitting on this prim
254 private string m_text = String.Empty; 264 private string m_text = String.Empty;
255 private string m_touchName = String.Empty; 265 private string m_touchName = String.Empty;
256 private readonly Stack<UndoState> m_undo = new Stack<UndoState>(5); 266 private readonly Stack<UndoState> m_undo = new Stack<UndoState>(5);
@@ -283,6 +293,7 @@ namespace OpenSim.Region.Framework.Scenes
283 protected Vector3 m_lastAcceleration; 293 protected Vector3 m_lastAcceleration;
284 protected Vector3 m_lastAngularVelocity; 294 protected Vector3 m_lastAngularVelocity;
285 protected int m_lastTerseSent; 295 protected int m_lastTerseSent;
296 protected float m_buoyancy = 0.0f;
286 297
287 /// <summary> 298 /// <summary>
288 /// Stores media texture data 299 /// Stores media texture data
@@ -338,7 +349,7 @@ namespace OpenSim.Region.Framework.Scenes
338 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition, 349 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition,
339 Quaternion rotationOffset, Vector3 offsetPosition) : this() 350 Quaternion rotationOffset, Vector3 offsetPosition) : this()
340 { 351 {
341 m_name = "Primitive"; 352 m_name = "Object";
342 353
343 CreationDate = (int)Utils.DateTimeToUnixTime(Rezzed); 354 CreationDate = (int)Utils.DateTimeToUnixTime(Rezzed);
344 LastOwnerID = CreatorID = OwnerID = ownerID; 355 LastOwnerID = CreatorID = OwnerID = ownerID;
@@ -378,7 +389,7 @@ namespace OpenSim.Region.Framework.Scenes
378 private uint _ownerMask = (uint)PermissionMask.All; 389 private uint _ownerMask = (uint)PermissionMask.All;
379 private uint _groupMask = (uint)PermissionMask.None; 390 private uint _groupMask = (uint)PermissionMask.None;
380 private uint _everyoneMask = (uint)PermissionMask.None; 391 private uint _everyoneMask = (uint)PermissionMask.None;
381 private uint _nextOwnerMask = (uint)PermissionMask.All; 392 private uint _nextOwnerMask = (uint)(PermissionMask.Move | PermissionMask.Modify | PermissionMask.Transfer);
382 private PrimFlags _flags = PrimFlags.None; 393 private PrimFlags _flags = PrimFlags.None;
383 private DateTime m_expires; 394 private DateTime m_expires;
384 private DateTime m_rezzed; 395 private DateTime m_rezzed;
@@ -472,12 +483,16 @@ namespace OpenSim.Region.Framework.Scenes
472 } 483 }
473 484
474 /// <value> 485 /// <value>
475 /// Access should be via Inventory directly - this property temporarily remains for xml serialization purposes 486 /// Get the inventory list
476 /// </value> 487 /// </value>
477 public TaskInventoryDictionary TaskInventory 488 public TaskInventoryDictionary TaskInventory
478 { 489 {
479 get { return m_inventory.Items; } 490 get {
480 set { m_inventory.Items = value; } 491 return m_inventory.Items;
492 }
493 set {
494 m_inventory.Items = value;
495 }
481 } 496 }
482 497
483 /// <summary> 498 /// <summary>
@@ -621,14 +636,12 @@ namespace OpenSim.Region.Framework.Scenes
621 set { m_LoopSoundSlavePrims = value; } 636 set { m_LoopSoundSlavePrims = value; }
622 } 637 }
623 638
624
625 public Byte[] TextureAnimation 639 public Byte[] TextureAnimation
626 { 640 {
627 get { return m_TextureAnimation; } 641 get { return m_TextureAnimation; }
628 set { m_TextureAnimation = value; } 642 set { m_TextureAnimation = value; }
629 } 643 }
630 644
631
632 public Byte[] ParticleSystem 645 public Byte[] ParticleSystem
633 { 646 {
634 get { return m_particleSystem; } 647 get { return m_particleSystem; }
@@ -665,9 +678,11 @@ namespace OpenSim.Region.Framework.Scenes
665 { 678 {
666 // If this is a linkset, we don't want the physics engine mucking up our group position here. 679 // If this is a linkset, we don't want the physics engine mucking up our group position here.
667 PhysicsActor actor = PhysActor; 680 PhysicsActor actor = PhysActor;
668 if (actor != null && ParentID == 0) 681 if (ParentID == 0)
669 { 682 {
670 m_groupPosition = actor.Position; 683 if (actor != null)
684 m_groupPosition = actor.Position;
685 return m_groupPosition;
671 } 686 }
672 687
673 if (ParentGroup.IsAttachment) 688 if (ParentGroup.IsAttachment)
@@ -677,12 +692,14 @@ namespace OpenSim.Region.Framework.Scenes
677 return sp.AbsolutePosition; 692 return sp.AbsolutePosition;
678 } 693 }
679 694
695 // use root prim's group position. Physics may have updated it
696 if (ParentGroup.RootPart != this)
697 m_groupPosition = ParentGroup.RootPart.GroupPosition;
680 return m_groupPosition; 698 return m_groupPosition;
681 } 699 }
682 set 700 set
683 { 701 {
684 m_groupPosition = value; 702 m_groupPosition = value;
685
686 PhysicsActor actor = PhysActor; 703 PhysicsActor actor = PhysActor;
687 if (actor != null) 704 if (actor != null)
688 { 705 {
@@ -708,16 +725,6 @@ namespace OpenSim.Region.Framework.Scenes
708 m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message); 725 m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message);
709 } 726 }
710 } 727 }
711
712 // TODO if we decide to do sitting in a more SL compatible way (multiple avatars per prim), this has to be fixed, too
713 if (SitTargetAvatar != UUID.Zero)
714 {
715 ScenePresence avatar;
716 if (ParentGroup.Scene.TryGetScenePresence(SitTargetAvatar, out avatar))
717 {
718 avatar.ParentPosition = GetWorldPosition();
719 }
720 }
721 } 728 }
722 } 729 }
723 730
@@ -726,7 +733,7 @@ namespace OpenSim.Region.Framework.Scenes
726 get { return m_offsetPosition; } 733 get { return m_offsetPosition; }
727 set 734 set
728 { 735 {
729// StoreUndoState(); 736 Vector3 oldpos = m_offsetPosition;
730 m_offsetPosition = value; 737 m_offsetPosition = value;
731 738
732 if (ParentGroup != null && !ParentGroup.IsDeleted) 739 if (ParentGroup != null && !ParentGroup.IsDeleted)
@@ -741,7 +748,22 @@ namespace OpenSim.Region.Framework.Scenes
741 if (ParentGroup.Scene != null) 748 if (ParentGroup.Scene != null)
742 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 749 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
743 } 750 }
751
752 if (!m_parentGroup.m_dupeInProgress)
753 {
754 List<ScenePresence> avs = ParentGroup.GetLinkedAvatars();
755 foreach (ScenePresence av in avs)
756 {
757 if (av.ParentID == m_localId)
758 {
759 Vector3 offset = (m_offsetPosition - oldpos);
760 av.AbsolutePosition += offset;
761 av.SendAvatarDataToAllAgents();
762 }
763 }
764 }
744 } 765 }
766 TriggerScriptChangedEvent(Changed.POSITION);
745 } 767 }
746 } 768 }
747 769
@@ -890,7 +912,16 @@ namespace OpenSim.Region.Framework.Scenes
890 /// <summary></summary> 912 /// <summary></summary>
891 public Vector3 Acceleration 913 public Vector3 Acceleration
892 { 914 {
893 get { return m_acceleration; } 915 get
916 {
917 PhysicsActor actor = PhysActor;
918 if (actor != null)
919 {
920 m_acceleration = actor.Acceleration;
921 }
922 return m_acceleration;
923 }
924
894 set { m_acceleration = value; } 925 set { m_acceleration = value; }
895 } 926 }
896 927
@@ -1027,10 +1058,7 @@ namespace OpenSim.Region.Framework.Scenes
1027 { 1058 {
1028 get 1059 get
1029 { 1060 {
1030 if (ParentGroup.IsAttachment) 1061 return GroupPosition + (m_offsetPosition * ParentGroup.RootPart.RotationOffset);
1031 return GroupPosition;
1032
1033 return m_offsetPosition + m_groupPosition;
1034 } 1062 }
1035 } 1063 }
1036 1064
@@ -1200,6 +1228,13 @@ namespace OpenSim.Region.Framework.Scenes
1200 _flags = value; 1228 _flags = value;
1201 } 1229 }
1202 } 1230 }
1231
1232 [XmlIgnore]
1233 public bool IsOccupied // KF If an av is sittingon this prim
1234 {
1235 get { return m_occupied; }
1236 set { m_occupied = value; }
1237 }
1203 1238
1204 /// <summary> 1239 /// <summary>
1205 /// ID of the avatar that is sat on us. If there is no such avatar then is UUID.Zero 1240 /// ID of the avatar that is sat on us. If there is no such avatar then is UUID.Zero
@@ -1259,6 +1294,19 @@ namespace OpenSim.Region.Framework.Scenes
1259 set { m_collisionSoundVolume = value; } 1294 set { m_collisionSoundVolume = value; }
1260 } 1295 }
1261 1296
1297 public float Buoyancy
1298 {
1299 get { return m_buoyancy; }
1300 set
1301 {
1302 m_buoyancy = value;
1303 if (PhysActor != null)
1304 {
1305 PhysActor.Buoyancy = value;
1306 }
1307 }
1308 }
1309
1262 #endregion Public Properties with only Get 1310 #endregion Public Properties with only Get
1263 1311
1264 private uint ApplyMask(uint val, bool set, uint mask) 1312 private uint ApplyMask(uint val, bool set, uint mask)
@@ -1583,6 +1631,9 @@ namespace OpenSim.Region.Framework.Scenes
1583 1631
1584 // Move afterwards ResetIDs as it clears the localID 1632 // Move afterwards ResetIDs as it clears the localID
1585 dupe.LocalId = localID; 1633 dupe.LocalId = localID;
1634 if(dupe.PhysActor != null)
1635 dupe.PhysActor.LocalID = localID;
1636
1586 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated. 1637 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated.
1587 dupe.LastOwnerID = OwnerID; 1638 dupe.LastOwnerID = OwnerID;
1588 1639
@@ -2588,17 +2639,18 @@ namespace OpenSim.Region.Framework.Scenes
2588 //Trys to fetch sound id from prim's inventory. 2639 //Trys to fetch sound id from prim's inventory.
2589 //Prim's inventory doesn't support non script items yet 2640 //Prim's inventory doesn't support non script items yet
2590 2641
2591 lock (TaskInventory) 2642 TaskInventory.LockItemsForRead(true);
2643
2644 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2592 { 2645 {
2593 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 2646 if (item.Value.Name == sound)
2594 { 2647 {
2595 if (item.Value.Name == sound) 2648 soundID = item.Value.ItemID;
2596 { 2649 break;
2597 soundID = item.Value.ItemID;
2598 break;
2599 }
2600 } 2650 }
2601 } 2651 }
2652
2653 TaskInventory.LockItemsForRead(false);
2602 } 2654 }
2603 2655
2604 ParentGroup.Scene.ForEachRootScenePresence(delegate(ScenePresence sp) 2656 ParentGroup.Scene.ForEachRootScenePresence(delegate(ScenePresence sp)
@@ -2918,8 +2970,8 @@ namespace OpenSim.Region.Framework.Scenes
2918 { 2970 {
2919 const float ROTATION_TOLERANCE = 0.01f; 2971 const float ROTATION_TOLERANCE = 0.01f;
2920 const float VELOCITY_TOLERANCE = 0.001f; 2972 const float VELOCITY_TOLERANCE = 0.001f;
2921 const float POSITION_TOLERANCE = 0.05f; 2973 const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary
2922 const int TIME_MS_TOLERANCE = 3000; 2974 const int TIME_MS_TOLERANCE = 200; //llSetPos has a 200ms delay. This should NOT be 3 seconds.
2923 2975
2924 switch (UpdateFlag) 2976 switch (UpdateFlag)
2925 { 2977 {
@@ -2981,17 +3033,16 @@ namespace OpenSim.Region.Framework.Scenes
2981 if (!UUID.TryParse(sound, out soundID)) 3033 if (!UUID.TryParse(sound, out soundID))
2982 { 3034 {
2983 // search sound file from inventory 3035 // search sound file from inventory
2984 lock (TaskInventory) 3036 TaskInventory.LockItemsForRead(true);
3037 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2985 { 3038 {
2986 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 3039 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound)
2987 { 3040 {
2988 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound) 3041 soundID = item.Value.ItemID;
2989 { 3042 break;
2990 soundID = item.Value.ItemID;
2991 break;
2992 }
2993 } 3043 }
2994 } 3044 }
3045 TaskInventory.LockItemsForRead(false);
2995 } 3046 }
2996 3047
2997 if (soundID == UUID.Zero) 3048 if (soundID == UUID.Zero)
@@ -3458,10 +3509,10 @@ namespace OpenSim.Region.Framework.Scenes
3458 // TODO: May need to fix for group comparison 3509 // TODO: May need to fix for group comparison
3459 if (last.Compare(this)) 3510 if (last.Compare(this))
3460 { 3511 {
3461 // m_log.DebugFormat( 3512 // m_log.DebugFormat(
3462 // "[SCENE OBJECT PART]: Not storing undo for {0} {1} since current state is same as last undo state, initial stack size {2}", 3513 // "[SCENE OBJECT PART]: Not storing undo for {0} {1} since current state is same as last undo state, initial stack size {2}",
3463 // Name, LocalId, m_undo.Count); 3514 // Name, LocalId, m_undo.Count);
3464 3515
3465 return; 3516 return;
3466 } 3517 }
3467 } 3518 }
@@ -3474,29 +3525,29 @@ namespace OpenSim.Region.Framework.Scenes
3474 if (ParentGroup.GetSceneMaxUndo() > 0) 3525 if (ParentGroup.GetSceneMaxUndo() > 0)
3475 { 3526 {
3476 UndoState nUndo = new UndoState(this, forGroup); 3527 UndoState nUndo = new UndoState(this, forGroup);
3477 3528
3478 m_undo.Push(nUndo); 3529 m_undo.Push(nUndo);
3479 3530
3480 if (m_redo.Count > 0) 3531 if (m_redo.Count > 0)
3481 m_redo.Clear(); 3532 m_redo.Clear();
3482 3533
3483 // m_log.DebugFormat( 3534 // m_log.DebugFormat(
3484 // "[SCENE OBJECT PART]: Stored undo state for {0} {1}, forGroup {2}, stack size now {3}", 3535 // "[SCENE OBJECT PART]: Stored undo state for {0} {1}, forGroup {2}, stack size now {3}",
3485 // Name, LocalId, forGroup, m_undo.Count); 3536 // Name, LocalId, forGroup, m_undo.Count);
3486 } 3537 }
3487 } 3538 }
3488 } 3539 }
3489 } 3540 }
3490// else 3541 // else
3491// { 3542 // {
3492// m_log.DebugFormat("[SCENE OBJECT PART]: Ignoring undo store for {0} {1}", Name, LocalId); 3543 // m_log.DebugFormat("[SCENE OBJECT PART]: Ignoring undo store for {0} {1}", Name, LocalId);
3493// } 3544 // }
3494 } 3545 }
3495// else 3546 // else
3496// { 3547 // {
3497// m_log.DebugFormat( 3548 // m_log.DebugFormat(
3498// "[SCENE OBJECT PART]: Ignoring undo store for {0} {1} since already undoing", Name, LocalId); 3549 // "[SCENE OBJECT PART]: Ignoring undo store for {0} {1} since already undoing", Name, LocalId);
3499// } 3550 // }
3500 } 3551 }
3501 3552
3502 /// <summary> 3553 /// <summary>
@@ -4227,6 +4278,9 @@ namespace OpenSim.Region.Framework.Scenes
4227 bool wasPhantom = ((Flags & PrimFlags.Phantom) != 0); 4278 bool wasPhantom = ((Flags & PrimFlags.Phantom) != 0);
4228 bool wasVD = VolumeDetectActive; 4279 bool wasVD = VolumeDetectActive;
4229 4280
4281// m_log.DebugFormat("[SOP]: Old states: phys: {0} temp: {1} phan: {2} vd: {3}", wasUsingPhysics, wasTemporary, wasPhantom, wasVD);
4282// m_log.DebugFormat("[SOP]: New states: phys: {0} temp: {1} phan: {2} vd: {3}", UsePhysics, SetTemporary, SetPhantom, SetVD);
4283
4230 if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD)) 4284 if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD))
4231 return; 4285 return;
4232 4286
@@ -4256,6 +4310,11 @@ namespace OpenSim.Region.Framework.Scenes
4256 SetPhantom = false; 4310 SetPhantom = false;
4257 } 4311 }
4258 } 4312 }
4313 else if (wasVD)
4314 {
4315 // Correspondingly, if VD is turned off, also turn off phantom
4316 SetPhantom = false;
4317 }
4259 4318
4260 if (UsePhysics && IsJoint()) 4319 if (UsePhysics && IsJoint())
4261 { 4320 {
@@ -4754,5 +4813,17 @@ namespace OpenSim.Region.Framework.Scenes
4754 Color color = Color; 4813 Color color = Color;
4755 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A)); 4814 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A));
4756 } 4815 }
4816
4817 public void ResetOwnerChangeFlag()
4818 {
4819 List<UUID> inv = Inventory.GetInventoryList();
4820
4821 foreach (UUID itemID in inv)
4822 {
4823 TaskInventoryItem item = Inventory.GetInventoryItem(itemID);
4824 item.OwnerChanged = false;
4825 Inventory.UpdateInventoryItem(item, false, false);
4826 }
4827 }
4757 } 4828 }
4758} 4829}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index 0c36dcd..dc64281 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
@@ -48,6 +48,9 @@ namespace OpenSim.Region.Framework.Scenes
48 private string m_inventoryFileName = String.Empty; 48 private string m_inventoryFileName = String.Empty;
49 private byte[] m_inventoryFileData = new byte[0]; 49 private byte[] m_inventoryFileData = new byte[0];
50 private uint m_inventoryFileNameSerial = 0; 50 private uint m_inventoryFileNameSerial = 0;
51 private bool m_inventoryPrivileged = false;
52
53 private Dictionary<UUID, ArrayList> m_scriptErrors = new Dictionary<UUID, ArrayList>();
51 54
52 /// <value> 55 /// <value>
53 /// The part to which the inventory belongs. 56 /// The part to which the inventory belongs.
@@ -84,11 +87,14 @@ namespace OpenSim.Region.Framework.Scenes
84 /// </value> 87 /// </value>
85 protected internal TaskInventoryDictionary Items 88 protected internal TaskInventoryDictionary Items
86 { 89 {
87 get { return m_items; } 90 get {
91 return m_items;
92 }
88 set 93 set
89 { 94 {
90 m_items = value; 95 m_items = value;
91 m_inventorySerial++; 96 m_inventorySerial++;
97 QueryScriptStates();
92 } 98 }
93 } 99 }
94 100
@@ -123,38 +129,45 @@ namespace OpenSim.Region.Framework.Scenes
123 public void ResetInventoryIDs() 129 public void ResetInventoryIDs()
124 { 130 {
125 if (null == m_part) 131 if (null == m_part)
126 return; 132 m_items.LockItemsForWrite(true);
127 133
128 lock (m_items) 134 if (Items.Count == 0)
129 { 135 {
130 if (0 == m_items.Count) 136 m_items.LockItemsForWrite(false);
131 return; 137 return;
138 }
132 139
133 IList<TaskInventoryItem> items = GetInventoryItems(); 140 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
134 m_items.Clear(); 141 Items.Clear();
135 142
136 foreach (TaskInventoryItem item in items) 143 foreach (TaskInventoryItem item in items)
137 { 144 {
138 item.ResetIDs(m_part.UUID); 145 item.ResetIDs(m_part.UUID);
139 m_items.Add(item.ItemID, item); 146 Items.Add(item.ItemID, item);
140 }
141 } 147 }
148 m_items.LockItemsForWrite(false);
142 } 149 }
143 150
144 public void ResetObjectID() 151 public void ResetObjectID()
145 { 152 {
146 lock (Items) 153 m_items.LockItemsForWrite(true);
154
155 if (Items.Count == 0)
147 { 156 {
148 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values); 157 m_items.LockItemsForWrite(false);
149 Items.Clear(); 158 return;
150
151 foreach (TaskInventoryItem item in items)
152 {
153 item.ParentPartID = m_part.UUID;
154 item.ParentID = m_part.UUID;
155 Items.Add(item.ItemID, item);
156 }
157 } 159 }
160
161 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
162 Items.Clear();
163
164 foreach (TaskInventoryItem item in items)
165 {
166 item.ParentPartID = m_part.UUID;
167 item.ParentID = m_part.UUID;
168 Items.Add(item.ItemID, item);
169 }
170 m_items.LockItemsForWrite(false);
158 } 171 }
159 172
160 /// <summary> 173 /// <summary>
@@ -163,12 +176,11 @@ namespace OpenSim.Region.Framework.Scenes
163 /// <param name="ownerId"></param> 176 /// <param name="ownerId"></param>
164 public void ChangeInventoryOwner(UUID ownerId) 177 public void ChangeInventoryOwner(UUID ownerId)
165 { 178 {
166 lock (Items) 179 m_items.LockItemsForWrite(true);
180 if (0 == Items.Count)
167 { 181 {
168 if (0 == Items.Count) 182 m_items.LockItemsForWrite(false);
169 { 183 return;
170 return;
171 }
172 } 184 }
173 185
174 HasInventoryChanged = true; 186 HasInventoryChanged = true;
@@ -184,6 +196,7 @@ namespace OpenSim.Region.Framework.Scenes
184 item.PermsGranter = UUID.Zero; 196 item.PermsGranter = UUID.Zero;
185 item.OwnerChanged = true; 197 item.OwnerChanged = true;
186 } 198 }
199 m_items.LockItemsForWrite(false);
187 } 200 }
188 201
189 /// <summary> 202 /// <summary>
@@ -192,12 +205,11 @@ namespace OpenSim.Region.Framework.Scenes
192 /// <param name="groupID"></param> 205 /// <param name="groupID"></param>
193 public void ChangeInventoryGroup(UUID groupID) 206 public void ChangeInventoryGroup(UUID groupID)
194 { 207 {
195 lock (Items) 208 m_items.LockItemsForWrite(true);
209 if (0 == Items.Count)
196 { 210 {
197 if (0 == Items.Count) 211 m_items.LockItemsForWrite(false);
198 { 212 return;
199 return;
200 }
201 } 213 }
202 214
203 // Don't let this set the HasGroupChanged flag for attachments 215 // Don't let this set the HasGroupChanged flag for attachments
@@ -209,12 +221,45 @@ namespace OpenSim.Region.Framework.Scenes
209 m_part.ParentGroup.HasGroupChanged = true; 221 m_part.ParentGroup.HasGroupChanged = true;
210 } 222 }
211 223
212 List<TaskInventoryItem> items = GetInventoryItems(); 224 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
213 foreach (TaskInventoryItem item in items) 225 foreach (TaskInventoryItem item in items)
214 { 226 {
215 if (groupID != item.GroupID) 227 if (groupID != item.GroupID)
228 {
216 item.GroupID = groupID; 229 item.GroupID = groupID;
230 }
231 }
232 m_items.LockItemsForWrite(false);
233 }
234
235 private void QueryScriptStates()
236 {
237 if (m_part == null || m_part.ParentGroup == null)
238 return;
239
240 IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>();
241 if (engines == null) // No engine at all
242 return;
243
244 Items.LockItemsForRead(true);
245 foreach (TaskInventoryItem item in Items.Values)
246 {
247 if (item.InvType == (int)InventoryType.LSL)
248 {
249 foreach (IScriptModule e in engines)
250 {
251 bool running;
252
253 if (e.HasScript(item.ItemID, out running))
254 {
255 item.ScriptRunning = running;
256 break;
257 }
258 }
259 }
217 } 260 }
261
262 Items.LockItemsForRead(false);
218 } 263 }
219 264
220 /// <summary> 265 /// <summary>
@@ -222,9 +267,14 @@ namespace OpenSim.Region.Framework.Scenes
222 /// </summary> 267 /// </summary>
223 public void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource) 268 public void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource)
224 { 269 {
225 List<TaskInventoryItem> scripts = GetInventoryScripts(); 270 Items.LockItemsForRead(true);
226 foreach (TaskInventoryItem item in scripts) 271 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
227 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource); 272 Items.LockItemsForRead(false);
273 foreach (TaskInventoryItem item in items)
274 {
275 if ((int)InventoryType.LSL == item.InvType)
276 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource);
277 }
228 } 278 }
229 279
230 public ArrayList GetScriptErrors(UUID itemID) 280 public ArrayList GetScriptErrors(UUID itemID)
@@ -255,9 +305,18 @@ namespace OpenSim.Region.Framework.Scenes
255 /// </param> 305 /// </param>
256 public void RemoveScriptInstances(bool sceneObjectBeingDeleted) 306 public void RemoveScriptInstances(bool sceneObjectBeingDeleted)
257 { 307 {
258 List<TaskInventoryItem> scripts = GetInventoryScripts(); 308 Items.LockItemsForRead(true);
259 foreach (TaskInventoryItem item in scripts) 309 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
260 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted); 310 Items.LockItemsForRead(false);
311
312 foreach (TaskInventoryItem item in items)
313 {
314 if ((int)InventoryType.LSL == item.InvType)
315 {
316 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted);
317 m_part.RemoveScriptEvents(item.ItemID);
318 }
319 }
261 } 320 }
262 321
263 /// <summary> 322 /// <summary>
@@ -273,7 +332,10 @@ namespace OpenSim.Region.Framework.Scenes
273 // item.Name, item.ItemID, Name, UUID); 332 // item.Name, item.ItemID, Name, UUID);
274 333
275 if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID)) 334 if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID))
335 {
336 StoreScriptError(item.ItemID, "no permission");
276 return; 337 return;
338 }
277 339
278 m_part.AddFlag(PrimFlags.Scripted); 340 m_part.AddFlag(PrimFlags.Scripted);
279 341
@@ -282,14 +344,13 @@ namespace OpenSim.Region.Framework.Scenes
282 if (stateSource == 2 && // Prim crossing 344 if (stateSource == 2 && // Prim crossing
283 m_part.ParentGroup.Scene.m_trustBinaries) 345 m_part.ParentGroup.Scene.m_trustBinaries)
284 { 346 {
285 lock (m_items) 347 m_items.LockItemsForWrite(true);
286 { 348 m_items[item.ItemID].PermsMask = 0;
287 m_items[item.ItemID].PermsMask = 0; 349 m_items[item.ItemID].PermsGranter = UUID.Zero;
288 m_items[item.ItemID].PermsGranter = UUID.Zero; 350 m_items.LockItemsForWrite(false);
289 }
290
291 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 351 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
292 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource); 352 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource);
353 StoreScriptErrors(item.ItemID, null);
293 m_part.ParentGroup.AddActiveScriptCount(1); 354 m_part.ParentGroup.AddActiveScriptCount(1);
294 m_part.ScheduleFullUpdate(); 355 m_part.ScheduleFullUpdate();
295 return; 356 return;
@@ -298,6 +359,8 @@ namespace OpenSim.Region.Framework.Scenes
298 AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString()); 359 AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString());
299 if (null == asset) 360 if (null == asset)
300 { 361 {
362 string msg = String.Format("asset ID {0} could not be found", item.AssetID);
363 StoreScriptError(item.ItemID, msg);
301 m_log.ErrorFormat( 364 m_log.ErrorFormat(
302 "[PRIM INVENTORY]: " + 365 "[PRIM INVENTORY]: " +
303 "Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found", 366 "Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found",
@@ -309,16 +372,21 @@ namespace OpenSim.Region.Framework.Scenes
309 if (m_part.ParentGroup.m_savedScriptState != null) 372 if (m_part.ParentGroup.m_savedScriptState != null)
310 item.OldItemID = RestoreSavedScriptState(item.LoadedItemID, item.OldItemID, item.ItemID); 373 item.OldItemID = RestoreSavedScriptState(item.LoadedItemID, item.OldItemID, item.ItemID);
311 374
312 lock (m_items) 375 m_items.LockItemsForWrite(true);
313 { 376
314 m_items[item.ItemID].OldItemID = item.OldItemID; 377 m_items[item.ItemID].OldItemID = item.OldItemID;
315 m_items[item.ItemID].PermsMask = 0; 378 m_items[item.ItemID].PermsMask = 0;
316 m_items[item.ItemID].PermsGranter = UUID.Zero; 379 m_items[item.ItemID].PermsGranter = UUID.Zero;
317 }
318 380
381 m_items.LockItemsForWrite(false);
382
319 string script = Utils.BytesToString(asset.Data); 383 string script = Utils.BytesToString(asset.Data);
320 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 384 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
321 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource); 385 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource);
386 StoreScriptErrors(item.ItemID, null);
387 if (!item.ScriptRunning)
388 m_part.ParentGroup.Scene.EventManager.TriggerStopScript(
389 m_part.LocalId, item.ItemID);
322 m_part.ParentGroup.AddActiveScriptCount(1); 390 m_part.ParentGroup.AddActiveScriptCount(1);
323 m_part.ScheduleFullUpdate(); 391 m_part.ScheduleFullUpdate();
324 } 392 }
@@ -389,21 +457,145 @@ namespace OpenSim.Region.Framework.Scenes
389 457
390 /// <summary> 458 /// <summary>
391 /// Start a script which is in this prim's inventory. 459 /// Start a script which is in this prim's inventory.
460 /// Some processing may occur in the background, but this routine returns asap.
392 /// </summary> 461 /// </summary>
393 /// <param name="itemId"> 462 /// <param name="itemId">
394 /// A <see cref="UUID"/> 463 /// A <see cref="UUID"/>
395 /// </param> 464 /// </param>
396 public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource) 465 public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
397 { 466 {
398 TaskInventoryItem item = GetInventoryItem(itemId); 467 lock (m_scriptErrors)
399 if (item != null) 468 {
400 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource); 469 // Indicate to CreateScriptInstanceInternal() we don't want it to wait for completion
470 m_scriptErrors.Remove(itemId);
471 }
472 CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
473 }
474
475 private void CreateScriptInstanceInternal(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
476 {
477 m_items.LockItemsForRead(true);
478 if (m_items.ContainsKey(itemId))
479 {
480 if (m_items.ContainsKey(itemId))
481 {
482 m_items.LockItemsForRead(false);
483 CreateScriptInstance(m_items[itemId], startParam, postOnRez, engine, stateSource);
484 }
485 else
486 {
487 m_items.LockItemsForRead(false);
488 string msg = String.Format("couldn't be found for prim {0}, {1} at {2} in {3}", m_part.Name, m_part.UUID,
489 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
490 StoreScriptError(itemId, msg);
491 m_log.ErrorFormat(
492 "[PRIM INVENTORY]: " +
493 "Couldn't start script with ID {0} since it {1}", itemId, msg);
494 }
495 }
401 else 496 else
497 {
498 m_items.LockItemsForRead(false);
499 string msg = String.Format("couldn't be found for prim {0}, {1}", m_part.Name, m_part.UUID);
500 StoreScriptError(itemId, msg);
402 m_log.ErrorFormat( 501 m_log.ErrorFormat(
403 "[PRIM INVENTORY]: " + 502 "[PRIM INVENTORY]: " +
404 "Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}", 503 "Couldn't start script with ID {0} since it {1}", itemId, msg);
405 itemId, m_part.Name, m_part.UUID, 504 }
406 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 505
506 }
507
508 /// <summary>
509 /// Start a script which is in this prim's inventory and return any compilation error messages.
510 /// </summary>
511 /// <param name="itemId">
512 /// A <see cref="UUID"/>
513 /// </param>
514 public ArrayList CreateScriptInstanceEr(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
515 {
516 ArrayList errors;
517
518 // Indicate to CreateScriptInstanceInternal() we want it to
519 // post any compilation/loading error messages
520 lock (m_scriptErrors)
521 {
522 m_scriptErrors[itemId] = null;
523 }
524
525 // Perform compilation/loading
526 CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
527
528 // Wait for and retrieve any errors
529 lock (m_scriptErrors)
530 {
531 while ((errors = m_scriptErrors[itemId]) == null)
532 {
533 if (!System.Threading.Monitor.Wait(m_scriptErrors, 15000))
534 {
535 m_log.ErrorFormat(
536 "[PRIM INVENTORY]: " +
537 "timedout waiting for script {0} errors", itemId);
538 errors = m_scriptErrors[itemId];
539 if (errors == null)
540 {
541 errors = new ArrayList(1);
542 errors.Add("timedout waiting for errors");
543 }
544 break;
545 }
546 }
547 m_scriptErrors.Remove(itemId);
548 }
549 return errors;
550 }
551
552 // Signal to CreateScriptInstanceEr() that compilation/loading is complete
553 private void StoreScriptErrors(UUID itemId, ArrayList errors)
554 {
555 lock (m_scriptErrors)
556 {
557 // If compilation/loading initiated via CreateScriptInstance(),
558 // it does not want the errors, so just get out
559 if (!m_scriptErrors.ContainsKey(itemId))
560 {
561 return;
562 }
563
564 // Initiated via CreateScriptInstanceEr(), if we know what the
565 // errors are, save them and wake CreateScriptInstanceEr().
566 if (errors != null)
567 {
568 m_scriptErrors[itemId] = errors;
569 System.Threading.Monitor.PulseAll(m_scriptErrors);
570 return;
571 }
572 }
573
574 // Initiated via CreateScriptInstanceEr() but we don't know what
575 // the errors are yet, so retrieve them from the script engine.
576 // This may involve some waiting internal to GetScriptErrors().
577 errors = GetScriptErrors(itemId);
578
579 // Get a default non-null value to indicate success.
580 if (errors == null)
581 {
582 errors = new ArrayList();
583 }
584
585 // Post to CreateScriptInstanceEr() and wake it up
586 lock (m_scriptErrors)
587 {
588 m_scriptErrors[itemId] = errors;
589 System.Threading.Monitor.PulseAll(m_scriptErrors);
590 }
591 }
592
593 // Like StoreScriptErrors(), but just posts a single string message
594 private void StoreScriptError(UUID itemId, string message)
595 {
596 ArrayList errors = new ArrayList(1);
597 errors.Add(message);
598 StoreScriptErrors(itemId, errors);
407 } 599 }
408 600
409 /// <summary> 601 /// <summary>
@@ -416,15 +608,7 @@ namespace OpenSim.Region.Framework.Scenes
416 /// </param> 608 /// </param>
417 public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted) 609 public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted)
418 { 610 {
419 bool scriptPresent = false; 611 if (m_items.ContainsKey(itemId))
420
421 lock (m_items)
422 {
423 if (m_items.ContainsKey(itemId))
424 scriptPresent = true;
425 }
426
427 if (scriptPresent)
428 { 612 {
429 if (!sceneObjectBeingDeleted) 613 if (!sceneObjectBeingDeleted)
430 m_part.RemoveScriptEvents(itemId); 614 m_part.RemoveScriptEvents(itemId);
@@ -449,14 +633,16 @@ namespace OpenSim.Region.Framework.Scenes
449 /// <returns></returns> 633 /// <returns></returns>
450 private bool InventoryContainsName(string name) 634 private bool InventoryContainsName(string name)
451 { 635 {
452 lock (m_items) 636 m_items.LockItemsForRead(true);
637 foreach (TaskInventoryItem item in m_items.Values)
453 { 638 {
454 foreach (TaskInventoryItem item in m_items.Values) 639 if (item.Name == name)
455 { 640 {
456 if (item.Name == name) 641 m_items.LockItemsForRead(false);
457 return true; 642 return true;
458 } 643 }
459 } 644 }
645 m_items.LockItemsForRead(false);
460 return false; 646 return false;
461 } 647 }
462 648
@@ -498,8 +684,9 @@ namespace OpenSim.Region.Framework.Scenes
498 /// <param name="item"></param> 684 /// <param name="item"></param>
499 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop) 685 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop)
500 { 686 {
501 List<TaskInventoryItem> il = GetInventoryItems(); 687 m_items.LockItemsForRead(true);
502 688 List<TaskInventoryItem> il = new List<TaskInventoryItem>(m_items.Values);
689 m_items.LockItemsForRead(false);
503 foreach (TaskInventoryItem i in il) 690 foreach (TaskInventoryItem i in il)
504 { 691 {
505 if (i.Name == item.Name) 692 if (i.Name == item.Name)
@@ -537,14 +724,14 @@ namespace OpenSim.Region.Framework.Scenes
537 item.Name = name; 724 item.Name = name;
538 item.GroupID = m_part.GroupID; 725 item.GroupID = m_part.GroupID;
539 726
540 lock (m_items) 727 m_items.LockItemsForWrite(true);
541 m_items.Add(item.ItemID, item); 728 m_items.Add(item.ItemID, item);
542 729 m_items.LockItemsForWrite(false);
543 if (allowedDrop) 730 if (allowedDrop)
544 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP); 731 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP);
545 else 732 else
546 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 733 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
547 734
548 m_inventorySerial++; 735 m_inventorySerial++;
549 //m_inventorySerial += 2; 736 //m_inventorySerial += 2;
550 HasInventoryChanged = true; 737 HasInventoryChanged = true;
@@ -560,15 +747,15 @@ namespace OpenSim.Region.Framework.Scenes
560 /// <param name="items"></param> 747 /// <param name="items"></param>
561 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items) 748 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items)
562 { 749 {
563 lock (m_items) 750 m_items.LockItemsForWrite(true);
751 foreach (TaskInventoryItem item in items)
564 { 752 {
565 foreach (TaskInventoryItem item in items) 753 m_items.Add(item.ItemID, item);
566 { 754// m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
567 m_items.Add(item.ItemID, item);
568// m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
569 }
570 m_inventorySerial++;
571 } 755 }
756 m_items.LockItemsForWrite(false);
757
758 m_inventorySerial++;
572 } 759 }
573 760
574 /// <summary> 761 /// <summary>
@@ -579,10 +766,9 @@ namespace OpenSim.Region.Framework.Scenes
579 public TaskInventoryItem GetInventoryItem(UUID itemId) 766 public TaskInventoryItem GetInventoryItem(UUID itemId)
580 { 767 {
581 TaskInventoryItem item; 768 TaskInventoryItem item;
582 769 m_items.LockItemsForRead(true);
583 lock (m_items) 770 m_items.TryGetValue(itemId, out item);
584 m_items.TryGetValue(itemId, out item); 771 m_items.LockItemsForRead(false);
585
586 return item; 772 return item;
587 } 773 }
588 774
@@ -598,15 +784,16 @@ namespace OpenSim.Region.Framework.Scenes
598 { 784 {
599 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(); 785 IList<TaskInventoryItem> items = new List<TaskInventoryItem>();
600 786
601 lock (m_items) 787 m_items.LockItemsForRead(true);
788
789 foreach (TaskInventoryItem item in m_items.Values)
602 { 790 {
603 foreach (TaskInventoryItem item in m_items.Values) 791 if (item.Name == name)
604 { 792 items.Add(item);
605 if (item.Name == name)
606 items.Add(item);
607 }
608 } 793 }
609 794
795 m_items.LockItemsForRead(false);
796
610 return items; 797 return items;
611 } 798 }
612 799
@@ -625,6 +812,9 @@ namespace OpenSim.Region.Framework.Scenes
625 string xmlData = Utils.BytesToString(rezAsset.Data); 812 string xmlData = Utils.BytesToString(rezAsset.Data);
626 SceneObjectGroup group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); 813 SceneObjectGroup group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
627 814
815 group.RootPart.AttachPoint = group.RootPart.Shape.State;
816 group.RootPart.AttachOffset = group.AbsolutePosition;
817
628 group.ResetIDs(); 818 group.ResetIDs();
629 819
630 SceneObjectPart rootPart = group.GetChildPart(group.UUID); 820 SceneObjectPart rootPart = group.GetChildPart(group.UUID);
@@ -699,8 +889,9 @@ namespace OpenSim.Region.Framework.Scenes
699 889
700 public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged) 890 public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged)
701 { 891 {
702 TaskInventoryItem it = GetInventoryItem(item.ItemID); 892 m_items.LockItemsForWrite(true);
703 if (it != null) 893
894 if (m_items.ContainsKey(item.ItemID))
704 { 895 {
705// m_log.DebugFormat("[PRIM INVENTORY]: Updating item {0} in {1}", item.Name, m_part.Name); 896// m_log.DebugFormat("[PRIM INVENTORY]: Updating item {0} in {1}", item.Name, m_part.Name);
706 897
@@ -713,14 +904,10 @@ namespace OpenSim.Region.Framework.Scenes
713 item.GroupID = m_part.GroupID; 904 item.GroupID = m_part.GroupID;
714 905
715 if (item.AssetID == UUID.Zero) 906 if (item.AssetID == UUID.Zero)
716 item.AssetID = it.AssetID; 907 item.AssetID = m_items[item.ItemID].AssetID;
717 908
718 lock (m_items) 909 m_items[item.ItemID] = item;
719 { 910 m_inventorySerial++;
720 m_items[item.ItemID] = item;
721 m_inventorySerial++;
722 }
723
724 if (fireScriptEvents) 911 if (fireScriptEvents)
725 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 912 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
726 913
@@ -729,7 +916,7 @@ namespace OpenSim.Region.Framework.Scenes
729 HasInventoryChanged = true; 916 HasInventoryChanged = true;
730 m_part.ParentGroup.HasGroupChanged = true; 917 m_part.ParentGroup.HasGroupChanged = true;
731 } 918 }
732 919 m_items.LockItemsForWrite(false);
733 return true; 920 return true;
734 } 921 }
735 else 922 else
@@ -740,8 +927,9 @@ namespace OpenSim.Region.Framework.Scenes
740 item.ItemID, m_part.Name, m_part.UUID, 927 item.ItemID, m_part.Name, m_part.UUID,
741 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 928 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
742 } 929 }
743 return false; 930 m_items.LockItemsForWrite(false);
744 931
932 return false;
745 } 933 }
746 934
747 /// <summary> 935 /// <summary>
@@ -752,43 +940,59 @@ namespace OpenSim.Region.Framework.Scenes
752 /// in this prim's inventory.</returns> 940 /// in this prim's inventory.</returns>
753 public int RemoveInventoryItem(UUID itemID) 941 public int RemoveInventoryItem(UUID itemID)
754 { 942 {
755 TaskInventoryItem item = GetInventoryItem(itemID); 943 m_items.LockItemsForRead(true);
756 if (item != null) 944
945 if (m_items.ContainsKey(itemID))
757 { 946 {
758 int type = m_items[itemID].InvType; 947 int type = m_items[itemID].InvType;
948 m_items.LockItemsForRead(false);
759 if (type == 10) // Script 949 if (type == 10) // Script
760 { 950 {
761 m_part.RemoveScriptEvents(itemID);
762 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID); 951 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID);
763 } 952 }
953 m_items.LockItemsForWrite(true);
764 m_items.Remove(itemID); 954 m_items.Remove(itemID);
955 m_items.LockItemsForWrite(false);
765 m_inventorySerial++; 956 m_inventorySerial++;
766 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 957 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
767 958
768 HasInventoryChanged = true; 959 HasInventoryChanged = true;
769 m_part.ParentGroup.HasGroupChanged = true; 960 m_part.ParentGroup.HasGroupChanged = true;
770 961
771 if (!ContainsScripts()) 962 int scriptcount = 0;
963 m_items.LockItemsForRead(true);
964 foreach (TaskInventoryItem item in m_items.Values)
965 {
966 if (item.Type == 10)
967 {
968 scriptcount++;
969 }
970 }
971 m_items.LockItemsForRead(false);
972
973
974 if (scriptcount <= 0)
975 {
772 m_part.RemFlag(PrimFlags.Scripted); 976 m_part.RemFlag(PrimFlags.Scripted);
977 }
773 978
774 m_part.ScheduleFullUpdate(); 979 m_part.ScheduleFullUpdate();
775 980
776 return type; 981 return type;
777
778 } 982 }
779 else 983 else
780 { 984 {
985 m_items.LockItemsForRead(false);
781 m_log.ErrorFormat( 986 m_log.ErrorFormat(
782 "[PRIM INVENTORY]: " + 987 "[PRIM INVENTORY]: " +
783 "Tried to remove item ID {0} from prim {1}, {2} at {3} in {4} but the item does not exist in this inventory", 988 "Tried to remove item ID {0} from prim {1}, {2} but the item does not exist in this inventory",
784 itemID, m_part.Name, m_part.UUID, 989 itemID, m_part.Name, m_part.UUID);
785 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
786 } 990 }
787 991
788 return -1; 992 return -1;
789 } 993 }
790 994
791 private bool CreateInventoryFile() 995 private bool CreateInventoryFileName()
792 { 996 {
793// m_log.DebugFormat( 997// m_log.DebugFormat(
794// "[PRIM INVENTORY]: Creating inventory file for {0} {1} {2}, serial {3}", 998// "[PRIM INVENTORY]: Creating inventory file for {0} {1} {2}, serial {3}",
@@ -797,116 +1001,125 @@ namespace OpenSim.Region.Framework.Scenes
797 if (m_inventoryFileName == String.Empty || 1001 if (m_inventoryFileName == String.Empty ||
798 m_inventoryFileNameSerial < m_inventorySerial) 1002 m_inventoryFileNameSerial < m_inventorySerial)
799 { 1003 {
800 // Something changed, we need to create a new file
801 m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp"; 1004 m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp";
802 m_inventoryFileNameSerial = m_inventorySerial; 1005 m_inventoryFileNameSerial = m_inventorySerial;
803 1006
804 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero); 1007 return true;
1008 }
1009
1010 return false;
1011 }
1012
1013 /// <summary>
1014 /// Serialize all the metadata for the items in this prim's inventory ready for sending to the client
1015 /// </summary>
1016 /// <param name="xferManager"></param>
1017 public void RequestInventoryFile(IClientAPI client, IXfer xferManager)
1018 {
1019 bool changed = CreateInventoryFileName();
1020
1021 bool includeAssets = false;
1022 if (m_part.ParentGroup.Scene.Permissions.CanEditObjectInventory(m_part.UUID, client.AgentId))
1023 includeAssets = true;
1024
1025 if (m_inventoryPrivileged != includeAssets)
1026 changed = true;
1027
1028 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero);
1029
1030 Items.LockItemsForRead(true);
1031
1032 if (m_inventorySerial == 0) // No inventory
1033 {
1034 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
1035 Items.LockItemsForRead(false);
1036 return;
1037 }
805 1038
806 lock (m_items) 1039 if (m_items.Count == 0) // No inventory
1040 {
1041 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
1042 Items.LockItemsForRead(false);
1043 return;
1044 }
1045
1046 if (!changed)
1047 {
1048 if (m_inventoryFileData.Length > 2)
807 { 1049 {
808 foreach (TaskInventoryItem item in m_items.Values) 1050 xferManager.AddNewFile(m_inventoryFileName,
809 { 1051 m_inventoryFileData);
810// m_log.DebugFormat( 1052 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
811// "[PRIM INVENTORY]: Adding item {0} {1} for serial {2} on prim {3} {4} {5}", 1053 Util.StringToBytes256(m_inventoryFileName));
812// item.Name, item.ItemID, m_inventorySerial, m_part.Name, m_part.UUID, m_part.LocalId);
813 1054
814 UUID ownerID = item.OwnerID; 1055 Items.LockItemsForRead(false);
815 uint everyoneMask = 0; 1056 return;
816 uint baseMask = item.BasePermissions; 1057 }
817 uint ownerMask = item.CurrentPermissions; 1058 }
818 uint groupMask = item.GroupPermissions;
819 1059
820 invString.AddItemStart(); 1060 m_inventoryPrivileged = includeAssets;
821 invString.AddNameValueLine("item_id", item.ItemID.ToString());
822 invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
823 1061
824 invString.AddPermissionsStart(); 1062 foreach (TaskInventoryItem item in m_items.Values)
1063 {
1064 UUID ownerID = item.OwnerID;
1065 uint everyoneMask = 0;
1066 uint baseMask = item.BasePermissions;
1067 uint ownerMask = item.CurrentPermissions;
1068 uint groupMask = item.GroupPermissions;
825 1069
826 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask)); 1070 invString.AddItemStart();
827 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask)); 1071 invString.AddNameValueLine("item_id", item.ItemID.ToString());
828 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask)); 1072 invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
829 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask));
830 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
831 1073
832 invString.AddNameValueLine("creator_id", item.CreatorID.ToString()); 1074 invString.AddPermissionsStart();
833 invString.AddNameValueLine("owner_id", ownerID.ToString());
834 1075
835 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString()); 1076 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask));
1077 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask));
1078 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask));
1079 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask));
1080 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
836 1081
837 invString.AddNameValueLine("group_id", item.GroupID.ToString()); 1082 invString.AddNameValueLine("creator_id", item.CreatorID.ToString());
838 invString.AddSectionEnd(); 1083 invString.AddNameValueLine("owner_id", ownerID.ToString());
839 1084
840 invString.AddNameValueLine("asset_id", item.AssetID.ToString()); 1085 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString());
841 invString.AddNameValueLine("type", Utils.AssetTypeToString((AssetType)item.Type));
842 invString.AddNameValueLine("inv_type", Utils.InventoryTypeToString((InventoryType)item.InvType));
843 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags));
844 1086
845 invString.AddSaleStart(); 1087 invString.AddNameValueLine("group_id", item.GroupID.ToString());
846 invString.AddNameValueLine("sale_type", "not"); 1088 invString.AddSectionEnd();
847 invString.AddNameValueLine("sale_price", "0");
848 invString.AddSectionEnd();
849 1089
850 invString.AddNameValueLine("name", item.Name + "|"); 1090 if (includeAssets)
851 invString.AddNameValueLine("desc", item.Description + "|"); 1091 invString.AddNameValueLine("asset_id", item.AssetID.ToString());
1092 else
1093 invString.AddNameValueLine("asset_id", UUID.Zero.ToString());
1094 invString.AddNameValueLine("type", Utils.AssetTypeToString((AssetType)item.Type));
1095 invString.AddNameValueLine("inv_type", Utils.InventoryTypeToString((InventoryType)item.InvType));
1096 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags));
852 1097
853 invString.AddNameValueLine("creation_date", item.CreationDate.ToString()); 1098 invString.AddSaleStart();
854 invString.AddSectionEnd(); 1099 invString.AddNameValueLine("sale_type", "not");
855 } 1100 invString.AddNameValueLine("sale_price", "0");
856 } 1101 invString.AddSectionEnd();
857 1102
858 m_inventoryFileData = Utils.StringToBytes(invString.BuildString); 1103 invString.AddNameValueLine("name", item.Name + "|");
1104 invString.AddNameValueLine("desc", item.Description + "|");
859 1105
860 return true; 1106 invString.AddNameValueLine("creation_date", item.CreationDate.ToString());
1107 invString.AddSectionEnd();
861 } 1108 }
862 1109
863 // No need to recreate, the existing file is fine 1110 Items.LockItemsForRead(false);
864 return false;
865 }
866 1111
867 /// <summary> 1112 m_inventoryFileData = Utils.StringToBytes(invString.BuildString);
868 /// Serialize all the metadata for the items in this prim's inventory ready for sending to the client
869 /// </summary>
870 /// <param name="xferManager"></param>
871 public void RequestInventoryFile(IClientAPI client, IXfer xferManager)
872 {
873 lock (m_items)
874 {
875 // Don't send a inventory xfer name if there are no items. Doing so causes viewer 3 to crash when rezzing
876 // a new script if any previous deletion has left the prim inventory empty.
877 if (m_items.Count == 0) // No inventory
878 {
879// m_log.DebugFormat(
880// "[PRIM INVENTORY]: Not sending inventory data for part {0} {1} {2} for {3} since no items",
881// m_part.Name, m_part.LocalId, m_part.UUID, client.Name);
882 1113
883 client.SendTaskInventory(m_part.UUID, 0, new byte[0]); 1114 if (m_inventoryFileData.Length > 2)
884 return; 1115 {
885 } 1116 xferManager.AddNewFile(m_inventoryFileName, m_inventoryFileData);
886 1117 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
887 CreateInventoryFile(); 1118 Util.StringToBytes256(m_inventoryFileName));
888 1119 return;
889 // In principle, we should only do the rest if the inventory changed;
890 // by sending m_inventorySerial to the client, it ought to know
891 // that nothing changed and that it doesn't need to request the file.
892 // Unfortunately, it doesn't look like the client optimizes this;
893 // the client seems to always come back and request the Xfer,
894 // no matter what value m_inventorySerial has.
895 // FIXME: Could probably be > 0 here rather than > 2
896 if (m_inventoryFileData.Length > 2)
897 {
898 // Add the file for Xfer
899 // m_log.DebugFormat(
900 // "[PRIM INVENTORY]: Adding inventory file {0} (length {1}) for transfer on {2} {3} {4}",
901 // m_inventoryFileName, m_inventoryFileData.Length, m_part.Name, m_part.UUID, m_part.LocalId);
902
903 xferManager.AddNewFile(m_inventoryFileName, m_inventoryFileData);
904 }
905
906 // Tell the client we're ready to Xfer the file
907 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
908 Util.StringToBytes256(m_inventoryFileName));
909 } 1120 }
1121
1122 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
910 } 1123 }
911 1124
912 /// <summary> 1125 /// <summary>
@@ -915,13 +1128,19 @@ namespace OpenSim.Region.Framework.Scenes
915 /// <param name="datastore"></param> 1128 /// <param name="datastore"></param>
916 public void ProcessInventoryBackup(ISimulationDataService datastore) 1129 public void ProcessInventoryBackup(ISimulationDataService datastore)
917 { 1130 {
918 if (HasInventoryChanged) 1131// Removed this because linking will cause an immediate delete of the new
919 { 1132// child prim from the database and the subsequent storing of the prim sees
920 HasInventoryChanged = false; 1133// the inventory of it as unchanged and doesn't store it at all. The overhead
921 List<TaskInventoryItem> items = GetInventoryItems(); 1134// of storing prim inventory needlessly is much less than the aggravation
922 datastore.StorePrimInventory(m_part.UUID, items); 1135// of prim inventory loss.
1136// if (HasInventoryChanged)
1137// {
1138 Items.LockItemsForRead(true);
1139 datastore.StorePrimInventory(m_part.UUID, Items.Values);
1140 Items.LockItemsForRead(false);
923 1141
924 } 1142 HasInventoryChanged = false;
1143// }
925 } 1144 }
926 1145
927 public class InventoryStringBuilder 1146 public class InventoryStringBuilder
@@ -987,82 +1206,63 @@ namespace OpenSim.Region.Framework.Scenes
987 { 1206 {
988 uint mask=0x7fffffff; 1207 uint mask=0x7fffffff;
989 1208
990 lock (m_items) 1209 foreach (TaskInventoryItem item in m_items.Values)
991 { 1210 {
992 foreach (TaskInventoryItem item in m_items.Values) 1211 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0)
1212 mask &= ~((uint)PermissionMask.Copy >> 13);
1213 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0)
1214 mask &= ~((uint)PermissionMask.Transfer >> 13);
1215 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0)
1216 mask &= ~((uint)PermissionMask.Modify >> 13);
1217
1218 if (item.InvType == (int)InventoryType.Object)
993 { 1219 {
994 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0) 1220 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
995 mask &= ~((uint)PermissionMask.Copy >> 13); 1221 mask &= ~((uint)PermissionMask.Copy >> 13);
996 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0) 1222 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
997 mask &= ~((uint)PermissionMask.Transfer >> 13); 1223 mask &= ~((uint)PermissionMask.Transfer >> 13);
998 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0) 1224 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
999 mask &= ~((uint)PermissionMask.Modify >> 13); 1225 mask &= ~((uint)PermissionMask.Modify >> 13);
1000
1001 if (item.InvType != (int)InventoryType.Object)
1002 {
1003 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0)
1004 mask &= ~((uint)PermissionMask.Copy >> 13);
1005 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0)
1006 mask &= ~((uint)PermissionMask.Transfer >> 13);
1007 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0)
1008 mask &= ~((uint)PermissionMask.Modify >> 13);
1009 }
1010 else
1011 {
1012 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
1013 mask &= ~((uint)PermissionMask.Copy >> 13);
1014 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
1015 mask &= ~((uint)PermissionMask.Transfer >> 13);
1016 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1017 mask &= ~((uint)PermissionMask.Modify >> 13);
1018 }
1019
1020 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
1021 mask &= ~(uint)PermissionMask.Copy;
1022 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
1023 mask &= ~(uint)PermissionMask.Transfer;
1024 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
1025 mask &= ~(uint)PermissionMask.Modify;
1026 } 1226 }
1227
1228 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
1229 mask &= ~(uint)PermissionMask.Copy;
1230 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
1231 mask &= ~(uint)PermissionMask.Transfer;
1232 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
1233 mask &= ~(uint)PermissionMask.Modify;
1027 } 1234 }
1028
1029 return mask; 1235 return mask;
1030 } 1236 }
1031 1237
1032 public void ApplyNextOwnerPermissions() 1238 public void ApplyNextOwnerPermissions()
1033 { 1239 {
1034 lock (m_items) 1240 foreach (TaskInventoryItem item in m_items.Values)
1035 { 1241 {
1036 foreach (TaskInventoryItem item in m_items.Values) 1242 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0)
1037 { 1243 {
1038 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0) 1244 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
1039 { 1245 item.CurrentPermissions &= ~(uint)PermissionMask.Copy;
1040 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0) 1246 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
1041 item.CurrentPermissions &= ~(uint)PermissionMask.Copy; 1247 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer;
1042 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0) 1248 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1043 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer; 1249 item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
1044 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1045 item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
1046 }
1047 item.CurrentPermissions &= item.NextPermissions;
1048 item.BasePermissions &= item.NextPermissions;
1049 item.EveryonePermissions &= item.NextPermissions;
1050 item.OwnerChanged = true;
1051 item.PermsMask = 0;
1052 item.PermsGranter = UUID.Zero;
1053 } 1250 }
1251 item.OwnerChanged = true;
1252 item.CurrentPermissions &= item.NextPermissions;
1253 item.BasePermissions &= item.NextPermissions;
1254 item.EveryonePermissions &= item.NextPermissions;
1255 item.PermsMask = 0;
1256 item.PermsGranter = UUID.Zero;
1054 } 1257 }
1055 } 1258 }
1056 1259
1057 public void ApplyGodPermissions(uint perms) 1260 public void ApplyGodPermissions(uint perms)
1058 { 1261 {
1059 lock (m_items) 1262 foreach (TaskInventoryItem item in m_items.Values)
1060 { 1263 {
1061 foreach (TaskInventoryItem item in m_items.Values) 1264 item.CurrentPermissions = perms;
1062 { 1265 item.BasePermissions = perms;
1063 item.CurrentPermissions = perms;
1064 item.BasePermissions = perms;
1065 }
1066 } 1266 }
1067 1267
1068 m_inventorySerial++; 1268 m_inventorySerial++;
@@ -1075,17 +1275,13 @@ namespace OpenSim.Region.Framework.Scenes
1075 /// <returns></returns> 1275 /// <returns></returns>
1076 public bool ContainsScripts() 1276 public bool ContainsScripts()
1077 { 1277 {
1078 lock (m_items) 1278 foreach (TaskInventoryItem item in m_items.Values)
1079 { 1279 {
1080 foreach (TaskInventoryItem item in m_items.Values) 1280 if (item.InvType == (int)InventoryType.LSL)
1081 { 1281 {
1082 if (item.InvType == (int)InventoryType.LSL) 1282 return true;
1083 {
1084 return true;
1085 }
1086 } 1283 }
1087 } 1284 }
1088
1089 return false; 1285 return false;
1090 } 1286 }
1091 1287
@@ -1093,11 +1289,8 @@ namespace OpenSim.Region.Framework.Scenes
1093 { 1289 {
1094 List<UUID> ret = new List<UUID>(); 1290 List<UUID> ret = new List<UUID>();
1095 1291
1096 lock (m_items) 1292 foreach (TaskInventoryItem item in m_items.Values)
1097 { 1293 ret.Add(item.ItemID);
1098 foreach (TaskInventoryItem item in m_items.Values)
1099 ret.Add(item.ItemID);
1100 }
1101 1294
1102 return ret; 1295 return ret;
1103 } 1296 }
@@ -1128,6 +1321,11 @@ namespace OpenSim.Region.Framework.Scenes
1128 1321
1129 public Dictionary<UUID, string> GetScriptStates() 1322 public Dictionary<UUID, string> GetScriptStates()
1130 { 1323 {
1324 return GetScriptStates(false);
1325 }
1326
1327 public Dictionary<UUID, string> GetScriptStates(bool oldIDs)
1328 {
1131 Dictionary<UUID, string> ret = new Dictionary<UUID, string>(); 1329 Dictionary<UUID, string> ret = new Dictionary<UUID, string>();
1132 1330
1133 if (m_part.ParentGroup.Scene == null) // Group not in a scene 1331 if (m_part.ParentGroup.Scene == null) // Group not in a scene
@@ -1138,25 +1336,35 @@ namespace OpenSim.Region.Framework.Scenes
1138 if (engines.Length == 0) // No engine at all 1336 if (engines.Length == 0) // No engine at all
1139 return ret; 1337 return ret;
1140 1338
1141 List<TaskInventoryItem> scripts = GetInventoryScripts(); 1339 Items.LockItemsForRead(true);
1142 1340 foreach (TaskInventoryItem item in m_items.Values)
1143 foreach (TaskInventoryItem item in scripts)
1144 { 1341 {
1145 foreach (IScriptModule e in engines) 1342 if (item.InvType == (int)InventoryType.LSL)
1146 { 1343 {
1147 if (e != null) 1344 foreach (IScriptModule e in engines)
1148 { 1345 {
1149 string n = e.GetXMLState(item.ItemID); 1346 if (e != null)
1150 if (n != String.Empty)
1151 { 1347 {
1152 if (!ret.ContainsKey(item.ItemID)) 1348 string n = e.GetXMLState(item.ItemID);
1153 ret[item.ItemID] = n; 1349 if (n != String.Empty)
1154 break; 1350 {
1351 if (oldIDs)
1352 {
1353 if (!ret.ContainsKey(item.OldItemID))
1354 ret[item.OldItemID] = n;
1355 }
1356 else
1357 {
1358 if (!ret.ContainsKey(item.ItemID))
1359 ret[item.ItemID] = n;
1360 }
1361 break;
1362 }
1155 } 1363 }
1156 } 1364 }
1157 } 1365 }
1158 } 1366 }
1159 1367 Items.LockItemsForRead(false);
1160 return ret; 1368 return ret;
1161 } 1369 }
1162 1370
@@ -1166,21 +1374,27 @@ namespace OpenSim.Region.Framework.Scenes
1166 if (engines.Length == 0) 1374 if (engines.Length == 0)
1167 return; 1375 return;
1168 1376
1169 List<TaskInventoryItem> scripts = GetInventoryScripts();
1170 1377
1171 foreach (TaskInventoryItem item in scripts) 1378 Items.LockItemsForRead(true);
1379
1380 foreach (TaskInventoryItem item in m_items.Values)
1172 { 1381 {
1173 foreach (IScriptModule engine in engines) 1382 if (item.InvType == (int)InventoryType.LSL)
1174 { 1383 {
1175 if (engine != null) 1384 foreach (IScriptModule engine in engines)
1176 { 1385 {
1177 if (item.OwnerChanged) 1386 if (engine != null)
1178 engine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.OWNER }); 1387 {
1179 item.OwnerChanged = false; 1388 if (item.OwnerChanged)
1180 engine.ResumeScript(item.ItemID); 1389 engine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.OWNER });
1390 item.OwnerChanged = false;
1391 engine.ResumeScript(item.ItemID);
1392 }
1181 } 1393 }
1182 } 1394 }
1183 } 1395 }
1396
1397 Items.LockItemsForRead(false);
1184 } 1398 }
1185 } 1399 }
1186} 1400}
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 5c56150..c7c90da 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -168,6 +168,7 @@ namespace OpenSim.Region.Framework.Scenes
168// private int m_lastColCount = -1; //KF: Look for Collision chnages 168// private int m_lastColCount = -1; //KF: Look for Collision chnages
169// private int m_updateCount = 0; //KF: Update Anims for a while 169// private int m_updateCount = 0; //KF: Update Anims for a while
170// private static readonly int UPDATE_COUNT = 10; // how many frames to update for 170// private static readonly int UPDATE_COUNT = 10; // how many frames to update for
171 private List<uint> m_lastColliders = new List<uint>();
171 172
172 private TeleportFlags m_teleportFlags; 173 private TeleportFlags m_teleportFlags;
173 public TeleportFlags TeleportFlags 174 public TeleportFlags TeleportFlags
@@ -229,6 +230,9 @@ namespace OpenSim.Region.Framework.Scenes
229 //private int m_moveToPositionStateStatus; 230 //private int m_moveToPositionStateStatus;
230 //***************************************************** 231 //*****************************************************
231 232
233 private bool m_collisionEventFlag = false;
234 private object m_collisionEventLock = new Object();
235
232 protected AvatarAppearance m_appearance; 236 protected AvatarAppearance m_appearance;
233 237
234 public AvatarAppearance Appearance 238 public AvatarAppearance Appearance
@@ -1751,9 +1755,9 @@ namespace OpenSim.Region.Framework.Scenes
1751 if (pos.Z - terrainHeight < 0.2) 1755 if (pos.Z - terrainHeight < 0.2)
1752 pos.Z = terrainHeight; 1756 pos.Z = terrainHeight;
1753 1757
1754 m_log.DebugFormat( 1758// m_log.DebugFormat(
1755 "[SCENE PRESENCE]: Avatar {0} set move to target {1} (terrain height {2}) in {3}", 1759// "[SCENE PRESENCE]: Avatar {0} set move to target {1} (terrain height {2}) in {3}",
1756 Name, pos, terrainHeight, m_scene.RegionInfo.RegionName); 1760// Name, pos, terrainHeight, m_scene.RegionInfo.RegionName);
1757 1761
1758 if (noFly) 1762 if (noFly)
1759 Flying = false; 1763 Flying = false;
@@ -1837,6 +1841,7 @@ namespace OpenSim.Region.Framework.Scenes
1837 if (part.SitTargetAvatar == UUID) 1841 if (part.SitTargetAvatar == UUID)
1838 part.SitTargetAvatar = UUID.Zero; 1842 part.SitTargetAvatar = UUID.Zero;
1839 1843
1844 part.ParentGroup.DeleteAvatar(UUID);
1840 ParentPosition = part.GetWorldPosition(); 1845 ParentPosition = part.GetWorldPosition();
1841 ControllingClient.SendClearFollowCamProperties(part.ParentUUID); 1846 ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
1842 } 1847 }
@@ -1975,7 +1980,7 @@ namespace OpenSim.Region.Framework.Scenes
1975 forceMouselook = part.GetForceMouselook(); 1980 forceMouselook = part.GetForceMouselook();
1976 1981
1977 ControllingClient.SendSitResponse( 1982 ControllingClient.SendSitResponse(
1978 targetID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook); 1983 part.UUID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook);
1979 1984
1980 m_requestedSitTargetUUID = targetID; 1985 m_requestedSitTargetUUID = targetID;
1981 1986
@@ -2260,11 +2265,13 @@ namespace OpenSim.Region.Framework.Scenes
2260 m_pos = sitTargetPos + SIT_TARGET_ADJUSTMENT; 2265 m_pos = sitTargetPos + SIT_TARGET_ADJUSTMENT;
2261 Rotation = sitTargetOrient; 2266 Rotation = sitTargetOrient;
2262 ParentPosition = part.AbsolutePosition; 2267 ParentPosition = part.AbsolutePosition;
2268 part.ParentGroup.AddAvatar(UUID);
2263 } 2269 }
2264 else 2270 else
2265 { 2271 {
2266 m_pos -= part.AbsolutePosition; 2272 m_pos -= part.AbsolutePosition;
2267 ParentPosition = part.AbsolutePosition; 2273 ParentPosition = part.AbsolutePosition;
2274 part.ParentGroup.AddAvatar(UUID);
2268 2275
2269// m_log.DebugFormat( 2276// m_log.DebugFormat(
2270// "[SCENE PRESENCE]: Sitting {0} at position {1} ({2} + {3}) on part {4} {5} without sit target", 2277// "[SCENE PRESENCE]: Sitting {0} at position {1} ({2} + {3}) on part {4} {5} without sit target",
@@ -3370,6 +3377,8 @@ namespace OpenSim.Region.Framework.Scenes
3370 } 3377 }
3371 } 3378 }
3372 3379
3380 RaiseCollisionScriptEvents(coldata);
3381
3373 if (Invulnerable) 3382 if (Invulnerable)
3374 return; 3383 return;
3375 3384
@@ -3881,6 +3890,12 @@ namespace OpenSim.Region.Framework.Scenes
3881 3890
3882 private void CheckAndAdjustLandingPoint(ref Vector3 pos) 3891 private void CheckAndAdjustLandingPoint(ref Vector3 pos)
3883 { 3892 {
3893 string reason;
3894
3895 // Honor bans
3896 if (!m_scene.TestLandRestrictions(UUID, out reason, ref pos.X, ref pos.Y))
3897 return;
3898
3884 SceneObjectGroup telehub = null; 3899 SceneObjectGroup telehub = null;
3885 if (m_scene.RegionInfo.RegionSettings.TelehubObject != UUID.Zero && (telehub = m_scene.GetSceneObjectGroup(m_scene.RegionInfo.RegionSettings.TelehubObject)) != null) 3900 if (m_scene.RegionInfo.RegionSettings.TelehubObject != UUID.Zero && (telehub = m_scene.GetSceneObjectGroup(m_scene.RegionInfo.RegionSettings.TelehubObject)) != null)
3886 { 3901 {
@@ -3920,11 +3935,173 @@ namespace OpenSim.Region.Framework.Scenes
3920 pos = land.LandData.UserLocation; 3935 pos = land.LandData.UserLocation;
3921 } 3936 }
3922 } 3937 }
3923 3938
3924 land.SendLandUpdateToClient(ControllingClient); 3939 land.SendLandUpdateToClient(ControllingClient);
3925 } 3940 }
3926 } 3941 }
3927 3942
3943 private void RaiseCollisionScriptEvents(Dictionary<uint, ContactPoint> coldata)
3944 {
3945 lock(m_collisionEventLock)
3946 {
3947 if (m_collisionEventFlag)
3948 return;
3949 m_collisionEventFlag = true;
3950 }
3951
3952 Util.FireAndForget(delegate(object x)
3953 {
3954 try
3955 {
3956 List<uint> thisHitColliders = new List<uint>();
3957 List<uint> endedColliders = new List<uint>();
3958 List<uint> startedColliders = new List<uint>();
3959
3960 foreach (uint localid in coldata.Keys)
3961 {
3962 thisHitColliders.Add(localid);
3963 if (!m_lastColliders.Contains(localid))
3964 {
3965 startedColliders.Add(localid);
3966 }
3967 //m_log.Debug("[SCENE PRESENCE]: Collided with:" + localid.ToString() + " at depth of: " + collissionswith[localid].ToString());
3968 }
3969
3970 // calculate things that ended colliding
3971 foreach (uint localID in m_lastColliders)
3972 {
3973 if (!thisHitColliders.Contains(localID))
3974 {
3975 endedColliders.Add(localID);
3976 }
3977 }
3978 //add the items that started colliding this time to the last colliders list.
3979 foreach (uint localID in startedColliders)
3980 {
3981 m_lastColliders.Add(localID);
3982 }
3983 // remove things that ended colliding from the last colliders list
3984 foreach (uint localID in endedColliders)
3985 {
3986 m_lastColliders.Remove(localID);
3987 }
3988
3989 // do event notification
3990 if (startedColliders.Count > 0)
3991 {
3992 ColliderArgs StartCollidingMessage = new ColliderArgs();
3993 List<DetectedObject> colliding = new List<DetectedObject>();
3994 foreach (uint localId in startedColliders)
3995 {
3996 if (localId == 0)
3997 continue;
3998
3999 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
4000 string data = "";
4001 if (obj != null)
4002 {
4003 DetectedObject detobj = new DetectedObject();
4004 detobj.keyUUID = obj.UUID;
4005 detobj.nameStr = obj.Name;
4006 detobj.ownerUUID = obj.OwnerID;
4007 detobj.posVector = obj.AbsolutePosition;
4008 detobj.rotQuat = obj.GetWorldRotation();
4009 detobj.velVector = obj.Velocity;
4010 detobj.colliderType = 0;
4011 detobj.groupUUID = obj.GroupID;
4012 colliding.Add(detobj);
4013 }
4014 }
4015
4016 if (colliding.Count > 0)
4017 {
4018 StartCollidingMessage.Colliders = colliding;
4019
4020 foreach (SceneObjectGroup att in GetAttachments())
4021 Scene.EventManager.TriggerScriptCollidingStart(att.LocalId, StartCollidingMessage);
4022 }
4023 }
4024
4025 if (endedColliders.Count > 0)
4026 {
4027 ColliderArgs EndCollidingMessage = new ColliderArgs();
4028 List<DetectedObject> colliding = new List<DetectedObject>();
4029 foreach (uint localId in endedColliders)
4030 {
4031 if (localId == 0)
4032 continue;
4033
4034 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
4035 string data = "";
4036 if (obj != null)
4037 {
4038 DetectedObject detobj = new DetectedObject();
4039 detobj.keyUUID = obj.UUID;
4040 detobj.nameStr = obj.Name;
4041 detobj.ownerUUID = obj.OwnerID;
4042 detobj.posVector = obj.AbsolutePosition;
4043 detobj.rotQuat = obj.GetWorldRotation();
4044 detobj.velVector = obj.Velocity;
4045 detobj.colliderType = 0;
4046 detobj.groupUUID = obj.GroupID;
4047 colliding.Add(detobj);
4048 }
4049 }
4050
4051 if (colliding.Count > 0)
4052 {
4053 EndCollidingMessage.Colliders = colliding;
4054
4055 foreach (SceneObjectGroup att in GetAttachments())
4056 Scene.EventManager.TriggerScriptCollidingEnd(att.LocalId, EndCollidingMessage);
4057 }
4058 }
4059
4060 if (thisHitColliders.Count > 0)
4061 {
4062 ColliderArgs CollidingMessage = new ColliderArgs();
4063 List<DetectedObject> colliding = new List<DetectedObject>();
4064 foreach (uint localId in thisHitColliders)
4065 {
4066 if (localId == 0)
4067 continue;
4068
4069 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
4070 string data = "";
4071 if (obj != null)
4072 {
4073 DetectedObject detobj = new DetectedObject();
4074 detobj.keyUUID = obj.UUID;
4075 detobj.nameStr = obj.Name;
4076 detobj.ownerUUID = obj.OwnerID;
4077 detobj.posVector = obj.AbsolutePosition;
4078 detobj.rotQuat = obj.GetWorldRotation();
4079 detobj.velVector = obj.Velocity;
4080 detobj.colliderType = 0;
4081 detobj.groupUUID = obj.GroupID;
4082 colliding.Add(detobj);
4083 }
4084 }
4085
4086 if (colliding.Count > 0)
4087 {
4088 CollidingMessage.Colliders = colliding;
4089
4090 lock (m_attachments)
4091 {
4092 foreach (SceneObjectGroup att in m_attachments)
4093 Scene.EventManager.TriggerScriptColliding(att.LocalId, CollidingMessage);
4094 }
4095 }
4096 }
4097 }
4098 finally
4099 {
4100 m_collisionEventFlag = false;
4101 }
4102 });
4103 }
4104
3928 private void TeleportFlagsDebug() { 4105 private void TeleportFlagsDebug() {
3929 4106
3930 // Some temporary debugging help to show all the TeleportFlags we have... 4107 // Some temporary debugging help to show all the TeleportFlags we have...
@@ -3949,6 +4126,5 @@ namespace OpenSim.Region.Framework.Scenes
3949 m_log.InfoFormat("[SCENE PRESENCE]: TELEPORT ******************"); 4126 m_log.InfoFormat("[SCENE PRESENCE]: TELEPORT ******************");
3950 4127
3951 } 4128 }
3952
3953 } 4129 }
3954} 4130}
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
index ab02f92..ba33122 100644
--- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
+++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
@@ -346,6 +346,9 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
346 m_SOPXmlProcessors.Add("PayPrice2", ProcessPayPrice2); 346 m_SOPXmlProcessors.Add("PayPrice2", ProcessPayPrice2);
347 m_SOPXmlProcessors.Add("PayPrice3", ProcessPayPrice3); 347 m_SOPXmlProcessors.Add("PayPrice3", ProcessPayPrice3);
348 m_SOPXmlProcessors.Add("PayPrice4", ProcessPayPrice4); 348 m_SOPXmlProcessors.Add("PayPrice4", ProcessPayPrice4);
349
350 m_SOPXmlProcessors.Add("Buoyancy", ProcessBuoyancy);
351 m_SOPXmlProcessors.Add("VolumeDetectActive", ProcessVolumeDetectActive);
349 #endregion 352 #endregion
350 353
351 #region TaskInventoryXmlProcessors initialization 354 #region TaskInventoryXmlProcessors initialization
@@ -730,6 +733,16 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
730 obj.PayPrice[4] = (int)reader.ReadElementContentAsInt("PayPrice4", String.Empty); 733 obj.PayPrice[4] = (int)reader.ReadElementContentAsInt("PayPrice4", String.Empty);
731 } 734 }
732 735
736 private static void ProcessBuoyancy(SceneObjectPart obj, XmlTextReader reader)
737 {
738 obj.Buoyancy = (int)reader.ReadElementContentAsFloat("Buoyancy", String.Empty);
739 }
740
741 private static void ProcessVolumeDetectActive(SceneObjectPart obj, XmlTextReader reader)
742 {
743 obj.VolumeDetectActive = Util.ReadBoolean(reader);
744 }
745
733 #endregion 746 #endregion
734 747
735 #region TaskInventoryXmlProcessors 748 #region TaskInventoryXmlProcessors
@@ -1215,6 +1228,9 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1215 writer.WriteElementString("PayPrice3", sop.PayPrice[3].ToString()); 1228 writer.WriteElementString("PayPrice3", sop.PayPrice[3].ToString());
1216 writer.WriteElementString("PayPrice4", sop.PayPrice[4].ToString()); 1229 writer.WriteElementString("PayPrice4", sop.PayPrice[4].ToString());
1217 1230
1231 writer.WriteElementString("Buoyancy", sop.Buoyancy.ToString());
1232 writer.WriteElementString("VolumeDetectActive", sop.VolumeDetectActive.ToString().ToLower());
1233
1218 writer.WriteEndElement(); 1234 writer.WriteEndElement();
1219 } 1235 }
1220 1236
@@ -1484,12 +1500,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1484 { 1500 {
1485 TaskInventoryDictionary tinv = new TaskInventoryDictionary(); 1501 TaskInventoryDictionary tinv = new TaskInventoryDictionary();
1486 1502
1487 if (reader.IsEmptyElement)
1488 {
1489 reader.Read();
1490 return tinv;
1491 }
1492
1493 reader.ReadStartElement(name, String.Empty); 1503 reader.ReadStartElement(name, String.Empty);
1494 1504
1495 while (reader.Name == "TaskInventoryItem") 1505 while (reader.Name == "TaskInventoryItem")
@@ -1527,12 +1537,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1527 1537
1528 PrimitiveBaseShape shape = new PrimitiveBaseShape(); 1538 PrimitiveBaseShape shape = new PrimitiveBaseShape();
1529 1539
1530 if (reader.IsEmptyElement)
1531 {
1532 reader.Read();
1533 return shape;
1534 }
1535
1536 reader.ReadStartElement(name, String.Empty); // Shape 1540 reader.ReadStartElement(name, String.Empty); // Shape
1537 1541
1538 ExternalRepresentationUtils.ExecuteReadProcessors( 1542 ExternalRepresentationUtils.ExecuteReadProcessors(
diff --git a/OpenSim/Region/Framework/Scenes/UndoState.cs b/OpenSim/Region/Framework/Scenes/UndoState.cs
index 860172c..5ed3c79 100644
--- a/OpenSim/Region/Framework/Scenes/UndoState.cs
+++ b/OpenSim/Region/Framework/Scenes/UndoState.cs
@@ -30,12 +30,27 @@ using System.Reflection;
30using log4net; 30using log4net;
31using OpenMetaverse; 31using OpenMetaverse;
32using OpenSim.Region.Framework.Interfaces; 32using OpenSim.Region.Framework.Interfaces;
33using System;
33 34
34namespace OpenSim.Region.Framework.Scenes 35namespace OpenSim.Region.Framework.Scenes
35{ 36{
37 [Flags]
38 public enum UndoType
39 {
40 STATE_PRIM_POSITION = 1,
41 STATE_PRIM_ROTATION = 2,
42 STATE_PRIM_SCALE = 4,
43 STATE_PRIM_ALL = 7,
44 STATE_GROUP_POSITION = 8,
45 STATE_GROUP_ROTATION = 16,
46 STATE_GROUP_SCALE = 32,
47 STATE_GROUP_ALL = 56,
48 STATE_ALL = 63
49 }
50
36 public class UndoState 51 public class UndoState
37 { 52 {
38// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 53 // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
39 54
40 public Vector3 Position = Vector3.Zero; 55 public Vector3 Position = Vector3.Zero;
41 public Vector3 Scale = Vector3.Zero; 56 public Vector3 Scale = Vector3.Zero;
@@ -57,37 +72,37 @@ namespace OpenSim.Region.Framework.Scenes
57 { 72 {
58 ForGroup = forGroup; 73 ForGroup = forGroup;
59 74
60// if (ForGroup) 75 // if (ForGroup)
61 Position = part.ParentGroup.AbsolutePosition; 76 Position = part.ParentGroup.AbsolutePosition;
62// else 77 // else
63// Position = part.OffsetPosition; 78 // Position = part.OffsetPosition;
64 79
65// m_log.DebugFormat( 80 // m_log.DebugFormat(
66// "[UNDO STATE]: Storing undo position {0} for root part", Position); 81 // "[UNDO STATE]: Storing undo position {0} for root part", Position);
67 82
68 Rotation = part.RotationOffset; 83 Rotation = part.RotationOffset;
69 84
70// m_log.DebugFormat( 85 // m_log.DebugFormat(
71// "[UNDO STATE]: Storing undo rotation {0} for root part", Rotation); 86 // "[UNDO STATE]: Storing undo rotation {0} for root part", Rotation);
72 87
73 Scale = part.Shape.Scale; 88 Scale = part.Shape.Scale;
74 89
75// m_log.DebugFormat( 90 // m_log.DebugFormat(
76// "[UNDO STATE]: Storing undo scale {0} for root part", Scale); 91 // "[UNDO STATE]: Storing undo scale {0} for root part", Scale);
77 } 92 }
78 else 93 else
79 { 94 {
80 Position = part.OffsetPosition; 95 Position = part.OffsetPosition;
81// m_log.DebugFormat( 96 // m_log.DebugFormat(
82// "[UNDO STATE]: Storing undo position {0} for child part", Position); 97 // "[UNDO STATE]: Storing undo position {0} for child part", Position);
83 98
84 Rotation = part.RotationOffset; 99 Rotation = part.RotationOffset;
85// m_log.DebugFormat( 100 // m_log.DebugFormat(
86// "[UNDO STATE]: Storing undo rotation {0} for child part", Rotation); 101 // "[UNDO STATE]: Storing undo rotation {0} for child part", Rotation);
87 102
88 Scale = part.Shape.Scale; 103 Scale = part.Shape.Scale;
89// m_log.DebugFormat( 104 // m_log.DebugFormat(
90// "[UNDO STATE]: Storing undo scale {0} for child part", Scale); 105 // "[UNDO STATE]: Storing undo scale {0} for child part", Scale);
91 } 106 }
92 } 107 }
93 108
@@ -121,9 +136,9 @@ namespace OpenSim.Region.Framework.Scenes
121 136
122 if (part.ParentID == 0) 137 if (part.ParentID == 0)
123 { 138 {
124// m_log.DebugFormat( 139 // m_log.DebugFormat(
125// "[UNDO STATE]: Undoing position to {0} for root part {1} {2}", 140 // "[UNDO STATE]: Undoing position to {0} for root part {1} {2}",
126// Position, part.Name, part.LocalId); 141 // Position, part.Name, part.LocalId);
127 142
128 if (Position != Vector3.Zero) 143 if (Position != Vector3.Zero)
129 { 144 {
@@ -133,9 +148,9 @@ namespace OpenSim.Region.Framework.Scenes
133 part.ParentGroup.UpdateRootPosition(Position); 148 part.ParentGroup.UpdateRootPosition(Position);
134 } 149 }
135 150
136// m_log.DebugFormat( 151 // m_log.DebugFormat(
137// "[UNDO STATE]: Undoing rotation {0} to {1} for root part {2} {3}", 152 // "[UNDO STATE]: Undoing rotation {0} to {1} for root part {2} {3}",
138// part.RotationOffset, Rotation, part.Name, part.LocalId); 153 // part.RotationOffset, Rotation, part.Name, part.LocalId);
139 154
140 if (ForGroup) 155 if (ForGroup)
141 part.UpdateRotation(Rotation); 156 part.UpdateRotation(Rotation);
@@ -144,9 +159,9 @@ namespace OpenSim.Region.Framework.Scenes
144 159
145 if (Scale != Vector3.Zero) 160 if (Scale != Vector3.Zero)
146 { 161 {
147// m_log.DebugFormat( 162 // m_log.DebugFormat(
148// "[UNDO STATE]: Undoing scale {0} to {1} for root part {2} {3}", 163 // "[UNDO STATE]: Undoing scale {0} to {1} for root part {2} {3}",
149// part.Shape.Scale, Scale, part.Name, part.LocalId); 164 // part.Shape.Scale, Scale, part.Name, part.LocalId);
150 165
151 if (ForGroup) 166 if (ForGroup)
152 part.ParentGroup.GroupResize(Scale); 167 part.ParentGroup.GroupResize(Scale);
@@ -161,24 +176,24 @@ namespace OpenSim.Region.Framework.Scenes
161 // Note: Updating these properties on sop automatically schedules an update if needed 176 // Note: Updating these properties on sop automatically schedules an update if needed
162 if (Position != Vector3.Zero) 177 if (Position != Vector3.Zero)
163 { 178 {
164// m_log.DebugFormat( 179 // m_log.DebugFormat(
165// "[UNDO STATE]: Undoing position {0} to {1} for child part {2} {3}", 180 // "[UNDO STATE]: Undoing position {0} to {1} for child part {2} {3}",
166// part.OffsetPosition, Position, part.Name, part.LocalId); 181 // part.OffsetPosition, Position, part.Name, part.LocalId);
167 182
168 part.OffsetPosition = Position; 183 part.OffsetPosition = Position;
169 } 184 }
170 185
171// m_log.DebugFormat( 186 // m_log.DebugFormat(
172// "[UNDO STATE]: Undoing rotation {0} to {1} for child part {2} {3}", 187 // "[UNDO STATE]: Undoing rotation {0} to {1} for child part {2} {3}",
173// part.RotationOffset, Rotation, part.Name, part.LocalId); 188 // part.RotationOffset, Rotation, part.Name, part.LocalId);
174 189
175 part.UpdateRotation(Rotation); 190 part.UpdateRotation(Rotation);
176 191
177 if (Scale != Vector3.Zero) 192 if (Scale != Vector3.Zero)
178 { 193 {
179// m_log.DebugFormat( 194 // m_log.DebugFormat(
180// "[UNDO STATE]: Undoing scale {0} to {1} for child part {2} {3}", 195 // "[UNDO STATE]: Undoing scale {0} to {1} for child part {2} {3}",
181// part.Shape.Scale, Scale, part.Name, part.LocalId); 196 // part.Shape.Scale, Scale, part.Name, part.LocalId);
182 197
183 part.Resize(Scale); 198 part.Resize(Scale);
184 } 199 }
@@ -247,4 +262,4 @@ namespace OpenSim.Region.Framework.Scenes
247 m_terrainModule.UndoTerrain(m_terrainChannel); 262 m_terrainModule.UndoTerrain(m_terrainChannel);
248 } 263 }
249 } 264 }
250} \ No newline at end of file 265}
diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
index efb68a2..411e421 100644
--- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
+++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
@@ -87,10 +87,6 @@ namespace OpenSim.Region.Framework.Scenes
87 /// <param name="assetUuids">The assets gathered</param> 87 /// <param name="assetUuids">The assets gathered</param>
88 public void GatherAssetUuids(UUID assetUuid, AssetType assetType, IDictionary<UUID, AssetType> assetUuids) 88 public void GatherAssetUuids(UUID assetUuid, AssetType assetType, IDictionary<UUID, AssetType> assetUuids)
89 { 89 {
90 // avoid infinite loops
91 if (assetUuids.ContainsKey(assetUuid))
92 return;
93
94 try 90 try
95 { 91 {
96 assetUuids[assetUuid] = assetType; 92 assetUuids[assetUuid] = assetType;