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.cs504
-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.cs227
-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.cs678
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs199
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs804
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs327
-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, 2495 insertions, 780 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 5a5307c..fff39fb 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 333
@@ -732,6 +715,8 @@ namespace OpenSim.Region.Framework.Scenes
732 return; 715 return;
733 } 716 }
734 717
718 if (newName == null) newName = item.Name;
719
735 AssetBase asset = AssetService.Get(item.AssetID.ToString()); 720 AssetBase asset = AssetService.Get(item.AssetID.ToString());
736 721
737 if (asset != null) 722 if (asset != null)
@@ -788,6 +773,24 @@ namespace OpenSim.Region.Framework.Scenes
788 } 773 }
789 774
790 /// <summary> 775 /// <summary>
776 /// Move an item within the agent's inventory, and leave a copy (used in making a new outfit)
777 /// </summary>
778 public void MoveInventoryItemsLeaveCopy(IClientAPI remoteClient, List<InventoryItemBase> items, UUID destfolder)
779 {
780 List<InventoryItemBase> moveitems = new List<InventoryItemBase>();
781 foreach (InventoryItemBase b in items)
782 {
783 CopyInventoryItem(remoteClient, 0, remoteClient.AgentId, b.ID, b.Folder, null);
784 InventoryItemBase n = InventoryService.GetItem(b);
785 n.Folder = destfolder;
786 moveitems.Add(n);
787 remoteClient.SendInventoryItemCreateUpdate(n, 0);
788 }
789
790 MoveInventoryItem(remoteClient, moveitems);
791 }
792
793 /// <summary>
791 /// Move an item within the agent's inventory. 794 /// Move an item within the agent's inventory.
792 /// </summary> 795 /// </summary>
793 /// <param name="remoteClient"></param> 796 /// <param name="remoteClient"></param>
@@ -1130,6 +1133,10 @@ namespace OpenSim.Region.Framework.Scenes
1130 { 1133 {
1131 SceneObjectPart part = GetSceneObjectPart(primLocalId); 1134 SceneObjectPart part = GetSceneObjectPart(primLocalId);
1132 1135
1136 // Can't move a null item
1137 if (itemId == UUID.Zero)
1138 return;
1139
1133 if (null == part) 1140 if (null == part)
1134 { 1141 {
1135 m_log.WarnFormat( 1142 m_log.WarnFormat(
@@ -1240,6 +1247,10 @@ namespace OpenSim.Region.Framework.Scenes
1240 if ((part.OwnerID != destPart.OwnerID) && ((srcTaskItem.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)) 1247 if ((part.OwnerID != destPart.OwnerID) && ((srcTaskItem.CurrentPermissions & (uint)PermissionMask.Transfer) == 0))
1241 return; 1248 return;
1242 1249
1250 bool overrideNoMod = false;
1251 if ((part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) != 0)
1252 overrideNoMod = true;
1253
1243 if (part.OwnerID != destPart.OwnerID && (part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) == 0) 1254 if (part.OwnerID != destPart.OwnerID && (part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) == 0)
1244 { 1255 {
1245 // object cannot copy items to an object owned by a different owner 1256 // object cannot copy items to an object owned by a different owner
@@ -1249,7 +1260,7 @@ namespace OpenSim.Region.Framework.Scenes
1249 } 1260 }
1250 1261
1251 // must have both move and modify permission to put an item in an object 1262 // must have both move and modify permission to put an item in an object
1252 if ((part.OwnerMask & ((uint)PermissionMask.Move | (uint)PermissionMask.Modify)) == 0) 1263 if (((part.OwnerMask & (uint)PermissionMask.Modify) == 0) && (!overrideNoMod))
1253 { 1264 {
1254 return; 1265 return;
1255 } 1266 }
@@ -1308,6 +1319,14 @@ namespace OpenSim.Region.Framework.Scenes
1308 1319
1309 public UUID MoveTaskInventoryItems(UUID destID, string category, SceneObjectPart host, List<UUID> items) 1320 public UUID MoveTaskInventoryItems(UUID destID, string category, SceneObjectPart host, List<UUID> items)
1310 { 1321 {
1322 SceneObjectPart destPart = GetSceneObjectPart(destID);
1323 if (destPart != null) // Move into a prim
1324 {
1325 foreach(UUID itemID in items)
1326 MoveTaskInventoryItem(destID, host, itemID);
1327 return destID; // Prim folder ID == prim ID
1328 }
1329
1311 InventoryFolderBase rootFolder = InventoryService.GetRootFolder(destID); 1330 InventoryFolderBase rootFolder = InventoryService.GetRootFolder(destID);
1312 1331
1313 UUID newFolderID = UUID.Random(); 1332 UUID newFolderID = UUID.Random();
@@ -1493,12 +1512,12 @@ namespace OpenSim.Region.Framework.Scenes
1493 agentTransactions.HandleTaskItemUpdateFromTransaction( 1512 agentTransactions.HandleTaskItemUpdateFromTransaction(
1494 remoteClient, part, transactionID, currentItem); 1513 remoteClient, part, transactionID, currentItem);
1495 1514
1496 if ((InventoryType)itemInfo.InvType == InventoryType.Notecard) 1515// if ((InventoryType)itemInfo.InvType == InventoryType.Notecard)
1497 remoteClient.SendAgentAlertMessage("Notecard saved", false); 1516// remoteClient.SendAgentAlertMessage("Notecard saved", false);
1498 else if ((InventoryType)itemInfo.InvType == InventoryType.LSL) 1517// else if ((InventoryType)itemInfo.InvType == InventoryType.LSL)
1499 remoteClient.SendAgentAlertMessage("Script saved", false); 1518// remoteClient.SendAgentAlertMessage("Script saved", false);
1500 else 1519// else
1501 remoteClient.SendAgentAlertMessage("Item saved", false); 1520// remoteClient.SendAgentAlertMessage("Item saved", false);
1502 } 1521 }
1503 } 1522 }
1504 1523
@@ -1678,7 +1697,7 @@ namespace OpenSim.Region.Framework.Scenes
1678 } 1697 }
1679 1698
1680 AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType, 1699 AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType,
1681 Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n}"), 1700 Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n\n touch_start(integer num)\n {\n }\n}"),
1682 agentID); 1701 agentID);
1683 AssetService.Store(asset); 1702 AssetService.Store(asset);
1684 1703
@@ -1830,23 +1849,32 @@ namespace OpenSim.Region.Framework.Scenes
1830 // build a list of eligible objects 1849 // build a list of eligible objects
1831 List<uint> deleteIDs = new List<uint>(); 1850 List<uint> deleteIDs = new List<uint>();
1832 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>(); 1851 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>();
1833 1852 List<SceneObjectGroup> takeGroups = new List<SceneObjectGroup>();
1834 // Start with true for both, then remove the flags if objects
1835 // that we can't derez are part of the selection
1836 bool permissionToTake = true;
1837 bool permissionToTakeCopy = true;
1838 bool permissionToDelete = true;
1839 1853
1840 foreach (uint localID in localIDs) 1854 foreach (uint localID in localIDs)
1841 { 1855 {
1856 // Start with true for both, then remove the flags if objects
1857 // that we can't derez are part of the selection
1858 bool permissionToTake = true;
1859 bool permissionToTakeCopy = true;
1860 bool permissionToDelete = true;
1861
1842 // Invalid id 1862 // Invalid id
1843 SceneObjectPart part = GetSceneObjectPart(localID); 1863 SceneObjectPart part = GetSceneObjectPart(localID);
1844 if (part == null) 1864 if (part == null)
1865 {
1866 //Client still thinks the object exists, kill it
1867 deleteIDs.Add(localID);
1845 continue; 1868 continue;
1869 }
1846 1870
1847 // Already deleted by someone else 1871 // Already deleted by someone else
1848 if (part.ParentGroup.IsDeleted) 1872 if (part.ParentGroup.IsDeleted)
1873 {
1874 //Client still thinks the object exists, kill it
1875 deleteIDs.Add(localID);
1849 continue; 1876 continue;
1877 }
1850 1878
1851 // Can't delete child prims 1879 // Can't delete child prims
1852 if (part != part.ParentGroup.RootPart) 1880 if (part != part.ParentGroup.RootPart)
@@ -1854,9 +1882,6 @@ namespace OpenSim.Region.Framework.Scenes
1854 1882
1855 SceneObjectGroup grp = part.ParentGroup; 1883 SceneObjectGroup grp = part.ParentGroup;
1856 1884
1857 deleteIDs.Add(localID);
1858 deleteGroups.Add(grp);
1859
1860 if (remoteClient == null) 1885 if (remoteClient == null)
1861 { 1886 {
1862 // Autoreturn has a null client. Nothing else does. So 1887 // Autoreturn has a null client. Nothing else does. So
@@ -1873,83 +1898,195 @@ namespace OpenSim.Region.Framework.Scenes
1873 } 1898 }
1874 else 1899 else
1875 { 1900 {
1876 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId)) 1901 if (action == DeRezAction.TakeCopy)
1902 {
1903 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId))
1904 permissionToTakeCopy = false;
1905 }
1906 else
1907 {
1877 permissionToTakeCopy = false; 1908 permissionToTakeCopy = false;
1878 1909 }
1879 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId)) 1910 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId))
1880 permissionToTake = false; 1911 permissionToTake = false;
1881 1912
1882 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId)) 1913 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId))
1883 permissionToDelete = false; 1914 permissionToDelete = false;
1884 } 1915 }
1885 }
1886 1916
1887 // Handle god perms 1917 // Handle god perms
1888 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId)) 1918 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId))
1889 { 1919 {
1890 permissionToTake = true; 1920 permissionToTake = true;
1891 permissionToTakeCopy = true; 1921 permissionToTakeCopy = true;
1892 permissionToDelete = true; 1922 permissionToDelete = true;
1893 } 1923 }
1894 1924
1895 // If we're re-saving, we don't even want to delete 1925 // If we're re-saving, we don't even want to delete
1896 if (action == DeRezAction.SaveToExistingUserInventoryItem) 1926 if (action == DeRezAction.SaveToExistingUserInventoryItem)
1897 permissionToDelete = false; 1927 permissionToDelete = false;
1898 1928
1899 // if we want to take a copy, we also don't want to delete 1929 // if we want to take a copy, we also don't want to delete
1900 // Note: after this point, the permissionToTakeCopy flag 1930 // Note: after this point, the permissionToTakeCopy flag
1901 // becomes irrelevant. It already includes the permissionToTake 1931 // becomes irrelevant. It already includes the permissionToTake
1902 // permission and after excluding no copy items here, we can 1932 // permission and after excluding no copy items here, we can
1903 // just use that. 1933 // just use that.
1904 if (action == DeRezAction.TakeCopy) 1934 if (action == DeRezAction.TakeCopy)
1905 { 1935 {
1906 // If we don't have permission, stop right here 1936 // If we don't have permission, stop right here
1907 if (!permissionToTakeCopy) 1937 if (!permissionToTakeCopy)
1908 return; 1938 return;
1909 1939
1910 permissionToTake = true; 1940 permissionToTake = true;
1911 // Don't delete 1941 // Don't delete
1912 permissionToDelete = false; 1942 permissionToDelete = false;
1913 } 1943 }
1914 1944
1915 if (action == DeRezAction.Return) 1945 if (action == DeRezAction.Return)
1916 {
1917 if (remoteClient != null)
1918 { 1946 {
1919 if (Permissions.CanReturnObjects( 1947 if (remoteClient != null)
1920 null,
1921 remoteClient.AgentId,
1922 deleteGroups))
1923 { 1948 {
1924 permissionToTake = true; 1949 if (Permissions.CanReturnObjects(
1925 permissionToDelete = true; 1950 null,
1926 1951 remoteClient.AgentId,
1927 foreach (SceneObjectGroup g in deleteGroups) 1952 deleteGroups))
1928 { 1953 {
1929 AddReturn(g.OwnerID, g.Name, g.AbsolutePosition, "parcel owner return"); 1954 permissionToTake = true;
1955 permissionToDelete = true;
1956
1957 AddReturn(grp.OwnerID, grp.Name, grp.AbsolutePosition, "parcel owner return");
1930 } 1958 }
1931 } 1959 }
1960 else // Auto return passes through here with null agent
1961 {
1962 permissionToTake = true;
1963 permissionToDelete = true;
1964 }
1932 } 1965 }
1933 else // Auto return passes through here with null agent 1966
1967 if (permissionToTake && (!permissionToDelete))
1968 takeGroups.Add(grp);
1969
1970 if (permissionToDelete)
1934 { 1971 {
1935 permissionToTake = true; 1972 if (permissionToTake)
1936 permissionToDelete = true; 1973 deleteGroups.Add(grp);
1974 deleteIDs.Add(grp.LocalId);
1937 } 1975 }
1938 } 1976 }
1939 1977
1940 if (permissionToTake) 1978 SendKillObject(deleteIDs);
1979
1980 if (deleteGroups.Count > 0)
1941 { 1981 {
1982 foreach (SceneObjectGroup g in deleteGroups)
1983 deleteIDs.Remove(g.LocalId);
1984
1942 m_asyncSceneObjectDeleter.DeleteToInventory( 1985 m_asyncSceneObjectDeleter.DeleteToInventory(
1943 action, destinationID, deleteGroups, remoteClient, 1986 action, destinationID, deleteGroups, remoteClient,
1944 permissionToDelete); 1987 true);
1988 }
1989 if (takeGroups.Count > 0)
1990 {
1991 m_asyncSceneObjectDeleter.DeleteToInventory(
1992 action, destinationID, takeGroups, remoteClient,
1993 false);
1945 } 1994 }
1946 else if (permissionToDelete) 1995 if (deleteIDs.Count > 0)
1947 { 1996 {
1948 foreach (SceneObjectGroup g in deleteGroups) 1997 foreach (SceneObjectGroup g in deleteGroups)
1949 DeleteSceneObject(g, false); 1998 DeleteSceneObject(g, true);
1950 } 1999 }
1951 } 2000 }
1952 2001
2002 public UUID attachObjectAssetStore(IClientAPI remoteClient, SceneObjectGroup grp, UUID AgentId, out UUID itemID)
2003 {
2004 itemID = UUID.Zero;
2005 if (grp != null)
2006 {
2007 Vector3 inventoryStoredPosition = new Vector3
2008 (((grp.AbsolutePosition.X > (int)Constants.RegionSize)
2009 ? 250
2010 : grp.AbsolutePosition.X)
2011 ,
2012 (grp.AbsolutePosition.X > (int)Constants.RegionSize)
2013 ? 250
2014 : grp.AbsolutePosition.X,
2015 grp.AbsolutePosition.Z);
2016
2017 Vector3 originalPosition = grp.AbsolutePosition;
2018
2019 grp.AbsolutePosition = inventoryStoredPosition;
2020
2021 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp);
2022
2023 grp.AbsolutePosition = originalPosition;
2024
2025 AssetBase asset = CreateAsset(
2026 grp.GetPartName(grp.LocalId),
2027 grp.GetPartDescription(grp.LocalId),
2028 (sbyte)AssetType.Object,
2029 Utils.StringToBytes(sceneObjectXml),
2030 remoteClient.AgentId);
2031 AssetService.Store(asset);
2032
2033 InventoryItemBase item = new InventoryItemBase();
2034 item.CreatorId = grp.RootPart.CreatorID.ToString();
2035 item.CreatorData = grp.RootPart.CreatorData;
2036 item.Owner = remoteClient.AgentId;
2037 item.ID = UUID.Random();
2038 item.AssetID = asset.FullID;
2039 item.Description = asset.Description;
2040 item.Name = asset.Name;
2041 item.AssetType = asset.Type;
2042 item.InvType = (int)InventoryType.Object;
2043
2044 InventoryFolderBase folder = InventoryService.GetFolderForType(remoteClient.AgentId, AssetType.Object);
2045 if (folder != null)
2046 item.Folder = folder.ID;
2047 else // oopsies
2048 item.Folder = UUID.Zero;
2049
2050 // Set up base perms properly
2051 uint permsBase = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify);
2052 permsBase &= grp.RootPart.BaseMask;
2053 permsBase |= (uint)PermissionMask.Move;
2054
2055 // Make sure we don't lock it
2056 grp.RootPart.NextOwnerMask |= (uint)PermissionMask.Move;
2057
2058 if ((remoteClient.AgentId != grp.RootPart.OwnerID) && Permissions.PropagatePermissions())
2059 {
2060 item.BasePermissions = permsBase & grp.RootPart.NextOwnerMask;
2061 item.CurrentPermissions = permsBase & grp.RootPart.NextOwnerMask;
2062 item.NextPermissions = permsBase & grp.RootPart.NextOwnerMask;
2063 item.EveryOnePermissions = permsBase & grp.RootPart.EveryoneMask & grp.RootPart.NextOwnerMask;
2064 item.GroupPermissions = permsBase & grp.RootPart.GroupMask & grp.RootPart.NextOwnerMask;
2065 }
2066 else
2067 {
2068 item.BasePermissions = permsBase;
2069 item.CurrentPermissions = permsBase & grp.RootPart.OwnerMask;
2070 item.NextPermissions = permsBase & grp.RootPart.NextOwnerMask;
2071 item.EveryOnePermissions = permsBase & grp.RootPart.EveryoneMask;
2072 item.GroupPermissions = permsBase & grp.RootPart.GroupMask;
2073 }
2074 item.CreationDate = Util.UnixTimeSinceEpoch();
2075
2076 // sets itemID so client can show item as 'attached' in inventory
2077 grp.SetFromItemID(item.ID);
2078
2079 if (AddInventoryItem(item))
2080 remoteClient.SendInventoryItemCreateUpdate(item, 0);
2081 else
2082 m_dialogModule.SendAlertToUser(remoteClient, "Operation failed");
2083
2084 itemID = item.ID;
2085 return item.AssetID;
2086 }
2087 return UUID.Zero;
2088 }
2089
1953 /// <summary> 2090 /// <summary>
1954 /// Event Handler Rez an object into a scene 2091 /// Event Handler Rez an object into a scene
1955 /// Calls the non-void event handler 2092 /// Calls the non-void event handler
@@ -2076,6 +2213,9 @@ namespace OpenSim.Region.Framework.Scenes
2076 2213
2077 public void SetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID, bool running) 2214 public void SetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID, bool running)
2078 { 2215 {
2216 if (!Permissions.CanEditScript(itemID, objectID, controllingClient.AgentId))
2217 return;
2218
2079 SceneObjectPart part = GetSceneObjectPart(objectID); 2219 SceneObjectPart part = GetSceneObjectPart(objectID);
2080 if (part == null) 2220 if (part == null)
2081 return; 2221 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 4c8e2d2..bbdf35d 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;
@@ -677,6 +700,7 @@ namespace OpenSim.Region.Framework.Scenes
677 m_persistAfter *= 10000000; 700 m_persistAfter *= 10000000;
678 701
679 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine"); 702 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine");
703 m_log.InfoFormat("[SCENE]: Default script engine {0}", m_defaultScriptEngine);
680 704
681 IConfig packetConfig = m_config.Configs["PacketPool"]; 705 IConfig packetConfig = m_config.Configs["PacketPool"];
682 if (packetConfig != null) 706 if (packetConfig != null)
@@ -686,6 +710,8 @@ namespace OpenSim.Region.Framework.Scenes
686 } 710 }
687 711
688 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl); 712 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl);
713 m_seeIntoBannedRegion = startupConfig.GetBoolean("SeeIntoBannedRegion", m_seeIntoBannedRegion);
714 CombineRegions = startupConfig.GetBoolean("CombineContiguousRegions", false);
689 715
690 m_generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", true); 716 m_generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", true);
691 if (m_generateMaptiles) 717 if (m_generateMaptiles)
@@ -721,9 +747,9 @@ namespace OpenSim.Region.Framework.Scenes
721 m_update_terrain = startupConfig.GetInt( "UpdateTerrainEveryNFrames", m_update_terrain); 747 m_update_terrain = startupConfig.GetInt( "UpdateTerrainEveryNFrames", m_update_terrain);
722 m_update_temp_cleaning = startupConfig.GetInt( "UpdateTempCleaningEveryNFrames", m_update_temp_cleaning); 748 m_update_temp_cleaning = startupConfig.GetInt( "UpdateTempCleaningEveryNFrames", m_update_temp_cleaning);
723 } 749 }
724 catch 750 catch (Exception e)
725 { 751 {
726 m_log.Warn("[SCENE]: Failed to load StartupConfig"); 752 m_log.Error("[SCENE]: Failed to load StartupConfig: " + e.ToString());
727 } 753 }
728 754
729 #endregion Region Config 755 #endregion Region Config
@@ -1134,7 +1160,22 @@ namespace OpenSim.Region.Framework.Scenes
1134 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat); 1160 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat);
1135 if (HeartbeatThread != null) 1161 if (HeartbeatThread != null)
1136 { 1162 {
1163 m_hbRestarts++;
1164 if(m_hbRestarts > 10)
1165 Environment.Exit(1);
1166 m_log.ErrorFormat("[SCENE]: Restarting heartbeat thread because it hasn't reported in in region {0}", RegionInfo.RegionName);
1167
1168//int pid = System.Diagnostics.Process.GetCurrentProcess().Id;
1169//System.Diagnostics.Process proc = new System.Diagnostics.Process();
1170//proc.EnableRaisingEvents=false;
1171//proc.StartInfo.FileName = "/bin/kill";
1172//proc.StartInfo.Arguments = "-QUIT " + pid.ToString();
1173//proc.Start();
1174//proc.WaitForExit();
1175//Thread.Sleep(1000);
1176//Environment.Exit(1);
1137 HeartbeatThread.Abort(); 1177 HeartbeatThread.Abort();
1178 Watchdog.AbortThread(HeartbeatThread.ManagedThreadId);
1138 HeartbeatThread = null; 1179 HeartbeatThread = null;
1139 } 1180 }
1140 m_lastUpdate = Util.EnvironmentTickCount(); 1181 m_lastUpdate = Util.EnvironmentTickCount();
@@ -1181,9 +1222,6 @@ namespace OpenSim.Region.Framework.Scenes
1181 m_eventManager.TriggerOnRegionStarted(this); 1222 m_eventManager.TriggerOnRegionStarted(this);
1182 while (!shuttingdown) 1223 while (!shuttingdown)
1183 Update(); 1224 Update();
1184
1185 m_lastUpdate = Util.EnvironmentTickCount();
1186 m_firstHeartbeat = false;
1187 } 1225 }
1188 catch (ThreadAbortException) 1226 catch (ThreadAbortException)
1189 { 1227 {
@@ -1281,6 +1319,13 @@ namespace OpenSim.Region.Framework.Scenes
1281 eventMS = Util.EnvironmentTickCountSubtract(evMS); ; 1319 eventMS = Util.EnvironmentTickCountSubtract(evMS); ;
1282 } 1320 }
1283 1321
1322 // if (Frame % m_update_land == 0)
1323 // {
1324 // int ldMS = Util.EnvironmentTickCount();
1325 // UpdateLand();
1326 // landMS = Util.EnvironmentTickCountSubtract(ldMS);
1327 // }
1328
1284 if (Frame % m_update_backup == 0) 1329 if (Frame % m_update_backup == 0)
1285 { 1330 {
1286 int backMS = Util.EnvironmentTickCount(); 1331 int backMS = Util.EnvironmentTickCount();
@@ -1390,12 +1435,16 @@ namespace OpenSim.Region.Framework.Scenes
1390 maintc = Util.EnvironmentTickCountSubtract(maintc); 1435 maintc = Util.EnvironmentTickCountSubtract(maintc);
1391 maintc = (int)(MinFrameTime * 1000) - maintc; 1436 maintc = (int)(MinFrameTime * 1000) - maintc;
1392 1437
1438
1439 m_lastUpdate = Util.EnvironmentTickCount();
1440 m_firstHeartbeat = false;
1441
1393 if (maintc > 0) 1442 if (maintc > 0)
1394 Thread.Sleep(maintc); 1443 Thread.Sleep(maintc);
1395 1444
1396 // Tell the watchdog that this thread is still alive 1445 // Tell the watchdog that this thread is still alive
1397 Watchdog.UpdateThread(); 1446 Watchdog.UpdateThread();
1398 } 1447 }
1399 1448
1400 public void AddGroupTarget(SceneObjectGroup grp) 1449 public void AddGroupTarget(SceneObjectGroup grp)
1401 { 1450 {
@@ -1411,9 +1460,9 @@ namespace OpenSim.Region.Framework.Scenes
1411 1460
1412 private void CheckAtTargets() 1461 private void CheckAtTargets()
1413 { 1462 {
1414 Dictionary<UUID, SceneObjectGroup>.ValueCollection objs; 1463 List<SceneObjectGroup> objs = new List<SceneObjectGroup>();
1415 lock (m_groupsWithTargets) 1464 lock (m_groupsWithTargets)
1416 objs = m_groupsWithTargets.Values; 1465 objs = new List<SceneObjectGroup>(m_groupsWithTargets.Values);
1417 1466
1418 foreach (SceneObjectGroup entry in objs) 1467 foreach (SceneObjectGroup entry in objs)
1419 entry.checkAtTargets(); 1468 entry.checkAtTargets();
@@ -1495,7 +1544,7 @@ namespace OpenSim.Region.Framework.Scenes
1495 msg.fromAgentName = "Server"; 1544 msg.fromAgentName = "Server";
1496 msg.dialog = (byte)19; // Object msg 1545 msg.dialog = (byte)19; // Object msg
1497 msg.fromGroup = false; 1546 msg.fromGroup = false;
1498 msg.offline = (byte)0; 1547 msg.offline = (byte)1;
1499 msg.ParentEstateID = RegionInfo.EstateSettings.ParentEstateID; 1548 msg.ParentEstateID = RegionInfo.EstateSettings.ParentEstateID;
1500 msg.Position = Vector3.Zero; 1549 msg.Position = Vector3.Zero;
1501 msg.RegionID = RegionInfo.RegionID.Guid; 1550 msg.RegionID = RegionInfo.RegionID.Guid;
@@ -1726,14 +1775,24 @@ namespace OpenSim.Region.Framework.Scenes
1726 /// <returns></returns> 1775 /// <returns></returns>
1727 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter) 1776 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter)
1728 { 1777 {
1778
1779 float wheight = (float)RegionInfo.RegionSettings.WaterHeight;
1780 Vector3 wpos = Vector3.Zero;
1781 // Check for water surface intersection from above
1782 if ( (RayStart.Z > wheight) && (RayEnd.Z < wheight) )
1783 {
1784 float ratio = (RayStart.Z - wheight) / (RayStart.Z - RayEnd.Z);
1785 wpos.X = RayStart.X - (ratio * (RayStart.X - RayEnd.X));
1786 wpos.Y = RayStart.Y - (ratio * (RayStart.Y - RayEnd.Y));
1787 wpos.Z = wheight;
1788 }
1789
1729 Vector3 pos = Vector3.Zero; 1790 Vector3 pos = Vector3.Zero;
1730 if (RayEndIsIntersection == (byte)1) 1791 if (RayEndIsIntersection == (byte)1)
1731 { 1792 {
1732 pos = RayEnd; 1793 pos = RayEnd;
1733 return pos;
1734 } 1794 }
1735 1795 else if (RayTargetID != UUID.Zero)
1736 if (RayTargetID != UUID.Zero)
1737 { 1796 {
1738 SceneObjectPart target = GetSceneObjectPart(RayTargetID); 1797 SceneObjectPart target = GetSceneObjectPart(RayTargetID);
1739 1798
@@ -1755,7 +1814,7 @@ namespace OpenSim.Region.Framework.Scenes
1755 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter); 1814 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter);
1756 1815
1757 // Un-comment out the following line to Get Raytrace results printed to the console. 1816 // 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()); 1817 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
1759 float ScaleOffset = 0.5f; 1818 float ScaleOffset = 0.5f;
1760 1819
1761 // If we hit something 1820 // If we hit something
@@ -1778,13 +1837,10 @@ namespace OpenSim.Region.Framework.Scenes
1778 //pos.Z -= 0.25F; 1837 //pos.Z -= 0.25F;
1779 1838
1780 } 1839 }
1781
1782 return pos;
1783 } 1840 }
1784 else 1841 else
1785 { 1842 {
1786 // We don't have a target here, so we're going to raytrace all the objects in the scene. 1843 // 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); 1844 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false);
1789 1845
1790 // Un-comment the following line to print the raytrace results to the console. 1846 // Un-comment the following line to print the raytrace results to the console.
@@ -1793,13 +1849,12 @@ namespace OpenSim.Region.Framework.Scenes
1793 if (ei.HitTF) 1849 if (ei.HitTF)
1794 { 1850 {
1795 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z); 1851 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z);
1796 } else 1852 }
1853 else
1797 { 1854 {
1798 // fall back to our stupid functionality 1855 // fall back to our stupid functionality
1799 pos = RayEnd; 1856 pos = RayEnd;
1800 } 1857 }
1801
1802 return pos;
1803 } 1858 }
1804 } 1859 }
1805 else 1860 else
@@ -1810,8 +1865,12 @@ namespace OpenSim.Region.Framework.Scenes
1810 //increase height so its above the ground. 1865 //increase height so its above the ground.
1811 //should be getting the normal of the ground at the rez point and using that? 1866 //should be getting the normal of the ground at the rez point and using that?
1812 pos.Z += scale.Z / 2f; 1867 pos.Z += scale.Z / 2f;
1813 return pos; 1868// return pos;
1814 } 1869 }
1870
1871 // check against posible water intercept
1872 if (wpos.Z > pos.Z) pos = wpos;
1873 return pos;
1815 } 1874 }
1816 1875
1817 1876
@@ -1895,7 +1954,10 @@ namespace OpenSim.Region.Framework.Scenes
1895 public bool AddRestoredSceneObject( 1954 public bool AddRestoredSceneObject(
1896 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 1955 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
1897 { 1956 {
1898 return m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates); 1957 bool result = m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates);
1958 if (result)
1959 sceneObject.IsDeleted = false;
1960 return result;
1899 } 1961 }
1900 1962
1901 /// <summary> 1963 /// <summary>
@@ -1987,6 +2049,15 @@ namespace OpenSim.Region.Framework.Scenes
1987 /// </summary> 2049 /// </summary>
1988 public void DeleteAllSceneObjects() 2050 public void DeleteAllSceneObjects()
1989 { 2051 {
2052 DeleteAllSceneObjects(false);
2053 }
2054
2055 /// <summary>
2056 /// Delete every object from the scene. This does not include attachments worn by avatars.
2057 /// </summary>
2058 public void DeleteAllSceneObjects(bool exceptNoCopy)
2059 {
2060 List<SceneObjectGroup> toReturn = new List<SceneObjectGroup>();
1990 lock (Entities) 2061 lock (Entities)
1991 { 2062 {
1992 EntityBase[] entities = Entities.GetEntities(); 2063 EntityBase[] entities = Entities.GetEntities();
@@ -1995,11 +2066,24 @@ namespace OpenSim.Region.Framework.Scenes
1995 if (e is SceneObjectGroup) 2066 if (e is SceneObjectGroup)
1996 { 2067 {
1997 SceneObjectGroup sog = (SceneObjectGroup)e; 2068 SceneObjectGroup sog = (SceneObjectGroup)e;
1998 if (!sog.IsAttachment) 2069 if (sog != null && !sog.IsAttachment)
1999 DeleteSceneObject((SceneObjectGroup)e, false); 2070 {
2071 if (!exceptNoCopy || ((sog.GetEffectivePermissions() & (uint)PermissionMask.Copy) != 0))
2072 {
2073 DeleteSceneObject((SceneObjectGroup)e, false);
2074 }
2075 else
2076 {
2077 toReturn.Add((SceneObjectGroup)e);
2078 }
2079 }
2000 } 2080 }
2001 } 2081 }
2002 } 2082 }
2083 if (toReturn.Count > 0)
2084 {
2085 returnObjects(toReturn.ToArray(), UUID.Zero);
2086 }
2003 } 2087 }
2004 2088
2005 /// <summary> 2089 /// <summary>
@@ -2047,6 +2131,8 @@ namespace OpenSim.Region.Framework.Scenes
2047 } 2131 }
2048 2132
2049 group.DeleteGroupFromScene(silent); 2133 group.DeleteGroupFromScene(silent);
2134 if (!silent)
2135 SendKillObject(new List<uint>() { group.LocalId });
2050 2136
2051// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID); 2137// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID);
2052 } 2138 }
@@ -2401,10 +2487,17 @@ namespace OpenSim.Region.Framework.Scenes
2401 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns> 2487 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns>
2402 public bool AddSceneObject(SceneObjectGroup sceneObject) 2488 public bool AddSceneObject(SceneObjectGroup sceneObject)
2403 { 2489 {
2490 if (sceneObject.OwnerID == UUID.Zero)
2491 {
2492 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero", sceneObject.UUID);
2493 return false;
2494 }
2495
2404 // If the user is banned, we won't let any of their objects 2496 // If the user is banned, we won't let any of their objects
2405 // enter. Period. 2497 // enter. Period.
2406 // 2498 //
2407 if (m_regInfo.EstateSettings.IsBanned(sceneObject.OwnerID)) 2499 int flags = GetUserFlags(sceneObject.OwnerID);
2500 if (m_regInfo.EstateSettings.IsBanned(sceneObject.OwnerID, flags))
2408 { 2501 {
2409 m_log.InfoFormat("[INTERREGION]: Denied prim crossing for banned avatar {0}", sceneObject.OwnerID); 2502 m_log.InfoFormat("[INTERREGION]: Denied prim crossing for banned avatar {0}", sceneObject.OwnerID);
2410 2503
@@ -2450,12 +2543,23 @@ namespace OpenSim.Region.Framework.Scenes
2450 } 2543 }
2451 else 2544 else
2452 { 2545 {
2546 m_log.DebugFormat("[SCENE]: Attachment {0} arrived and scene presence was not found, setting to temp", sceneObject.UUID);
2453 RootPrim.RemFlag(PrimFlags.TemporaryOnRez); 2547 RootPrim.RemFlag(PrimFlags.TemporaryOnRez);
2454 RootPrim.AddFlag(PrimFlags.TemporaryOnRez); 2548 RootPrim.AddFlag(PrimFlags.TemporaryOnRez);
2455 } 2549 }
2550 if (sceneObject.OwnerID == UUID.Zero)
2551 {
2552 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero after attachment processing. BUG!", sceneObject.UUID);
2553 return false;
2554 }
2456 } 2555 }
2457 else 2556 else
2458 { 2557 {
2558 if (sceneObject.OwnerID == UUID.Zero)
2559 {
2560 m_log.ErrorFormat("[SCENE]: Owner ID for non-attachment {0} was zero", sceneObject.UUID);
2561 return false;
2562 }
2459 AddRestoredSceneObject(sceneObject, true, false); 2563 AddRestoredSceneObject(sceneObject, true, false);
2460 2564
2461 if (!Permissions.CanObjectEntry(sceneObject.UUID, 2565 if (!Permissions.CanObjectEntry(sceneObject.UUID,
@@ -2484,6 +2588,24 @@ namespace OpenSim.Region.Framework.Scenes
2484 return 2; // StateSource.PrimCrossing 2588 return 2; // StateSource.PrimCrossing
2485 } 2589 }
2486 2590
2591 public int GetUserFlags(UUID user)
2592 {
2593 //Unfortunately the SP approach means that the value is cached until region is restarted
2594 /*
2595 ScenePresence sp;
2596 if (TryGetScenePresence(user, out sp))
2597 {
2598 return sp.UserFlags;
2599 }
2600 else
2601 {
2602 */
2603 UserAccount uac = UserAccountService.GetUserAccount(RegionInfo.ScopeID, user);
2604 if (uac == null)
2605 return 0;
2606 return uac.UserFlags;
2607 //}
2608 }
2487 #endregion 2609 #endregion
2488 2610
2489 #region Add/Remove Avatar Methods 2611 #region Add/Remove Avatar Methods
@@ -2498,6 +2620,7 @@ namespace OpenSim.Region.Framework.Scenes
2498 || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; 2620 || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0;
2499 2621
2500 CheckHeartbeat(); 2622 CheckHeartbeat();
2623 ScenePresence presence;
2501 2624
2502 ScenePresence sp = GetScenePresence(client.AgentId); 2625 ScenePresence sp = GetScenePresence(client.AgentId);
2503 2626
@@ -2546,7 +2669,13 @@ namespace OpenSim.Region.Framework.Scenes
2546 2669
2547 EventManager.TriggerOnNewClient(client); 2670 EventManager.TriggerOnNewClient(client);
2548 if (vialogin) 2671 if (vialogin)
2672 {
2549 EventManager.TriggerOnClientLogin(client); 2673 EventManager.TriggerOnClientLogin(client);
2674 // Send initial parcel data
2675 Vector3 pos = sp.AbsolutePosition;
2676 ILandObject land = LandChannel.GetLandObject(pos.X, pos.Y);
2677 land.SendLandUpdateToClient(client);
2678 }
2550 2679
2551 return sp; 2680 return sp;
2552 } 2681 }
@@ -2636,19 +2765,12 @@ namespace OpenSim.Region.Framework.Scenes
2636 // and the scene presence and the client, if they exist 2765 // and the scene presence and the client, if they exist
2637 try 2766 try
2638 { 2767 {
2639 // We need to wait for the client to make UDP contact first. 2768 ScenePresence sp = GetScenePresence(agentID);
2640 // It's the UDP contact that creates the scene presence 2769 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
2641 ScenePresence sp = WaitGetScenePresence(agentID); 2770
2642 if (sp != null) 2771 if (sp != null)
2643 {
2644 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
2645
2646 sp.ControllingClient.Close(); 2772 sp.ControllingClient.Close();
2647 } 2773
2648 else
2649 {
2650 m_log.WarnFormat("[SCENE]: Could not find scene presence for {0}", agentID);
2651 }
2652 // BANG! SLASH! 2774 // BANG! SLASH!
2653 m_authenticateHandler.RemoveCircuit(agentID); 2775 m_authenticateHandler.RemoveCircuit(agentID);
2654 2776
@@ -2749,6 +2871,7 @@ namespace OpenSim.Region.Framework.Scenes
2749 client.OnFetchInventory += m_asyncInventorySender.HandleFetchInventory; 2871 client.OnFetchInventory += m_asyncInventorySender.HandleFetchInventory;
2750 client.OnUpdateInventoryItem += UpdateInventoryItemAsset; 2872 client.OnUpdateInventoryItem += UpdateInventoryItemAsset;
2751 client.OnCopyInventoryItem += CopyInventoryItem; 2873 client.OnCopyInventoryItem += CopyInventoryItem;
2874 client.OnMoveItemsAndLeaveCopy += MoveInventoryItemsLeaveCopy;
2752 client.OnMoveInventoryItem += MoveInventoryItem; 2875 client.OnMoveInventoryItem += MoveInventoryItem;
2753 client.OnRemoveInventoryItem += RemoveInventoryItem; 2876 client.OnRemoveInventoryItem += RemoveInventoryItem;
2754 client.OnRemoveInventoryFolder += RemoveInventoryFolder; 2877 client.OnRemoveInventoryFolder += RemoveInventoryFolder;
@@ -2924,15 +3047,16 @@ namespace OpenSim.Region.Framework.Scenes
2924 /// </summary> 3047 /// </summary>
2925 /// <param name="agentId">The avatar's Unique ID</param> 3048 /// <param name="agentId">The avatar's Unique ID</param>
2926 /// <param name="client">The IClientAPI for the client</param> 3049 /// <param name="client">The IClientAPI for the client</param>
2927 public virtual void TeleportClientHome(UUID agentId, IClientAPI client) 3050 public virtual bool TeleportClientHome(UUID agentId, IClientAPI client)
2928 { 3051 {
2929 if (m_teleportModule != null) 3052 if (m_teleportModule != null)
2930 m_teleportModule.TeleportHome(agentId, client); 3053 return m_teleportModule.TeleportHome(agentId, client);
2931 else 3054 else
2932 { 3055 {
2933 m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active"); 3056 m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active");
2934 client.SendTeleportFailed("Unable to perform teleports on this simulator."); 3057 client.SendTeleportFailed("Unable to perform teleports on this simulator.");
2935 } 3058 }
3059 return false;
2936 } 3060 }
2937 3061
2938 /// <summary> 3062 /// <summary>
@@ -3042,6 +3166,16 @@ namespace OpenSim.Region.Framework.Scenes
3042 /// <param name="flags"></param> 3166 /// <param name="flags"></param>
3043 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags) 3167 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags)
3044 { 3168 {
3169 //Add half the avatar's height so that the user doesn't fall through prims
3170 ScenePresence presence;
3171 if (TryGetScenePresence(remoteClient.AgentId, out presence))
3172 {
3173 if (presence.Appearance != null)
3174 {
3175 position.Z = position.Z + (presence.Appearance.AvatarHeight / 2);
3176 }
3177 }
3178
3045 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt)) 3179 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. 3180 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot.
3047 m_dialogModule.SendAlertToUser(remoteClient, "Home position set."); 3181 m_dialogModule.SendAlertToUser(remoteClient, "Home position set.");
@@ -3110,8 +3244,9 @@ namespace OpenSim.Region.Framework.Scenes
3110 regions.Remove(RegionInfo.RegionHandle); 3244 regions.Remove(RegionInfo.RegionHandle);
3111 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); 3245 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions);
3112 } 3246 }
3113 3247 m_log.Debug("[Scene] Beginning ClientClosed");
3114 m_eventManager.TriggerClientClosed(agentID, this); 3248 m_eventManager.TriggerClientClosed(agentID, this);
3249 m_log.Debug("[Scene] Finished ClientClosed");
3115 } 3250 }
3116 catch (NullReferenceException) 3251 catch (NullReferenceException)
3117 { 3252 {
@@ -3173,9 +3308,10 @@ namespace OpenSim.Region.Framework.Scenes
3173 { 3308 {
3174 m_log.ErrorFormat("[SCENE] Scene.cs:RemoveClient exception {0}{1}", e.Message, e.StackTrace); 3309 m_log.ErrorFormat("[SCENE] Scene.cs:RemoveClient exception {0}{1}", e.Message, e.StackTrace);
3175 } 3310 }
3176 3311 m_log.Debug("[Scene] Done. Firing RemoveCircuit");
3177 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode); 3312 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode);
3178// CleanDroppedAttachments(); 3313// CleanDroppedAttachments();
3314 m_log.Debug("[Scene] The avatar has left the building");
3179 //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false)); 3315 //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)); 3316 //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true));
3181 } 3317 }
@@ -3294,13 +3430,16 @@ namespace OpenSim.Region.Framework.Scenes
3294 sp = null; 3430 sp = null;
3295 } 3431 }
3296 3432
3297 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3298 3433
3299 //On login test land permisions 3434 //On login test land permisions
3300 if (vialogin) 3435 if (vialogin)
3301 { 3436 {
3302 if (land != null && !TestLandRestrictions(agent, land, out reason)) 3437 IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>();
3438 if (cache != null)
3439 cache.Remove(agent.firstname + " " + agent.lastname);
3440 if (!TestLandRestrictions(agent.AgentID, out reason, ref agent.startpos.X, ref agent.startpos.Y))
3303 { 3441 {
3442 m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString());
3304 return false; 3443 return false;
3305 } 3444 }
3306 } 3445 }
@@ -3324,8 +3463,13 @@ namespace OpenSim.Region.Framework.Scenes
3324 3463
3325 try 3464 try
3326 { 3465 {
3327 if (!AuthorizeUser(agent, out reason)) 3466 // Always check estate if this is a login. Always
3328 return false; 3467 // check if banned regions are to be blacked out.
3468 if (vialogin || (!m_seeIntoBannedRegion))
3469 {
3470 if (!AuthorizeUser(agent, out reason))
3471 return false;
3472 }
3329 } 3473 }
3330 catch (Exception e) 3474 catch (Exception e)
3331 { 3475 {
@@ -3428,6 +3572,8 @@ namespace OpenSim.Region.Framework.Scenes
3428 } 3572 }
3429 } 3573 }
3430 // Honor parcel landing type and position. 3574 // Honor parcel landing type and position.
3575 /*
3576 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3431 if (land != null) 3577 if (land != null)
3432 { 3578 {
3433 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) 3579 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero)
@@ -3435,26 +3581,34 @@ namespace OpenSim.Region.Framework.Scenes
3435 agent.startpos = land.LandData.UserLocation; 3581 agent.startpos = land.LandData.UserLocation;
3436 } 3582 }
3437 } 3583 }
3584 */// This is now handled properly in ScenePresence.MakeRootAgent
3438 } 3585 }
3439 3586
3440 return true; 3587 return true;
3441 } 3588 }
3442 3589
3443 private bool TestLandRestrictions(AgentCircuitData agent, ILandObject land, out string reason) 3590 public bool TestLandRestrictions(UUID agentID, out string reason, ref float posX, ref float posY)
3444 { 3591 {
3445 3592 reason = String.Empty;
3446 bool banned = land.IsBannedFromLand(agent.AgentID); 3593 if (Permissions.IsGod(agentID))
3447 bool restricted = land.IsRestrictedFromLand(agent.AgentID); 3594 return true;
3595
3596 ILandObject land = LandChannel.GetLandObject(posX, posY);
3597 if (land == null)
3598 return false;
3599
3600 bool banned = land.IsBannedFromLand(agentID);
3601 bool restricted = land.IsRestrictedFromLand(agentID);
3448 3602
3449 if (banned || restricted) 3603 if (banned || restricted)
3450 { 3604 {
3451 ILandObject nearestParcel = GetNearestAllowedParcel(agent.AgentID, agent.startpos.X, agent.startpos.Y); 3605 ILandObject nearestParcel = GetNearestAllowedParcel(agentID, posX, posY);
3452 if (nearestParcel != null) 3606 if (nearestParcel != null)
3453 { 3607 {
3454 //Move agent to nearest allowed 3608 //Move agent to nearest allowed
3455 Vector3 newPosition = GetParcelCenterAtGround(nearestParcel); 3609 Vector3 newPosition = GetParcelCenterAtGround(nearestParcel);
3456 agent.startpos.X = newPosition.X; 3610 posX = newPosition.X;
3457 agent.startpos.Y = newPosition.Y; 3611 posY = newPosition.Y;
3458 } 3612 }
3459 else 3613 else
3460 { 3614 {
@@ -3516,7 +3670,7 @@ namespace OpenSim.Region.Framework.Scenes
3516 3670
3517 if (!m_strictAccessControl) return true; 3671 if (!m_strictAccessControl) return true;
3518 if (Permissions.IsGod(agent.AgentID)) return true; 3672 if (Permissions.IsGod(agent.AgentID)) return true;
3519 3673
3520 if (AuthorizationService != null) 3674 if (AuthorizationService != null)
3521 { 3675 {
3522 if (!AuthorizationService.IsAuthorizedForRegion( 3676 if (!AuthorizationService.IsAuthorizedForRegion(
@@ -3524,14 +3678,14 @@ namespace OpenSim.Region.Framework.Scenes
3524 { 3678 {
3525 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the region", 3679 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); 3680 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
3527 3681
3528 return false; 3682 return false;
3529 } 3683 }
3530 } 3684 }
3531 3685
3532 if (m_regInfo.EstateSettings != null) 3686 if (m_regInfo.EstateSettings != null)
3533 { 3687 {
3534 if (m_regInfo.EstateSettings.IsBanned(agent.AgentID)) 3688 if (m_regInfo.EstateSettings.IsBanned(agent.AgentID,0))
3535 { 3689 {
3536 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist", 3690 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); 3691 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
@@ -3723,6 +3877,13 @@ namespace OpenSim.Region.Framework.Scenes
3723 3877
3724 // We have to wait until the viewer contacts this region after receiving EAC. 3878 // We have to wait until the viewer contacts this region after receiving EAC.
3725 // That calls AddNewClient, which finally creates the ScenePresence 3879 // That calls AddNewClient, which finally creates the ScenePresence
3880 int flags = GetUserFlags(cAgentData.AgentID);
3881 if (m_regInfo.EstateSettings.IsBanned(cAgentData.AgentID, flags))
3882 {
3883 m_log.DebugFormat("[SCENE]: Denying root agent entry to {0}: banned", cAgentData.AgentID);
3884 return false;
3885 }
3886
3726 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2); 3887 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2);
3727 if (nearestParcel == null) 3888 if (nearestParcel == null)
3728 { 3889 {
@@ -3804,12 +3965,22 @@ namespace OpenSim.Region.Framework.Scenes
3804 return false; 3965 return false;
3805 } 3966 }
3806 3967
3968 public bool IncomingCloseAgent(UUID agentID)
3969 {
3970 return IncomingCloseAgent(agentID, false);
3971 }
3972
3973 public bool IncomingCloseChildAgent(UUID agentID)
3974 {
3975 return IncomingCloseAgent(agentID, true);
3976 }
3977
3807 /// <summary> 3978 /// <summary>
3808 /// Tell a single agent to disconnect from the region. 3979 /// Tell a single agent to disconnect from the region.
3809 /// </summary> 3980 /// </summary>
3810 /// <param name="regionHandle"></param>
3811 /// <param name="agentID"></param> 3981 /// <param name="agentID"></param>
3812 public bool IncomingCloseAgent(UUID agentID) 3982 /// <param name="childOnly"></param>
3983 public bool IncomingCloseAgent(UUID agentID, bool childOnly)
3813 { 3984 {
3814 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); 3985 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID);
3815 3986
@@ -3821,7 +3992,7 @@ namespace OpenSim.Region.Framework.Scenes
3821 { 3992 {
3822 m_sceneGraph.removeUserCount(false); 3993 m_sceneGraph.removeUserCount(false);
3823 } 3994 }
3824 else 3995 else if (!childOnly)
3825 { 3996 {
3826 m_sceneGraph.removeUserCount(true); 3997 m_sceneGraph.removeUserCount(true);
3827 } 3998 }
@@ -3837,9 +4008,12 @@ namespace OpenSim.Region.Framework.Scenes
3837 } 4008 }
3838 else 4009 else
3839 presence.ControllingClient.SendShutdownConnectionNotice(); 4010 presence.ControllingClient.SendShutdownConnectionNotice();
4011 presence.ControllingClient.Close(false);
4012 }
4013 else if (!childOnly)
4014 {
4015 presence.ControllingClient.Close(true);
3840 } 4016 }
3841
3842 presence.ControllingClient.Close();
3843 return true; 4017 return true;
3844 } 4018 }
3845 4019
@@ -4432,34 +4606,78 @@ namespace OpenSim.Region.Framework.Scenes
4432 SimulationDataService.RemoveObject(uuid, m_regInfo.RegionID); 4606 SimulationDataService.RemoveObject(uuid, m_regInfo.RegionID);
4433 } 4607 }
4434 4608
4435 public int GetHealth() 4609 public int GetHealth(out int flags, out string message)
4436 { 4610 {
4437 // Returns: 4611 // Returns:
4438 // 1 = sim is up and accepting http requests. The heartbeat has 4612 // 1 = sim is up and accepting http requests. The heartbeat has
4439 // stopped and the sim is probably locked up, but a remote 4613 // stopped and the sim is probably locked up, but a remote
4440 // admin restart may succeed 4614 // admin restart may succeed
4441 // 4615 //
4442 // 2 = Sim is up and the heartbeat is running. The sim is likely 4616 // 2 = Sim is up and the heartbeat is running. The sim is likely
4443 // usable for people within and logins _may_ work 4617 // usable for people within
4618 //
4619 // 3 = Sim is up and one packet thread is running. Sim is
4620 // unstable and will not accept new logins
4621 //
4622 // 4 = Sim is up and both packet threads are running. Sim is
4623 // likely usable
4444 // 4624 //
4445 // 3 = We have seen a new user enter within the past 4 minutes 4625 // 5 = We have seen a new user enter within the past 4 minutes
4446 // which can be seen as positive confirmation of sim health 4626 // which can be seen as positive confirmation of sim health
4447 // 4627 //
4628
4629 flags = 0;
4630 message = String.Empty;
4631
4632 CheckHeartbeat();
4633
4634 if (m_firstHeartbeat || (m_lastIncoming == 0 && m_lastOutgoing == 0))
4635 {
4636 // We're still starting
4637 // 0 means "in startup", it can't happen another way, since
4638 // to get here, we must be able to accept http connections
4639 return 0;
4640 }
4641
4448 int health=1; // Start at 1, means we're up 4642 int health=1; // Start at 1, means we're up
4449 4643
4450 if ((Util.EnvironmentTickCountSubtract(m_lastUpdate)) < 1000) 4644 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) < 1000)
4645 {
4646 health+=1;
4647 flags |= 1;
4648 }
4649
4650 if (Util.EnvironmentTickCountSubtract(m_lastIncoming) < 1000)
4651 {
4652 health+=1;
4653 flags |= 2;
4654 }
4655
4656 if (Util.EnvironmentTickCountSubtract(m_lastOutgoing) < 1000)
4657 {
4451 health+=1; 4658 health+=1;
4659 flags |= 4;
4660 }
4452 else 4661 else
4662 {
4663int pid = System.Diagnostics.Process.GetCurrentProcess().Id;
4664System.Diagnostics.Process proc = new System.Diagnostics.Process();
4665proc.EnableRaisingEvents=false;
4666proc.StartInfo.FileName = "/bin/kill";
4667proc.StartInfo.Arguments = "-QUIT " + pid.ToString();
4668proc.Start();
4669proc.WaitForExit();
4670Thread.Sleep(1000);
4671Environment.Exit(1);
4672 }
4673
4674 if (flags != 7)
4453 return health; 4675 return health;
4454 4676
4455 // A login in the last 4 mins? We can't be doing too badly 4677 // A login in the last 4 mins? We can't be doing too badly
4456 // 4678 //
4457 if ((Util.EnvironmentTickCountSubtract(m_LastLogin)) < 240000) 4679 if (Util.EnvironmentTickCountSubtract(m_LastLogin) < 240000)
4458 health++; 4680 health++;
4459 else
4460 return health;
4461
4462 CheckHeartbeat();
4463 4681
4464 return health; 4682 return health;
4465 } 4683 }
@@ -4652,7 +4870,7 @@ namespace OpenSim.Region.Framework.Scenes
4652 if (m_firstHeartbeat) 4870 if (m_firstHeartbeat)
4653 return; 4871 return;
4654 4872
4655 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) > 2000) 4873 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) > 5000)
4656 StartTimer(); 4874 StartTimer();
4657 } 4875 }
4658 4876
@@ -4666,9 +4884,14 @@ namespace OpenSim.Region.Framework.Scenes
4666 get { return m_allowScriptCrossings; } 4884 get { return m_allowScriptCrossings; }
4667 } 4885 }
4668 4886
4669 public Vector3? GetNearestAllowedPosition(ScenePresence avatar) 4887 public Vector3 GetNearestAllowedPosition(ScenePresence avatar)
4888 {
4889 return GetNearestAllowedPosition(avatar, null);
4890 }
4891
4892 public Vector3 GetNearestAllowedPosition(ScenePresence avatar, ILandObject excludeParcel)
4670 { 4893 {
4671 ILandObject nearestParcel = GetNearestAllowedParcel(avatar.UUID, avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); 4894 ILandObject nearestParcel = GetNearestAllowedParcel(avatar.UUID, avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y, excludeParcel);
4672 4895
4673 if (nearestParcel != null) 4896 if (nearestParcel != null)
4674 { 4897 {
@@ -4727,13 +4950,18 @@ namespace OpenSim.Region.Framework.Scenes
4727 4950
4728 public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y) 4951 public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y)
4729 { 4952 {
4953 return GetNearestAllowedParcel(avatarId, x, y, null);
4954 }
4955
4956 public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y, ILandObject excludeParcel)
4957 {
4730 List<ILandObject> all = AllParcels(); 4958 List<ILandObject> all = AllParcels();
4731 float minParcelDistance = float.MaxValue; 4959 float minParcelDistance = float.MaxValue;
4732 ILandObject nearestParcel = null; 4960 ILandObject nearestParcel = null;
4733 4961
4734 foreach (var parcel in all) 4962 foreach (var parcel in all)
4735 { 4963 {
4736 if (!parcel.IsEitherBannedOrRestricted(avatarId)) 4964 if (!parcel.IsEitherBannedOrRestricted(avatarId) && parcel != excludeParcel)
4737 { 4965 {
4738 float parcelDistance = GetParcelDistancefromPoint(parcel, x, y); 4966 float parcelDistance = GetParcelDistancefromPoint(parcel, x, y);
4739 if (parcelDistance < minParcelDistance) 4967 if (parcelDistance < minParcelDistance)
@@ -4975,7 +5203,55 @@ namespace OpenSim.Region.Framework.Scenes
4975 mapModule.GenerateMaptile(); 5203 mapModule.GenerateMaptile();
4976 } 5204 }
4977 5205
4978 private void RegenerateMaptileAndReregister(object sender, ElapsedEventArgs e) 5206// public void CleanDroppedAttachments()
5207// {
5208// List<SceneObjectGroup> objectsToDelete =
5209// new List<SceneObjectGroup>();
5210//
5211// lock (m_cleaningAttachments)
5212// {
5213// ForEachSOG(delegate (SceneObjectGroup grp)
5214// {
5215// if (grp.RootPart.Shape.PCode == 0 && grp.RootPart.Shape.State != 0 && (!objectsToDelete.Contains(grp)))
5216// {
5217// UUID agentID = grp.OwnerID;
5218// if (agentID == UUID.Zero)
5219// {
5220// objectsToDelete.Add(grp);
5221// return;
5222// }
5223//
5224// ScenePresence sp = GetScenePresence(agentID);
5225// if (sp == null)
5226// {
5227// objectsToDelete.Add(grp);
5228// return;
5229// }
5230// }
5231// });
5232// }
5233//
5234// foreach (SceneObjectGroup grp in objectsToDelete)
5235// {
5236// m_log.InfoFormat("[SCENE]: Deleting dropped attachment {0} of user {1}", grp.UUID, grp.OwnerID);
5237// DeleteSceneObject(grp, true);
5238// }
5239// }
5240
5241 public void ThreadAlive(int threadCode)
5242 {
5243 switch(threadCode)
5244 {
5245 case 1: // Incoming
5246 m_lastIncoming = Util.EnvironmentTickCount();
5247 break;
5248 case 2: // Incoming
5249 m_lastOutgoing = Util.EnvironmentTickCount();
5250 break;
5251 }
5252 }
5253
5254 public void RegenerateMaptileAndReregister(object sender, ElapsedEventArgs e)
4979 { 5255 {
4980 RegenerateMaptile(); 5256 RegenerateMaptile();
4981 5257
@@ -4994,6 +5270,14 @@ namespace OpenSim.Region.Framework.Scenes
4994 // child agent creation, thereby emulating the SL behavior. 5270 // child agent creation, thereby emulating the SL behavior.
4995 public bool QueryAccess(UUID agentID, Vector3 position, out string reason) 5271 public bool QueryAccess(UUID agentID, Vector3 position, out string reason)
4996 { 5272 {
5273 reason = "You are banned from the region";
5274
5275 if (Permissions.IsGod(agentID))
5276 {
5277 reason = String.Empty;
5278 return true;
5279 }
5280
4997 int num = m_sceneGraph.GetNumberOfScenePresences(); 5281 int num = m_sceneGraph.GetNumberOfScenePresences();
4998 5282
4999 if (num >= RegionInfo.RegionSettings.AgentLimit) 5283 if (num >= RegionInfo.RegionSettings.AgentLimit)
@@ -5005,6 +5289,41 @@ namespace OpenSim.Region.Framework.Scenes
5005 } 5289 }
5006 } 5290 }
5007 5291
5292 ScenePresence presence = GetScenePresence(agentID);
5293 IClientAPI client = null;
5294 AgentCircuitData aCircuit = null;
5295
5296 if (presence != null)
5297 {
5298 client = presence.ControllingClient;
5299 if (client != null)
5300 aCircuit = client.RequestClientInfo();
5301 }
5302
5303 // We may be called before there is a presence or a client.
5304 // Fake AgentCircuitData to keep IAuthorizationModule smiling
5305 if (client == null)
5306 {
5307 aCircuit = new AgentCircuitData();
5308 aCircuit.AgentID = agentID;
5309 aCircuit.firstname = String.Empty;
5310 aCircuit.lastname = String.Empty;
5311 }
5312
5313 try
5314 {
5315 if (!AuthorizeUser(aCircuit, out reason))
5316 {
5317 // m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID);
5318 return false;
5319 }
5320 }
5321 catch (Exception e)
5322 {
5323 m_log.DebugFormat("[SCENE]: Exception authorizing agent: {0} "+ e.StackTrace, e.Message);
5324 return false;
5325 }
5326
5008 if (position == Vector3.Zero) // Teleport 5327 if (position == Vector3.Zero) // Teleport
5009 { 5328 {
5010 if (!RegionInfo.EstateSettings.AllowDirectTeleport) 5329 if (!RegionInfo.EstateSettings.AllowDirectTeleport)
@@ -5033,13 +5352,46 @@ namespace OpenSim.Region.Framework.Scenes
5033 } 5352 }
5034 } 5353 }
5035 } 5354 }
5355
5356 float posX = 128.0f;
5357 float posY = 128.0f;
5358
5359 if (!TestLandRestrictions(agentID, out reason, ref posX, ref posY))
5360 {
5361 // m_log.DebugFormat("[SCENE]: Denying {0} because they are banned on all parcels", agentID);
5362 return false;
5363 }
5364 }
5365 else // Walking
5366 {
5367 ILandObject land = LandChannel.GetLandObject(position.X, position.Y);
5368 if (land == null)
5369 return false;
5370
5371 bool banned = land.IsBannedFromLand(agentID);
5372 bool restricted = land.IsRestrictedFromLand(agentID);
5373
5374 if (banned || restricted)
5375 return false;
5036 } 5376 }
5037 5377
5038 reason = String.Empty; 5378 reason = String.Empty;
5039 return true; 5379 return true;
5040 } 5380 }
5041 5381
5042 /// <summary> 5382 public void StartTimerWatchdog()
5383 {
5384 m_timerWatchdog.Interval = 1000;
5385 m_timerWatchdog.Elapsed += TimerWatchdog;
5386 m_timerWatchdog.AutoReset = true;
5387 m_timerWatchdog.Start();
5388 }
5389
5390 public void TimerWatchdog(object sender, ElapsedEventArgs e)
5391 {
5392 CheckHeartbeat();
5393 }
5394
5043 /// This method deals with movement when an avatar is automatically moving (but this is distinct from the 5395 /// 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!. 5396 /// autopilot that moves an avatar to a sit target!.
5045 /// </summary> 5397 /// </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 e66678a..5405358 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
@@ -1669,9 +1758,13 @@ namespace OpenSim.Region.Framework.Scenes
1669 // Make sure no child prim is set for sale 1758 // Make sure no child prim is set for sale
1670 // So that, on delink, no prims are unwittingly 1759 // So that, on delink, no prims are unwittingly
1671 // left for sale and sold off 1760 // left for sale and sold off
1672 child.RootPart.ObjectSaleType = 0; 1761
1673 child.RootPart.SalePrice = 10; 1762 if (child != null)
1674 childGroups.Add(child); 1763 {
1764 child.RootPart.ObjectSaleType = 0;
1765 child.RootPart.SalePrice = 10;
1766 childGroups.Add(child);
1767 }
1675 } 1768 }
1676 1769
1677 foreach (SceneObjectGroup child in childGroups) 1770 foreach (SceneObjectGroup child in childGroups)
@@ -1698,6 +1791,16 @@ namespace OpenSim.Region.Framework.Scenes
1698 } 1791 }
1699 finally 1792 finally
1700 { 1793 {
1794 lock (SceneObjectGroupsByLocalPartID)
1795 {
1796 foreach (SceneObjectPart part in parentGroup.Parts)
1797 SceneObjectGroupsByLocalPartID[part.LocalId] = parentGroup;
1798 }
1799
1800 parentGroup.areUpdatesSuspended = false;
1801 parentGroup.HasGroupChanged = true;
1802 parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true);
1803 parentGroup.ScheduleGroupForFullUpdate();
1701 Monitor.Exit(m_updateLock); 1804 Monitor.Exit(m_updateLock);
1702 } 1805 }
1703 } 1806 }
@@ -1734,21 +1837,24 @@ namespace OpenSim.Region.Framework.Scenes
1734 1837
1735 SceneObjectGroup group = part.ParentGroup; 1838 SceneObjectGroup group = part.ParentGroup;
1736 if (!affectedGroups.Contains(group)) 1839 if (!affectedGroups.Contains(group))
1840 {
1841 group.areUpdatesSuspended = true;
1737 affectedGroups.Add(group); 1842 affectedGroups.Add(group);
1843 }
1738 } 1844 }
1739 } 1845 }
1740 } 1846 }
1741 1847
1742 foreach (SceneObjectPart child in childParts) 1848 if (childParts.Count > 0)
1743 { 1849 {
1744 // Unlink all child parts from their groups 1850 foreach (SceneObjectPart child in childParts)
1745 // 1851 {
1746 child.ParentGroup.DelinkFromGroup(child, true); 1852 // Unlink all child parts from their groups
1747 1853 //
1748 // These are not in affected groups and will not be 1854 child.ParentGroup.DelinkFromGroup(child, true);
1749 // handled further. Do the honors here. 1855 child.ParentGroup.HasGroupChanged = true;
1750 child.ParentGroup.HasGroupChanged = true; 1856 child.ParentGroup.ScheduleGroupForFullUpdate();
1751 child.ParentGroup.ScheduleGroupForFullUpdate(); 1857 }
1752 } 1858 }
1753 1859
1754 foreach (SceneObjectPart root in rootParts) 1860 foreach (SceneObjectPart root in rootParts)
@@ -1758,56 +1864,68 @@ namespace OpenSim.Region.Framework.Scenes
1758 // However, editing linked parts and unlinking may be different 1864 // However, editing linked parts and unlinking may be different
1759 // 1865 //
1760 SceneObjectGroup group = root.ParentGroup; 1866 SceneObjectGroup group = root.ParentGroup;
1867 group.areUpdatesSuspended = true;
1761 1868
1762 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); 1869 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts);
1763 int numChildren = newSet.Count; 1870 int numChildren = newSet.Count;
1764 1871
1872 if (numChildren == 1)
1873 break;
1874
1765 // If there are prims left in a link set, but the root is 1875 // If there are prims left in a link set, but the root is
1766 // slated for unlink, we need to do this 1876 // slated for unlink, we need to do this
1877 // Unlink the remaining set
1767 // 1878 //
1768 if (numChildren != 1) 1879 bool sendEventsToRemainder = true;
1769 { 1880 if (numChildren > 1)
1770 // Unlink the remaining set 1881 sendEventsToRemainder = false;
1771 //
1772 bool sendEventsToRemainder = true;
1773 if (numChildren > 1)
1774 sendEventsToRemainder = false;
1775 1882
1776 foreach (SceneObjectPart p in newSet) 1883 foreach (SceneObjectPart p in newSet)
1884 {
1885 if (p != group.RootPart)
1777 { 1886 {
1778 if (p != group.RootPart) 1887 group.DelinkFromGroup(p, sendEventsToRemainder);
1779 group.DelinkFromGroup(p, sendEventsToRemainder); 1888 if (numChildren > 2)
1889 {
1890 p.ParentGroup.areUpdatesSuspended = true;
1891 }
1892 else
1893 {
1894 p.ParentGroup.HasGroupChanged = true;
1895 p.ParentGroup.ScheduleGroupForFullUpdate();
1896 }
1780 } 1897 }
1898 }
1899
1900 // If there is more than one prim remaining, we
1901 // need to re-link
1902 //
1903 if (numChildren > 2)
1904 {
1905 // Remove old root
1906 //
1907 if (newSet.Contains(root))
1908 newSet.Remove(root);
1781 1909
1782 // If there is more than one prim remaining, we 1910 // Preserve link ordering
1783 // need to re-link
1784 // 1911 //
1785 if (numChildren > 2) 1912 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1786 { 1913 {
1787 // Remove old root 1914 return a.LinkNum.CompareTo(b.LinkNum);
1788 // 1915 });
1789 if (newSet.Contains(root))
1790 newSet.Remove(root);
1791
1792 // Preserve link ordering
1793 //
1794 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1795 {
1796 return a.LinkNum.CompareTo(b.LinkNum);
1797 });
1798 1916
1799 // Determine new root 1917 // Determine new root
1800 // 1918 //
1801 SceneObjectPart newRoot = newSet[0]; 1919 SceneObjectPart newRoot = newSet[0];
1802 newSet.RemoveAt(0); 1920 newSet.RemoveAt(0);
1803 1921
1804 foreach (SceneObjectPart newChild in newSet) 1922 foreach (SceneObjectPart newChild in newSet)
1805 newChild.ClearUpdateSchedule(); 1923 newChild.ClearUpdateSchedule();
1806 1924
1807 LinkObjects(newRoot, newSet); 1925 newRoot.ParentGroup.areUpdatesSuspended = true;
1808 if (!affectedGroups.Contains(newRoot.ParentGroup)) 1926 LinkObjects(newRoot, newSet);
1809 affectedGroups.Add(newRoot.ParentGroup); 1927 if (!affectedGroups.Contains(newRoot.ParentGroup))
1810 } 1928 affectedGroups.Add(newRoot.ParentGroup);
1811 } 1929 }
1812 } 1930 }
1813 1931
@@ -1815,8 +1933,14 @@ namespace OpenSim.Region.Framework.Scenes
1815 // 1933 //
1816 foreach (SceneObjectGroup g in affectedGroups) 1934 foreach (SceneObjectGroup g in affectedGroups)
1817 { 1935 {
1936 // Child prims that have been unlinked and deleted will
1937 // return unless the root is deleted. This will remove them
1938 // from the database. They will be rewritten immediately,
1939 // minus the rows for the unlinked child prims.
1940 m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID);
1818 g.TriggerScriptChangedEvent(Changed.LINK); 1941 g.TriggerScriptChangedEvent(Changed.LINK);
1819 g.HasGroupChanged = true; // Persist 1942 g.HasGroupChanged = true; // Persist
1943 g.areUpdatesSuspended = false;
1820 g.ScheduleGroupForFullUpdate(); 1944 g.ScheduleGroupForFullUpdate();
1821 } 1945 }
1822 } 1946 }
@@ -1918,9 +2042,6 @@ namespace OpenSim.Region.Framework.Scenes
1918 child.ApplyNextOwnerPermissions(); 2042 child.ApplyNextOwnerPermissions();
1919 } 2043 }
1920 } 2044 }
1921
1922 copy.RootPart.ObjectSaleType = 0;
1923 copy.RootPart.SalePrice = 10;
1924 } 2045 }
1925 2046
1926 // FIXME: This section needs to be refactored so that it just calls AddSceneObject() 2047 // 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 a73d9b6..f3660a5 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
@@ -380,6 +384,9 @@ namespace OpenSim.Region.Framework.Scenes
380 384
381 public void ResumeScripts() 385 public void ResumeScripts()
382 { 386 {
387 if (m_scene.RegionInfo.RegionSettings.DisableScripts)
388 return;
389
383 SceneObjectPart[] parts = m_parts.GetArray(); 390 SceneObjectPart[] parts = m_parts.GetArray();
384 for (int i = 0; i < parts.Length; i++) 391 for (int i = 0; i < parts.Length; i++)
385 parts[i].Inventory.ResumeScripts(); 392 parts[i].Inventory.ResumeScripts();
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 5b838f8..a4ca0fb 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; }
@@ -392,10 +465,84 @@ namespace OpenSim.Region.Framework.Scenes
392 || Scene.TestBorderCross(val - Vector3.UnitY, Cardinals.N) || Scene.TestBorderCross(val + Vector3.UnitY, Cardinals.S)) 465 || Scene.TestBorderCross(val - Vector3.UnitY, Cardinals.N) || Scene.TestBorderCross(val + Vector3.UnitY, Cardinals.S))
393 && !IsAttachmentCheckFull() && (!Scene.LoadingPrims)) 466 && !IsAttachmentCheckFull() && (!Scene.LoadingPrims))
394 { 467 {
395 m_scene.CrossPrimGroupIntoNewRegion(val, this, true); 468 IEntityTransferModule entityTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>();
469 uint x = 0;
470 uint y = 0;
471 string version = String.Empty;
472 Vector3 newpos = Vector3.Zero;
473 OpenSim.Services.Interfaces.GridRegion destination = null;
474
475 bool canCross = true;
476 foreach (ScenePresence av in m_linkedAvatars)
477 {
478 // We need to cross these agents. First, let's find
479 // out if any of them can't cross for some reason.
480 // We have to deny the crossing entirely if any
481 // of them are banned. Alternatively, we could
482 // unsit banned agents....
483
484
485 // We set the avatar position as being the object
486 // position to get the region to send to
487 if ((destination = entityTransfer.GetDestination(m_scene, av.UUID, val, out x, out y, out version, out newpos)) == null)
488 {
489 canCross = false;
490 break;
491 }
492
493 m_log.DebugFormat("[SCENE OBJECT]: Avatar {0} needs to be crossed to {1}", av.Name, destination.RegionName);
494 }
495
496 if (canCross)
497 {
498 // We unparent the SP quietly so that it won't
499 // be made to stand up
500 foreach (ScenePresence av in m_linkedAvatars)
501 {
502 SceneObjectPart parentPart = m_scene.GetSceneObjectPart(av.ParentID);
503 if (parentPart != null)
504 av.ParentUUID = parentPart.UUID;
505
506 av.ParentID = 0;
507 }
508
509 m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
510
511 // Normalize
512 if (val.X >= Constants.RegionSize)
513 val.X -= Constants.RegionSize;
514 if (val.Y >= Constants.RegionSize)
515 val.Y -= Constants.RegionSize;
516 if (val.X < 0)
517 val.X += Constants.RegionSize;
518 if (val.Y < 0)
519 val.Y += Constants.RegionSize;
520
521 // If it's deleted, crossing was successful
522 if (IsDeleted)
523 {
524 foreach (ScenePresence av in m_linkedAvatars)
525 {
526 m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar {0} to {1}", av.Name, val);
527
528 av.IsInTransit = true;
529
530 CrossAgentToNewRegionDelegate d = entityTransfer.CrossAgentToNewRegionAsync;
531 d.BeginInvoke(av, val, x, y, destination, av.Flying, version, CrossAgentToNewRegionCompleted, d);
532 }
533
534 return;
535 }
536 }
537
538 val = AbsolutePosition;
396 } 539 }
397 } 540 }
398 541
542 foreach (SceneObjectPart part in m_parts.GetArray())
543 {
544 part.IgnoreUndoUpdate = true;
545 }
399 if (RootPart.GetStatusSandbox()) 546 if (RootPart.GetStatusSandbox())
400 { 547 {
401 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) 548 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10)
@@ -409,10 +556,30 @@ namespace OpenSim.Region.Framework.Scenes
409 return; 556 return;
410 } 557 }
411 } 558 }
412
413 SceneObjectPart[] parts = m_parts.GetArray(); 559 SceneObjectPart[] parts = m_parts.GetArray();
414 for (int i = 0; i < parts.Length; i++) 560 bool triggerScriptEvent = m_rootPart.GroupPosition != val;
415 parts[i].GroupPosition = val; 561 if (m_dupeInProgress)
562 triggerScriptEvent = false;
563 foreach (SceneObjectPart part in parts)
564 {
565 part.GroupPosition = val;
566 if (triggerScriptEvent)
567 part.TriggerScriptChangedEvent(Changed.POSITION);
568 }
569 if (!m_dupeInProgress)
570 {
571 foreach (ScenePresence av in m_linkedAvatars)
572 {
573 SceneObjectPart p = m_scene.GetSceneObjectPart(av.ParentID);
574 if (m_parts.TryGetValue(p.UUID, out p))
575 {
576 Vector3 offset = p.GetWorldPosition() - av.ParentPosition;
577 av.AbsolutePosition += offset;
578 av.ParentPosition = p.GetWorldPosition(); //ParentPosition gets cleared by AbsolutePosition
579 av.SendAvatarDataToAllAgents();
580 }
581 }
582 }
416 583
417 //if (m_rootPart.PhysActor != null) 584 //if (m_rootPart.PhysActor != null)
418 //{ 585 //{
@@ -427,6 +594,23 @@ namespace OpenSim.Region.Framework.Scenes
427 } 594 }
428 } 595 }
429 596
597 private void CrossAgentToNewRegionCompleted(IAsyncResult iar)
598 {
599 CrossAgentToNewRegionDelegate icon = (CrossAgentToNewRegionDelegate)iar.AsyncState;
600 ScenePresence agent = icon.EndInvoke(iar);
601
602 //// If the cross was successful, this agent is a child agent
603 //if (agent.IsChildAgent)
604 // agent.Reset();
605 //else // Not successful
606 // agent.RestoreInCurrentScene();
607
608 // In any case
609 agent.IsInTransit = false;
610
611 m_log.DebugFormat("[SCENE OBJECT]: Crossing agent {0} {1} completed.", agent.Firstname, agent.Lastname);
612 }
613
430 public override uint LocalId 614 public override uint LocalId
431 { 615 {
432 get { return m_rootPart.LocalId; } 616 get { return m_rootPart.LocalId; }
@@ -578,6 +762,7 @@ namespace OpenSim.Region.Framework.Scenes
578 /// </summary> 762 /// </summary>
579 public SceneObjectGroup() 763 public SceneObjectGroup()
580 { 764 {
765
581 } 766 }
582 767
583 /// <summary> 768 /// <summary>
@@ -594,7 +779,7 @@ namespace OpenSim.Region.Framework.Scenes
594 /// Constructor. This object is added to the scene later via AttachToScene() 779 /// Constructor. This object is added to the scene later via AttachToScene()
595 /// </summary> 780 /// </summary>
596 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) 781 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape)
597 { 782 {
598 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero)); 783 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero));
599 } 784 }
600 785
@@ -642,6 +827,9 @@ namespace OpenSim.Region.Framework.Scenes
642 /// </summary> 827 /// </summary>
643 public virtual void AttachToBackup() 828 public virtual void AttachToBackup()
644 { 829 {
830 if (IsAttachment) return;
831 m_scene.SceneGraph.FireAttachToBackup(this);
832
645 if (InSceneBackup) 833 if (InSceneBackup)
646 { 834 {
647 //m_log.DebugFormat( 835 //m_log.DebugFormat(
@@ -684,6 +872,9 @@ namespace OpenSim.Region.Framework.Scenes
684 872
685 ApplyPhysics(); 873 ApplyPhysics();
686 874
875 if (RootPart.PhysActor != null)
876 RootPart.Buoyancy = RootPart.Buoyancy;
877
687 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled 878 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled
688 // for the same object with very different properties. The caller must schedule the update. 879 // for the same object with very different properties. The caller must schedule the update.
689 //ScheduleGroupForFullUpdate(); 880 //ScheduleGroupForFullUpdate();
@@ -699,6 +890,10 @@ namespace OpenSim.Region.Framework.Scenes
699 EntityIntersection result = new EntityIntersection(); 890 EntityIntersection result = new EntityIntersection();
700 891
701 SceneObjectPart[] parts = m_parts.GetArray(); 892 SceneObjectPart[] parts = m_parts.GetArray();
893
894 // Find closest hit here
895 float idist = float.MaxValue;
896
702 for (int i = 0; i < parts.Length; i++) 897 for (int i = 0; i < parts.Length; i++)
703 { 898 {
704 SceneObjectPart part = parts[i]; 899 SceneObjectPart part = parts[i];
@@ -713,11 +908,6 @@ namespace OpenSim.Region.Framework.Scenes
713 908
714 EntityIntersection inter = part.TestIntersectionOBB(hRay, parentrotation, frontFacesOnly, faceCenters); 909 EntityIntersection inter = part.TestIntersectionOBB(hRay, parentrotation, frontFacesOnly, faceCenters);
715 910
716 // This may need to be updated to the maximum draw distance possible..
717 // We might (and probably will) be checking for prim creation from other sims
718 // when the camera crosses the border.
719 float idist = Constants.RegionSize;
720
721 if (inter.HitTF) 911 if (inter.HitTF)
722 { 912 {
723 // We need to find the closest prim to return to the testcaller along the ray 913 // We need to find the closest prim to return to the testcaller along the ray
@@ -728,10 +918,11 @@ namespace OpenSim.Region.Framework.Scenes
728 result.obj = part; 918 result.obj = part;
729 result.normal = inter.normal; 919 result.normal = inter.normal;
730 result.distance = inter.distance; 920 result.distance = inter.distance;
921
922 idist = inter.distance;
731 } 923 }
732 } 924 }
733 } 925 }
734
735 return result; 926 return result;
736 } 927 }
737 928
@@ -751,17 +942,19 @@ namespace OpenSim.Region.Framework.Scenes
751 minZ = 8192f; 942 minZ = 8192f;
752 943
753 SceneObjectPart[] parts = m_parts.GetArray(); 944 SceneObjectPart[] parts = m_parts.GetArray();
754 for (int i = 0; i < parts.Length; i++) 945 foreach (SceneObjectPart part in parts)
755 { 946 {
756 SceneObjectPart part = parts[i];
757
758 Vector3 worldPos = part.GetWorldPosition(); 947 Vector3 worldPos = part.GetWorldPosition();
759 Vector3 offset = worldPos - AbsolutePosition; 948 Vector3 offset = worldPos - AbsolutePosition;
760 Quaternion worldRot; 949 Quaternion worldRot;
761 if (part.ParentID == 0) 950 if (part.ParentID == 0)
951 {
762 worldRot = part.RotationOffset; 952 worldRot = part.RotationOffset;
953 }
763 else 954 else
955 {
764 worldRot = part.GetWorldRotation(); 956 worldRot = part.GetWorldRotation();
957 }
765 958
766 Vector3 frontTopLeft; 959 Vector3 frontTopLeft;
767 Vector3 frontTopRight; 960 Vector3 frontTopRight;
@@ -773,6 +966,8 @@ namespace OpenSim.Region.Framework.Scenes
773 Vector3 backBottomLeft; 966 Vector3 backBottomLeft;
774 Vector3 backBottomRight; 967 Vector3 backBottomRight;
775 968
969 // Vector3[] corners = new Vector3[8];
970
776 Vector3 orig = Vector3.Zero; 971 Vector3 orig = Vector3.Zero;
777 972
778 frontTopLeft.X = orig.X - (part.Scale.X / 2); 973 frontTopLeft.X = orig.X - (part.Scale.X / 2);
@@ -807,6 +1002,38 @@ namespace OpenSim.Region.Framework.Scenes
807 backBottomRight.Y = orig.Y + (part.Scale.Y / 2); 1002 backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
808 backBottomRight.Z = orig.Z - (part.Scale.Z / 2); 1003 backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
809 1004
1005
1006
1007 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
1008 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
1009 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
1010 //m_log.InfoFormat("pre corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
1011 //m_log.InfoFormat("pre corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
1012 //m_log.InfoFormat("pre corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
1013 //m_log.InfoFormat("pre corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
1014 //m_log.InfoFormat("pre corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
1015
1016 //for (int i = 0; i < 8; i++)
1017 //{
1018 // corners[i] = corners[i] * worldRot;
1019 // corners[i] += offset;
1020
1021 // if (corners[i].X > maxX)
1022 // maxX = corners[i].X;
1023 // if (corners[i].X < minX)
1024 // minX = corners[i].X;
1025
1026 // if (corners[i].Y > maxY)
1027 // maxY = corners[i].Y;
1028 // if (corners[i].Y < minY)
1029 // minY = corners[i].Y;
1030
1031 // if (corners[i].Z > maxZ)
1032 // maxZ = corners[i].Y;
1033 // if (corners[i].Z < minZ)
1034 // minZ = corners[i].Z;
1035 //}
1036
810 frontTopLeft = frontTopLeft * worldRot; 1037 frontTopLeft = frontTopLeft * worldRot;
811 frontTopRight = frontTopRight * worldRot; 1038 frontTopRight = frontTopRight * worldRot;
812 frontBottomLeft = frontBottomLeft * worldRot; 1039 frontBottomLeft = frontBottomLeft * worldRot;
@@ -828,6 +1055,15 @@ namespace OpenSim.Region.Framework.Scenes
828 backTopLeft += offset; 1055 backTopLeft += offset;
829 backTopRight += offset; 1056 backTopRight += offset;
830 1057
1058 //m_log.InfoFormat("corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
1059 //m_log.InfoFormat("corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
1060 //m_log.InfoFormat("corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
1061 //m_log.InfoFormat("corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
1062 //m_log.InfoFormat("corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
1063 //m_log.InfoFormat("corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
1064 //m_log.InfoFormat("corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
1065 //m_log.InfoFormat("corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
1066
831 if (frontTopRight.X > maxX) 1067 if (frontTopRight.X > maxX)
832 maxX = frontTopRight.X; 1068 maxX = frontTopRight.X;
833 if (frontTopLeft.X > maxX) 1069 if (frontTopLeft.X > maxX)
@@ -973,15 +1209,20 @@ namespace OpenSim.Region.Framework.Scenes
973 1209
974 public void SaveScriptedState(XmlTextWriter writer) 1210 public void SaveScriptedState(XmlTextWriter writer)
975 { 1211 {
1212 SaveScriptedState(writer, false);
1213 }
1214
1215 public void SaveScriptedState(XmlTextWriter writer, bool oldIDs)
1216 {
976 XmlDocument doc = new XmlDocument(); 1217 XmlDocument doc = new XmlDocument();
977 Dictionary<UUID,string> states = new Dictionary<UUID,string>(); 1218 Dictionary<UUID,string> states = new Dictionary<UUID,string>();
978 1219
979 SceneObjectPart[] parts = m_parts.GetArray(); 1220 SceneObjectPart[] parts = m_parts.GetArray();
980 for (int i = 0; i < parts.Length; i++) 1221 for (int i = 0; i < parts.Length; i++)
981 { 1222 {
982 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(); 1223 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(oldIDs);
983 foreach (KeyValuePair<UUID, string> kvp in pstates) 1224 foreach (KeyValuePair<UUID, string> kvp in pstates)
984 states.Add(kvp.Key, kvp.Value); 1225 states[kvp.Key] = kvp.Value;
985 } 1226 }
986 1227
987 if (states.Count > 0) 1228 if (states.Count > 0)
@@ -1001,6 +1242,168 @@ namespace OpenSim.Region.Framework.Scenes
1001 } 1242 }
1002 1243
1003 /// <summary> 1244 /// <summary>
1245 /// Add the avatar to this linkset (avatar is sat).
1246 /// </summary>
1247 /// <param name="agentID"></param>
1248 public void AddAvatar(UUID agentID)
1249 {
1250 ScenePresence presence;
1251 if (m_scene.TryGetScenePresence(agentID, out presence))
1252 {
1253 if (!m_linkedAvatars.Contains(presence))
1254 {
1255 m_linkedAvatars.Add(presence);
1256 }
1257 }
1258 }
1259
1260 /// <summary>
1261 /// Delete the avatar from this linkset (avatar is unsat).
1262 /// </summary>
1263 /// <param name="agentID"></param>
1264 public void DeleteAvatar(UUID agentID)
1265 {
1266 ScenePresence presence;
1267 if (m_scene.TryGetScenePresence(agentID, out presence))
1268 {
1269 if (m_linkedAvatars.Contains(presence))
1270 {
1271 m_linkedAvatars.Remove(presence);
1272 }
1273 }
1274 }
1275
1276 /// <summary>
1277 /// Returns the list of linked presences (avatars sat on this group)
1278 /// </summary>
1279 /// <param name="agentID"></param>
1280 public List<ScenePresence> GetLinkedAvatars()
1281 {
1282 return m_linkedAvatars;
1283 }
1284
1285 /// <summary>
1286 /// Attach this scene object to the given avatar.
1287 /// </summary>
1288 /// <param name="agentID"></param>
1289 /// <param name="attachmentpoint"></param>
1290 /// <param name="AttachOffset"></param>
1291 private void AttachToAgent(
1292 ScenePresence avatar, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent)
1293 {
1294 if (avatar != null)
1295 {
1296 // don't attach attachments to child agents
1297 if (avatar.IsChildAgent) return;
1298
1299 // Remove from database and parcel prim count
1300 m_scene.DeleteFromStorage(so.UUID);
1301 m_scene.EventManager.TriggerParcelPrimCountTainted();
1302
1303 so.AttachedAvatar = avatar.UUID;
1304
1305 if (so.RootPart.PhysActor != null)
1306 {
1307 m_scene.PhysicsScene.RemovePrim(so.RootPart.PhysActor);
1308 so.RootPart.PhysActor = null;
1309 }
1310
1311 so.AbsolutePosition = attachOffset;
1312 so.RootPart.AttachedPos = attachOffset;
1313 so.IsAttachment = true;
1314 so.RootPart.SetParentLocalId(avatar.LocalId);
1315 so.AttachmentPoint = attachmentpoint;
1316
1317 avatar.AddAttachment(this);
1318
1319 if (!silent)
1320 {
1321 // Killing it here will cause the client to deselect it
1322 // It then reappears on the avatar, deselected
1323 // through the full update below
1324 //
1325 if (IsSelected)
1326 {
1327 m_scene.SendKillObject(new List<uint> { m_rootPart.LocalId });
1328 }
1329
1330 IsSelected = false; // fudge....
1331 ScheduleGroupForFullUpdate();
1332 }
1333 }
1334 else
1335 {
1336 m_log.WarnFormat(
1337 "[SOG]: Tried to add attachment {0} to avatar with UUID {1} in region {2} but the avatar is not present",
1338 UUID, avatar.ControllingClient.AgentId, Scene.RegionInfo.RegionName);
1339 }
1340 }
1341
1342 public byte GetAttachmentPoint()
1343 {
1344 return m_rootPart.Shape.State;
1345 }
1346
1347 public void DetachToGround()
1348 {
1349 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
1350 if (avatar == null)
1351 return;
1352
1353 avatar.RemoveAttachment(this);
1354
1355 Vector3 detachedpos = new Vector3(127f,127f,127f);
1356 if (avatar == null)
1357 return;
1358
1359 detachedpos = avatar.AbsolutePosition;
1360 RootPart.FromItemID = UUID.Zero;
1361
1362 AbsolutePosition = detachedpos;
1363 AttachedAvatar = UUID.Zero;
1364
1365 //SceneObjectPart[] parts = m_parts.GetArray();
1366 //for (int i = 0; i < parts.Length; i++)
1367 // parts[i].AttachedAvatar = UUID.Zero;
1368
1369 m_rootPart.SetParentLocalId(0);
1370 AttachmentPoint = (byte)0;
1371 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive);
1372 HasGroupChanged = true;
1373 RootPart.Rezzed = DateTime.Now;
1374 RootPart.RemFlag(PrimFlags.TemporaryOnRez);
1375 AttachToBackup();
1376 m_scene.EventManager.TriggerParcelPrimCountTainted();
1377 m_rootPart.ScheduleFullUpdate();
1378 m_rootPart.ClearUndoState();
1379 }
1380
1381 public void DetachToInventoryPrep()
1382 {
1383 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
1384 //Vector3 detachedpos = new Vector3(127f, 127f, 127f);
1385 if (avatar != null)
1386 {
1387 //detachedpos = avatar.AbsolutePosition;
1388 avatar.RemoveAttachment(this);
1389 }
1390
1391 AttachedAvatar = UUID.Zero;
1392
1393 /*SceneObjectPart[] parts = m_parts.GetArray();
1394 for (int i = 0; i < parts.Length; i++)
1395 parts[i].AttachedAvatar = UUID.Zero;*/
1396
1397 m_rootPart.SetParentLocalId(0);
1398 //m_rootPart.SetAttachmentPoint((byte)0);
1399 IsAttachment = false;
1400 AbsolutePosition = m_rootPart.AttachedPos;
1401 //m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_scene.m_physicalPrim);
1402 //AttachToBackup();
1403 //m_rootPart.ScheduleFullUpdate();
1404 }
1405
1406 /// <summary>
1004 /// 1407 ///
1005 /// </summary> 1408 /// </summary>
1006 /// <param name="part"></param> 1409 /// <param name="part"></param>
@@ -1050,7 +1453,10 @@ namespace OpenSim.Region.Framework.Scenes
1050 public void AddPart(SceneObjectPart part) 1453 public void AddPart(SceneObjectPart part)
1051 { 1454 {
1052 part.SetParent(this); 1455 part.SetParent(this);
1053 part.LinkNum = m_parts.Add(part.UUID, part); 1456 m_parts.Add(part.UUID, part);
1457
1458 part.LinkNum = m_parts.Count;
1459
1054 if (part.LinkNum == 2) 1460 if (part.LinkNum == 2)
1055 RootPart.LinkNum = 1; 1461 RootPart.LinkNum = 1;
1056 } 1462 }
@@ -1158,6 +1564,11 @@ namespace OpenSim.Region.Framework.Scenes
1158 /// <param name="silent">If true then deletion is not broadcast to clients</param> 1564 /// <param name="silent">If true then deletion is not broadcast to clients</param>
1159 public void DeleteGroupFromScene(bool silent) 1565 public void DeleteGroupFromScene(bool silent)
1160 { 1566 {
1567 // We need to keep track of this state in case this group is still queued for backup.
1568 IsDeleted = true;
1569
1570 DetachFromBackup();
1571
1161 SceneObjectPart[] parts = m_parts.GetArray(); 1572 SceneObjectPart[] parts = m_parts.GetArray();
1162 for (int i = 0; i < parts.Length; i++) 1573 for (int i = 0; i < parts.Length; i++)
1163 { 1574 {
@@ -1180,6 +1591,8 @@ namespace OpenSim.Region.Framework.Scenes
1180 } 1591 }
1181 }); 1592 });
1182 } 1593 }
1594
1595
1183 } 1596 }
1184 1597
1185 public void AddScriptLPS(int count) 1598 public void AddScriptLPS(int count)
@@ -1275,7 +1688,12 @@ namespace OpenSim.Region.Framework.Scenes
1275 1688
1276 public void SetOwnerId(UUID userId) 1689 public void SetOwnerId(UUID userId)
1277 { 1690 {
1278 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); 1691 ForEachPart(delegate(SceneObjectPart part)
1692 {
1693
1694 part.OwnerID = userId;
1695
1696 });
1279 } 1697 }
1280 1698
1281 public void ForEachPart(Action<SceneObjectPart> whatToDo) 1699 public void ForEachPart(Action<SceneObjectPart> whatToDo)
@@ -1307,11 +1725,17 @@ namespace OpenSim.Region.Framework.Scenes
1307 return; 1725 return;
1308 } 1726 }
1309 1727
1728 if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
1729 return;
1730
1310 // Since this is the top of the section of call stack for backing up a particular scene object, don't let 1731 // Since this is the top of the section of call stack for backing up a particular scene object, don't let
1311 // any exception propogate upwards. 1732 // any exception propogate upwards.
1312 try 1733 try
1313 { 1734 {
1314 if (!m_scene.ShuttingDown) // if shutting down then there will be nothing to handle the return so leave till next restart 1735 if (!m_scene.ShuttingDown || // if shutting down then there will be nothing to handle the return so leave till next restart
1736 m_scene.LoginsDisabled || // We're starting up or doing maintenance, don't mess with things
1737 m_scene.LoadingPrims) // Land may not be valid yet
1738
1315 { 1739 {
1316 ILandObject parcel = m_scene.LandChannel.GetLandObject( 1740 ILandObject parcel = m_scene.LandChannel.GetLandObject(
1317 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y); 1741 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y);
@@ -1338,6 +1762,7 @@ namespace OpenSim.Region.Framework.Scenes
1338 } 1762 }
1339 } 1763 }
1340 } 1764 }
1765
1341 } 1766 }
1342 1767
1343 if (m_scene.UseBackup && HasGroupChanged) 1768 if (m_scene.UseBackup && HasGroupChanged)
@@ -1345,6 +1770,20 @@ namespace OpenSim.Region.Framework.Scenes
1345 // don't backup while it's selected or you're asking for changes mid stream. 1770 // don't backup while it's selected or you're asking for changes mid stream.
1346 if (isTimeToPersist() || forcedBackup) 1771 if (isTimeToPersist() || forcedBackup)
1347 { 1772 {
1773 if (m_rootPart.PhysActor != null &&
1774 (!m_rootPart.PhysActor.IsPhysical))
1775 {
1776 // Possible ghost prim
1777 if (m_rootPart.PhysActor.Position != m_rootPart.GroupPosition)
1778 {
1779 foreach (SceneObjectPart part in m_parts.GetArray())
1780 {
1781 // Re-set physics actor positions and
1782 // orientations
1783 part.GroupPosition = m_rootPart.GroupPosition;
1784 }
1785 }
1786 }
1348// m_log.DebugFormat( 1787// m_log.DebugFormat(
1349// "[SCENE]: Storing {0}, {1} in {2}", 1788// "[SCENE]: Storing {0}, {1} in {2}",
1350// Name, UUID, m_scene.RegionInfo.RegionName); 1789// Name, UUID, m_scene.RegionInfo.RegionName);
@@ -1428,7 +1867,7 @@ namespace OpenSim.Region.Framework.Scenes
1428 // This is only necessary when userExposed is false! 1867 // This is only necessary when userExposed is false!
1429 1868
1430 bool previousAttachmentStatus = dupe.IsAttachment; 1869 bool previousAttachmentStatus = dupe.IsAttachment;
1431 1870
1432 if (!userExposed) 1871 if (!userExposed)
1433 dupe.IsAttachment = true; 1872 dupe.IsAttachment = true;
1434 1873
@@ -1446,11 +1885,11 @@ namespace OpenSim.Region.Framework.Scenes
1446 dupe.m_rootPart.TrimPermissions(); 1885 dupe.m_rootPart.TrimPermissions();
1447 1886
1448 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray()); 1887 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray());
1449 1888
1450 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) 1889 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1451 { 1890 {
1452 return p1.LinkNum.CompareTo(p2.LinkNum); 1891 return p1.LinkNum.CompareTo(p2.LinkNum);
1453 } 1892 }
1454 ); 1893 );
1455 1894
1456 foreach (SceneObjectPart part in partList) 1895 foreach (SceneObjectPart part in partList)
@@ -1470,7 +1909,7 @@ namespace OpenSim.Region.Framework.Scenes
1470 if (part.PhysActor != null && userExposed) 1909 if (part.PhysActor != null && userExposed)
1471 { 1910 {
1472 PrimitiveBaseShape pbs = newPart.Shape; 1911 PrimitiveBaseShape pbs = newPart.Shape;
1473 1912
1474 newPart.PhysActor 1913 newPart.PhysActor
1475 = m_scene.PhysicsScene.AddPrimShape( 1914 = m_scene.PhysicsScene.AddPrimShape(
1476 string.Format("{0}/{1}", newPart.Name, newPart.UUID), 1915 string.Format("{0}/{1}", newPart.Name, newPart.UUID),
@@ -1480,11 +1919,11 @@ namespace OpenSim.Region.Framework.Scenes
1480 newPart.RotationOffset, 1919 newPart.RotationOffset,
1481 part.PhysActor.IsPhysical, 1920 part.PhysActor.IsPhysical,
1482 newPart.LocalId); 1921 newPart.LocalId);
1483 1922
1484 newPart.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true); 1923 newPart.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true);
1485 } 1924 }
1486 } 1925 }
1487 1926
1488 if (userExposed) 1927 if (userExposed)
1489 { 1928 {
1490 dupe.UpdateParentIDs(); 1929 dupe.UpdateParentIDs();
@@ -1599,6 +2038,7 @@ namespace OpenSim.Region.Framework.Scenes
1599 return Vector3.Zero; 2038 return Vector3.Zero;
1600 } 2039 }
1601 2040
2041 // This is used by both Double-Click Auto-Pilot and llMoveToTarget() in an attached object
1602 public void moveToTarget(Vector3 target, float tau) 2042 public void moveToTarget(Vector3 target, float tau)
1603 { 2043 {
1604 if (IsAttachment) 2044 if (IsAttachment)
@@ -1626,6 +2066,46 @@ namespace OpenSim.Region.Framework.Scenes
1626 RootPart.PhysActor.PIDActive = false; 2066 RootPart.PhysActor.PIDActive = false;
1627 } 2067 }
1628 2068
2069 public void rotLookAt(Quaternion target, float strength, float damping)
2070 {
2071 SceneObjectPart rootpart = m_rootPart;
2072 if (rootpart != null)
2073 {
2074 if (IsAttachment)
2075 {
2076 /*
2077 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
2078 if (avatar != null)
2079 {
2080 Rotate the Av?
2081 } */
2082 }
2083 else
2084 {
2085 if (rootpart.PhysActor != null)
2086 { // APID must be implemented in your physics system for this to function.
2087 rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W);
2088 rootpart.PhysActor.APIDStrength = strength;
2089 rootpart.PhysActor.APIDDamping = damping;
2090 rootpart.PhysActor.APIDActive = true;
2091 }
2092 }
2093 }
2094 }
2095
2096 public void stopLookAt()
2097 {
2098 SceneObjectPart rootpart = m_rootPart;
2099 if (rootpart != null)
2100 {
2101 if (rootpart.PhysActor != null)
2102 { // APID must be implemented in your physics system for this to function.
2103 rootpart.PhysActor.APIDActive = false;
2104 }
2105 }
2106
2107 }
2108
1629 /// <summary> 2109 /// <summary>
1630 /// Uses a PID to attempt to clamp the object on the Z axis at the given height over tau seconds. 2110 /// Uses a PID to attempt to clamp the object on the Z axis at the given height over tau seconds.
1631 /// </summary> 2111 /// </summary>
@@ -1681,6 +2161,8 @@ namespace OpenSim.Region.Framework.Scenes
1681 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) 2161 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
1682 { 2162 {
1683 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 2163 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
2164 newPart.SetParent(this);
2165
1684 AddPart(newPart); 2166 AddPart(newPart);
1685 2167
1686 SetPartAsNonRoot(newPart); 2168 SetPartAsNonRoot(newPart);
@@ -1809,11 +2291,11 @@ namespace OpenSim.Region.Framework.Scenes
1809 /// Immediately send a full update for this scene object. 2291 /// Immediately send a full update for this scene object.
1810 /// </summary> 2292 /// </summary>
1811 public void SendGroupFullUpdate() 2293 public void SendGroupFullUpdate()
1812 { 2294 {
1813 if (IsDeleted) 2295 if (IsDeleted)
1814 return; 2296 return;
1815 2297
1816// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); 2298// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID);
1817 2299
1818 RootPart.SendFullUpdateToAllClients(); 2300 RootPart.SendFullUpdateToAllClients();
1819 2301
@@ -1957,6 +2439,11 @@ namespace OpenSim.Region.Framework.Scenes
1957 /// <param name="objectGroup">The group of prims which should be linked to this group</param> 2439 /// <param name="objectGroup">The group of prims which should be linked to this group</param>
1958 public void LinkToGroup(SceneObjectGroup objectGroup) 2440 public void LinkToGroup(SceneObjectGroup objectGroup)
1959 { 2441 {
2442 LinkToGroup(objectGroup, false);
2443 }
2444
2445 public void LinkToGroup(SceneObjectGroup objectGroup, bool insert)
2446 {
1960// m_log.DebugFormat( 2447// m_log.DebugFormat(
1961// "[SCENE OBJECT GROUP]: Linking group with root part {0}, {1} to group with root part {2}, {3}", 2448// "[SCENE OBJECT GROUP]: Linking group with root part {0}, {1} to group with root part {2}, {3}",
1962// objectGroup.RootPart.Name, objectGroup.RootPart.UUID, RootPart.Name, RootPart.UUID); 2449// objectGroup.RootPart.Name, objectGroup.RootPart.UUID, RootPart.Name, RootPart.UUID);
@@ -1990,7 +2477,20 @@ namespace OpenSim.Region.Framework.Scenes
1990 2477
1991 lock (m_parts.SyncRoot) 2478 lock (m_parts.SyncRoot)
1992 { 2479 {
1993 int linkNum = PrimCount + 1; 2480 int linkNum;
2481 if (insert)
2482 {
2483 linkNum = 2;
2484 foreach (SceneObjectPart part in Parts)
2485 {
2486 if (part.LinkNum > 1)
2487 part.LinkNum++;
2488 }
2489 }
2490 else
2491 {
2492 linkNum = PrimCount + 1;
2493 }
1994 2494
1995 m_parts.Add(linkPart.UUID, linkPart); 2495 m_parts.Add(linkPart.UUID, linkPart);
1996 2496
@@ -2018,7 +2518,7 @@ namespace OpenSim.Region.Framework.Scenes
2018 objectGroup.IsDeleted = true; 2518 objectGroup.IsDeleted = true;
2019 2519
2020 objectGroup.m_parts.Clear(); 2520 objectGroup.m_parts.Clear();
2021 2521
2022 // Can't do this yet since backup still makes use of the root part without any synchronization 2522 // Can't do this yet since backup still makes use of the root part without any synchronization
2023// objectGroup.m_rootPart = null; 2523// objectGroup.m_rootPart = null;
2024 2524
@@ -2152,6 +2652,7 @@ namespace OpenSim.Region.Framework.Scenes
2152 /// <param name="objectGroup"></param> 2652 /// <param name="objectGroup"></param>
2153 public virtual void DetachFromBackup() 2653 public virtual void DetachFromBackup()
2154 { 2654 {
2655 m_scene.SceneGraph.FireDetachFromBackup(this);
2155 if (m_isBackedUp && Scene != null) 2656 if (m_isBackedUp && Scene != null)
2156 m_scene.EventManager.OnBackup -= ProcessBackup; 2657 m_scene.EventManager.OnBackup -= ProcessBackup;
2157 2658
@@ -2170,7 +2671,8 @@ namespace OpenSim.Region.Framework.Scenes
2170 2671
2171 axPos *= parentRot; 2672 axPos *= parentRot;
2172 part.OffsetPosition = axPos; 2673 part.OffsetPosition = axPos;
2173 part.GroupPosition = oldGroupPosition + part.OffsetPosition; 2674 Vector3 newPos = oldGroupPosition + part.OffsetPosition;
2675 part.GroupPosition = newPos;
2174 part.OffsetPosition = Vector3.Zero; 2676 part.OffsetPosition = Vector3.Zero;
2175 part.RotationOffset = worldRot; 2677 part.RotationOffset = worldRot;
2176 2678
@@ -2181,7 +2683,7 @@ namespace OpenSim.Region.Framework.Scenes
2181 2683
2182 part.LinkNum = linkNum; 2684 part.LinkNum = linkNum;
2183 2685
2184 part.OffsetPosition = part.GroupPosition - AbsolutePosition; 2686 part.OffsetPosition = newPos - AbsolutePosition;
2185 2687
2186 Quaternion rootRotation = m_rootPart.RotationOffset; 2688 Quaternion rootRotation = m_rootPart.RotationOffset;
2187 2689
@@ -2191,7 +2693,7 @@ namespace OpenSim.Region.Framework.Scenes
2191 2693
2192 parentRot = m_rootPart.RotationOffset; 2694 parentRot = m_rootPart.RotationOffset;
2193 oldRot = part.RotationOffset; 2695 oldRot = part.RotationOffset;
2194 Quaternion newRot = Quaternion.Inverse(parentRot) * oldRot; 2696 Quaternion newRot = Quaternion.Inverse(parentRot) * worldRot;
2195 part.RotationOffset = newRot; 2697 part.RotationOffset = newRot;
2196 } 2698 }
2197 2699
@@ -2438,8 +2940,12 @@ namespace OpenSim.Region.Framework.Scenes
2438 } 2940 }
2439 } 2941 }
2440 2942
2943 RootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect);
2441 for (int i = 0; i < parts.Length; i++) 2944 for (int i = 0; i < parts.Length; i++)
2442 parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect); 2945 {
2946 if (parts[i] != RootPart)
2947 parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect);
2948 }
2443 } 2949 }
2444 } 2950 }
2445 2951
@@ -2452,6 +2958,17 @@ namespace OpenSim.Region.Framework.Scenes
2452 } 2958 }
2453 } 2959 }
2454 2960
2961
2962
2963 /// <summary>
2964 /// Gets the number of parts
2965 /// </summary>
2966 /// <returns></returns>
2967 public int GetPartCount()
2968 {
2969 return Parts.Count();
2970 }
2971
2455 /// <summary> 2972 /// <summary>
2456 /// Update the texture entry for this part 2973 /// Update the texture entry for this part
2457 /// </summary> 2974 /// </summary>
@@ -2513,7 +3030,6 @@ namespace OpenSim.Region.Framework.Scenes
2513 { 3030 {
2514// m_log.DebugFormat( 3031// m_log.DebugFormat(
2515// "[SCENE OBJECT GROUP]: Group resizing {0} {1} from {2} to {3}", Name, LocalId, RootPart.Scale, scale); 3032// "[SCENE OBJECT GROUP]: Group resizing {0} {1} from {2} to {3}", Name, LocalId, RootPart.Scale, scale);
2516
2517 RootPart.StoreUndoState(true); 3033 RootPart.StoreUndoState(true);
2518 3034
2519 scale.X = Math.Min(scale.X, Scene.m_maxNonphys); 3035 scale.X = Math.Min(scale.X, Scene.m_maxNonphys);
@@ -2614,7 +3130,6 @@ namespace OpenSim.Region.Framework.Scenes
2614 prevScale.X *= x; 3130 prevScale.X *= x;
2615 prevScale.Y *= y; 3131 prevScale.Y *= y;
2616 prevScale.Z *= z; 3132 prevScale.Z *= z;
2617
2618// RootPart.IgnoreUndoUpdate = true; 3133// RootPart.IgnoreUndoUpdate = true;
2619 RootPart.Resize(prevScale); 3134 RootPart.Resize(prevScale);
2620// RootPart.IgnoreUndoUpdate = false; 3135// RootPart.IgnoreUndoUpdate = false;
@@ -2645,7 +3160,9 @@ namespace OpenSim.Region.Framework.Scenes
2645 } 3160 }
2646 3161
2647// obPart.IgnoreUndoUpdate = false; 3162// obPart.IgnoreUndoUpdate = false;
2648// obPart.StoreUndoState(); 3163 HasGroupChanged = true;
3164 m_rootPart.TriggerScriptChangedEvent(Changed.SCALE);
3165 ScheduleGroupForTerseUpdate();
2649 } 3166 }
2650 3167
2651// m_log.DebugFormat( 3168// m_log.DebugFormat(
@@ -2705,9 +3222,9 @@ namespace OpenSim.Region.Framework.Scenes
2705 { 3222 {
2706 SceneObjectPart part = GetChildPart(localID); 3223 SceneObjectPart part = GetChildPart(localID);
2707 3224
2708// SceneObjectPart[] parts = m_parts.GetArray(); 3225 SceneObjectPart[] parts = m_parts.GetArray();
2709// for (int i = 0; i < parts.Length; i++) 3226 for (int i = 0; i < parts.Length; i++)
2710// parts[i].StoreUndoState(); 3227 parts[i].StoreUndoState();
2711 3228
2712 if (part != null) 3229 if (part != null)
2713 { 3230 {
@@ -2763,10 +3280,27 @@ namespace OpenSim.Region.Framework.Scenes
2763 obPart.OffsetPosition = obPart.OffsetPosition + diff; 3280 obPart.OffsetPosition = obPart.OffsetPosition + diff;
2764 } 3281 }
2765 3282
2766 AbsolutePosition = newPos; 3283 //We have to set undoing here because otherwise an undo state will be saved
3284 if (!m_rootPart.Undoing)
3285 {
3286 m_rootPart.Undoing = true;
3287 AbsolutePosition = newPos;
3288 m_rootPart.Undoing = false;
3289 }
3290 else
3291 {
3292 AbsolutePosition = newPos;
3293 }
2767 3294
2768 HasGroupChanged = true; 3295 HasGroupChanged = true;
2769 ScheduleGroupForTerseUpdate(); 3296 if (m_rootPart.Undoing)
3297 {
3298 ScheduleGroupForFullUpdate();
3299 }
3300 else
3301 {
3302 ScheduleGroupForTerseUpdate();
3303 }
2770 } 3304 }
2771 3305
2772 #endregion 3306 #endregion
@@ -2843,10 +3377,7 @@ namespace OpenSim.Region.Framework.Scenes
2843 public void UpdateSingleRotation(Quaternion rot, uint localID) 3377 public void UpdateSingleRotation(Quaternion rot, uint localID)
2844 { 3378 {
2845 SceneObjectPart part = GetChildPart(localID); 3379 SceneObjectPart part = GetChildPart(localID);
2846
2847 SceneObjectPart[] parts = m_parts.GetArray(); 3380 SceneObjectPart[] parts = m_parts.GetArray();
2848 for (int i = 0; i < parts.Length; i++)
2849 parts[i].StoreUndoState();
2850 3381
2851 if (part != null) 3382 if (part != null)
2852 { 3383 {
@@ -2884,7 +3415,16 @@ namespace OpenSim.Region.Framework.Scenes
2884 if (part.UUID == m_rootPart.UUID) 3415 if (part.UUID == m_rootPart.UUID)
2885 { 3416 {
2886 UpdateRootRotation(rot); 3417 UpdateRootRotation(rot);
2887 AbsolutePosition = pos; 3418 if (!m_rootPart.Undoing)
3419 {
3420 m_rootPart.Undoing = true;
3421 AbsolutePosition = pos;
3422 m_rootPart.Undoing = false;
3423 }
3424 else
3425 {
3426 AbsolutePosition = pos;
3427 }
2888 } 3428 }
2889 else 3429 else
2890 { 3430 {
@@ -2908,9 +3448,10 @@ namespace OpenSim.Region.Framework.Scenes
2908 3448
2909 Quaternion axRot = rot; 3449 Quaternion axRot = rot;
2910 Quaternion oldParentRot = m_rootPart.RotationOffset; 3450 Quaternion oldParentRot = m_rootPart.RotationOffset;
2911
2912 m_rootPart.StoreUndoState(); 3451 m_rootPart.StoreUndoState();
2913 m_rootPart.UpdateRotation(rot); 3452
3453 //Don't use UpdateRotation because it schedules an update prematurely
3454 m_rootPart.RotationOffset = rot;
2914 if (m_rootPart.PhysActor != null) 3455 if (m_rootPart.PhysActor != null)
2915 { 3456 {
2916 m_rootPart.PhysActor.Orientation = m_rootPart.RotationOffset; 3457 m_rootPart.PhysActor.Orientation = m_rootPart.RotationOffset;
@@ -2924,15 +3465,17 @@ namespace OpenSim.Region.Framework.Scenes
2924 if (prim.UUID != m_rootPart.UUID) 3465 if (prim.UUID != m_rootPart.UUID)
2925 { 3466 {
2926 prim.IgnoreUndoUpdate = true; 3467 prim.IgnoreUndoUpdate = true;
3468
3469 Quaternion NewRot = oldParentRot * prim.RotationOffset;
3470 NewRot = Quaternion.Inverse(axRot) * NewRot;
3471 prim.RotationOffset = NewRot;
3472
2927 Vector3 axPos = prim.OffsetPosition; 3473 Vector3 axPos = prim.OffsetPosition;
3474
2928 axPos *= oldParentRot; 3475 axPos *= oldParentRot;
2929 axPos *= Quaternion.Inverse(axRot); 3476 axPos *= Quaternion.Inverse(axRot);
2930 prim.OffsetPosition = axPos; 3477 prim.OffsetPosition = axPos;
2931 Quaternion primsRot = prim.RotationOffset; 3478
2932 Quaternion newRot = oldParentRot * primsRot;
2933 newRot = Quaternion.Inverse(axRot) * newRot;
2934 prim.RotationOffset = newRot;
2935 prim.ScheduleTerseUpdate();
2936 prim.IgnoreUndoUpdate = false; 3479 prim.IgnoreUndoUpdate = false;
2937 } 3480 }
2938 } 3481 }
@@ -2946,8 +3489,8 @@ namespace OpenSim.Region.Framework.Scenes
2946//// childpart.StoreUndoState(); 3489//// childpart.StoreUndoState();
2947// } 3490// }
2948// } 3491// }
2949 3492 HasGroupChanged = true;
2950 m_rootPart.ScheduleTerseUpdate(); 3493 ScheduleGroupForFullUpdate();
2951 3494
2952// m_log.DebugFormat( 3495// m_log.DebugFormat(
2953// "[SCENE OBJECT GROUP]: Updated root rotation of {0} {1} to {2}", 3496// "[SCENE OBJECT GROUP]: Updated root rotation of {0} {1} to {2}",
@@ -3175,7 +3718,6 @@ namespace OpenSim.Region.Framework.Scenes
3175 public float GetMass() 3718 public float GetMass()
3176 { 3719 {
3177 float retmass = 0f; 3720 float retmass = 0f;
3178
3179 SceneObjectPart[] parts = m_parts.GetArray(); 3721 SceneObjectPart[] parts = m_parts.GetArray();
3180 for (int i = 0; i < parts.Length; i++) 3722 for (int i = 0; i < parts.Length; i++)
3181 retmass += parts[i].GetMass(); 3723 retmass += parts[i].GetMass();
@@ -3271,6 +3813,14 @@ namespace OpenSim.Region.Framework.Scenes
3271 SetFromItemID(uuid); 3813 SetFromItemID(uuid);
3272 } 3814 }
3273 3815
3816 public void ResetOwnerChangeFlag()
3817 {
3818 ForEachPart(delegate(SceneObjectPart part)
3819 {
3820 part.ResetOwnerChangeFlag();
3821 });
3822 }
3823
3274 #endregion 3824 #endregion
3275 } 3825 }
3276} 3826}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index b130bf7..6cde89c 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
@@ -341,7 +352,7 @@ namespace OpenSim.Region.Framework.Scenes
341 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition, 352 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition,
342 Quaternion rotationOffset, Vector3 offsetPosition) : this() 353 Quaternion rotationOffset, Vector3 offsetPosition) : this()
343 { 354 {
344 m_name = "Primitive"; 355 m_name = "Object";
345 356
346 CreationDate = (int)Utils.DateTimeToUnixTime(Rezzed); 357 CreationDate = (int)Utils.DateTimeToUnixTime(Rezzed);
347 LastOwnerID = CreatorID = OwnerID = ownerID; 358 LastOwnerID = CreatorID = OwnerID = ownerID;
@@ -381,7 +392,7 @@ namespace OpenSim.Region.Framework.Scenes
381 private uint _ownerMask = (uint)PermissionMask.All; 392 private uint _ownerMask = (uint)PermissionMask.All;
382 private uint _groupMask = (uint)PermissionMask.None; 393 private uint _groupMask = (uint)PermissionMask.None;
383 private uint _everyoneMask = (uint)PermissionMask.None; 394 private uint _everyoneMask = (uint)PermissionMask.None;
384 private uint _nextOwnerMask = (uint)PermissionMask.All; 395 private uint _nextOwnerMask = (uint)(PermissionMask.Move | PermissionMask.Modify | PermissionMask.Transfer);
385 private PrimFlags _flags = PrimFlags.None; 396 private PrimFlags _flags = PrimFlags.None;
386 private DateTime m_expires; 397 private DateTime m_expires;
387 private DateTime m_rezzed; 398 private DateTime m_rezzed;
@@ -475,12 +486,16 @@ namespace OpenSim.Region.Framework.Scenes
475 } 486 }
476 487
477 /// <value> 488 /// <value>
478 /// Access should be via Inventory directly - this property temporarily remains for xml serialization purposes 489 /// Get the inventory list
479 /// </value> 490 /// </value>
480 public TaskInventoryDictionary TaskInventory 491 public TaskInventoryDictionary TaskInventory
481 { 492 {
482 get { return m_inventory.Items; } 493 get {
483 set { m_inventory.Items = value; } 494 return m_inventory.Items;
495 }
496 set {
497 m_inventory.Items = value;
498 }
484 } 499 }
485 500
486 /// <summary> 501 /// <summary>
@@ -624,14 +639,12 @@ namespace OpenSim.Region.Framework.Scenes
624 set { m_LoopSoundSlavePrims = value; } 639 set { m_LoopSoundSlavePrims = value; }
625 } 640 }
626 641
627
628 public Byte[] TextureAnimation 642 public Byte[] TextureAnimation
629 { 643 {
630 get { return m_TextureAnimation; } 644 get { return m_TextureAnimation; }
631 set { m_TextureAnimation = value; } 645 set { m_TextureAnimation = value; }
632 } 646 }
633 647
634
635 public Byte[] ParticleSystem 648 public Byte[] ParticleSystem
636 { 649 {
637 get { return m_particleSystem; } 650 get { return m_particleSystem; }
@@ -668,9 +681,11 @@ namespace OpenSim.Region.Framework.Scenes
668 { 681 {
669 // If this is a linkset, we don't want the physics engine mucking up our group position here. 682 // If this is a linkset, we don't want the physics engine mucking up our group position here.
670 PhysicsActor actor = PhysActor; 683 PhysicsActor actor = PhysActor;
671 if (actor != null && ParentID == 0) 684 if (ParentID == 0)
672 { 685 {
673 m_groupPosition = actor.Position; 686 if (actor != null)
687 m_groupPosition = actor.Position;
688 return m_groupPosition;
674 } 689 }
675 690
676 if (ParentGroup.IsAttachment) 691 if (ParentGroup.IsAttachment)
@@ -680,12 +695,14 @@ namespace OpenSim.Region.Framework.Scenes
680 return sp.AbsolutePosition; 695 return sp.AbsolutePosition;
681 } 696 }
682 697
698 // use root prim's group position. Physics may have updated it
699 if (ParentGroup.RootPart != this)
700 m_groupPosition = ParentGroup.RootPart.GroupPosition;
683 return m_groupPosition; 701 return m_groupPosition;
684 } 702 }
685 set 703 set
686 { 704 {
687 m_groupPosition = value; 705 m_groupPosition = value;
688
689 PhysicsActor actor = PhysActor; 706 PhysicsActor actor = PhysActor;
690 if (actor != null) 707 if (actor != null)
691 { 708 {
@@ -711,16 +728,6 @@ namespace OpenSim.Region.Framework.Scenes
711 m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message); 728 m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message);
712 } 729 }
713 } 730 }
714
715 // TODO if we decide to do sitting in a more SL compatible way (multiple avatars per prim), this has to be fixed, too
716 if (SitTargetAvatar != UUID.Zero)
717 {
718 ScenePresence avatar;
719 if (ParentGroup.Scene.TryGetScenePresence(SitTargetAvatar, out avatar))
720 {
721 avatar.ParentPosition = GetWorldPosition();
722 }
723 }
724 } 731 }
725 } 732 }
726 733
@@ -729,7 +736,7 @@ namespace OpenSim.Region.Framework.Scenes
729 get { return m_offsetPosition; } 736 get { return m_offsetPosition; }
730 set 737 set
731 { 738 {
732// StoreUndoState(); 739 Vector3 oldpos = m_offsetPosition;
733 m_offsetPosition = value; 740 m_offsetPosition = value;
734 741
735 if (ParentGroup != null && !ParentGroup.IsDeleted) 742 if (ParentGroup != null && !ParentGroup.IsDeleted)
@@ -744,7 +751,22 @@ namespace OpenSim.Region.Framework.Scenes
744 if (ParentGroup.Scene != null) 751 if (ParentGroup.Scene != null)
745 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 752 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
746 } 753 }
754
755 if (!m_parentGroup.m_dupeInProgress)
756 {
757 List<ScenePresence> avs = ParentGroup.GetLinkedAvatars();
758 foreach (ScenePresence av in avs)
759 {
760 if (av.ParentID == m_localId)
761 {
762 Vector3 offset = (m_offsetPosition - oldpos);
763 av.AbsolutePosition += offset;
764 av.SendAvatarDataToAllAgents();
765 }
766 }
767 }
747 } 768 }
769 TriggerScriptChangedEvent(Changed.POSITION);
748 } 770 }
749 } 771 }
750 772
@@ -893,7 +915,16 @@ namespace OpenSim.Region.Framework.Scenes
893 /// <summary></summary> 915 /// <summary></summary>
894 public Vector3 Acceleration 916 public Vector3 Acceleration
895 { 917 {
896 get { return m_acceleration; } 918 get
919 {
920 PhysicsActor actor = PhysActor;
921 if (actor != null)
922 {
923 m_acceleration = actor.Acceleration;
924 }
925 return m_acceleration;
926 }
927
897 set { m_acceleration = value; } 928 set { m_acceleration = value; }
898 } 929 }
899 930
@@ -1030,10 +1061,7 @@ namespace OpenSim.Region.Framework.Scenes
1030 { 1061 {
1031 get 1062 get
1032 { 1063 {
1033 if (ParentGroup.IsAttachment) 1064 return GroupPosition + (m_offsetPosition * ParentGroup.RootPart.RotationOffset);
1034 return GroupPosition;
1035
1036 return m_offsetPosition + m_groupPosition;
1037 } 1065 }
1038 } 1066 }
1039 1067
@@ -1203,6 +1231,13 @@ namespace OpenSim.Region.Framework.Scenes
1203 _flags = value; 1231 _flags = value;
1204 } 1232 }
1205 } 1233 }
1234
1235 [XmlIgnore]
1236 public bool IsOccupied // KF If an av is sittingon this prim
1237 {
1238 get { return m_occupied; }
1239 set { m_occupied = value; }
1240 }
1206 1241
1207 /// <summary> 1242 /// <summary>
1208 /// ID of the avatar that is sat on us. If there is no such avatar then is UUID.Zero 1243 /// ID of the avatar that is sat on us. If there is no such avatar then is UUID.Zero
@@ -1262,6 +1297,19 @@ namespace OpenSim.Region.Framework.Scenes
1262 set { m_collisionSoundVolume = value; } 1297 set { m_collisionSoundVolume = value; }
1263 } 1298 }
1264 1299
1300 public float Buoyancy
1301 {
1302 get { return m_buoyancy; }
1303 set
1304 {
1305 m_buoyancy = value;
1306 if (PhysActor != null)
1307 {
1308 PhysActor.Buoyancy = value;
1309 }
1310 }
1311 }
1312
1265 #endregion Public Properties with only Get 1313 #endregion Public Properties with only Get
1266 1314
1267 private uint ApplyMask(uint val, bool set, uint mask) 1315 private uint ApplyMask(uint val, bool set, uint mask)
@@ -1582,6 +1630,9 @@ namespace OpenSim.Region.Framework.Scenes
1582 1630
1583 // Move afterwards ResetIDs as it clears the localID 1631 // Move afterwards ResetIDs as it clears the localID
1584 dupe.LocalId = localID; 1632 dupe.LocalId = localID;
1633 if(dupe.PhysActor != null)
1634 dupe.PhysActor.LocalID = localID;
1635
1585 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated. 1636 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated.
1586 dupe.LastOwnerID = OwnerID; 1637 dupe.LastOwnerID = OwnerID;
1587 1638
@@ -2587,17 +2638,18 @@ namespace OpenSim.Region.Framework.Scenes
2587 //Trys to fetch sound id from prim's inventory. 2638 //Trys to fetch sound id from prim's inventory.
2588 //Prim's inventory doesn't support non script items yet 2639 //Prim's inventory doesn't support non script items yet
2589 2640
2590 lock (TaskInventory) 2641 TaskInventory.LockItemsForRead(true);
2642
2643 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2591 { 2644 {
2592 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 2645 if (item.Value.Name == sound)
2593 { 2646 {
2594 if (item.Value.Name == sound) 2647 soundID = item.Value.ItemID;
2595 { 2648 break;
2596 soundID = item.Value.ItemID;
2597 break;
2598 }
2599 } 2649 }
2600 } 2650 }
2651
2652 TaskInventory.LockItemsForRead(false);
2601 } 2653 }
2602 2654
2603 ParentGroup.Scene.ForEachRootScenePresence(delegate(ScenePresence sp) 2655 ParentGroup.Scene.ForEachRootScenePresence(delegate(ScenePresence sp)
@@ -2917,8 +2969,8 @@ namespace OpenSim.Region.Framework.Scenes
2917 { 2969 {
2918 const float ROTATION_TOLERANCE = 0.01f; 2970 const float ROTATION_TOLERANCE = 0.01f;
2919 const float VELOCITY_TOLERANCE = 0.001f; 2971 const float VELOCITY_TOLERANCE = 0.001f;
2920 const float POSITION_TOLERANCE = 0.05f; 2972 const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary
2921 const int TIME_MS_TOLERANCE = 3000; 2973 const int TIME_MS_TOLERANCE = 200; //llSetPos has a 200ms delay. This should NOT be 3 seconds.
2922 2974
2923 switch (UpdateFlag) 2975 switch (UpdateFlag)
2924 { 2976 {
@@ -2980,17 +3032,16 @@ namespace OpenSim.Region.Framework.Scenes
2980 if (!UUID.TryParse(sound, out soundID)) 3032 if (!UUID.TryParse(sound, out soundID))
2981 { 3033 {
2982 // search sound file from inventory 3034 // search sound file from inventory
2983 lock (TaskInventory) 3035 TaskInventory.LockItemsForRead(true);
3036 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2984 { 3037 {
2985 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 3038 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound)
2986 { 3039 {
2987 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound) 3040 soundID = item.Value.ItemID;
2988 { 3041 break;
2989 soundID = item.Value.ItemID;
2990 break;
2991 }
2992 } 3042 }
2993 } 3043 }
3044 TaskInventory.LockItemsForRead(false);
2994 } 3045 }
2995 3046
2996 if (soundID == UUID.Zero) 3047 if (soundID == UUID.Zero)
@@ -3457,10 +3508,10 @@ namespace OpenSim.Region.Framework.Scenes
3457 // TODO: May need to fix for group comparison 3508 // TODO: May need to fix for group comparison
3458 if (last.Compare(this)) 3509 if (last.Compare(this))
3459 { 3510 {
3460 // m_log.DebugFormat( 3511 // m_log.DebugFormat(
3461 // "[SCENE OBJECT PART]: Not storing undo for {0} {1} since current state is same as last undo state, initial stack size {2}", 3512 // "[SCENE OBJECT PART]: Not storing undo for {0} {1} since current state is same as last undo state, initial stack size {2}",
3462 // Name, LocalId, m_undo.Count); 3513 // Name, LocalId, m_undo.Count);
3463 3514
3464 return; 3515 return;
3465 } 3516 }
3466 } 3517 }
@@ -3473,29 +3524,29 @@ namespace OpenSim.Region.Framework.Scenes
3473 if (ParentGroup.GetSceneMaxUndo() > 0) 3524 if (ParentGroup.GetSceneMaxUndo() > 0)
3474 { 3525 {
3475 UndoState nUndo = new UndoState(this, forGroup); 3526 UndoState nUndo = new UndoState(this, forGroup);
3476 3527
3477 m_undo.Push(nUndo); 3528 m_undo.Push(nUndo);
3478 3529
3479 if (m_redo.Count > 0) 3530 if (m_redo.Count > 0)
3480 m_redo.Clear(); 3531 m_redo.Clear();
3481 3532
3482 // m_log.DebugFormat( 3533 // m_log.DebugFormat(
3483 // "[SCENE OBJECT PART]: Stored undo state for {0} {1}, forGroup {2}, stack size now {3}", 3534 // "[SCENE OBJECT PART]: Stored undo state for {0} {1}, forGroup {2}, stack size now {3}",
3484 // Name, LocalId, forGroup, m_undo.Count); 3535 // Name, LocalId, forGroup, m_undo.Count);
3485 } 3536 }
3486 } 3537 }
3487 } 3538 }
3488 } 3539 }
3489// else 3540 // else
3490// { 3541 // {
3491// m_log.DebugFormat("[SCENE OBJECT PART]: Ignoring undo store for {0} {1}", Name, LocalId); 3542 // m_log.DebugFormat("[SCENE OBJECT PART]: Ignoring undo store for {0} {1}", Name, LocalId);
3492// } 3543 // }
3493 } 3544 }
3494// else 3545 // else
3495// { 3546 // {
3496// m_log.DebugFormat( 3547 // m_log.DebugFormat(
3497// "[SCENE OBJECT PART]: Ignoring undo store for {0} {1} since already undoing", Name, LocalId); 3548 // "[SCENE OBJECT PART]: Ignoring undo store for {0} {1} since already undoing", Name, LocalId);
3498// } 3549 // }
3499 } 3550 }
3500 3551
3501 /// <summary> 3552 /// <summary>
@@ -4226,6 +4277,9 @@ namespace OpenSim.Region.Framework.Scenes
4226 bool wasPhantom = ((Flags & PrimFlags.Phantom) != 0); 4277 bool wasPhantom = ((Flags & PrimFlags.Phantom) != 0);
4227 bool wasVD = VolumeDetectActive; 4278 bool wasVD = VolumeDetectActive;
4228 4279
4280// m_log.DebugFormat("[SOP]: Old states: phys: {0} temp: {1} phan: {2} vd: {3}", wasUsingPhysics, wasTemporary, wasPhantom, wasVD);
4281// m_log.DebugFormat("[SOP]: New states: phys: {0} temp: {1} phan: {2} vd: {3}", UsePhysics, SetTemporary, SetPhantom, SetVD);
4282
4229 if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD)) 4283 if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD))
4230 return; 4284 return;
4231 4285
@@ -4255,6 +4309,11 @@ namespace OpenSim.Region.Framework.Scenes
4255 SetPhantom = false; 4309 SetPhantom = false;
4256 } 4310 }
4257 } 4311 }
4312 else if (wasVD)
4313 {
4314 // Correspondingly, if VD is turned off, also turn off phantom
4315 SetPhantom = false;
4316 }
4258 4317
4259 if (UsePhysics && IsJoint()) 4318 if (UsePhysics && IsJoint())
4260 { 4319 {
@@ -4753,5 +4812,17 @@ namespace OpenSim.Region.Framework.Scenes
4753 Color color = Color; 4812 Color color = Color;
4754 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A)); 4813 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A));
4755 } 4814 }
4815
4816 public void ResetOwnerChangeFlag()
4817 {
4818 List<UUID> inv = Inventory.GetInventoryList();
4819
4820 foreach (UUID itemID in inv)
4821 {
4822 TaskInventoryItem item = Inventory.GetInventoryItem(itemID);
4823 item.OwnerChanged = false;
4824 Inventory.UpdateInventoryItem(item, false, false);
4825 }
4826 }
4756 } 4827 }
4757} 4828}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index f2d1915..ca85d10 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 }
217 } 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 }
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>
@@ -271,7 +330,10 @@ namespace OpenSim.Region.Framework.Scenes
271// item.Name, item.ItemID, m_part.Name, m_part.UUID, m_part.ParentGroup.Scene.RegionInfo.RegionName); 330// item.Name, item.ItemID, m_part.Name, m_part.UUID, m_part.ParentGroup.Scene.RegionInfo.RegionName);
272 331
273 if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID)) 332 if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID))
333 {
334 StoreScriptError(item.ItemID, "no permission");
274 return; 335 return;
336 }
275 337
276 m_part.AddFlag(PrimFlags.Scripted); 338 m_part.AddFlag(PrimFlags.Scripted);
277 339
@@ -280,14 +342,13 @@ namespace OpenSim.Region.Framework.Scenes
280 if (stateSource == 2 && // Prim crossing 342 if (stateSource == 2 && // Prim crossing
281 m_part.ParentGroup.Scene.m_trustBinaries) 343 m_part.ParentGroup.Scene.m_trustBinaries)
282 { 344 {
283 lock (m_items) 345 m_items.LockItemsForWrite(true);
284 { 346 m_items[item.ItemID].PermsMask = 0;
285 m_items[item.ItemID].PermsMask = 0; 347 m_items[item.ItemID].PermsGranter = UUID.Zero;
286 m_items[item.ItemID].PermsGranter = UUID.Zero; 348 m_items.LockItemsForWrite(false);
287 }
288
289 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 349 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
290 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource); 350 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource);
351 StoreScriptErrors(item.ItemID, null);
291 m_part.ParentGroup.AddActiveScriptCount(1); 352 m_part.ParentGroup.AddActiveScriptCount(1);
292 m_part.ScheduleFullUpdate(); 353 m_part.ScheduleFullUpdate();
293 return; 354 return;
@@ -296,6 +357,8 @@ namespace OpenSim.Region.Framework.Scenes
296 AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString()); 357 AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString());
297 if (null == asset) 358 if (null == asset)
298 { 359 {
360 string msg = String.Format("asset ID {0} could not be found", item.AssetID);
361 StoreScriptError(item.ItemID, msg);
299 m_log.ErrorFormat( 362 m_log.ErrorFormat(
300 "[PRIM INVENTORY]: Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found", 363 "[PRIM INVENTORY]: Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found",
301 item.Name, item.ItemID, m_part.AbsolutePosition, 364 item.Name, item.ItemID, m_part.AbsolutePosition,
@@ -306,16 +369,21 @@ namespace OpenSim.Region.Framework.Scenes
306 if (m_part.ParentGroup.m_savedScriptState != null) 369 if (m_part.ParentGroup.m_savedScriptState != null)
307 item.OldItemID = RestoreSavedScriptState(item.LoadedItemID, item.OldItemID, item.ItemID); 370 item.OldItemID = RestoreSavedScriptState(item.LoadedItemID, item.OldItemID, item.ItemID);
308 371
309 lock (m_items) 372 m_items.LockItemsForWrite(true);
310 {
311 m_items[item.ItemID].OldItemID = item.OldItemID;
312 m_items[item.ItemID].PermsMask = 0;
313 m_items[item.ItemID].PermsGranter = UUID.Zero;
314 }
315 373
374 m_items[item.ItemID].OldItemID = item.OldItemID;
375 m_items[item.ItemID].PermsMask = 0;
376 m_items[item.ItemID].PermsGranter = UUID.Zero;
377
378 m_items.LockItemsForWrite(false);
379
316 string script = Utils.BytesToString(asset.Data); 380 string script = Utils.BytesToString(asset.Data);
317 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 381 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
318 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource); 382 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource);
383 StoreScriptErrors(item.ItemID, null);
384 if (!item.ScriptRunning)
385 m_part.ParentGroup.Scene.EventManager.TriggerStopScript(
386 m_part.LocalId, item.ItemID);
319 m_part.ParentGroup.AddActiveScriptCount(1); 387 m_part.ParentGroup.AddActiveScriptCount(1);
320 m_part.ScheduleFullUpdate(); 388 m_part.ScheduleFullUpdate();
321 } 389 }
@@ -386,20 +454,146 @@ namespace OpenSim.Region.Framework.Scenes
386 454
387 /// <summary> 455 /// <summary>
388 /// Start a script which is in this prim's inventory. 456 /// Start a script which is in this prim's inventory.
457 /// Some processing may occur in the background, but this routine returns asap.
389 /// </summary> 458 /// </summary>
390 /// <param name="itemId"> 459 /// <param name="itemId">
391 /// A <see cref="UUID"/> 460 /// A <see cref="UUID"/>
392 /// </param> 461 /// </param>
393 public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource) 462 public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
394 { 463 {
395 TaskInventoryItem item = GetInventoryItem(itemId); 464 lock (m_scriptErrors)
396 if (item != null) 465 {
397 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource); 466 // Indicate to CreateScriptInstanceInternal() we don't want it to wait for completion
467 m_scriptErrors.Remove(itemId);
468 }
469 CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
470 }
471
472 private void CreateScriptInstanceInternal(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
473 {
474 m_items.LockItemsForRead(true);
475 if (m_items.ContainsKey(itemId))
476 {
477 if (m_items.ContainsKey(itemId))
478 {
479 m_items.LockItemsForRead(false);
480 CreateScriptInstance(m_items[itemId], startParam, postOnRez, engine, stateSource);
481 }
482 else
483 {
484 m_items.LockItemsForRead(false);
485 string msg = String.Format("couldn't be found for prim {0}, {1} at {2} in {3}", m_part.Name, m_part.UUID,
486 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
487 StoreScriptError(itemId, msg);
488 m_log.ErrorFormat(
489 "[PRIM INVENTORY]: " +
490 "Couldn't start script with ID {0} since it {1}", itemId, msg);
491 }
492 }
398 else 493 else
494 {
495 m_items.LockItemsForRead(false);
496 string msg = String.Format("couldn't be found for prim {0}, {1}", m_part.Name, m_part.UUID);
497 StoreScriptError(itemId, msg);
399 m_log.ErrorFormat( 498 m_log.ErrorFormat(
400 "[PRIM INVENTORY]: Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}", 499 "[PRIM INVENTORY]: Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}",
401 itemId, m_part.Name, m_part.UUID, 500 itemId, m_part.Name, m_part.UUID,
402 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 501 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
502 }
503
504 }
505
506 /// <summary>
507 /// Start a script which is in this prim's inventory and return any compilation error messages.
508 /// </summary>
509 /// <param name="itemId">
510 /// A <see cref="UUID"/>
511 /// </param>
512 public ArrayList CreateScriptInstanceEr(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
513 {
514 ArrayList errors;
515
516 // Indicate to CreateScriptInstanceInternal() we want it to
517 // post any compilation/loading error messages
518 lock (m_scriptErrors)
519 {
520 m_scriptErrors[itemId] = null;
521 }
522
523 // Perform compilation/loading
524 CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
525
526 // Wait for and retrieve any errors
527 lock (m_scriptErrors)
528 {
529 while ((errors = m_scriptErrors[itemId]) == null)
530 {
531 if (!System.Threading.Monitor.Wait(m_scriptErrors, 15000))
532 {
533 m_log.ErrorFormat(
534 "[PRIM INVENTORY]: " +
535 "timedout waiting for script {0} errors", itemId);
536 errors = m_scriptErrors[itemId];
537 if (errors == null)
538 {
539 errors = new ArrayList(1);
540 errors.Add("timedout waiting for errors");
541 }
542 break;
543 }
544 }
545 m_scriptErrors.Remove(itemId);
546 }
547 return errors;
548 }
549
550 // Signal to CreateScriptInstanceEr() that compilation/loading is complete
551 private void StoreScriptErrors(UUID itemId, ArrayList errors)
552 {
553 lock (m_scriptErrors)
554 {
555 // If compilation/loading initiated via CreateScriptInstance(),
556 // it does not want the errors, so just get out
557 if (!m_scriptErrors.ContainsKey(itemId))
558 {
559 return;
560 }
561
562 // Initiated via CreateScriptInstanceEr(), if we know what the
563 // errors are, save them and wake CreateScriptInstanceEr().
564 if (errors != null)
565 {
566 m_scriptErrors[itemId] = errors;
567 System.Threading.Monitor.PulseAll(m_scriptErrors);
568 return;
569 }
570 }
571
572 // Initiated via CreateScriptInstanceEr() but we don't know what
573 // the errors are yet, so retrieve them from the script engine.
574 // This may involve some waiting internal to GetScriptErrors().
575 errors = GetScriptErrors(itemId);
576
577 // Get a default non-null value to indicate success.
578 if (errors == null)
579 {
580 errors = new ArrayList();
581 }
582
583 // Post to CreateScriptInstanceEr() and wake it up
584 lock (m_scriptErrors)
585 {
586 m_scriptErrors[itemId] = errors;
587 System.Threading.Monitor.PulseAll(m_scriptErrors);
588 }
589 }
590
591 // Like StoreScriptErrors(), but just posts a single string message
592 private void StoreScriptError(UUID itemId, string message)
593 {
594 ArrayList errors = new ArrayList(1);
595 errors.Add(message);
596 StoreScriptErrors(itemId, errors);
403 } 597 }
404 598
405 /// <summary> 599 /// <summary>
@@ -412,15 +606,7 @@ namespace OpenSim.Region.Framework.Scenes
412 /// </param> 606 /// </param>
413 public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted) 607 public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted)
414 { 608 {
415 bool scriptPresent = false; 609 if (m_items.ContainsKey(itemId))
416
417 lock (m_items)
418 {
419 if (m_items.ContainsKey(itemId))
420 scriptPresent = true;
421 }
422
423 if (scriptPresent)
424 { 610 {
425 if (!sceneObjectBeingDeleted) 611 if (!sceneObjectBeingDeleted)
426 m_part.RemoveScriptEvents(itemId); 612 m_part.RemoveScriptEvents(itemId);
@@ -445,14 +631,16 @@ namespace OpenSim.Region.Framework.Scenes
445 /// <returns></returns> 631 /// <returns></returns>
446 private bool InventoryContainsName(string name) 632 private bool InventoryContainsName(string name)
447 { 633 {
448 lock (m_items) 634 m_items.LockItemsForRead(true);
635 foreach (TaskInventoryItem item in m_items.Values)
449 { 636 {
450 foreach (TaskInventoryItem item in m_items.Values) 637 if (item.Name == name)
451 { 638 {
452 if (item.Name == name) 639 m_items.LockItemsForRead(false);
453 return true; 640 return true;
454 } 641 }
455 } 642 }
643 m_items.LockItemsForRead(false);
456 return false; 644 return false;
457 } 645 }
458 646
@@ -494,8 +682,9 @@ namespace OpenSim.Region.Framework.Scenes
494 /// <param name="item"></param> 682 /// <param name="item"></param>
495 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop) 683 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop)
496 { 684 {
497 List<TaskInventoryItem> il = GetInventoryItems(); 685 m_items.LockItemsForRead(true);
498 686 List<TaskInventoryItem> il = new List<TaskInventoryItem>(m_items.Values);
687 m_items.LockItemsForRead(false);
499 foreach (TaskInventoryItem i in il) 688 foreach (TaskInventoryItem i in il)
500 { 689 {
501 if (i.Name == item.Name) 690 if (i.Name == item.Name)
@@ -533,14 +722,14 @@ namespace OpenSim.Region.Framework.Scenes
533 item.Name = name; 722 item.Name = name;
534 item.GroupID = m_part.GroupID; 723 item.GroupID = m_part.GroupID;
535 724
536 lock (m_items) 725 m_items.LockItemsForWrite(true);
537 m_items.Add(item.ItemID, item); 726 m_items.Add(item.ItemID, item);
538 727 m_items.LockItemsForWrite(false);
539 if (allowedDrop) 728 if (allowedDrop)
540 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP); 729 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP);
541 else 730 else
542 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 731 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
543 732
544 m_inventorySerial++; 733 m_inventorySerial++;
545 //m_inventorySerial += 2; 734 //m_inventorySerial += 2;
546 HasInventoryChanged = true; 735 HasInventoryChanged = true;
@@ -556,15 +745,15 @@ namespace OpenSim.Region.Framework.Scenes
556 /// <param name="items"></param> 745 /// <param name="items"></param>
557 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items) 746 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items)
558 { 747 {
559 lock (m_items) 748 m_items.LockItemsForWrite(true);
749 foreach (TaskInventoryItem item in items)
560 { 750 {
561 foreach (TaskInventoryItem item in items) 751 m_items.Add(item.ItemID, item);
562 { 752// m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
563 m_items.Add(item.ItemID, item);
564// m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
565 }
566 m_inventorySerial++;
567 } 753 }
754 m_items.LockItemsForWrite(false);
755
756 m_inventorySerial++;
568 } 757 }
569 758
570 /// <summary> 759 /// <summary>
@@ -575,10 +764,9 @@ namespace OpenSim.Region.Framework.Scenes
575 public TaskInventoryItem GetInventoryItem(UUID itemId) 764 public TaskInventoryItem GetInventoryItem(UUID itemId)
576 { 765 {
577 TaskInventoryItem item; 766 TaskInventoryItem item;
578 767 m_items.LockItemsForRead(true);
579 lock (m_items) 768 m_items.TryGetValue(itemId, out item);
580 m_items.TryGetValue(itemId, out item); 769 m_items.LockItemsForRead(false);
581
582 return item; 770 return item;
583 } 771 }
584 772
@@ -594,15 +782,16 @@ namespace OpenSim.Region.Framework.Scenes
594 { 782 {
595 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(); 783 IList<TaskInventoryItem> items = new List<TaskInventoryItem>();
596 784
597 lock (m_items) 785 m_items.LockItemsForRead(true);
786
787 foreach (TaskInventoryItem item in m_items.Values)
598 { 788 {
599 foreach (TaskInventoryItem item in m_items.Values) 789 if (item.Name == name)
600 { 790 items.Add(item);
601 if (item.Name == name)
602 items.Add(item);
603 }
604 } 791 }
605 792
793 m_items.LockItemsForRead(false);
794
606 return items; 795 return items;
607 } 796 }
608 797
@@ -621,6 +810,9 @@ namespace OpenSim.Region.Framework.Scenes
621 string xmlData = Utils.BytesToString(rezAsset.Data); 810 string xmlData = Utils.BytesToString(rezAsset.Data);
622 SceneObjectGroup group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); 811 SceneObjectGroup group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
623 812
813 group.RootPart.AttachPoint = group.RootPart.Shape.State;
814 group.RootPart.AttachOffset = group.AbsolutePosition;
815
624 group.ResetIDs(); 816 group.ResetIDs();
625 817
626 SceneObjectPart rootPart = group.GetChildPart(group.UUID); 818 SceneObjectPart rootPart = group.GetChildPart(group.UUID);
@@ -695,8 +887,9 @@ namespace OpenSim.Region.Framework.Scenes
695 887
696 public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged) 888 public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged)
697 { 889 {
698 TaskInventoryItem it = GetInventoryItem(item.ItemID); 890 m_items.LockItemsForWrite(true);
699 if (it != null) 891
892 if (m_items.ContainsKey(item.ItemID))
700 { 893 {
701// m_log.DebugFormat("[PRIM INVENTORY]: Updating item {0} in {1}", item.Name, m_part.Name); 894// m_log.DebugFormat("[PRIM INVENTORY]: Updating item {0} in {1}", item.Name, m_part.Name);
702 895
@@ -709,14 +902,10 @@ namespace OpenSim.Region.Framework.Scenes
709 item.GroupID = m_part.GroupID; 902 item.GroupID = m_part.GroupID;
710 903
711 if (item.AssetID == UUID.Zero) 904 if (item.AssetID == UUID.Zero)
712 item.AssetID = it.AssetID; 905 item.AssetID = m_items[item.ItemID].AssetID;
713 906
714 lock (m_items) 907 m_items[item.ItemID] = item;
715 { 908 m_inventorySerial++;
716 m_items[item.ItemID] = item;
717 m_inventorySerial++;
718 }
719
720 if (fireScriptEvents) 909 if (fireScriptEvents)
721 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 910 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
722 911
@@ -725,7 +914,7 @@ namespace OpenSim.Region.Framework.Scenes
725 HasInventoryChanged = true; 914 HasInventoryChanged = true;
726 m_part.ParentGroup.HasGroupChanged = true; 915 m_part.ParentGroup.HasGroupChanged = true;
727 } 916 }
728 917 m_items.LockItemsForWrite(false);
729 return true; 918 return true;
730 } 919 }
731 else 920 else
@@ -736,8 +925,9 @@ namespace OpenSim.Region.Framework.Scenes
736 item.ItemID, m_part.Name, m_part.UUID, 925 item.ItemID, m_part.Name, m_part.UUID,
737 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 926 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
738 } 927 }
739 return false; 928 m_items.LockItemsForWrite(false);
740 929
930 return false;
741 } 931 }
742 932
743 /// <summary> 933 /// <summary>
@@ -748,43 +938,59 @@ namespace OpenSim.Region.Framework.Scenes
748 /// in this prim's inventory.</returns> 938 /// in this prim's inventory.</returns>
749 public int RemoveInventoryItem(UUID itemID) 939 public int RemoveInventoryItem(UUID itemID)
750 { 940 {
751 TaskInventoryItem item = GetInventoryItem(itemID); 941 m_items.LockItemsForRead(true);
752 if (item != null) 942
943 if (m_items.ContainsKey(itemID))
753 { 944 {
754 int type = m_items[itemID].InvType; 945 int type = m_items[itemID].InvType;
946 m_items.LockItemsForRead(false);
755 if (type == 10) // Script 947 if (type == 10) // Script
756 { 948 {
757 m_part.RemoveScriptEvents(itemID);
758 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID); 949 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID);
759 } 950 }
951 m_items.LockItemsForWrite(true);
760 m_items.Remove(itemID); 952 m_items.Remove(itemID);
953 m_items.LockItemsForWrite(false);
761 m_inventorySerial++; 954 m_inventorySerial++;
762 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 955 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
763 956
764 HasInventoryChanged = true; 957 HasInventoryChanged = true;
765 m_part.ParentGroup.HasGroupChanged = true; 958 m_part.ParentGroup.HasGroupChanged = true;
766 959
767 if (!ContainsScripts()) 960 int scriptcount = 0;
961 m_items.LockItemsForRead(true);
962 foreach (TaskInventoryItem item in m_items.Values)
963 {
964 if (item.Type == 10)
965 {
966 scriptcount++;
967 }
968 }
969 m_items.LockItemsForRead(false);
970
971
972 if (scriptcount <= 0)
973 {
768 m_part.RemFlag(PrimFlags.Scripted); 974 m_part.RemFlag(PrimFlags.Scripted);
975 }
769 976
770 m_part.ScheduleFullUpdate(); 977 m_part.ScheduleFullUpdate();
771 978
772 return type; 979 return type;
773
774 } 980 }
775 else 981 else
776 { 982 {
983 m_items.LockItemsForRead(false);
777 m_log.ErrorFormat( 984 m_log.ErrorFormat(
778 "[PRIM INVENTORY]: " + 985 "[PRIM INVENTORY]: " +
779 "Tried to remove item ID {0} from prim {1}, {2} at {3} in {4} but the item does not exist in this inventory", 986 "Tried to remove item ID {0} from prim {1}, {2} but the item does not exist in this inventory",
780 itemID, m_part.Name, m_part.UUID, 987 itemID, m_part.Name, m_part.UUID);
781 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
782 } 988 }
783 989
784 return -1; 990 return -1;
785 } 991 }
786 992
787 private bool CreateInventoryFile() 993 private bool CreateInventoryFileName()
788 { 994 {
789// m_log.DebugFormat( 995// m_log.DebugFormat(
790// "[PRIM INVENTORY]: Creating inventory file for {0} {1} {2}, serial {3}", 996// "[PRIM INVENTORY]: Creating inventory file for {0} {1} {2}, serial {3}",
@@ -793,116 +999,125 @@ namespace OpenSim.Region.Framework.Scenes
793 if (m_inventoryFileName == String.Empty || 999 if (m_inventoryFileName == String.Empty ||
794 m_inventoryFileNameSerial < m_inventorySerial) 1000 m_inventoryFileNameSerial < m_inventorySerial)
795 { 1001 {
796 // Something changed, we need to create a new file
797 m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp"; 1002 m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp";
798 m_inventoryFileNameSerial = m_inventorySerial; 1003 m_inventoryFileNameSerial = m_inventorySerial;
799 1004
800 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero); 1005 return true;
1006 }
1007
1008 return false;
1009 }
1010
1011 /// <summary>
1012 /// Serialize all the metadata for the items in this prim's inventory ready for sending to the client
1013 /// </summary>
1014 /// <param name="xferManager"></param>
1015 public void RequestInventoryFile(IClientAPI client, IXfer xferManager)
1016 {
1017 bool changed = CreateInventoryFileName();
1018
1019 bool includeAssets = false;
1020 if (m_part.ParentGroup.Scene.Permissions.CanEditObjectInventory(m_part.UUID, client.AgentId))
1021 includeAssets = true;
1022
1023 if (m_inventoryPrivileged != includeAssets)
1024 changed = true;
1025
1026 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero);
1027
1028 Items.LockItemsForRead(true);
1029
1030 if (m_inventorySerial == 0) // No inventory
1031 {
1032 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
1033 Items.LockItemsForRead(false);
1034 return;
1035 }
801 1036
802 lock (m_items) 1037 if (m_items.Count == 0) // No inventory
1038 {
1039 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
1040 Items.LockItemsForRead(false);
1041 return;
1042 }
1043
1044 if (!changed)
1045 {
1046 if (m_inventoryFileData.Length > 2)
803 { 1047 {
804 foreach (TaskInventoryItem item in m_items.Values) 1048 xferManager.AddNewFile(m_inventoryFileName,
805 { 1049 m_inventoryFileData);
806// m_log.DebugFormat( 1050 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
807// "[PRIM INVENTORY]: Adding item {0} {1} for serial {2} on prim {3} {4} {5}", 1051 Util.StringToBytes256(m_inventoryFileName));
808// item.Name, item.ItemID, m_inventorySerial, m_part.Name, m_part.UUID, m_part.LocalId);
809 1052
810 UUID ownerID = item.OwnerID; 1053 Items.LockItemsForRead(false);
811 uint everyoneMask = 0; 1054 return;
812 uint baseMask = item.BasePermissions; 1055 }
813 uint ownerMask = item.CurrentPermissions; 1056 }
814 uint groupMask = item.GroupPermissions;
815 1057
816 invString.AddItemStart(); 1058 m_inventoryPrivileged = includeAssets;
817 invString.AddNameValueLine("item_id", item.ItemID.ToString());
818 invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
819 1059
820 invString.AddPermissionsStart(); 1060 foreach (TaskInventoryItem item in m_items.Values)
1061 {
1062 UUID ownerID = item.OwnerID;
1063 uint everyoneMask = 0;
1064 uint baseMask = item.BasePermissions;
1065 uint ownerMask = item.CurrentPermissions;
1066 uint groupMask = item.GroupPermissions;
821 1067
822 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask)); 1068 invString.AddItemStart();
823 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask)); 1069 invString.AddNameValueLine("item_id", item.ItemID.ToString());
824 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask)); 1070 invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
825 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask));
826 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
827 1071
828 invString.AddNameValueLine("creator_id", item.CreatorID.ToString()); 1072 invString.AddPermissionsStart();
829 invString.AddNameValueLine("owner_id", ownerID.ToString());
830 1073
831 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString()); 1074 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask));
1075 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask));
1076 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask));
1077 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask));
1078 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
832 1079
833 invString.AddNameValueLine("group_id", item.GroupID.ToString()); 1080 invString.AddNameValueLine("creator_id", item.CreatorID.ToString());
834 invString.AddSectionEnd(); 1081 invString.AddNameValueLine("owner_id", ownerID.ToString());
835 1082
836 invString.AddNameValueLine("asset_id", item.AssetID.ToString()); 1083 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString());
837 invString.AddNameValueLine("type", Utils.AssetTypeToString((AssetType)item.Type));
838 invString.AddNameValueLine("inv_type", Utils.InventoryTypeToString((InventoryType)item.InvType));
839 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags));
840 1084
841 invString.AddSaleStart(); 1085 invString.AddNameValueLine("group_id", item.GroupID.ToString());
842 invString.AddNameValueLine("sale_type", "not"); 1086 invString.AddSectionEnd();
843 invString.AddNameValueLine("sale_price", "0");
844 invString.AddSectionEnd();
845 1087
846 invString.AddNameValueLine("name", item.Name + "|"); 1088 if (includeAssets)
847 invString.AddNameValueLine("desc", item.Description + "|"); 1089 invString.AddNameValueLine("asset_id", item.AssetID.ToString());
1090 else
1091 invString.AddNameValueLine("asset_id", UUID.Zero.ToString());
1092 invString.AddNameValueLine("type", Utils.AssetTypeToString((AssetType)item.Type));
1093 invString.AddNameValueLine("inv_type", Utils.InventoryTypeToString((InventoryType)item.InvType));
1094 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags));
848 1095
849 invString.AddNameValueLine("creation_date", item.CreationDate.ToString()); 1096 invString.AddSaleStart();
850 invString.AddSectionEnd(); 1097 invString.AddNameValueLine("sale_type", "not");
851 } 1098 invString.AddNameValueLine("sale_price", "0");
852 } 1099 invString.AddSectionEnd();
853 1100
854 m_inventoryFileData = Utils.StringToBytes(invString.BuildString); 1101 invString.AddNameValueLine("name", item.Name + "|");
1102 invString.AddNameValueLine("desc", item.Description + "|");
855 1103
856 return true; 1104 invString.AddNameValueLine("creation_date", item.CreationDate.ToString());
1105 invString.AddSectionEnd();
857 } 1106 }
858 1107
859 // No need to recreate, the existing file is fine 1108 Items.LockItemsForRead(false);
860 return false;
861 }
862
863 /// <summary>
864 /// Serialize all the metadata for the items in this prim's inventory ready for sending to the client
865 /// </summary>
866 /// <param name="xferManager"></param>
867 public void RequestInventoryFile(IClientAPI client, IXfer xferManager)
868 {
869 lock (m_items)
870 {
871 // Don't send a inventory xfer name if there are no items. Doing so causes viewer 3 to crash when rezzing
872 // a new script if any previous deletion has left the prim inventory empty.
873 if (m_items.Count == 0) // No inventory
874 {
875// m_log.DebugFormat(
876// "[PRIM INVENTORY]: Not sending inventory data for part {0} {1} {2} for {3} since no items",
877// m_part.Name, m_part.LocalId, m_part.UUID, client.Name);
878 1109
879 client.SendTaskInventory(m_part.UUID, 0, new byte[0]); 1110 m_inventoryFileData = Utils.StringToBytes(invString.BuildString);
880 return;
881 }
882 1111
883 CreateInventoryFile(); 1112 if (m_inventoryFileData.Length > 2)
884 1113 {
885 // In principle, we should only do the rest if the inventory changed; 1114 xferManager.AddNewFile(m_inventoryFileName, m_inventoryFileData);
886 // by sending m_inventorySerial to the client, it ought to know 1115 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
887 // that nothing changed and that it doesn't need to request the file. 1116 Util.StringToBytes256(m_inventoryFileName));
888 // Unfortunately, it doesn't look like the client optimizes this; 1117 return;
889 // the client seems to always come back and request the Xfer,
890 // no matter what value m_inventorySerial has.
891 // FIXME: Could probably be > 0 here rather than > 2
892 if (m_inventoryFileData.Length > 2)
893 {
894 // Add the file for Xfer
895 // m_log.DebugFormat(
896 // "[PRIM INVENTORY]: Adding inventory file {0} (length {1}) for transfer on {2} {3} {4}",
897 // m_inventoryFileName, m_inventoryFileData.Length, m_part.Name, m_part.UUID, m_part.LocalId);
898
899 xferManager.AddNewFile(m_inventoryFileName, m_inventoryFileData);
900 }
901
902 // Tell the client we're ready to Xfer the file
903 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
904 Util.StringToBytes256(m_inventoryFileName));
905 } 1118 }
1119
1120 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
906 } 1121 }
907 1122
908 /// <summary> 1123 /// <summary>
@@ -911,13 +1126,19 @@ namespace OpenSim.Region.Framework.Scenes
911 /// <param name="datastore"></param> 1126 /// <param name="datastore"></param>
912 public void ProcessInventoryBackup(ISimulationDataService datastore) 1127 public void ProcessInventoryBackup(ISimulationDataService datastore)
913 { 1128 {
914 if (HasInventoryChanged) 1129// Removed this because linking will cause an immediate delete of the new
915 { 1130// child prim from the database and the subsequent storing of the prim sees
916 HasInventoryChanged = false; 1131// the inventory of it as unchanged and doesn't store it at all. The overhead
917 List<TaskInventoryItem> items = GetInventoryItems(); 1132// of storing prim inventory needlessly is much less than the aggravation
918 datastore.StorePrimInventory(m_part.UUID, items); 1133// of prim inventory loss.
1134// if (HasInventoryChanged)
1135// {
1136 Items.LockItemsForRead(true);
1137 datastore.StorePrimInventory(m_part.UUID, Items.Values);
1138 Items.LockItemsForRead(false);
919 1139
920 } 1140 HasInventoryChanged = false;
1141// }
921 } 1142 }
922 1143
923 public class InventoryStringBuilder 1144 public class InventoryStringBuilder
@@ -983,82 +1204,63 @@ namespace OpenSim.Region.Framework.Scenes
983 { 1204 {
984 uint mask=0x7fffffff; 1205 uint mask=0x7fffffff;
985 1206
986 lock (m_items) 1207 foreach (TaskInventoryItem item in m_items.Values)
987 { 1208 {
988 foreach (TaskInventoryItem item in m_items.Values) 1209 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0)
1210 mask &= ~((uint)PermissionMask.Copy >> 13);
1211 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0)
1212 mask &= ~((uint)PermissionMask.Transfer >> 13);
1213 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0)
1214 mask &= ~((uint)PermissionMask.Modify >> 13);
1215
1216 if (item.InvType == (int)InventoryType.Object)
989 { 1217 {
990 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0) 1218 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
991 mask &= ~((uint)PermissionMask.Copy >> 13); 1219 mask &= ~((uint)PermissionMask.Copy >> 13);
992 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0) 1220 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
993 mask &= ~((uint)PermissionMask.Transfer >> 13); 1221 mask &= ~((uint)PermissionMask.Transfer >> 13);
994 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0) 1222 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
995 mask &= ~((uint)PermissionMask.Modify >> 13); 1223 mask &= ~((uint)PermissionMask.Modify >> 13);
996
997 if (item.InvType != (int)InventoryType.Object)
998 {
999 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0)
1000 mask &= ~((uint)PermissionMask.Copy >> 13);
1001 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0)
1002 mask &= ~((uint)PermissionMask.Transfer >> 13);
1003 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0)
1004 mask &= ~((uint)PermissionMask.Modify >> 13);
1005 }
1006 else
1007 {
1008 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
1009 mask &= ~((uint)PermissionMask.Copy >> 13);
1010 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
1011 mask &= ~((uint)PermissionMask.Transfer >> 13);
1012 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1013 mask &= ~((uint)PermissionMask.Modify >> 13);
1014 }
1015
1016 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
1017 mask &= ~(uint)PermissionMask.Copy;
1018 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
1019 mask &= ~(uint)PermissionMask.Transfer;
1020 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
1021 mask &= ~(uint)PermissionMask.Modify;
1022 } 1224 }
1225
1226 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
1227 mask &= ~(uint)PermissionMask.Copy;
1228 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
1229 mask &= ~(uint)PermissionMask.Transfer;
1230 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
1231 mask &= ~(uint)PermissionMask.Modify;
1023 } 1232 }
1024
1025 return mask; 1233 return mask;
1026 } 1234 }
1027 1235
1028 public void ApplyNextOwnerPermissions() 1236 public void ApplyNextOwnerPermissions()
1029 { 1237 {
1030 lock (m_items) 1238 foreach (TaskInventoryItem item in m_items.Values)
1031 { 1239 {
1032 foreach (TaskInventoryItem item in m_items.Values) 1240 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0)
1033 { 1241 {
1034 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0) 1242 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
1035 { 1243 item.CurrentPermissions &= ~(uint)PermissionMask.Copy;
1036 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0) 1244 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
1037 item.CurrentPermissions &= ~(uint)PermissionMask.Copy; 1245 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer;
1038 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0) 1246 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1039 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer; 1247 item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
1040 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1041 item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
1042 }
1043 item.CurrentPermissions &= item.NextPermissions;
1044 item.BasePermissions &= item.NextPermissions;
1045 item.EveryonePermissions &= item.NextPermissions;
1046 item.OwnerChanged = true;
1047 item.PermsMask = 0;
1048 item.PermsGranter = UUID.Zero;
1049 } 1248 }
1249 item.OwnerChanged = true;
1250 item.CurrentPermissions &= item.NextPermissions;
1251 item.BasePermissions &= item.NextPermissions;
1252 item.EveryonePermissions &= item.NextPermissions;
1253 item.PermsMask = 0;
1254 item.PermsGranter = UUID.Zero;
1050 } 1255 }
1051 } 1256 }
1052 1257
1053 public void ApplyGodPermissions(uint perms) 1258 public void ApplyGodPermissions(uint perms)
1054 { 1259 {
1055 lock (m_items) 1260 foreach (TaskInventoryItem item in m_items.Values)
1056 { 1261 {
1057 foreach (TaskInventoryItem item in m_items.Values) 1262 item.CurrentPermissions = perms;
1058 { 1263 item.BasePermissions = perms;
1059 item.CurrentPermissions = perms;
1060 item.BasePermissions = perms;
1061 }
1062 } 1264 }
1063 1265
1064 m_inventorySerial++; 1266 m_inventorySerial++;
@@ -1071,17 +1273,13 @@ namespace OpenSim.Region.Framework.Scenes
1071 /// <returns></returns> 1273 /// <returns></returns>
1072 public bool ContainsScripts() 1274 public bool ContainsScripts()
1073 { 1275 {
1074 lock (m_items) 1276 foreach (TaskInventoryItem item in m_items.Values)
1075 { 1277 {
1076 foreach (TaskInventoryItem item in m_items.Values) 1278 if (item.InvType == (int)InventoryType.LSL)
1077 { 1279 {
1078 if (item.InvType == (int)InventoryType.LSL) 1280 return true;
1079 {
1080 return true;
1081 }
1082 } 1281 }
1083 } 1282 }
1084
1085 return false; 1283 return false;
1086 } 1284 }
1087 1285
@@ -1089,11 +1287,8 @@ namespace OpenSim.Region.Framework.Scenes
1089 { 1287 {
1090 List<UUID> ret = new List<UUID>(); 1288 List<UUID> ret = new List<UUID>();
1091 1289
1092 lock (m_items) 1290 foreach (TaskInventoryItem item in m_items.Values)
1093 { 1291 ret.Add(item.ItemID);
1094 foreach (TaskInventoryItem item in m_items.Values)
1095 ret.Add(item.ItemID);
1096 }
1097 1292
1098 return ret; 1293 return ret;
1099 } 1294 }
@@ -1124,6 +1319,11 @@ namespace OpenSim.Region.Framework.Scenes
1124 1319
1125 public Dictionary<UUID, string> GetScriptStates() 1320 public Dictionary<UUID, string> GetScriptStates()
1126 { 1321 {
1322 return GetScriptStates(false);
1323 }
1324
1325 public Dictionary<UUID, string> GetScriptStates(bool oldIDs)
1326 {
1127 Dictionary<UUID, string> ret = new Dictionary<UUID, string>(); 1327 Dictionary<UUID, string> ret = new Dictionary<UUID, string>();
1128 1328
1129 if (m_part.ParentGroup.Scene == null) // Group not in a scene 1329 if (m_part.ParentGroup.Scene == null) // Group not in a scene
@@ -1134,25 +1334,35 @@ namespace OpenSim.Region.Framework.Scenes
1134 if (engines.Length == 0) // No engine at all 1334 if (engines.Length == 0) // No engine at all
1135 return ret; 1335 return ret;
1136 1336
1137 List<TaskInventoryItem> scripts = GetInventoryScripts(); 1337 Items.LockItemsForRead(true);
1138 1338 foreach (TaskInventoryItem item in m_items.Values)
1139 foreach (TaskInventoryItem item in scripts)
1140 { 1339 {
1141 foreach (IScriptModule e in engines) 1340 if (item.InvType == (int)InventoryType.LSL)
1142 { 1341 {
1143 if (e != null) 1342 foreach (IScriptModule e in engines)
1144 { 1343 {
1145 string n = e.GetXMLState(item.ItemID); 1344 if (e != null)
1146 if (n != String.Empty)
1147 { 1345 {
1148 if (!ret.ContainsKey(item.ItemID)) 1346 string n = e.GetXMLState(item.ItemID);
1149 ret[item.ItemID] = n; 1347 if (n != String.Empty)
1150 break; 1348 {
1349 if (oldIDs)
1350 {
1351 if (!ret.ContainsKey(item.OldItemID))
1352 ret[item.OldItemID] = n;
1353 }
1354 else
1355 {
1356 if (!ret.ContainsKey(item.ItemID))
1357 ret[item.ItemID] = n;
1358 }
1359 break;
1360 }
1151 } 1361 }
1152 } 1362 }
1153 } 1363 }
1154 } 1364 }
1155 1365 Items.LockItemsForRead(false);
1156 return ret; 1366 return ret;
1157 } 1367 }
1158 1368
@@ -1162,21 +1372,27 @@ namespace OpenSim.Region.Framework.Scenes
1162 if (engines.Length == 0) 1372 if (engines.Length == 0)
1163 return; 1373 return;
1164 1374
1165 List<TaskInventoryItem> scripts = GetInventoryScripts();
1166 1375
1167 foreach (TaskInventoryItem item in scripts) 1376 Items.LockItemsForRead(true);
1377
1378 foreach (TaskInventoryItem item in m_items.Values)
1168 { 1379 {
1169 foreach (IScriptModule engine in engines) 1380 if (item.InvType == (int)InventoryType.LSL)
1170 { 1381 {
1171 if (engine != null) 1382 foreach (IScriptModule engine in engines)
1172 { 1383 {
1173 if (item.OwnerChanged) 1384 if (engine != null)
1174 engine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.OWNER }); 1385 {
1175 item.OwnerChanged = false; 1386 if (item.OwnerChanged)
1176 engine.ResumeScript(item.ItemID); 1387 engine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.OWNER });
1388 item.OwnerChanged = false;
1389 engine.ResumeScript(item.ItemID);
1390 }
1177 } 1391 }
1178 } 1392 }
1179 } 1393 }
1394
1395 Items.LockItemsForRead(false);
1180 } 1396 }
1181 } 1397 }
1182} 1398}
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 77f7b32..429fc06 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,11 @@ 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
236 private Vector3 m_prevSitOffset;
237
232 protected AvatarAppearance m_appearance; 238 protected AvatarAppearance m_appearance;
233 239
234 public AvatarAppearance Appearance 240 public AvatarAppearance Appearance
@@ -640,6 +646,13 @@ namespace OpenSim.Region.Framework.Scenes
640 } 646 }
641 private uint m_parentID; 647 private uint m_parentID;
642 648
649 public UUID ParentUUID
650 {
651 get { return m_parentUUID; }
652 set { m_parentUUID = value; }
653 }
654 private UUID m_parentUUID = UUID.Zero;
655
643 public float Health 656 public float Health
644 { 657 {
645 get { return m_health; } 658 get { return m_health; }
@@ -861,7 +874,26 @@ namespace OpenSim.Region.Framework.Scenes
861 "[SCENE]: Upgrading child to root agent for {0} in {1}", 874 "[SCENE]: Upgrading child to root agent for {0} in {1}",
862 Name, m_scene.RegionInfo.RegionName); 875 Name, m_scene.RegionInfo.RegionName);
863 876
864 //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count); 877 if (ParentUUID != UUID.Zero)
878 {
879 m_log.DebugFormat("[SCENE PRESENCE]: Sitting avatar back on prim {0}", ParentUUID);
880 SceneObjectPart part = m_scene.GetSceneObjectPart(ParentUUID);
881 if (part == null)
882 {
883 m_log.ErrorFormat("[SCENE PRESENCE]: Can't find prim {0} to sit on", ParentUUID);
884 }
885 else
886 {
887 part.ParentGroup.AddAvatar(UUID);
888 if (part.SitTargetPosition != Vector3.Zero)
889 part.SitTargetAvatar = UUID;
890 ParentPosition = part.GetWorldPosition();
891 ParentID = part.LocalId;
892 m_pos = m_prevSitOffset;
893 pos = ParentPosition;
894 }
895 ParentUUID = UUID.Zero;
896 }
865 897
866 bool wasChild = IsChildAgent; 898 bool wasChild = IsChildAgent;
867 IsChildAgent = false; 899 IsChildAgent = false;
@@ -874,62 +906,64 @@ namespace OpenSim.Region.Framework.Scenes
874 906
875 m_scene.EventManager.TriggerSetRootAgentScene(m_uuid, m_scene); 907 m_scene.EventManager.TriggerSetRootAgentScene(m_uuid, m_scene);
876 908
877 // Moved this from SendInitialData to ensure that Appearance is initialized 909 if (ParentID == 0)
878 // before the inventory is processed in MakeRootAgent. This fixes a race condition
879 // related to the handling of attachments
880 //m_scene.GetAvatarAppearance(ControllingClient, out Appearance);
881 if (m_scene.TestBorderCross(pos, Cardinals.E))
882 { 910 {
883 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.E); 911 // Moved this from SendInitialData to ensure that Appearance is initialized
884 pos.X = crossedBorder.BorderLine.Z - 1; 912 // before the inventory is processed in MakeRootAgent. This fixes a race condition
885 } 913 // related to the handling of attachments
914 //m_scene.GetAvatarAppearance(ControllingClient, out Appearance);
915 if (m_scene.TestBorderCross(pos, Cardinals.E))
916 {
917 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.E);
918 pos.X = crossedBorder.BorderLine.Z - 1;
919 }
886 920
887 if (m_scene.TestBorderCross(pos, Cardinals.N)) 921 if (m_scene.TestBorderCross(pos, Cardinals.N))
888 { 922 {
889 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N); 923 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N);
890 pos.Y = crossedBorder.BorderLine.Z - 1; 924 pos.Y = crossedBorder.BorderLine.Z - 1;
891 } 925 }
892 926
893 CheckAndAdjustLandingPoint(ref pos); 927 CheckAndAdjustLandingPoint(ref pos);
894 928
895 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f) 929 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f)
896 { 930 {
897 m_log.WarnFormat( 931 m_log.WarnFormat(
898 "[SCENE PRESENCE]: MakeRootAgent() was given an illegal position of {0} for avatar {1}, {2}. Clamping", 932 "[SCENE PRESENCE]: MakeRootAgent() was given an illegal position of {0} for avatar {1}, {2}. Clamping",
899 pos, Name, UUID); 933 pos, Name, UUID);
900 934
901 if (pos.X < 0f) pos.X = 0f; 935 if (pos.X < 0f) pos.X = 0f;
902 if (pos.Y < 0f) pos.Y = 0f; 936 if (pos.Y < 0f) pos.Y = 0f;
903 if (pos.Z < 0f) pos.Z = 0f; 937 if (pos.Z < 0f) pos.Z = 0f;
904 } 938 }
905 939
906 float localAVHeight = 1.56f; 940 float localAVHeight = 1.56f;
907 if (Appearance.AvatarHeight > 0) 941 if (Appearance.AvatarHeight > 0)
908 localAVHeight = Appearance.AvatarHeight; 942 localAVHeight = Appearance.AvatarHeight;
909 943
910 float posZLimit = 0; 944 float posZLimit = 0;
911 945
912 if (pos.X < Constants.RegionSize && pos.Y < Constants.RegionSize) 946 if (pos.X < Constants.RegionSize && pos.Y < Constants.RegionSize)
913 posZLimit = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y]; 947 posZLimit = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y];
914 948
915 float newPosZ = posZLimit + localAVHeight / 2; 949 float newPosZ = posZLimit + localAVHeight / 2;
916 if (posZLimit >= (pos.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ))) 950 if (posZLimit >= (pos.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ)))
917 { 951 {
918 pos.Z = newPosZ; 952 pos.Z = newPosZ;
919 } 953 }
920 AbsolutePosition = pos; 954 AbsolutePosition = pos;
921 955
922 AddToPhysicalScene(isFlying); 956 AddToPhysicalScene(isFlying);
923 957
924 if (ForceFly) 958 if (ForceFly)
925 { 959 {
926 Flying = true; 960 Flying = true;
927 } 961 }
928 else if (FlyDisabled) 962 else if (FlyDisabled)
929 { 963 {
930 Flying = false; 964 Flying = false;
965 }
931 } 966 }
932
933 // Don't send an animation pack here, since on a region crossing this will sometimes cause a flying 967 // Don't send an animation pack here, since on a region crossing this will sometimes cause a flying
934 // avatar to return to the standing position in mid-air. On login it looks like this is being sent 968 // avatar to return to the standing position in mid-air. On login it looks like this is being sent
935 // elsewhere anyway 969 // elsewhere anyway
@@ -947,11 +981,13 @@ namespace OpenSim.Region.Framework.Scenes
947 { 981 {
948 m_log.DebugFormat("[SCENE PRESENCE]: Restarting scripts in attachments..."); 982 m_log.DebugFormat("[SCENE PRESENCE]: Restarting scripts in attachments...");
949 // Resume scripts 983 // Resume scripts
950 foreach (SceneObjectGroup sog in m_attachments) 984 Util.FireAndForget(delegate(object x) {
951 { 985 foreach (SceneObjectGroup sog in m_attachments)
952 sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource()); 986 {
953 sog.ResumeScripts(); 987 sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource());
954 } 988 sog.ResumeScripts();
989 }
990 });
955 } 991 }
956 } 992 }
957 993
@@ -1748,9 +1784,9 @@ namespace OpenSim.Region.Framework.Scenes
1748 if (pos.Z - terrainHeight < 0.2) 1784 if (pos.Z - terrainHeight < 0.2)
1749 pos.Z = terrainHeight; 1785 pos.Z = terrainHeight;
1750 1786
1751 m_log.DebugFormat( 1787// m_log.DebugFormat(
1752 "[SCENE PRESENCE]: Avatar {0} set move to target {1} (terrain height {2}) in {3}", 1788// "[SCENE PRESENCE]: Avatar {0} set move to target {1} (terrain height {2}) in {3}",
1753 Name, pos, terrainHeight, m_scene.RegionInfo.RegionName); 1789// Name, pos, terrainHeight, m_scene.RegionInfo.RegionName);
1754 1790
1755 if (noFly) 1791 if (noFly)
1756 Flying = false; 1792 Flying = false;
@@ -1834,6 +1870,7 @@ namespace OpenSim.Region.Framework.Scenes
1834 if (part.SitTargetAvatar == UUID) 1870 if (part.SitTargetAvatar == UUID)
1835 part.SitTargetAvatar = UUID.Zero; 1871 part.SitTargetAvatar = UUID.Zero;
1836 1872
1873 part.ParentGroup.DeleteAvatar(UUID);
1837 ParentPosition = part.GetWorldPosition(); 1874 ParentPosition = part.GetWorldPosition();
1838 ControllingClient.SendClearFollowCamProperties(part.ParentUUID); 1875 ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
1839 } 1876 }
@@ -1972,7 +2009,7 @@ namespace OpenSim.Region.Framework.Scenes
1972 forceMouselook = part.GetForceMouselook(); 2009 forceMouselook = part.GetForceMouselook();
1973 2010
1974 ControllingClient.SendSitResponse( 2011 ControllingClient.SendSitResponse(
1975 targetID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook); 2012 part.UUID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook);
1976 2013
1977 m_requestedSitTargetUUID = targetID; 2014 m_requestedSitTargetUUID = targetID;
1978 2015
@@ -2257,11 +2294,13 @@ namespace OpenSim.Region.Framework.Scenes
2257 m_pos = sitTargetPos + SIT_TARGET_ADJUSTMENT; 2294 m_pos = sitTargetPos + SIT_TARGET_ADJUSTMENT;
2258 Rotation = sitTargetOrient; 2295 Rotation = sitTargetOrient;
2259 ParentPosition = part.AbsolutePosition; 2296 ParentPosition = part.AbsolutePosition;
2297 part.ParentGroup.AddAvatar(UUID);
2260 } 2298 }
2261 else 2299 else
2262 { 2300 {
2263 m_pos -= part.AbsolutePosition; 2301 m_pos -= part.AbsolutePosition;
2264 ParentPosition = part.AbsolutePosition; 2302 ParentPosition = part.AbsolutePosition;
2303 part.ParentGroup.AddAvatar(UUID);
2265 2304
2266// m_log.DebugFormat( 2305// m_log.DebugFormat(
2267// "[SCENE PRESENCE]: Sitting {0} at position {1} ({2} + {3}) on part {4} {5} without sit target", 2306// "[SCENE PRESENCE]: Sitting {0} at position {1} ({2} + {3}) on part {4} {5} without sit target",
@@ -3102,6 +3141,9 @@ namespace OpenSim.Region.Framework.Scenes
3102 cAgent.AlwaysRun = SetAlwaysRun; 3141 cAgent.AlwaysRun = SetAlwaysRun;
3103 3142
3104 cAgent.Appearance = new AvatarAppearance(Appearance); 3143 cAgent.Appearance = new AvatarAppearance(Appearance);
3144
3145 cAgent.ParentPart = ParentUUID;
3146 cAgent.SitOffset = m_pos;
3105 3147
3106 lock (scriptedcontrols) 3148 lock (scriptedcontrols)
3107 { 3149 {
@@ -3161,6 +3203,8 @@ namespace OpenSim.Region.Framework.Scenes
3161 CameraAtAxis = cAgent.AtAxis; 3203 CameraAtAxis = cAgent.AtAxis;
3162 CameraLeftAxis = cAgent.LeftAxis; 3204 CameraLeftAxis = cAgent.LeftAxis;
3163 m_CameraUpAxis = cAgent.UpAxis; 3205 m_CameraUpAxis = cAgent.UpAxis;
3206 ParentUUID = cAgent.ParentPart;
3207 m_prevSitOffset = cAgent.SitOffset;
3164 3208
3165 // When we get to the point of re-computing neighbors everytime this 3209 // When we get to the point of re-computing neighbors everytime this
3166 // changes, then start using the agent's drawdistance rather than the 3210 // changes, then start using the agent's drawdistance rather than the
@@ -3367,6 +3411,8 @@ namespace OpenSim.Region.Framework.Scenes
3367 } 3411 }
3368 } 3412 }
3369 3413
3414 RaiseCollisionScriptEvents(coldata);
3415
3370 if (Invulnerable) 3416 if (Invulnerable)
3371 return; 3417 return;
3372 3418
@@ -3878,6 +3924,12 @@ namespace OpenSim.Region.Framework.Scenes
3878 3924
3879 private void CheckAndAdjustLandingPoint(ref Vector3 pos) 3925 private void CheckAndAdjustLandingPoint(ref Vector3 pos)
3880 { 3926 {
3927 string reason;
3928
3929 // Honor bans
3930 if (!m_scene.TestLandRestrictions(UUID, out reason, ref pos.X, ref pos.Y))
3931 return;
3932
3881 SceneObjectGroup telehub = null; 3933 SceneObjectGroup telehub = null;
3882 if (m_scene.RegionInfo.RegionSettings.TelehubObject != UUID.Zero && (telehub = m_scene.GetSceneObjectGroup(m_scene.RegionInfo.RegionSettings.TelehubObject)) != null) 3934 if (m_scene.RegionInfo.RegionSettings.TelehubObject != UUID.Zero && (telehub = m_scene.GetSceneObjectGroup(m_scene.RegionInfo.RegionSettings.TelehubObject)) != null)
3883 { 3935 {
@@ -3917,11 +3969,173 @@ namespace OpenSim.Region.Framework.Scenes
3917 pos = land.LandData.UserLocation; 3969 pos = land.LandData.UserLocation;
3918 } 3970 }
3919 } 3971 }
3920 3972
3921 land.SendLandUpdateToClient(ControllingClient); 3973 land.SendLandUpdateToClient(ControllingClient);
3922 } 3974 }
3923 } 3975 }
3924 3976
3977 private void RaiseCollisionScriptEvents(Dictionary<uint, ContactPoint> coldata)
3978 {
3979 lock(m_collisionEventLock)
3980 {
3981 if (m_collisionEventFlag)
3982 return;
3983 m_collisionEventFlag = true;
3984 }
3985
3986 Util.FireAndForget(delegate(object x)
3987 {
3988 try
3989 {
3990 List<uint> thisHitColliders = new List<uint>();
3991 List<uint> endedColliders = new List<uint>();
3992 List<uint> startedColliders = new List<uint>();
3993
3994 foreach (uint localid in coldata.Keys)
3995 {
3996 thisHitColliders.Add(localid);
3997 if (!m_lastColliders.Contains(localid))
3998 {
3999 startedColliders.Add(localid);
4000 }
4001 //m_log.Debug("[SCENE PRESENCE]: Collided with:" + localid.ToString() + " at depth of: " + collissionswith[localid].ToString());
4002 }
4003
4004 // calculate things that ended colliding
4005 foreach (uint localID in m_lastColliders)
4006 {
4007 if (!thisHitColliders.Contains(localID))
4008 {
4009 endedColliders.Add(localID);
4010 }
4011 }
4012 //add the items that started colliding this time to the last colliders list.
4013 foreach (uint localID in startedColliders)
4014 {
4015 m_lastColliders.Add(localID);
4016 }
4017 // remove things that ended colliding from the last colliders list
4018 foreach (uint localID in endedColliders)
4019 {
4020 m_lastColliders.Remove(localID);
4021 }
4022
4023 // do event notification
4024 if (startedColliders.Count > 0)
4025 {
4026 ColliderArgs StartCollidingMessage = new ColliderArgs();
4027 List<DetectedObject> colliding = new List<DetectedObject>();
4028 foreach (uint localId in startedColliders)
4029 {
4030 if (localId == 0)
4031 continue;
4032
4033 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
4034 string data = "";
4035 if (obj != null)
4036 {
4037 DetectedObject detobj = new DetectedObject();
4038 detobj.keyUUID = obj.UUID;
4039 detobj.nameStr = obj.Name;
4040 detobj.ownerUUID = obj.OwnerID;
4041 detobj.posVector = obj.AbsolutePosition;
4042 detobj.rotQuat = obj.GetWorldRotation();
4043 detobj.velVector = obj.Velocity;
4044 detobj.colliderType = 0;
4045 detobj.groupUUID = obj.GroupID;
4046 colliding.Add(detobj);
4047 }
4048 }
4049
4050 if (colliding.Count > 0)
4051 {
4052 StartCollidingMessage.Colliders = colliding;
4053
4054 foreach (SceneObjectGroup att in GetAttachments())
4055 Scene.EventManager.TriggerScriptCollidingStart(att.LocalId, StartCollidingMessage);
4056 }
4057 }
4058
4059 if (endedColliders.Count > 0)
4060 {
4061 ColliderArgs EndCollidingMessage = new ColliderArgs();
4062 List<DetectedObject> colliding = new List<DetectedObject>();
4063 foreach (uint localId in endedColliders)
4064 {
4065 if (localId == 0)
4066 continue;
4067
4068 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
4069 string data = "";
4070 if (obj != null)
4071 {
4072 DetectedObject detobj = new DetectedObject();
4073 detobj.keyUUID = obj.UUID;
4074 detobj.nameStr = obj.Name;
4075 detobj.ownerUUID = obj.OwnerID;
4076 detobj.posVector = obj.AbsolutePosition;
4077 detobj.rotQuat = obj.GetWorldRotation();
4078 detobj.velVector = obj.Velocity;
4079 detobj.colliderType = 0;
4080 detobj.groupUUID = obj.GroupID;
4081 colliding.Add(detobj);
4082 }
4083 }
4084
4085 if (colliding.Count > 0)
4086 {
4087 EndCollidingMessage.Colliders = colliding;
4088
4089 foreach (SceneObjectGroup att in GetAttachments())
4090 Scene.EventManager.TriggerScriptCollidingEnd(att.LocalId, EndCollidingMessage);
4091 }
4092 }
4093
4094 if (thisHitColliders.Count > 0)
4095 {
4096 ColliderArgs CollidingMessage = new ColliderArgs();
4097 List<DetectedObject> colliding = new List<DetectedObject>();
4098 foreach (uint localId in thisHitColliders)
4099 {
4100 if (localId == 0)
4101 continue;
4102
4103 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
4104 string data = "";
4105 if (obj != null)
4106 {
4107 DetectedObject detobj = new DetectedObject();
4108 detobj.keyUUID = obj.UUID;
4109 detobj.nameStr = obj.Name;
4110 detobj.ownerUUID = obj.OwnerID;
4111 detobj.posVector = obj.AbsolutePosition;
4112 detobj.rotQuat = obj.GetWorldRotation();
4113 detobj.velVector = obj.Velocity;
4114 detobj.colliderType = 0;
4115 detobj.groupUUID = obj.GroupID;
4116 colliding.Add(detobj);
4117 }
4118 }
4119
4120 if (colliding.Count > 0)
4121 {
4122 CollidingMessage.Colliders = colliding;
4123
4124 lock (m_attachments)
4125 {
4126 foreach (SceneObjectGroup att in m_attachments)
4127 Scene.EventManager.TriggerScriptColliding(att.LocalId, CollidingMessage);
4128 }
4129 }
4130 }
4131 }
4132 finally
4133 {
4134 m_collisionEventFlag = false;
4135 }
4136 });
4137 }
4138
3925 private void TeleportFlagsDebug() { 4139 private void TeleportFlagsDebug() {
3926 4140
3927 // Some temporary debugging help to show all the TeleportFlags we have... 4141 // Some temporary debugging help to show all the TeleportFlags we have...
@@ -3946,6 +4160,5 @@ namespace OpenSim.Region.Framework.Scenes
3946 m_log.InfoFormat("[SCENE PRESENCE]: TELEPORT ******************"); 4160 m_log.InfoFormat("[SCENE PRESENCE]: TELEPORT ******************");
3947 4161
3948 } 4162 }
3949
3950 } 4163 }
3951} 4164}
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
index 0a32214..4b80e37 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 errors = ExternalRepresentationUtils.ExecuteReadProcessors( 1542 errors = 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;