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.cs323
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs3
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Permissions.cs17
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs492
-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.cs224
-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.cs567
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs201
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs806
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs175
-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
18 files changed, 2284 insertions, 729 deletions
diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs
index fd35c62..74d9e60 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;
@@ -791,6 +795,26 @@ namespace OpenSim.Region.Framework.Scenes
791 } 795 }
792 } 796 }
793 } 797 }
798 public void TriggerTerrainUpdate()
799 {
800 OnTerrainUpdateDelegate handlerTerrainUpdate = OnTerrainUpdate;
801 if (handlerTerrainUpdate != null)
802 {
803 foreach (OnTerrainUpdateDelegate d in handlerTerrainUpdate.GetInvocationList())
804 {
805 try
806 {
807 d();
808 }
809 catch (Exception e)
810 {
811 m_log.ErrorFormat(
812 "[EVENT MANAGER]: Delegate for TriggerTerrainUpdate failed - continuing. {0} {1}",
813 e.Message, e.StackTrace);
814 }
815 }
816 }
817 }
794 818
795 public void TriggerTerrainTick() 819 public void TriggerTerrainTick()
796 { 820 {
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 2444367..e005698 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -117,34 +117,22 @@ namespace OpenSim.Region.Framework.Scenes
117 /// <param name="item"></param> 117 /// <param name="item"></param>
118 public bool AddInventoryItem(InventoryItemBase item) 118 public bool AddInventoryItem(InventoryItemBase item)
119 { 119 {
120 if (UUID.Zero == item.Folder) 120 InventoryFolderBase folder;
121
122 if (item.Folder == UUID.Zero)
121 { 123 {
122 InventoryFolderBase f = InventoryService.GetFolderForType(item.Owner, (AssetType)item.AssetType); 124 folder = InventoryService.GetFolderForType(item.Owner, (AssetType)item.AssetType);
123 if (f != null) 125 if (folder == null)
124 { 126 {
125// m_log.DebugFormat( 127 folder = InventoryService.GetRootFolder(item.Owner);
126// "[LOCAL INVENTORY SERVICES CONNECTOR]: Found folder {0} type {1} for item {2}", 128
127// f.Name, (AssetType)f.Type, item.Name); 129 if (folder == null)
128
129 item.Folder = f.ID;
130 }
131 else
132 {
133 f = InventoryService.GetRootFolder(item.Owner);
134 if (f != null)
135 {
136 item.Folder = f.ID;
137 }
138 else
139 {
140 m_log.WarnFormat(
141 "[AGENT INVENTORY]: Could not find root folder for {0} when trying to add item {1} with no parent folder specified",
142 item.Owner, item.Name);
143 return false; 130 return false;
144 }
145 } 131 }
132
133 item.Folder = folder.ID;
146 } 134 }
147 135
148 if (InventoryService.AddItem(item)) 136 if (InventoryService.AddItem(item))
149 { 137 {
150 int userlevel = 0; 138 int userlevel = 0;
@@ -264,8 +252,7 @@ namespace OpenSim.Region.Framework.Scenes
264 252
265 // Update item with new asset 253 // Update item with new asset
266 item.AssetID = asset.FullID; 254 item.AssetID = asset.FullID;
267 if (group.UpdateInventoryItem(item)) 255 group.UpdateInventoryItem(item);
268 remoteClient.SendAgentAlertMessage("Script saved", false);
269 256
270 part.SendPropertiesToClient(remoteClient); 257 part.SendPropertiesToClient(remoteClient);
271 258
@@ -276,12 +263,7 @@ namespace OpenSim.Region.Framework.Scenes
276 { 263 {
277 // Needs to determine which engine was running it and use that 264 // Needs to determine which engine was running it and use that
278 // 265 //
279 part.Inventory.CreateScriptInstance(item.ItemID, 0, false, DefaultScriptEngine, 0); 266 errors = part.Inventory.CreateScriptInstanceEr(item.ItemID, 0, false, DefaultScriptEngine, 0);
280 errors = part.Inventory.GetScriptErrors(item.ItemID);
281 }
282 else
283 {
284 remoteClient.SendAgentAlertMessage("Script saved", false);
285 } 267 }
286 part.ParentGroup.ResumeScripts(); 268 part.ParentGroup.ResumeScripts();
287 return errors; 269 return errors;
@@ -345,6 +327,7 @@ namespace OpenSim.Region.Framework.Scenes
345 327
346 if (UUID.Zero == transactionID) 328 if (UUID.Zero == transactionID)
347 { 329 {
330 item.Flags = (item.Flags & ~(uint)255) | (itemUpd.Flags & (uint)255);
348 item.Name = itemUpd.Name; 331 item.Name = itemUpd.Name;
349 item.Description = itemUpd.Description; 332 item.Description = itemUpd.Description;
350 if (item.NextPermissions != (itemUpd.NextPermissions & item.BasePermissions)) 333 if (item.NextPermissions != (itemUpd.NextPermissions & item.BasePermissions))
@@ -723,6 +706,8 @@ namespace OpenSim.Region.Framework.Scenes
723 return; 706 return;
724 } 707 }
725 708
709 if (newName == null) newName = item.Name;
710
726 AssetBase asset = AssetService.Get(item.AssetID.ToString()); 711 AssetBase asset = AssetService.Get(item.AssetID.ToString());
727 712
728 if (asset != null) 713 if (asset != null)
@@ -779,6 +764,24 @@ namespace OpenSim.Region.Framework.Scenes
779 } 764 }
780 765
781 /// <summary> 766 /// <summary>
767 /// Move an item within the agent's inventory, and leave a copy (used in making a new outfit)
768 /// </summary>
769 public void MoveInventoryItemsLeaveCopy(IClientAPI remoteClient, List<InventoryItemBase> items, UUID destfolder)
770 {
771 List<InventoryItemBase> moveitems = new List<InventoryItemBase>();
772 foreach (InventoryItemBase b in items)
773 {
774 CopyInventoryItem(remoteClient, 0, remoteClient.AgentId, b.ID, b.Folder, null);
775 InventoryItemBase n = InventoryService.GetItem(b);
776 n.Folder = destfolder;
777 moveitems.Add(n);
778 remoteClient.SendInventoryItemCreateUpdate(n, 0);
779 }
780
781 MoveInventoryItem(remoteClient, moveitems);
782 }
783
784 /// <summary>
782 /// Move an item within the agent's inventory. 785 /// Move an item within the agent's inventory.
783 /// </summary> 786 /// </summary>
784 /// <param name="remoteClient"></param> 787 /// <param name="remoteClient"></param>
@@ -1121,6 +1124,10 @@ namespace OpenSim.Region.Framework.Scenes
1121 { 1124 {
1122 SceneObjectPart part = GetSceneObjectPart(primLocalId); 1125 SceneObjectPart part = GetSceneObjectPart(primLocalId);
1123 1126
1127 // Can't move a null item
1128 if (itemId == UUID.Zero)
1129 return;
1130
1124 if (null == part) 1131 if (null == part)
1125 { 1132 {
1126 m_log.WarnFormat( 1133 m_log.WarnFormat(
@@ -1231,6 +1238,10 @@ namespace OpenSim.Region.Framework.Scenes
1231 if ((part.OwnerID != destPart.OwnerID) && ((srcTaskItem.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)) 1238 if ((part.OwnerID != destPart.OwnerID) && ((srcTaskItem.CurrentPermissions & (uint)PermissionMask.Transfer) == 0))
1232 return; 1239 return;
1233 1240
1241 bool overrideNoMod = false;
1242 if ((part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) != 0)
1243 overrideNoMod = true;
1244
1234 if (part.OwnerID != destPart.OwnerID && (part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) == 0) 1245 if (part.OwnerID != destPart.OwnerID && (part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) == 0)
1235 { 1246 {
1236 // object cannot copy items to an object owned by a different owner 1247 // object cannot copy items to an object owned by a different owner
@@ -1240,7 +1251,7 @@ namespace OpenSim.Region.Framework.Scenes
1240 } 1251 }
1241 1252
1242 // must have both move and modify permission to put an item in an object 1253 // must have both move and modify permission to put an item in an object
1243 if ((part.OwnerMask & ((uint)PermissionMask.Move | (uint)PermissionMask.Modify)) == 0) 1254 if (((part.OwnerMask & (uint)PermissionMask.Modify) == 0) && (!overrideNoMod))
1244 { 1255 {
1245 return; 1256 return;
1246 } 1257 }
@@ -1299,6 +1310,14 @@ namespace OpenSim.Region.Framework.Scenes
1299 1310
1300 public UUID MoveTaskInventoryItems(UUID destID, string category, SceneObjectPart host, List<UUID> items) 1311 public UUID MoveTaskInventoryItems(UUID destID, string category, SceneObjectPart host, List<UUID> items)
1301 { 1312 {
1313 SceneObjectPart destPart = GetSceneObjectPart(destID);
1314 if (destPart != null) // Move into a prim
1315 {
1316 foreach(UUID itemID in items)
1317 MoveTaskInventoryItem(destID, host, itemID);
1318 return destID; // Prim folder ID == prim ID
1319 }
1320
1302 InventoryFolderBase rootFolder = InventoryService.GetRootFolder(destID); 1321 InventoryFolderBase rootFolder = InventoryService.GetRootFolder(destID);
1303 1322
1304 UUID newFolderID = UUID.Random(); 1323 UUID newFolderID = UUID.Random();
@@ -1478,13 +1497,6 @@ namespace OpenSim.Region.Framework.Scenes
1478 { 1497 {
1479 agentTransactions.HandleTaskItemUpdateFromTransaction( 1498 agentTransactions.HandleTaskItemUpdateFromTransaction(
1480 remoteClient, part, transactionID, currentItem); 1499 remoteClient, part, transactionID, currentItem);
1481
1482 if ((InventoryType)itemInfo.InvType == InventoryType.Notecard)
1483 remoteClient.SendAgentAlertMessage("Notecard saved", false);
1484 else if ((InventoryType)itemInfo.InvType == InventoryType.LSL)
1485 remoteClient.SendAgentAlertMessage("Script saved", false);
1486 else
1487 remoteClient.SendAgentAlertMessage("Item saved", false);
1488 } 1500 }
1489 1501
1490 // Base ALWAYS has move 1502 // Base ALWAYS has move
@@ -1625,7 +1637,7 @@ namespace OpenSim.Region.Framework.Scenes
1625 return; 1637 return;
1626 1638
1627 AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType, 1639 AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType,
1628 Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n}"), 1640 Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n\n touch_start(integer num)\n {\n }\n}"),
1629 remoteClient.AgentId); 1641 remoteClient.AgentId);
1630 AssetService.Store(asset); 1642 AssetService.Store(asset);
1631 1643
@@ -1778,23 +1790,32 @@ namespace OpenSim.Region.Framework.Scenes
1778 // build a list of eligible objects 1790 // build a list of eligible objects
1779 List<uint> deleteIDs = new List<uint>(); 1791 List<uint> deleteIDs = new List<uint>();
1780 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>(); 1792 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>();
1781 1793 List<SceneObjectGroup> takeGroups = new List<SceneObjectGroup>();
1782 // Start with true for both, then remove the flags if objects
1783 // that we can't derez are part of the selection
1784 bool permissionToTake = true;
1785 bool permissionToTakeCopy = true;
1786 bool permissionToDelete = true;
1787 1794
1788 foreach (uint localID in localIDs) 1795 foreach (uint localID in localIDs)
1789 { 1796 {
1797 // Start with true for both, then remove the flags if objects
1798 // that we can't derez are part of the selection
1799 bool permissionToTake = true;
1800 bool permissionToTakeCopy = true;
1801 bool permissionToDelete = true;
1802
1790 // Invalid id 1803 // Invalid id
1791 SceneObjectPart part = GetSceneObjectPart(localID); 1804 SceneObjectPart part = GetSceneObjectPart(localID);
1792 if (part == null) 1805 if (part == null)
1806 {
1807 //Client still thinks the object exists, kill it
1808 deleteIDs.Add(localID);
1793 continue; 1809 continue;
1810 }
1794 1811
1795 // Already deleted by someone else 1812 // Already deleted by someone else
1796 if (part.ParentGroup.IsDeleted) 1813 if (part.ParentGroup.IsDeleted)
1814 {
1815 //Client still thinks the object exists, kill it
1816 deleteIDs.Add(localID);
1797 continue; 1817 continue;
1818 }
1798 1819
1799 // Can't delete child prims 1820 // Can't delete child prims
1800 if (part != part.ParentGroup.RootPart) 1821 if (part != part.ParentGroup.RootPart)
@@ -1802,9 +1823,6 @@ namespace OpenSim.Region.Framework.Scenes
1802 1823
1803 SceneObjectGroup grp = part.ParentGroup; 1824 SceneObjectGroup grp = part.ParentGroup;
1804 1825
1805 deleteIDs.Add(localID);
1806 deleteGroups.Add(grp);
1807
1808 if (remoteClient == null) 1826 if (remoteClient == null)
1809 { 1827 {
1810 // Autoreturn has a null client. Nothing else does. So 1828 // Autoreturn has a null client. Nothing else does. So
@@ -1821,83 +1839,195 @@ namespace OpenSim.Region.Framework.Scenes
1821 } 1839 }
1822 else 1840 else
1823 { 1841 {
1824 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId)) 1842 if (action == DeRezAction.TakeCopy)
1843 {
1844 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId))
1845 permissionToTakeCopy = false;
1846 }
1847 else
1848 {
1825 permissionToTakeCopy = false; 1849 permissionToTakeCopy = false;
1826 1850 }
1827 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId)) 1851 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId))
1828 permissionToTake = false; 1852 permissionToTake = false;
1829 1853
1830 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId)) 1854 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId))
1831 permissionToDelete = false; 1855 permissionToDelete = false;
1832 } 1856 }
1833 }
1834 1857
1835 // Handle god perms 1858 // Handle god perms
1836 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId)) 1859 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId))
1837 { 1860 {
1838 permissionToTake = true; 1861 permissionToTake = true;
1839 permissionToTakeCopy = true; 1862 permissionToTakeCopy = true;
1840 permissionToDelete = true; 1863 permissionToDelete = true;
1841 } 1864 }
1842 1865
1843 // If we're re-saving, we don't even want to delete 1866 // If we're re-saving, we don't even want to delete
1844 if (action == DeRezAction.SaveToExistingUserInventoryItem) 1867 if (action == DeRezAction.SaveToExistingUserInventoryItem)
1845 permissionToDelete = false; 1868 permissionToDelete = false;
1846 1869
1847 // if we want to take a copy, we also don't want to delete 1870 // if we want to take a copy, we also don't want to delete
1848 // Note: after this point, the permissionToTakeCopy flag 1871 // Note: after this point, the permissionToTakeCopy flag
1849 // becomes irrelevant. It already includes the permissionToTake 1872 // becomes irrelevant. It already includes the permissionToTake
1850 // permission and after excluding no copy items here, we can 1873 // permission and after excluding no copy items here, we can
1851 // just use that. 1874 // just use that.
1852 if (action == DeRezAction.TakeCopy) 1875 if (action == DeRezAction.TakeCopy)
1853 { 1876 {
1854 // If we don't have permission, stop right here 1877 // If we don't have permission, stop right here
1855 if (!permissionToTakeCopy) 1878 if (!permissionToTakeCopy)
1856 return; 1879 return;
1857 1880
1858 permissionToTake = true; 1881 permissionToTake = true;
1859 // Don't delete 1882 // Don't delete
1860 permissionToDelete = false; 1883 permissionToDelete = false;
1861 } 1884 }
1862 1885
1863 if (action == DeRezAction.Return) 1886 if (action == DeRezAction.Return)
1864 {
1865 if (remoteClient != null)
1866 { 1887 {
1867 if (Permissions.CanReturnObjects( 1888 if (remoteClient != null)
1868 null,
1869 remoteClient.AgentId,
1870 deleteGroups))
1871 { 1889 {
1872 permissionToTake = true; 1890 if (Permissions.CanReturnObjects(
1873 permissionToDelete = true; 1891 null,
1874 1892 remoteClient.AgentId,
1875 foreach (SceneObjectGroup g in deleteGroups) 1893 deleteGroups))
1876 { 1894 {
1877 AddReturn(g.OwnerID, g.Name, g.AbsolutePosition, "parcel owner return"); 1895 permissionToTake = true;
1896 permissionToDelete = true;
1897
1898 AddReturn(grp.OwnerID, grp.Name, grp.AbsolutePosition, "parcel owner return");
1878 } 1899 }
1879 } 1900 }
1901 else // Auto return passes through here with null agent
1902 {
1903 permissionToTake = true;
1904 permissionToDelete = true;
1905 }
1880 } 1906 }
1881 else // Auto return passes through here with null agent 1907
1908 if (permissionToTake && (!permissionToDelete))
1909 takeGroups.Add(grp);
1910
1911 if (permissionToDelete)
1882 { 1912 {
1883 permissionToTake = true; 1913 if (permissionToTake)
1884 permissionToDelete = true; 1914 deleteGroups.Add(grp);
1915 deleteIDs.Add(grp.LocalId);
1885 } 1916 }
1886 } 1917 }
1887 1918
1888 if (permissionToTake) 1919 SendKillObject(deleteIDs);
1920
1921 if (deleteGroups.Count > 0)
1889 { 1922 {
1923 foreach (SceneObjectGroup g in deleteGroups)
1924 deleteIDs.Remove(g.LocalId);
1925
1890 m_asyncSceneObjectDeleter.DeleteToInventory( 1926 m_asyncSceneObjectDeleter.DeleteToInventory(
1891 action, destinationID, deleteGroups, remoteClient, 1927 action, destinationID, deleteGroups, remoteClient,
1892 permissionToDelete); 1928 true);
1893 } 1929 }
1894 else if (permissionToDelete) 1930 if (takeGroups.Count > 0)
1931 {
1932 m_asyncSceneObjectDeleter.DeleteToInventory(
1933 action, destinationID, takeGroups, remoteClient,
1934 false);
1935 }
1936 if (deleteIDs.Count > 0)
1895 { 1937 {
1896 foreach (SceneObjectGroup g in deleteGroups) 1938 foreach (SceneObjectGroup g in deleteGroups)
1897 DeleteSceneObject(g, false); 1939 DeleteSceneObject(g, true);
1898 } 1940 }
1899 } 1941 }
1900 1942
1943 public UUID attachObjectAssetStore(IClientAPI remoteClient, SceneObjectGroup grp, UUID AgentId, out UUID itemID)
1944 {
1945 itemID = UUID.Zero;
1946 if (grp != null)
1947 {
1948 Vector3 inventoryStoredPosition = new Vector3
1949 (((grp.AbsolutePosition.X > (int)Constants.RegionSize)
1950 ? 250
1951 : grp.AbsolutePosition.X)
1952 ,
1953 (grp.AbsolutePosition.X > (int)Constants.RegionSize)
1954 ? 250
1955 : grp.AbsolutePosition.X,
1956 grp.AbsolutePosition.Z);
1957
1958 Vector3 originalPosition = grp.AbsolutePosition;
1959
1960 grp.AbsolutePosition = inventoryStoredPosition;
1961
1962 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp);
1963
1964 grp.AbsolutePosition = originalPosition;
1965
1966 AssetBase asset = CreateAsset(
1967 grp.GetPartName(grp.LocalId),
1968 grp.GetPartDescription(grp.LocalId),
1969 (sbyte)AssetType.Object,
1970 Utils.StringToBytes(sceneObjectXml),
1971 remoteClient.AgentId);
1972 AssetService.Store(asset);
1973
1974 InventoryItemBase item = new InventoryItemBase();
1975 item.CreatorId = grp.RootPart.CreatorID.ToString();
1976 item.CreatorData = grp.RootPart.CreatorData;
1977 item.Owner = remoteClient.AgentId;
1978 item.ID = UUID.Random();
1979 item.AssetID = asset.FullID;
1980 item.Description = asset.Description;
1981 item.Name = asset.Name;
1982 item.AssetType = asset.Type;
1983 item.InvType = (int)InventoryType.Object;
1984
1985 InventoryFolderBase folder = InventoryService.GetFolderForType(remoteClient.AgentId, AssetType.Object);
1986 if (folder != null)
1987 item.Folder = folder.ID;
1988 else // oopsies
1989 item.Folder = UUID.Zero;
1990
1991 // Set up base perms properly
1992 uint permsBase = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify);
1993 permsBase &= grp.RootPart.BaseMask;
1994 permsBase |= (uint)PermissionMask.Move;
1995
1996 // Make sure we don't lock it
1997 grp.RootPart.NextOwnerMask |= (uint)PermissionMask.Move;
1998
1999 if ((remoteClient.AgentId != grp.RootPart.OwnerID) && Permissions.PropagatePermissions())
2000 {
2001 item.BasePermissions = permsBase & grp.RootPart.NextOwnerMask;
2002 item.CurrentPermissions = permsBase & grp.RootPart.NextOwnerMask;
2003 item.NextPermissions = permsBase & grp.RootPart.NextOwnerMask;
2004 item.EveryOnePermissions = permsBase & grp.RootPart.EveryoneMask & grp.RootPart.NextOwnerMask;
2005 item.GroupPermissions = permsBase & grp.RootPart.GroupMask & grp.RootPart.NextOwnerMask;
2006 }
2007 else
2008 {
2009 item.BasePermissions = permsBase;
2010 item.CurrentPermissions = permsBase & grp.RootPart.OwnerMask;
2011 item.NextPermissions = permsBase & grp.RootPart.NextOwnerMask;
2012 item.EveryOnePermissions = permsBase & grp.RootPart.EveryoneMask;
2013 item.GroupPermissions = permsBase & grp.RootPart.GroupMask;
2014 }
2015 item.CreationDate = Util.UnixTimeSinceEpoch();
2016
2017 // sets itemID so client can show item as 'attached' in inventory
2018 grp.SetFromItemID(item.ID);
2019
2020 if (AddInventoryItem(item))
2021 remoteClient.SendInventoryItemCreateUpdate(item, 0);
2022 else
2023 m_dialogModule.SendAlertToUser(remoteClient, "Operation failed");
2024
2025 itemID = item.ID;
2026 return item.AssetID;
2027 }
2028 return UUID.Zero;
2029 }
2030
1901 /// <summary> 2031 /// <summary>
1902 /// Event Handler Rez an object into a scene 2032 /// Event Handler Rez an object into a scene
1903 /// Calls the non-void event handler 2033 /// Calls the non-void event handler
@@ -2024,6 +2154,9 @@ namespace OpenSim.Region.Framework.Scenes
2024 2154
2025 public void SetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID, bool running) 2155 public void SetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID, bool running)
2026 { 2156 {
2157 if (!Permissions.CanEditScript(itemID, objectID, controllingClient.AgentId))
2158 return;
2159
2027 SceneObjectPart part = GetSceneObjectPart(objectID); 2160 SceneObjectPart part = GetSceneObjectPart(objectID);
2028 if (part == null) 2161 if (part == null)
2029 return; 2162 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.Permissions.cs b/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs
index e1fedf4..48beb9c 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs
@@ -49,6 +49,7 @@ namespace OpenSim.Region.Framework.Scenes
49 public delegate bool DuplicateObjectHandler(int objectCount, UUID objectID, UUID owner, Scene scene, Vector3 objectPosition); 49 public delegate bool DuplicateObjectHandler(int objectCount, UUID objectID, UUID owner, Scene scene, Vector3 objectPosition);
50 public delegate bool EditObjectHandler(UUID objectID, UUID editorID, Scene scene); 50 public delegate bool EditObjectHandler(UUID objectID, UUID editorID, Scene scene);
51 public delegate bool EditObjectInventoryHandler(UUID objectID, UUID editorID, Scene scene); 51 public delegate bool EditObjectInventoryHandler(UUID objectID, UUID editorID, Scene scene);
52 public delegate bool ViewObjectInventoryHandler(UUID objectID, UUID editorID, Scene scene);
52 public delegate bool MoveObjectHandler(UUID objectID, UUID moverID, Scene scene); 53 public delegate bool MoveObjectHandler(UUID objectID, UUID moverID, Scene scene);
53 public delegate bool ObjectEntryHandler(UUID objectID, bool enteringRegion, Vector3 newPoint, Scene scene); 54 public delegate bool ObjectEntryHandler(UUID objectID, bool enteringRegion, Vector3 newPoint, Scene scene);
54 public delegate bool ReturnObjectsHandler(ILandObject land, UUID user, List<SceneObjectGroup> objects, Scene scene); 55 public delegate bool ReturnObjectsHandler(ILandObject land, UUID user, List<SceneObjectGroup> objects, Scene scene);
@@ -116,6 +117,7 @@ namespace OpenSim.Region.Framework.Scenes
116 public event DuplicateObjectHandler OnDuplicateObject; 117 public event DuplicateObjectHandler OnDuplicateObject;
117 public event EditObjectHandler OnEditObject; 118 public event EditObjectHandler OnEditObject;
118 public event EditObjectInventoryHandler OnEditObjectInventory; 119 public event EditObjectInventoryHandler OnEditObjectInventory;
120 public event ViewObjectInventoryHandler OnViewObjectInventory;
119 public event MoveObjectHandler OnMoveObject; 121 public event MoveObjectHandler OnMoveObject;
120 public event ObjectEntryHandler OnObjectEntry; 122 public event ObjectEntryHandler OnObjectEntry;
121 public event ReturnObjectsHandler OnReturnObjects; 123 public event ReturnObjectsHandler OnReturnObjects;
@@ -401,6 +403,21 @@ namespace OpenSim.Region.Framework.Scenes
401 return true; 403 return true;
402 } 404 }
403 405
406 public bool CanViewObjectInventory(UUID objectID, UUID editorID)
407 {
408 ViewObjectInventoryHandler handler = OnViewObjectInventory;
409 if (handler != null)
410 {
411 Delegate[] list = handler.GetInvocationList();
412 foreach (ViewObjectInventoryHandler h in list)
413 {
414 if (h(objectID, editorID, m_scene) == false)
415 return false;
416 }
417 }
418 return true;
419 }
420
404 #endregion 421 #endregion
405 422
406 #region MOVE OBJECT 423 #region MOVE OBJECT
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 027ec96..4de494f 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -103,6 +103,7 @@ namespace OpenSim.Region.Framework.Scenes
103 // TODO: need to figure out how allow client agents but deny 103 // TODO: need to figure out how allow client agents but deny
104 // root agents when ACL denies access to root agent 104 // root agents when ACL denies access to root agent
105 public bool m_strictAccessControl = true; 105 public bool m_strictAccessControl = true;
106 public bool m_seeIntoBannedRegion = false;
106 public int MaxUndoCount = 5; 107 public int MaxUndoCount = 5;
107 // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet; 108 // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet;
108 public bool LoginLock = false; 109 public bool LoginLock = false;
@@ -118,12 +119,14 @@ namespace OpenSim.Region.Framework.Scenes
118 119
119 protected int m_splitRegionID; 120 protected int m_splitRegionID;
120 protected Timer m_restartWaitTimer = new Timer(); 121 protected Timer m_restartWaitTimer = new Timer();
122 protected Timer m_timerWatchdog = new Timer();
121 protected List<RegionInfo> m_regionRestartNotifyList = new List<RegionInfo>(); 123 protected List<RegionInfo> m_regionRestartNotifyList = new List<RegionInfo>();
122 protected List<RegionInfo> m_neighbours = new List<RegionInfo>(); 124 protected List<RegionInfo> m_neighbours = new List<RegionInfo>();
123 protected string m_simulatorVersion = "OpenSimulator Server"; 125 protected string m_simulatorVersion = "OpenSimulator Server";
124 protected ModuleLoader m_moduleLoader; 126 protected ModuleLoader m_moduleLoader;
125 protected AgentCircuitManager m_authenticateHandler; 127 protected AgentCircuitManager m_authenticateHandler;
126 protected SceneCommunicationService m_sceneGridService; 128 protected SceneCommunicationService m_sceneGridService;
129 protected ISnmpModule m_snmpService = null;
127 130
128 protected ISimulationDataService m_SimulationDataService; 131 protected ISimulationDataService m_SimulationDataService;
129 protected IEstateDataService m_EstateDataService; 132 protected IEstateDataService m_EstateDataService;
@@ -176,7 +179,7 @@ namespace OpenSim.Region.Framework.Scenes
176 private int m_update_events = 1; 179 private int m_update_events = 1;
177 private int m_update_backup = 200; 180 private int m_update_backup = 200;
178 private int m_update_terrain = 50; 181 private int m_update_terrain = 50;
179// private int m_update_land = 1; 182 private int m_update_land = 10;
180 private int m_update_coarse_locations = 50; 183 private int m_update_coarse_locations = 50;
181 184
182 private int agentMS; 185 private int agentMS;
@@ -191,6 +194,7 @@ namespace OpenSim.Region.Framework.Scenes
191 private int landMS; 194 private int landMS;
192 private int lastCompletedFrame; 195 private int lastCompletedFrame;
193 196
197 public bool CombineRegions = false;
194 /// <summary> 198 /// <summary>
195 /// Signals whether temporary objects are currently being cleaned up. Needed because this is launched 199 /// Signals whether temporary objects are currently being cleaned up. Needed because this is launched
196 /// asynchronously from the update loop. 200 /// asynchronously from the update loop.
@@ -213,11 +217,14 @@ namespace OpenSim.Region.Framework.Scenes
213 private bool m_scripts_enabled = true; 217 private bool m_scripts_enabled = true;
214 private string m_defaultScriptEngine; 218 private string m_defaultScriptEngine;
215 private int m_LastLogin; 219 private int m_LastLogin;
216 private Thread HeartbeatThread; 220 private Thread HeartbeatThread = null;
217 private volatile bool shuttingdown; 221 private volatile bool shuttingdown;
218 222
219 private int m_lastUpdate; 223 private int m_lastUpdate;
224 private int m_lastIncoming;
225 private int m_lastOutgoing;
220 private bool m_firstHeartbeat = true; 226 private bool m_firstHeartbeat = true;
227 private int m_hbRestarts = 0;
221 228
222 private object m_deleting_scene_object = new object(); 229 private object m_deleting_scene_object = new object();
223 230
@@ -264,6 +271,19 @@ namespace OpenSim.Region.Framework.Scenes
264 get { return m_sceneGridService; } 271 get { return m_sceneGridService; }
265 } 272 }
266 273
274 public ISnmpModule SnmpService
275 {
276 get
277 {
278 if (m_snmpService == null)
279 {
280 m_snmpService = RequestModuleInterface<ISnmpModule>();
281 }
282
283 return m_snmpService;
284 }
285 }
286
267 public ISimulationDataService SimulationDataService 287 public ISimulationDataService SimulationDataService
268 { 288 {
269 get 289 get
@@ -545,6 +565,9 @@ namespace OpenSim.Region.Framework.Scenes
545 m_EstateDataService = estateDataService; 565 m_EstateDataService = estateDataService;
546 m_regionHandle = m_regInfo.RegionHandle; 566 m_regionHandle = m_regInfo.RegionHandle;
547 m_regionName = m_regInfo.RegionName; 567 m_regionName = m_regInfo.RegionName;
568 m_lastUpdate = Util.EnvironmentTickCount();
569 m_lastIncoming = 0;
570 m_lastOutgoing = 0;
548 571
549 m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this); 572 m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this);
550 m_asyncSceneObjectDeleter.Enabled = true; 573 m_asyncSceneObjectDeleter.Enabled = true;
@@ -662,6 +685,7 @@ namespace OpenSim.Region.Framework.Scenes
662 CollidablePrims = startupConfig.GetBoolean("collidable_prim", true); 685 CollidablePrims = startupConfig.GetBoolean("collidable_prim", true);
663 686
664 m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys); 687 m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys);
688
665 if (RegionInfo.NonphysPrimMax > 0) 689 if (RegionInfo.NonphysPrimMax > 0)
666 { 690 {
667 m_maxNonphys = RegionInfo.NonphysPrimMax; 691 m_maxNonphys = RegionInfo.NonphysPrimMax;
@@ -693,6 +717,7 @@ namespace OpenSim.Region.Framework.Scenes
693 m_persistAfter *= 10000000; 717 m_persistAfter *= 10000000;
694 718
695 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine"); 719 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine");
720 m_log.InfoFormat("[SCENE]: Default script engine {0}", m_defaultScriptEngine);
696 721
697 IConfig packetConfig = m_config.Configs["PacketPool"]; 722 IConfig packetConfig = m_config.Configs["PacketPool"];
698 if (packetConfig != null) 723 if (packetConfig != null)
@@ -702,6 +727,8 @@ namespace OpenSim.Region.Framework.Scenes
702 } 727 }
703 728
704 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl); 729 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl);
730 m_seeIntoBannedRegion = startupConfig.GetBoolean("SeeIntoBannedRegion", m_seeIntoBannedRegion);
731 CombineRegions = startupConfig.GetBoolean("CombineContiguousRegions", false);
705 732
706 m_generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", true); 733 m_generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", true);
707 if (m_generateMaptiles) 734 if (m_generateMaptiles)
@@ -737,9 +764,9 @@ namespace OpenSim.Region.Framework.Scenes
737 m_update_terrain = startupConfig.GetInt( "UpdateTerrainEveryNFrames", m_update_terrain); 764 m_update_terrain = startupConfig.GetInt( "UpdateTerrainEveryNFrames", m_update_terrain);
738 m_update_temp_cleaning = startupConfig.GetInt( "UpdateTempCleaningEveryNFrames", m_update_temp_cleaning); 765 m_update_temp_cleaning = startupConfig.GetInt( "UpdateTempCleaningEveryNFrames", m_update_temp_cleaning);
739 } 766 }
740 catch 767 catch (Exception e)
741 { 768 {
742 m_log.Warn("[SCENE]: Failed to load StartupConfig"); 769 m_log.Error("[SCENE]: Failed to load StartupConfig: " + e.ToString());
743 } 770 }
744 771
745 #endregion Region Config 772 #endregion Region Config
@@ -1150,7 +1177,22 @@ namespace OpenSim.Region.Framework.Scenes
1150 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat); 1177 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat);
1151 if (HeartbeatThread != null) 1178 if (HeartbeatThread != null)
1152 { 1179 {
1180 m_hbRestarts++;
1181 if(m_hbRestarts > 10)
1182 Environment.Exit(1);
1183 m_log.ErrorFormat("[SCENE]: Restarting heartbeat thread because it hasn't reported in in region {0}", RegionInfo.RegionName);
1184
1185//int pid = System.Diagnostics.Process.GetCurrentProcess().Id;
1186//System.Diagnostics.Process proc = new System.Diagnostics.Process();
1187//proc.EnableRaisingEvents=false;
1188//proc.StartInfo.FileName = "/bin/kill";
1189//proc.StartInfo.Arguments = "-QUIT " + pid.ToString();
1190//proc.Start();
1191//proc.WaitForExit();
1192//Thread.Sleep(1000);
1193//Environment.Exit(1);
1153 HeartbeatThread.Abort(); 1194 HeartbeatThread.Abort();
1195 Watchdog.AbortThread(HeartbeatThread.ManagedThreadId);
1154 HeartbeatThread = null; 1196 HeartbeatThread = null;
1155 } 1197 }
1156 m_lastUpdate = Util.EnvironmentTickCount(); 1198 m_lastUpdate = Util.EnvironmentTickCount();
@@ -1197,9 +1239,6 @@ namespace OpenSim.Region.Framework.Scenes
1197 m_eventManager.TriggerOnRegionStarted(this); 1239 m_eventManager.TriggerOnRegionStarted(this);
1198 while (!shuttingdown) 1240 while (!shuttingdown)
1199 Update(); 1241 Update();
1200
1201 m_lastUpdate = Util.EnvironmentTickCount();
1202 m_firstHeartbeat = false;
1203 } 1242 }
1204 catch (ThreadAbortException) 1243 catch (ThreadAbortException)
1205 { 1244 {
@@ -1297,6 +1336,13 @@ namespace OpenSim.Region.Framework.Scenes
1297 eventMS = Util.EnvironmentTickCountSubtract(evMS); ; 1336 eventMS = Util.EnvironmentTickCountSubtract(evMS); ;
1298 } 1337 }
1299 1338
1339 // if (Frame % m_update_land == 0)
1340 // {
1341 // int ldMS = Util.EnvironmentTickCount();
1342 // UpdateLand();
1343 // landMS = Util.EnvironmentTickCountSubtract(ldMS);
1344 // }
1345
1300 if (Frame % m_update_backup == 0) 1346 if (Frame % m_update_backup == 0)
1301 { 1347 {
1302 int backMS = Util.EnvironmentTickCount(); 1348 int backMS = Util.EnvironmentTickCount();
@@ -1404,12 +1450,16 @@ namespace OpenSim.Region.Framework.Scenes
1404 maintc = Util.EnvironmentTickCountSubtract(maintc); 1450 maintc = Util.EnvironmentTickCountSubtract(maintc);
1405 maintc = (int)(MinFrameTime * 1000) - maintc; 1451 maintc = (int)(MinFrameTime * 1000) - maintc;
1406 1452
1453
1454 m_lastUpdate = Util.EnvironmentTickCount();
1455 m_firstHeartbeat = false;
1456
1407 if (maintc > 0) 1457 if (maintc > 0)
1408 Thread.Sleep(maintc); 1458 Thread.Sleep(maintc);
1409 1459
1410 // Tell the watchdog that this thread is still alive 1460 // Tell the watchdog that this thread is still alive
1411 Watchdog.UpdateThread(); 1461 Watchdog.UpdateThread();
1412 } 1462 }
1413 1463
1414 public void AddGroupTarget(SceneObjectGroup grp) 1464 public void AddGroupTarget(SceneObjectGroup grp)
1415 { 1465 {
@@ -1425,9 +1475,9 @@ namespace OpenSim.Region.Framework.Scenes
1425 1475
1426 private void CheckAtTargets() 1476 private void CheckAtTargets()
1427 { 1477 {
1428 Dictionary<UUID, SceneObjectGroup>.ValueCollection objs; 1478 List<SceneObjectGroup> objs = new List<SceneObjectGroup>();
1429 lock (m_groupsWithTargets) 1479 lock (m_groupsWithTargets)
1430 objs = m_groupsWithTargets.Values; 1480 objs = new List<SceneObjectGroup>(m_groupsWithTargets.Values);
1431 1481
1432 foreach (SceneObjectGroup entry in objs) 1482 foreach (SceneObjectGroup entry in objs)
1433 entry.checkAtTargets(); 1483 entry.checkAtTargets();
@@ -1509,7 +1559,7 @@ namespace OpenSim.Region.Framework.Scenes
1509 msg.fromAgentName = "Server"; 1559 msg.fromAgentName = "Server";
1510 msg.dialog = (byte)19; // Object msg 1560 msg.dialog = (byte)19; // Object msg
1511 msg.fromGroup = false; 1561 msg.fromGroup = false;
1512 msg.offline = (byte)0; 1562 msg.offline = (byte)1;
1513 msg.ParentEstateID = RegionInfo.EstateSettings.ParentEstateID; 1563 msg.ParentEstateID = RegionInfo.EstateSettings.ParentEstateID;
1514 msg.Position = Vector3.Zero; 1564 msg.Position = Vector3.Zero;
1515 msg.RegionID = RegionInfo.RegionID.Guid; 1565 msg.RegionID = RegionInfo.RegionID.Guid;
@@ -1740,14 +1790,24 @@ namespace OpenSim.Region.Framework.Scenes
1740 /// <returns></returns> 1790 /// <returns></returns>
1741 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter) 1791 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter)
1742 { 1792 {
1793
1794 float wheight = (float)RegionInfo.RegionSettings.WaterHeight;
1795 Vector3 wpos = Vector3.Zero;
1796 // Check for water surface intersection from above
1797 if ( (RayStart.Z > wheight) && (RayEnd.Z < wheight) )
1798 {
1799 float ratio = (RayStart.Z - wheight) / (RayStart.Z - RayEnd.Z);
1800 wpos.X = RayStart.X - (ratio * (RayStart.X - RayEnd.X));
1801 wpos.Y = RayStart.Y - (ratio * (RayStart.Y - RayEnd.Y));
1802 wpos.Z = wheight;
1803 }
1804
1743 Vector3 pos = Vector3.Zero; 1805 Vector3 pos = Vector3.Zero;
1744 if (RayEndIsIntersection == (byte)1) 1806 if (RayEndIsIntersection == (byte)1)
1745 { 1807 {
1746 pos = RayEnd; 1808 pos = RayEnd;
1747 return pos;
1748 } 1809 }
1749 1810 else if (RayTargetID != UUID.Zero)
1750 if (RayTargetID != UUID.Zero)
1751 { 1811 {
1752 SceneObjectPart target = GetSceneObjectPart(RayTargetID); 1812 SceneObjectPart target = GetSceneObjectPart(RayTargetID);
1753 1813
@@ -1769,7 +1829,7 @@ namespace OpenSim.Region.Framework.Scenes
1769 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter); 1829 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter);
1770 1830
1771 // Un-comment out the following line to Get Raytrace results printed to the console. 1831 // Un-comment out the following line to Get Raytrace results printed to the console.
1772 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString()); 1832 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
1773 float ScaleOffset = 0.5f; 1833 float ScaleOffset = 0.5f;
1774 1834
1775 // If we hit something 1835 // If we hit something
@@ -1792,13 +1852,10 @@ namespace OpenSim.Region.Framework.Scenes
1792 //pos.Z -= 0.25F; 1852 //pos.Z -= 0.25F;
1793 1853
1794 } 1854 }
1795
1796 return pos;
1797 } 1855 }
1798 else 1856 else
1799 { 1857 {
1800 // We don't have a target here, so we're going to raytrace all the objects in the scene. 1858 // We don't have a target here, so we're going to raytrace all the objects in the scene.
1801
1802 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false); 1859 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false);
1803 1860
1804 // Un-comment the following line to print the raytrace results to the console. 1861 // Un-comment the following line to print the raytrace results to the console.
@@ -1807,13 +1864,12 @@ namespace OpenSim.Region.Framework.Scenes
1807 if (ei.HitTF) 1864 if (ei.HitTF)
1808 { 1865 {
1809 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z); 1866 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z);
1810 } else 1867 }
1868 else
1811 { 1869 {
1812 // fall back to our stupid functionality 1870 // fall back to our stupid functionality
1813 pos = RayEnd; 1871 pos = RayEnd;
1814 } 1872 }
1815
1816 return pos;
1817 } 1873 }
1818 } 1874 }
1819 else 1875 else
@@ -1824,8 +1880,12 @@ namespace OpenSim.Region.Framework.Scenes
1824 //increase height so its above the ground. 1880 //increase height so its above the ground.
1825 //should be getting the normal of the ground at the rez point and using that? 1881 //should be getting the normal of the ground at the rez point and using that?
1826 pos.Z += scale.Z / 2f; 1882 pos.Z += scale.Z / 2f;
1827 return pos; 1883// return pos;
1828 } 1884 }
1885
1886 // check against posible water intercept
1887 if (wpos.Z > pos.Z) pos = wpos;
1888 return pos;
1829 } 1889 }
1830 1890
1831 1891
@@ -1909,7 +1969,10 @@ namespace OpenSim.Region.Framework.Scenes
1909 public bool AddRestoredSceneObject( 1969 public bool AddRestoredSceneObject(
1910 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 1970 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
1911 { 1971 {
1912 return m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates); 1972 bool result = m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates);
1973 if (result)
1974 sceneObject.IsDeleted = false;
1975 return result;
1913 } 1976 }
1914 1977
1915 /// <summary> 1978 /// <summary>
@@ -1999,6 +2062,15 @@ namespace OpenSim.Region.Framework.Scenes
1999 /// </summary> 2062 /// </summary>
2000 public void DeleteAllSceneObjects() 2063 public void DeleteAllSceneObjects()
2001 { 2064 {
2065 DeleteAllSceneObjects(false);
2066 }
2067
2068 /// <summary>
2069 /// Delete every object from the scene. This does not include attachments worn by avatars.
2070 /// </summary>
2071 public void DeleteAllSceneObjects(bool exceptNoCopy)
2072 {
2073 List<SceneObjectGroup> toReturn = new List<SceneObjectGroup>();
2002 lock (Entities) 2074 lock (Entities)
2003 { 2075 {
2004 EntityBase[] entities = Entities.GetEntities(); 2076 EntityBase[] entities = Entities.GetEntities();
@@ -2007,11 +2079,24 @@ namespace OpenSim.Region.Framework.Scenes
2007 if (e is SceneObjectGroup) 2079 if (e is SceneObjectGroup)
2008 { 2080 {
2009 SceneObjectGroup sog = (SceneObjectGroup)e; 2081 SceneObjectGroup sog = (SceneObjectGroup)e;
2010 if (!sog.IsAttachment) 2082 if (sog != null && !sog.IsAttachment)
2011 DeleteSceneObject((SceneObjectGroup)e, false); 2083 {
2084 if (!exceptNoCopy || ((sog.GetEffectivePermissions() & (uint)PermissionMask.Copy) != 0))
2085 {
2086 DeleteSceneObject((SceneObjectGroup)e, false);
2087 }
2088 else
2089 {
2090 toReturn.Add((SceneObjectGroup)e);
2091 }
2092 }
2012 } 2093 }
2013 } 2094 }
2014 } 2095 }
2096 if (toReturn.Count > 0)
2097 {
2098 returnObjects(toReturn.ToArray(), UUID.Zero);
2099 }
2015 } 2100 }
2016 2101
2017 /// <summary> 2102 /// <summary>
@@ -2059,6 +2144,8 @@ namespace OpenSim.Region.Framework.Scenes
2059 } 2144 }
2060 2145
2061 group.DeleteGroupFromScene(silent); 2146 group.DeleteGroupFromScene(silent);
2147 if (!silent)
2148 SendKillObject(new List<uint>() { group.LocalId });
2062 2149
2063// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID); 2150// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID);
2064 } 2151 }
@@ -2413,10 +2500,17 @@ namespace OpenSim.Region.Framework.Scenes
2413 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns> 2500 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns>
2414 public bool AddSceneObject(SceneObjectGroup sceneObject) 2501 public bool AddSceneObject(SceneObjectGroup sceneObject)
2415 { 2502 {
2503 if (sceneObject.OwnerID == UUID.Zero)
2504 {
2505 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero", sceneObject.UUID);
2506 return false;
2507 }
2508
2416 // If the user is banned, we won't let any of their objects 2509 // If the user is banned, we won't let any of their objects
2417 // enter. Period. 2510 // enter. Period.
2418 // 2511 //
2419 if (m_regInfo.EstateSettings.IsBanned(sceneObject.OwnerID)) 2512 int flags = GetUserFlags(sceneObject.OwnerID);
2513 if (m_regInfo.EstateSettings.IsBanned(sceneObject.OwnerID, flags))
2420 { 2514 {
2421 m_log.InfoFormat("[INTERREGION]: Denied prim crossing for banned avatar {0}", sceneObject.OwnerID); 2515 m_log.InfoFormat("[INTERREGION]: Denied prim crossing for banned avatar {0}", sceneObject.OwnerID);
2422 2516
@@ -2462,12 +2556,23 @@ namespace OpenSim.Region.Framework.Scenes
2462 } 2556 }
2463 else 2557 else
2464 { 2558 {
2559 m_log.DebugFormat("[SCENE]: Attachment {0} arrived and scene presence was not found, setting to temp", sceneObject.UUID);
2465 RootPrim.RemFlag(PrimFlags.TemporaryOnRez); 2560 RootPrim.RemFlag(PrimFlags.TemporaryOnRez);
2466 RootPrim.AddFlag(PrimFlags.TemporaryOnRez); 2561 RootPrim.AddFlag(PrimFlags.TemporaryOnRez);
2467 } 2562 }
2563 if (sceneObject.OwnerID == UUID.Zero)
2564 {
2565 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero after attachment processing. BUG!", sceneObject.UUID);
2566 return false;
2567 }
2468 } 2568 }
2469 else 2569 else
2470 { 2570 {
2571 if (sceneObject.OwnerID == UUID.Zero)
2572 {
2573 m_log.ErrorFormat("[SCENE]: Owner ID for non-attachment {0} was zero", sceneObject.UUID);
2574 return false;
2575 }
2471 AddRestoredSceneObject(sceneObject, true, false); 2576 AddRestoredSceneObject(sceneObject, true, false);
2472 2577
2473 if (!Permissions.CanObjectEntry(sceneObject.UUID, 2578 if (!Permissions.CanObjectEntry(sceneObject.UUID,
@@ -2496,6 +2601,24 @@ namespace OpenSim.Region.Framework.Scenes
2496 return 2; // StateSource.PrimCrossing 2601 return 2; // StateSource.PrimCrossing
2497 } 2602 }
2498 2603
2604 public int GetUserFlags(UUID user)
2605 {
2606 //Unfortunately the SP approach means that the value is cached until region is restarted
2607 /*
2608 ScenePresence sp;
2609 if (TryGetScenePresence(user, out sp))
2610 {
2611 return sp.UserFlags;
2612 }
2613 else
2614 {
2615 */
2616 UserAccount uac = UserAccountService.GetUserAccount(RegionInfo.ScopeID, user);
2617 if (uac == null)
2618 return 0;
2619 return uac.UserFlags;
2620 //}
2621 }
2499 #endregion 2622 #endregion
2500 2623
2501 #region Add/Remove Avatar Methods 2624 #region Add/Remove Avatar Methods
@@ -2510,6 +2633,7 @@ namespace OpenSim.Region.Framework.Scenes
2510 || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; 2633 || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0;
2511 2634
2512 CheckHeartbeat(); 2635 CheckHeartbeat();
2636 ScenePresence presence;
2513 2637
2514 ScenePresence sp = GetScenePresence(client.AgentId); 2638 ScenePresence sp = GetScenePresence(client.AgentId);
2515 2639
@@ -2558,7 +2682,13 @@ namespace OpenSim.Region.Framework.Scenes
2558 2682
2559 EventManager.TriggerOnNewClient(client); 2683 EventManager.TriggerOnNewClient(client);
2560 if (vialogin) 2684 if (vialogin)
2685 {
2561 EventManager.TriggerOnClientLogin(client); 2686 EventManager.TriggerOnClientLogin(client);
2687 // Send initial parcel data
2688 Vector3 pos = sp.AbsolutePosition;
2689 ILandObject land = LandChannel.GetLandObject(pos.X, pos.Y);
2690 land.SendLandUpdateToClient(client);
2691 }
2562 2692
2563 return sp; 2693 return sp;
2564 } 2694 }
@@ -2648,19 +2778,12 @@ namespace OpenSim.Region.Framework.Scenes
2648 // and the scene presence and the client, if they exist 2778 // and the scene presence and the client, if they exist
2649 try 2779 try
2650 { 2780 {
2651 // We need to wait for the client to make UDP contact first. 2781 ScenePresence sp = GetScenePresence(agentID);
2652 // It's the UDP contact that creates the scene presence 2782 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
2653 ScenePresence sp = WaitGetScenePresence(agentID); 2783
2654 if (sp != null) 2784 if (sp != null)
2655 {
2656 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
2657
2658 sp.ControllingClient.Close(); 2785 sp.ControllingClient.Close();
2659 } 2786
2660 else
2661 {
2662 m_log.WarnFormat("[SCENE]: Could not find scene presence for {0}", agentID);
2663 }
2664 // BANG! SLASH! 2787 // BANG! SLASH!
2665 m_authenticateHandler.RemoveCircuit(agentID); 2788 m_authenticateHandler.RemoveCircuit(agentID);
2666 2789
@@ -2761,6 +2884,7 @@ namespace OpenSim.Region.Framework.Scenes
2761 client.OnFetchInventory += m_asyncInventorySender.HandleFetchInventory; 2884 client.OnFetchInventory += m_asyncInventorySender.HandleFetchInventory;
2762 client.OnUpdateInventoryItem += UpdateInventoryItemAsset; 2885 client.OnUpdateInventoryItem += UpdateInventoryItemAsset;
2763 client.OnCopyInventoryItem += CopyInventoryItem; 2886 client.OnCopyInventoryItem += CopyInventoryItem;
2887 client.OnMoveItemsAndLeaveCopy += MoveInventoryItemsLeaveCopy;
2764 client.OnMoveInventoryItem += MoveInventoryItem; 2888 client.OnMoveInventoryItem += MoveInventoryItem;
2765 client.OnRemoveInventoryItem += RemoveInventoryItem; 2889 client.OnRemoveInventoryItem += RemoveInventoryItem;
2766 client.OnRemoveInventoryFolder += RemoveInventoryFolder; 2890 client.OnRemoveInventoryFolder += RemoveInventoryFolder;
@@ -2936,15 +3060,16 @@ namespace OpenSim.Region.Framework.Scenes
2936 /// </summary> 3060 /// </summary>
2937 /// <param name="agentId">The avatar's Unique ID</param> 3061 /// <param name="agentId">The avatar's Unique ID</param>
2938 /// <param name="client">The IClientAPI for the client</param> 3062 /// <param name="client">The IClientAPI for the client</param>
2939 public virtual void TeleportClientHome(UUID agentId, IClientAPI client) 3063 public virtual bool TeleportClientHome(UUID agentId, IClientAPI client)
2940 { 3064 {
2941 if (m_teleportModule != null) 3065 if (m_teleportModule != null)
2942 m_teleportModule.TeleportHome(agentId, client); 3066 return m_teleportModule.TeleportHome(agentId, client);
2943 else 3067 else
2944 { 3068 {
2945 m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active"); 3069 m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active");
2946 client.SendTeleportFailed("Unable to perform teleports on this simulator."); 3070 client.SendTeleportFailed("Unable to perform teleports on this simulator.");
2947 } 3071 }
3072 return false;
2948 } 3073 }
2949 3074
2950 /// <summary> 3075 /// <summary>
@@ -3036,6 +3161,16 @@ namespace OpenSim.Region.Framework.Scenes
3036 /// <param name="flags"></param> 3161 /// <param name="flags"></param>
3037 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags) 3162 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags)
3038 { 3163 {
3164 //Add half the avatar's height so that the user doesn't fall through prims
3165 ScenePresence presence;
3166 if (TryGetScenePresence(remoteClient.AgentId, out presence))
3167 {
3168 if (presence.Appearance != null)
3169 {
3170 position.Z = position.Z + (presence.Appearance.AvatarHeight / 2);
3171 }
3172 }
3173
3039 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt)) 3174 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt))
3040 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot. 3175 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot.
3041 m_dialogModule.SendAlertToUser(remoteClient, "Home position set."); 3176 m_dialogModule.SendAlertToUser(remoteClient, "Home position set.");
@@ -3104,8 +3239,9 @@ namespace OpenSim.Region.Framework.Scenes
3104 regions.Remove(RegionInfo.RegionHandle); 3239 regions.Remove(RegionInfo.RegionHandle);
3105 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); 3240 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions);
3106 } 3241 }
3107 3242 m_log.Debug("[Scene] Beginning ClientClosed");
3108 m_eventManager.TriggerClientClosed(agentID, this); 3243 m_eventManager.TriggerClientClosed(agentID, this);
3244 m_log.Debug("[Scene] Finished ClientClosed");
3109 } 3245 }
3110 catch (NullReferenceException) 3246 catch (NullReferenceException)
3111 { 3247 {
@@ -3157,9 +3293,10 @@ namespace OpenSim.Region.Framework.Scenes
3157 { 3293 {
3158 m_log.ErrorFormat("[SCENE] Scene.cs:RemoveClient exception {0}{1}", e.Message, e.StackTrace); 3294 m_log.ErrorFormat("[SCENE] Scene.cs:RemoveClient exception {0}{1}", e.Message, e.StackTrace);
3159 } 3295 }
3160 3296 m_log.Debug("[Scene] Done. Firing RemoveCircuit");
3161 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode); 3297 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode);
3162// CleanDroppedAttachments(); 3298// CleanDroppedAttachments();
3299 m_log.Debug("[Scene] The avatar has left the building");
3163 //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false)); 3300 //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false));
3164 //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true)); 3301 //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true));
3165 } 3302 }
@@ -3278,13 +3415,16 @@ namespace OpenSim.Region.Framework.Scenes
3278 sp = null; 3415 sp = null;
3279 } 3416 }
3280 3417
3281 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3282 3418
3283 //On login test land permisions 3419 //On login test land permisions
3284 if (vialogin) 3420 if (vialogin)
3285 { 3421 {
3286 if (land != null && !TestLandRestrictions(agent, land, out reason)) 3422 IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>();
3423 if (cache != null)
3424 cache.Remove(agent.firstname + " " + agent.lastname);
3425 if (!TestLandRestrictions(agent.AgentID, out reason, ref agent.startpos.X, ref agent.startpos.Y))
3287 { 3426 {
3427 m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString());
3288 return false; 3428 return false;
3289 } 3429 }
3290 } 3430 }
@@ -3308,8 +3448,13 @@ namespace OpenSim.Region.Framework.Scenes
3308 3448
3309 try 3449 try
3310 { 3450 {
3311 if (!AuthorizeUser(agent, out reason)) 3451 // Always check estate if this is a login. Always
3312 return false; 3452 // check if banned regions are to be blacked out.
3453 if (vialogin || (!m_seeIntoBannedRegion))
3454 {
3455 if (!AuthorizeUser(agent, out reason))
3456 return false;
3457 }
3313 } 3458 }
3314 catch (Exception e) 3459 catch (Exception e)
3315 { 3460 {
@@ -3412,6 +3557,8 @@ namespace OpenSim.Region.Framework.Scenes
3412 } 3557 }
3413 } 3558 }
3414 // Honor parcel landing type and position. 3559 // Honor parcel landing type and position.
3560 /*
3561 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3415 if (land != null) 3562 if (land != null)
3416 { 3563 {
3417 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) 3564 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero)
@@ -3419,26 +3566,34 @@ namespace OpenSim.Region.Framework.Scenes
3419 agent.startpos = land.LandData.UserLocation; 3566 agent.startpos = land.LandData.UserLocation;
3420 } 3567 }
3421 } 3568 }
3569 */// This is now handled properly in ScenePresence.MakeRootAgent
3422 } 3570 }
3423 3571
3424 return true; 3572 return true;
3425 } 3573 }
3426 3574
3427 private bool TestLandRestrictions(AgentCircuitData agent, ILandObject land, out string reason) 3575 private bool TestLandRestrictions(UUID agentID, out string reason, ref float posX, ref float posY)
3428 { 3576 {
3429 3577 reason = String.Empty;
3430 bool banned = land.IsBannedFromLand(agent.AgentID); 3578 if (Permissions.IsGod(agentID))
3431 bool restricted = land.IsRestrictedFromLand(agent.AgentID); 3579 return true;
3580
3581 ILandObject land = LandChannel.GetLandObject(posX, posY);
3582 if (land == null)
3583 return false;
3584
3585 bool banned = land.IsBannedFromLand(agentID);
3586 bool restricted = land.IsRestrictedFromLand(agentID);
3432 3587
3433 if (banned || restricted) 3588 if (banned || restricted)
3434 { 3589 {
3435 ILandObject nearestParcel = GetNearestAllowedParcel(agent.AgentID, agent.startpos.X, agent.startpos.Y); 3590 ILandObject nearestParcel = GetNearestAllowedParcel(agentID, posX, posY);
3436 if (nearestParcel != null) 3591 if (nearestParcel != null)
3437 { 3592 {
3438 //Move agent to nearest allowed 3593 //Move agent to nearest allowed
3439 Vector3 newPosition = GetParcelCenterAtGround(nearestParcel); 3594 Vector3 newPosition = GetParcelCenterAtGround(nearestParcel);
3440 agent.startpos.X = newPosition.X; 3595 posX = newPosition.X;
3441 agent.startpos.Y = newPosition.Y; 3596 posY = newPosition.Y;
3442 } 3597 }
3443 else 3598 else
3444 { 3599 {
@@ -3500,7 +3655,7 @@ namespace OpenSim.Region.Framework.Scenes
3500 3655
3501 if (!m_strictAccessControl) return true; 3656 if (!m_strictAccessControl) return true;
3502 if (Permissions.IsGod(agent.AgentID)) return true; 3657 if (Permissions.IsGod(agent.AgentID)) return true;
3503 3658
3504 if (AuthorizationService != null) 3659 if (AuthorizationService != null)
3505 { 3660 {
3506 if (!AuthorizationService.IsAuthorizedForRegion( 3661 if (!AuthorizationService.IsAuthorizedForRegion(
@@ -3508,14 +3663,14 @@ namespace OpenSim.Region.Framework.Scenes
3508 { 3663 {
3509 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the region", 3664 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the region",
3510 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 3665 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
3511 3666
3512 return false; 3667 return false;
3513 } 3668 }
3514 } 3669 }
3515 3670
3516 if (m_regInfo.EstateSettings != null) 3671 if (m_regInfo.EstateSettings != null)
3517 { 3672 {
3518 if (m_regInfo.EstateSettings.IsBanned(agent.AgentID)) 3673 if (m_regInfo.EstateSettings.IsBanned(agent.AgentID,0))
3519 { 3674 {
3520 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist", 3675 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist",
3521 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 3676 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
@@ -3707,6 +3862,13 @@ namespace OpenSim.Region.Framework.Scenes
3707 3862
3708 // We have to wait until the viewer contacts this region after receiving EAC. 3863 // We have to wait until the viewer contacts this region after receiving EAC.
3709 // That calls AddNewClient, which finally creates the ScenePresence 3864 // That calls AddNewClient, which finally creates the ScenePresence
3865 int flags = GetUserFlags(cAgentData.AgentID);
3866 if (m_regInfo.EstateSettings.IsBanned(cAgentData.AgentID, flags))
3867 {
3868 m_log.DebugFormat("[SCENE]: Denying root agent entry to {0}: banned", cAgentData.AgentID);
3869 return false;
3870 }
3871
3710 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2); 3872 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2);
3711 if (nearestParcel == null) 3873 if (nearestParcel == null)
3712 { 3874 {
@@ -3788,12 +3950,22 @@ namespace OpenSim.Region.Framework.Scenes
3788 return false; 3950 return false;
3789 } 3951 }
3790 3952
3953 public bool IncomingCloseAgent(UUID agentID)
3954 {
3955 return IncomingCloseAgent(agentID, false);
3956 }
3957
3958 public bool IncomingCloseChildAgent(UUID agentID)
3959 {
3960 return IncomingCloseAgent(agentID, true);
3961 }
3962
3791 /// <summary> 3963 /// <summary>
3792 /// Tell a single agent to disconnect from the region. 3964 /// Tell a single agent to disconnect from the region.
3793 /// </summary> 3965 /// </summary>
3794 /// <param name="regionHandle"></param>
3795 /// <param name="agentID"></param> 3966 /// <param name="agentID"></param>
3796 public bool IncomingCloseAgent(UUID agentID) 3967 /// <param name="childOnly"></param>
3968 public bool IncomingCloseAgent(UUID agentID, bool childOnly)
3797 { 3969 {
3798 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); 3970 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID);
3799 3971
@@ -3805,7 +3977,7 @@ namespace OpenSim.Region.Framework.Scenes
3805 { 3977 {
3806 m_sceneGraph.removeUserCount(false); 3978 m_sceneGraph.removeUserCount(false);
3807 } 3979 }
3808 else 3980 else if (!childOnly)
3809 { 3981 {
3810 m_sceneGraph.removeUserCount(true); 3982 m_sceneGraph.removeUserCount(true);
3811 } 3983 }
@@ -3821,9 +3993,12 @@ namespace OpenSim.Region.Framework.Scenes
3821 } 3993 }
3822 else 3994 else
3823 presence.ControllingClient.SendShutdownConnectionNotice(); 3995 presence.ControllingClient.SendShutdownConnectionNotice();
3996 presence.ControllingClient.Close(false);
3997 }
3998 else if (!childOnly)
3999 {
4000 presence.ControllingClient.Close(true);
3824 } 4001 }
3825
3826 presence.ControllingClient.Close();
3827 return true; 4002 return true;
3828 } 4003 }
3829 4004
@@ -4406,34 +4581,78 @@ namespace OpenSim.Region.Framework.Scenes
4406 SimulationDataService.RemoveObject(uuid, m_regInfo.RegionID); 4581 SimulationDataService.RemoveObject(uuid, m_regInfo.RegionID);
4407 } 4582 }
4408 4583
4409 public int GetHealth() 4584 public int GetHealth(out int flags, out string message)
4410 { 4585 {
4411 // Returns: 4586 // Returns:
4412 // 1 = sim is up and accepting http requests. The heartbeat has 4587 // 1 = sim is up and accepting http requests. The heartbeat has
4413 // stopped and the sim is probably locked up, but a remote 4588 // stopped and the sim is probably locked up, but a remote
4414 // admin restart may succeed 4589 // admin restart may succeed
4415 // 4590 //
4416 // 2 = Sim is up and the heartbeat is running. The sim is likely 4591 // 2 = Sim is up and the heartbeat is running. The sim is likely
4417 // usable for people within and logins _may_ work 4592 // usable for people within
4593 //
4594 // 3 = Sim is up and one packet thread is running. Sim is
4595 // unstable and will not accept new logins
4596 //
4597 // 4 = Sim is up and both packet threads are running. Sim is
4598 // likely usable
4418 // 4599 //
4419 // 3 = We have seen a new user enter within the past 4 minutes 4600 // 5 = We have seen a new user enter within the past 4 minutes
4420 // which can be seen as positive confirmation of sim health 4601 // which can be seen as positive confirmation of sim health
4421 // 4602 //
4603
4604 flags = 0;
4605 message = String.Empty;
4606
4607 CheckHeartbeat();
4608
4609 if (m_firstHeartbeat || (m_lastIncoming == 0 && m_lastOutgoing == 0))
4610 {
4611 // We're still starting
4612 // 0 means "in startup", it can't happen another way, since
4613 // to get here, we must be able to accept http connections
4614 return 0;
4615 }
4616
4422 int health=1; // Start at 1, means we're up 4617 int health=1; // Start at 1, means we're up
4423 4618
4424 if ((Util.EnvironmentTickCountSubtract(m_lastUpdate)) < 1000) 4619 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) < 1000)
4620 {
4621 health+=1;
4622 flags |= 1;
4623 }
4624
4625 if (Util.EnvironmentTickCountSubtract(m_lastIncoming) < 1000)
4626 {
4627 health+=1;
4628 flags |= 2;
4629 }
4630
4631 if (Util.EnvironmentTickCountSubtract(m_lastOutgoing) < 1000)
4632 {
4425 health+=1; 4633 health+=1;
4634 flags |= 4;
4635 }
4426 else 4636 else
4637 {
4638int pid = System.Diagnostics.Process.GetCurrentProcess().Id;
4639System.Diagnostics.Process proc = new System.Diagnostics.Process();
4640proc.EnableRaisingEvents=false;
4641proc.StartInfo.FileName = "/bin/kill";
4642proc.StartInfo.Arguments = "-QUIT " + pid.ToString();
4643proc.Start();
4644proc.WaitForExit();
4645Thread.Sleep(1000);
4646Environment.Exit(1);
4647 }
4648
4649 if (flags != 7)
4427 return health; 4650 return health;
4428 4651
4429 // A login in the last 4 mins? We can't be doing too badly 4652 // A login in the last 4 mins? We can't be doing too badly
4430 // 4653 //
4431 if ((Util.EnvironmentTickCountSubtract(m_LastLogin)) < 240000) 4654 if (Util.EnvironmentTickCountSubtract(m_LastLogin) < 240000)
4432 health++; 4655 health++;
4433 else
4434 return health;
4435
4436 CheckHeartbeat();
4437 4656
4438 return health; 4657 return health;
4439 } 4658 }
@@ -4626,7 +4845,7 @@ namespace OpenSim.Region.Framework.Scenes
4626 if (m_firstHeartbeat) 4845 if (m_firstHeartbeat)
4627 return; 4846 return;
4628 4847
4629 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) > 2000) 4848 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) > 5000)
4630 StartTimer(); 4849 StartTimer();
4631 } 4850 }
4632 4851
@@ -5036,7 +5255,55 @@ namespace OpenSim.Region.Framework.Scenes
5036 mapModule.GenerateMaptile(); 5255 mapModule.GenerateMaptile();
5037 } 5256 }
5038 5257
5039 private void RegenerateMaptileAndReregister(object sender, ElapsedEventArgs e) 5258// public void CleanDroppedAttachments()
5259// {
5260// List<SceneObjectGroup> objectsToDelete =
5261// new List<SceneObjectGroup>();
5262//
5263// lock (m_cleaningAttachments)
5264// {
5265// ForEachSOG(delegate (SceneObjectGroup grp)
5266// {
5267// if (grp.RootPart.Shape.PCode == 0 && grp.RootPart.Shape.State != 0 && (!objectsToDelete.Contains(grp)))
5268// {
5269// UUID agentID = grp.OwnerID;
5270// if (agentID == UUID.Zero)
5271// {
5272// objectsToDelete.Add(grp);
5273// return;
5274// }
5275//
5276// ScenePresence sp = GetScenePresence(agentID);
5277// if (sp == null)
5278// {
5279// objectsToDelete.Add(grp);
5280// return;
5281// }
5282// }
5283// });
5284// }
5285//
5286// foreach (SceneObjectGroup grp in objectsToDelete)
5287// {
5288// m_log.InfoFormat("[SCENE]: Deleting dropped attachment {0} of user {1}", grp.UUID, grp.OwnerID);
5289// DeleteSceneObject(grp, true);
5290// }
5291// }
5292
5293 public void ThreadAlive(int threadCode)
5294 {
5295 switch(threadCode)
5296 {
5297 case 1: // Incoming
5298 m_lastIncoming = Util.EnvironmentTickCount();
5299 break;
5300 case 2: // Incoming
5301 m_lastOutgoing = Util.EnvironmentTickCount();
5302 break;
5303 }
5304 }
5305
5306 public void RegenerateMaptileAndReregister(object sender, ElapsedEventArgs e)
5040 { 5307 {
5041 RegenerateMaptile(); 5308 RegenerateMaptile();
5042 5309
@@ -5055,6 +5322,14 @@ namespace OpenSim.Region.Framework.Scenes
5055 // child agent creation, thereby emulating the SL behavior. 5322 // child agent creation, thereby emulating the SL behavior.
5056 public bool QueryAccess(UUID agentID, Vector3 position, out string reason) 5323 public bool QueryAccess(UUID agentID, Vector3 position, out string reason)
5057 { 5324 {
5325 reason = "You are banned from the region";
5326
5327 if (Permissions.IsGod(agentID))
5328 {
5329 reason = String.Empty;
5330 return true;
5331 }
5332
5058 int num = m_sceneGraph.GetNumberOfScenePresences(); 5333 int num = m_sceneGraph.GetNumberOfScenePresences();
5059 5334
5060 if (num >= RegionInfo.RegionSettings.AgentLimit) 5335 if (num >= RegionInfo.RegionSettings.AgentLimit)
@@ -5066,11 +5341,82 @@ namespace OpenSim.Region.Framework.Scenes
5066 } 5341 }
5067 } 5342 }
5068 5343
5344 ScenePresence presence = GetScenePresence(agentID);
5345 IClientAPI client = null;
5346 AgentCircuitData aCircuit = null;
5347
5348 if (presence != null)
5349 {
5350 client = presence.ControllingClient;
5351 if (client != null)
5352 aCircuit = client.RequestClientInfo();
5353 }
5354
5355 // We may be called before there is a presence or a client.
5356 // Fake AgentCircuitData to keep IAuthorizationModule smiling
5357 if (client == null)
5358 {
5359 aCircuit = new AgentCircuitData();
5360 aCircuit.AgentID = agentID;
5361 aCircuit.firstname = String.Empty;
5362 aCircuit.lastname = String.Empty;
5363 }
5364
5365 try
5366 {
5367 if (!AuthorizeUser(aCircuit, out reason))
5368 {
5369 // m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID);
5370 return false;
5371 }
5372 }
5373 catch (Exception e)
5374 {
5375 m_log.DebugFormat("[SCENE]: Exception authorizing agent: {0} "+ e.StackTrace, e.Message);
5376 return false;
5377 }
5378
5379 if (position == Vector3.Zero) // Teleport
5380 {
5381 float posX = 128.0f;
5382 float posY = 128.0f;
5383
5384 if (!TestLandRestrictions(agentID, out reason, ref posX, ref posY))
5385 {
5386 // m_log.DebugFormat("[SCENE]: Denying {0} because they are banned on all parcels", agentID);
5387 return false;
5388 }
5389 }
5390 else // Walking
5391 {
5392 ILandObject land = LandChannel.GetLandObject(position.X, position.Y);
5393 if (land == null)
5394 return false;
5395
5396 bool banned = land.IsBannedFromLand(agentID);
5397 bool restricted = land.IsRestrictedFromLand(agentID);
5398
5399 if (banned || restricted)
5400 return false;
5401 }
5402
5069 reason = String.Empty; 5403 reason = String.Empty;
5070 return true; 5404 return true;
5071 } 5405 }
5072 5406
5073 /// <summary> 5407 public void StartTimerWatchdog()
5408 {
5409 m_timerWatchdog.Interval = 1000;
5410 m_timerWatchdog.Elapsed += TimerWatchdog;
5411 m_timerWatchdog.AutoReset = true;
5412 m_timerWatchdog.Start();
5413 }
5414
5415 public void TimerWatchdog(object sender, ElapsedEventArgs e)
5416 {
5417 CheckHeartbeat();
5418 }
5419
5074 /// This method deals with movement when an avatar is automatically moving (but this is distinct from the 5420 /// This method deals with movement when an avatar is automatically moving (but this is distinct from the
5075 /// autopilot that moves an avatar to a sit target!. 5421 /// autopilot that moves an avatar to a sit target!.
5076 /// </summary> 5422 /// </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 1e2901b..6c57d57 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -43,6 +43,12 @@ namespace OpenSim.Region.Framework.Scenes
43 43
44 public delegate void ObjectDuplicateDelegate(EntityBase original, EntityBase clone); 44 public delegate void ObjectDuplicateDelegate(EntityBase original, EntityBase clone);
45 45
46 public delegate void AttachToBackupDelegate(SceneObjectGroup sog);
47
48 public delegate void DetachFromBackupDelegate(SceneObjectGroup sog);
49
50 public delegate void ChangedBackupDelegate(SceneObjectGroup sog);
51
46 public delegate void ObjectCreateDelegate(EntityBase obj); 52 public delegate void ObjectCreateDelegate(EntityBase obj);
47 53
48 public delegate void ObjectDeleteDelegate(EntityBase obj); 54 public delegate void ObjectDeleteDelegate(EntityBase obj);
@@ -61,6 +67,9 @@ namespace OpenSim.Region.Framework.Scenes
61 private PhysicsCrash handlerPhysicsCrash = null; 67 private PhysicsCrash handlerPhysicsCrash = null;
62 68
63 public event ObjectDuplicateDelegate OnObjectDuplicate; 69 public event ObjectDuplicateDelegate OnObjectDuplicate;
70 public event AttachToBackupDelegate OnAttachToBackup;
71 public event DetachFromBackupDelegate OnDetachFromBackup;
72 public event ChangedBackupDelegate OnChangeBackup;
64 public event ObjectCreateDelegate OnObjectCreate; 73 public event ObjectCreateDelegate OnObjectCreate;
65 public event ObjectDeleteDelegate OnObjectRemove; 74 public event ObjectDeleteDelegate OnObjectRemove;
66 75
@@ -68,7 +77,7 @@ namespace OpenSim.Region.Framework.Scenes
68 77
69 #region Fields 78 #region Fields
70 79
71 protected object m_presenceLock = new object(); 80 protected OpenMetaverse.ReaderWriterLockSlim m_scenePresencesLock = new OpenMetaverse.ReaderWriterLockSlim();
72 protected Dictionary<UUID, ScenePresence> m_scenePresenceMap = new Dictionary<UUID, ScenePresence>(); 81 protected Dictionary<UUID, ScenePresence> m_scenePresenceMap = new Dictionary<UUID, ScenePresence>();
73 protected List<ScenePresence> m_scenePresenceArray = new List<ScenePresence>(); 82 protected List<ScenePresence> m_scenePresenceArray = new List<ScenePresence>();
74 83
@@ -130,13 +139,18 @@ namespace OpenSim.Region.Framework.Scenes
130 139
131 protected internal void Close() 140 protected internal void Close()
132 { 141 {
133 lock (m_presenceLock) 142 m_scenePresencesLock.EnterWriteLock();
143 try
134 { 144 {
135 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(); 145 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>();
136 List<ScenePresence> newlist = new List<ScenePresence>(); 146 List<ScenePresence> newlist = new List<ScenePresence>();
137 m_scenePresenceMap = newmap; 147 m_scenePresenceMap = newmap;
138 m_scenePresenceArray = newlist; 148 m_scenePresenceArray = newlist;
139 } 149 }
150 finally
151 {
152 m_scenePresencesLock.ExitWriteLock();
153 }
140 154
141 lock (SceneObjectGroupsByFullID) 155 lock (SceneObjectGroupsByFullID)
142 SceneObjectGroupsByFullID.Clear(); 156 SceneObjectGroupsByFullID.Clear();
@@ -275,6 +289,33 @@ namespace OpenSim.Region.Framework.Scenes
275 protected internal bool AddRestoredSceneObject( 289 protected internal bool AddRestoredSceneObject(
276 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 290 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
277 { 291 {
292 if (!m_parentScene.CombineRegions)
293 {
294 // KF: Check for out-of-region, move inside and make static.
295 Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X,
296 sceneObject.RootPart.GroupPosition.Y,
297 sceneObject.RootPart.GroupPosition.Z);
298 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 ||
299 npos.X > Constants.RegionSize ||
300 npos.Y > Constants.RegionSize))
301 {
302 if (npos.X < 0.0) npos.X = 1.0f;
303 if (npos.Y < 0.0) npos.Y = 1.0f;
304 if (npos.Z < 0.0) npos.Z = 0.0f;
305 if (npos.X > Constants.RegionSize) npos.X = Constants.RegionSize - 1.0f;
306 if (npos.Y > Constants.RegionSize) npos.Y = Constants.RegionSize - 1.0f;
307
308 foreach (SceneObjectPart part in sceneObject.Parts)
309 {
310 part.GroupPosition = npos;
311 }
312 sceneObject.RootPart.Velocity = Vector3.Zero;
313 sceneObject.RootPart.AngularVelocity = Vector3.Zero;
314 sceneObject.RootPart.Acceleration = Vector3.Zero;
315 sceneObject.RootPart.Velocity = Vector3.Zero;
316 }
317 }
318
278 if (attachToBackup && (!alreadyPersisted)) 319 if (attachToBackup && (!alreadyPersisted))
279 { 320 {
280 sceneObject.ForceInventoryPersistence(); 321 sceneObject.ForceInventoryPersistence();
@@ -491,6 +532,30 @@ namespace OpenSim.Region.Framework.Scenes
491 m_updateList[obj.UUID] = obj; 532 m_updateList[obj.UUID] = obj;
492 } 533 }
493 534
535 public void FireAttachToBackup(SceneObjectGroup obj)
536 {
537 if (OnAttachToBackup != null)
538 {
539 OnAttachToBackup(obj);
540 }
541 }
542
543 public void FireDetachFromBackup(SceneObjectGroup obj)
544 {
545 if (OnDetachFromBackup != null)
546 {
547 OnDetachFromBackup(obj);
548 }
549 }
550
551 public void FireChangeBackup(SceneObjectGroup obj)
552 {
553 if (OnChangeBackup != null)
554 {
555 OnChangeBackup(obj);
556 }
557 }
558
494 /// <summary> 559 /// <summary>
495 /// Process all pending updates 560 /// Process all pending updates
496 /// </summary> 561 /// </summary>
@@ -608,7 +673,8 @@ namespace OpenSim.Region.Framework.Scenes
608 673
609 Entities[presence.UUID] = presence; 674 Entities[presence.UUID] = presence;
610 675
611 lock (m_presenceLock) 676 m_scenePresencesLock.EnterWriteLock();
677 try
612 { 678 {
613 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 679 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
614 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 680 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -632,6 +698,10 @@ namespace OpenSim.Region.Framework.Scenes
632 m_scenePresenceMap = newmap; 698 m_scenePresenceMap = newmap;
633 m_scenePresenceArray = newlist; 699 m_scenePresenceArray = newlist;
634 } 700 }
701 finally
702 {
703 m_scenePresencesLock.ExitWriteLock();
704 }
635 } 705 }
636 706
637 /// <summary> 707 /// <summary>
@@ -646,7 +716,8 @@ namespace OpenSim.Region.Framework.Scenes
646 agentID); 716 agentID);
647 } 717 }
648 718
649 lock (m_presenceLock) 719 m_scenePresencesLock.EnterWriteLock();
720 try
650 { 721 {
651 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 722 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
652 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 723 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -668,6 +739,10 @@ namespace OpenSim.Region.Framework.Scenes
668 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); 739 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID);
669 } 740 }
670 } 741 }
742 finally
743 {
744 m_scenePresencesLock.ExitWriteLock();
745 }
671 } 746 }
672 747
673 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) 748 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F)
@@ -1381,8 +1456,13 @@ namespace OpenSim.Region.Framework.Scenes
1381 { 1456 {
1382 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) 1457 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0))
1383 { 1458 {
1384 if (m_parentScene.AttachmentsModule != null) 1459 // Set the new attachment point data in the object
1385 m_parentScene.AttachmentsModule.UpdateAttachmentPosition(group, pos); 1460 byte attachmentPoint = group.GetAttachmentPoint();
1461 group.UpdateGroupPosition(pos);
1462 group.IsAttachment = false;
1463 group.AbsolutePosition = group.RootPart.AttachedPos;
1464 group.AttachmentPoint = attachmentPoint;
1465 group.HasGroupChanged = true;
1386 } 1466 }
1387 else 1467 else
1388 { 1468 {
@@ -1654,8 +1734,11 @@ namespace OpenSim.Region.Framework.Scenes
1654 return; 1734 return;
1655 1735
1656 Monitor.Enter(m_updateLock); 1736 Monitor.Enter(m_updateLock);
1737
1657 try 1738 try
1658 { 1739 {
1740 parentGroup.areUpdatesSuspended = true;
1741
1659 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); 1742 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
1660 1743
1661 // We do this in reverse to get the link order of the prims correct 1744 // We do this in reverse to get the link order of the prims correct
@@ -1666,9 +1749,13 @@ namespace OpenSim.Region.Framework.Scenes
1666 // Make sure no child prim is set for sale 1749 // Make sure no child prim is set for sale
1667 // So that, on delink, no prims are unwittingly 1750 // So that, on delink, no prims are unwittingly
1668 // left for sale and sold off 1751 // left for sale and sold off
1669 child.RootPart.ObjectSaleType = 0; 1752
1670 child.RootPart.SalePrice = 10; 1753 if (child != null)
1671 childGroups.Add(child); 1754 {
1755 child.RootPart.ObjectSaleType = 0;
1756 child.RootPart.SalePrice = 10;
1757 childGroups.Add(child);
1758 }
1672 } 1759 }
1673 1760
1674 foreach (SceneObjectGroup child in childGroups) 1761 foreach (SceneObjectGroup child in childGroups)
@@ -1687,12 +1774,19 @@ namespace OpenSim.Region.Framework.Scenes
1687 // occur on link to invoke this elsewhere (such as object selection) 1774 // occur on link to invoke this elsewhere (such as object selection)
1688 parentGroup.RootPart.CreateSelected = true; 1775 parentGroup.RootPart.CreateSelected = true;
1689 parentGroup.TriggerScriptChangedEvent(Changed.LINK); 1776 parentGroup.TriggerScriptChangedEvent(Changed.LINK);
1690 parentGroup.HasGroupChanged = true;
1691 parentGroup.ScheduleGroupForFullUpdate();
1692
1693 } 1777 }
1694 finally 1778 finally
1695 { 1779 {
1780 lock (SceneObjectGroupsByLocalPartID)
1781 {
1782 foreach (SceneObjectPart part in parentGroup.Parts)
1783 SceneObjectGroupsByLocalPartID[part.LocalId] = parentGroup;
1784 }
1785
1786 parentGroup.areUpdatesSuspended = false;
1787 parentGroup.HasGroupChanged = true;
1788 parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true);
1789 parentGroup.ScheduleGroupForFullUpdate();
1696 Monitor.Exit(m_updateLock); 1790 Monitor.Exit(m_updateLock);
1697 } 1791 }
1698 } 1792 }
@@ -1729,21 +1823,24 @@ namespace OpenSim.Region.Framework.Scenes
1729 1823
1730 SceneObjectGroup group = part.ParentGroup; 1824 SceneObjectGroup group = part.ParentGroup;
1731 if (!affectedGroups.Contains(group)) 1825 if (!affectedGroups.Contains(group))
1826 {
1827 group.areUpdatesSuspended = true;
1732 affectedGroups.Add(group); 1828 affectedGroups.Add(group);
1829 }
1733 } 1830 }
1734 } 1831 }
1735 } 1832 }
1736 1833
1737 foreach (SceneObjectPart child in childParts) 1834 if (childParts.Count > 0)
1738 { 1835 {
1739 // Unlink all child parts from their groups 1836 foreach (SceneObjectPart child in childParts)
1740 // 1837 {
1741 child.ParentGroup.DelinkFromGroup(child, true); 1838 // Unlink all child parts from their groups
1742 1839 //
1743 // These are not in affected groups and will not be 1840 child.ParentGroup.DelinkFromGroup(child, true);
1744 // handled further. Do the honors here. 1841 child.ParentGroup.HasGroupChanged = true;
1745 child.ParentGroup.HasGroupChanged = true; 1842 child.ParentGroup.ScheduleGroupForFullUpdate();
1746 child.ParentGroup.ScheduleGroupForFullUpdate(); 1843 }
1747 } 1844 }
1748 1845
1749 foreach (SceneObjectPart root in rootParts) 1846 foreach (SceneObjectPart root in rootParts)
@@ -1753,56 +1850,68 @@ namespace OpenSim.Region.Framework.Scenes
1753 // However, editing linked parts and unlinking may be different 1850 // However, editing linked parts and unlinking may be different
1754 // 1851 //
1755 SceneObjectGroup group = root.ParentGroup; 1852 SceneObjectGroup group = root.ParentGroup;
1853 group.areUpdatesSuspended = true;
1756 1854
1757 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); 1855 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts);
1758 int numChildren = newSet.Count; 1856 int numChildren = newSet.Count;
1759 1857
1858 if (numChildren == 1)
1859 break;
1860
1760 // If there are prims left in a link set, but the root is 1861 // If there are prims left in a link set, but the root is
1761 // slated for unlink, we need to do this 1862 // slated for unlink, we need to do this
1863 // Unlink the remaining set
1762 // 1864 //
1763 if (numChildren != 1) 1865 bool sendEventsToRemainder = true;
1764 { 1866 if (numChildren > 1)
1765 // Unlink the remaining set 1867 sendEventsToRemainder = false;
1766 //
1767 bool sendEventsToRemainder = true;
1768 if (numChildren > 1)
1769 sendEventsToRemainder = false;
1770 1868
1771 foreach (SceneObjectPart p in newSet) 1869 foreach (SceneObjectPart p in newSet)
1870 {
1871 if (p != group.RootPart)
1772 { 1872 {
1773 if (p != group.RootPart) 1873 group.DelinkFromGroup(p, sendEventsToRemainder);
1774 group.DelinkFromGroup(p, sendEventsToRemainder); 1874 if (numChildren > 2)
1875 {
1876 p.ParentGroup.areUpdatesSuspended = true;
1877 }
1878 else
1879 {
1880 p.ParentGroup.HasGroupChanged = true;
1881 p.ParentGroup.ScheduleGroupForFullUpdate();
1882 }
1775 } 1883 }
1884 }
1885
1886 // If there is more than one prim remaining, we
1887 // need to re-link
1888 //
1889 if (numChildren > 2)
1890 {
1891 // Remove old root
1892 //
1893 if (newSet.Contains(root))
1894 newSet.Remove(root);
1776 1895
1777 // If there is more than one prim remaining, we 1896 // Preserve link ordering
1778 // need to re-link
1779 // 1897 //
1780 if (numChildren > 2) 1898 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1781 { 1899 {
1782 // Remove old root 1900 return a.LinkNum.CompareTo(b.LinkNum);
1783 // 1901 });
1784 if (newSet.Contains(root))
1785 newSet.Remove(root);
1786
1787 // Preserve link ordering
1788 //
1789 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1790 {
1791 return a.LinkNum.CompareTo(b.LinkNum);
1792 });
1793 1902
1794 // Determine new root 1903 // Determine new root
1795 // 1904 //
1796 SceneObjectPart newRoot = newSet[0]; 1905 SceneObjectPart newRoot = newSet[0];
1797 newSet.RemoveAt(0); 1906 newSet.RemoveAt(0);
1798 1907
1799 foreach (SceneObjectPart newChild in newSet) 1908 foreach (SceneObjectPart newChild in newSet)
1800 newChild.ClearUpdateSchedule(); 1909 newChild.ClearUpdateSchedule();
1801 1910
1802 LinkObjects(newRoot, newSet); 1911 newRoot.ParentGroup.areUpdatesSuspended = true;
1803 if (!affectedGroups.Contains(newRoot.ParentGroup)) 1912 LinkObjects(newRoot, newSet);
1804 affectedGroups.Add(newRoot.ParentGroup); 1913 if (!affectedGroups.Contains(newRoot.ParentGroup))
1805 } 1914 affectedGroups.Add(newRoot.ParentGroup);
1806 } 1915 }
1807 } 1916 }
1808 1917
@@ -1810,8 +1919,14 @@ namespace OpenSim.Region.Framework.Scenes
1810 // 1919 //
1811 foreach (SceneObjectGroup g in affectedGroups) 1920 foreach (SceneObjectGroup g in affectedGroups)
1812 { 1921 {
1922 // Child prims that have been unlinked and deleted will
1923 // return unless the root is deleted. This will remove them
1924 // from the database. They will be rewritten immediately,
1925 // minus the rows for the unlinked child prims.
1926 m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID);
1813 g.TriggerScriptChangedEvent(Changed.LINK); 1927 g.TriggerScriptChangedEvent(Changed.LINK);
1814 g.HasGroupChanged = true; // Persist 1928 g.HasGroupChanged = true; // Persist
1929 g.areUpdatesSuspended = false;
1815 g.ScheduleGroupForFullUpdate(); 1930 g.ScheduleGroupForFullUpdate();
1816 } 1931 }
1817 } 1932 }
@@ -1929,9 +2044,6 @@ namespace OpenSim.Region.Framework.Scenes
1929 child.ApplyNextOwnerPermissions(); 2044 child.ApplyNextOwnerPermissions();
1930 } 2045 }
1931 } 2046 }
1932
1933 copy.RootPart.ObjectSaleType = 0;
1934 copy.RootPart.SalePrice = 10;
1935 } 2047 }
1936 2048
1937 // FIXME: This section needs to be refactored so that it just calls AddSceneObject() 2049 // 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 905ecc9..c7da4f4 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();
@@ -234,6 +230,11 @@ namespace OpenSim.Region.Framework.Scenes
234 230
235 public uint GetEffectivePermissions() 231 public uint GetEffectivePermissions()
236 { 232 {
233 return GetEffectivePermissions(false);
234 }
235
236 public uint GetEffectivePermissions(bool useBase)
237 {
237 uint perms=(uint)(PermissionMask.Modify | 238 uint perms=(uint)(PermissionMask.Modify |
238 PermissionMask.Copy | 239 PermissionMask.Copy |
239 PermissionMask.Move | 240 PermissionMask.Move |
@@ -245,7 +246,10 @@ namespace OpenSim.Region.Framework.Scenes
245 for (int i = 0; i < parts.Length; i++) 246 for (int i = 0; i < parts.Length; i++)
246 { 247 {
247 SceneObjectPart part = parts[i]; 248 SceneObjectPart part = parts[i];
248 ownerMask &= part.OwnerMask; 249 if (useBase)
250 ownerMask &= part.BaseMask;
251 else
252 ownerMask &= part.OwnerMask;
249 perms &= part.Inventory.MaskEffectivePermissions(); 253 perms &= part.Inventory.MaskEffectivePermissions();
250 } 254 }
251 255
@@ -385,6 +389,9 @@ namespace OpenSim.Region.Framework.Scenes
385 389
386 public void ResumeScripts() 390 public void ResumeScripts()
387 { 391 {
392 if (m_scene.RegionInfo.RegionSettings.DisableScripts)
393 return;
394
388 SceneObjectPart[] parts = m_parts.GetArray(); 395 SceneObjectPart[] parts = m_parts.GetArray();
389 for (int i = 0; i < parts.Length; i++) 396 for (int i = 0; i < parts.Length; i++)
390 parts[i].Inventory.ResumeScripts(); 397 parts[i].Inventory.ResumeScripts();
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 8860764..3b0d1cd 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
@@ -281,6 +344,16 @@ namespace OpenSim.Region.Framework.Scenes
281 get { return m_parts.Count; } 344 get { return m_parts.Count; }
282 } 345 }
283 346
347// protected Quaternion m_rotation = Quaternion.Identity;
348//
349// public virtual Quaternion Rotation
350// {
351// get { return m_rotation; }
352// set {
353// m_rotation = value;
354// }
355// }
356
284 public Quaternion GroupRotation 357 public Quaternion GroupRotation
285 { 358 {
286 get { return m_rootPart.RotationOffset; } 359 get { return m_rootPart.RotationOffset; }
@@ -389,7 +462,11 @@ namespace OpenSim.Region.Framework.Scenes
389 m_scene.CrossPrimGroupIntoNewRegion(val, this, true); 462 m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
390 } 463 }
391 } 464 }
392 465
466 foreach (SceneObjectPart part in m_parts.GetArray())
467 {
468 part.IgnoreUndoUpdate = true;
469 }
393 if (RootPart.GetStatusSandbox()) 470 if (RootPart.GetStatusSandbox())
394 { 471 {
395 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) 472 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10)
@@ -403,10 +480,30 @@ namespace OpenSim.Region.Framework.Scenes
403 return; 480 return;
404 } 481 }
405 } 482 }
406
407 SceneObjectPart[] parts = m_parts.GetArray(); 483 SceneObjectPart[] parts = m_parts.GetArray();
408 for (int i = 0; i < parts.Length; i++) 484 bool triggerScriptEvent = m_rootPart.GroupPosition != val;
409 parts[i].GroupPosition = val; 485 if (m_dupeInProgress)
486 triggerScriptEvent = false;
487 foreach (SceneObjectPart part in parts)
488 {
489 part.GroupPosition = val;
490 if (triggerScriptEvent)
491 part.TriggerScriptChangedEvent(Changed.POSITION);
492 }
493 if (!m_dupeInProgress)
494 {
495 foreach (ScenePresence av in m_linkedAvatars)
496 {
497 SceneObjectPart p = m_scene.GetSceneObjectPart(av.ParentID);
498 if (m_parts.TryGetValue(p.UUID, out p))
499 {
500 Vector3 offset = p.GetWorldPosition() - av.ParentPosition;
501 av.AbsolutePosition += offset;
502 av.ParentPosition = p.GetWorldPosition(); //ParentPosition gets cleared by AbsolutePosition
503 av.SendAvatarDataToAllAgents();
504 }
505 }
506 }
410 507
411 //if (m_rootPart.PhysActor != null) 508 //if (m_rootPart.PhysActor != null)
412 //{ 509 //{
@@ -565,6 +662,7 @@ namespace OpenSim.Region.Framework.Scenes
565 /// </summary> 662 /// </summary>
566 public SceneObjectGroup() 663 public SceneObjectGroup()
567 { 664 {
665
568 } 666 }
569 667
570 /// <summary> 668 /// <summary>
@@ -581,7 +679,7 @@ namespace OpenSim.Region.Framework.Scenes
581 /// Constructor. This object is added to the scene later via AttachToScene() 679 /// Constructor. This object is added to the scene later via AttachToScene()
582 /// </summary> 680 /// </summary>
583 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) 681 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape)
584 { 682 {
585 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero)); 683 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero));
586 } 684 }
587 685
@@ -629,6 +727,9 @@ namespace OpenSim.Region.Framework.Scenes
629 /// </summary> 727 /// </summary>
630 public virtual void AttachToBackup() 728 public virtual void AttachToBackup()
631 { 729 {
730 if (IsAttachment) return;
731 m_scene.SceneGraph.FireAttachToBackup(this);
732
632 if (InSceneBackup) 733 if (InSceneBackup)
633 { 734 {
634 //m_log.DebugFormat( 735 //m_log.DebugFormat(
@@ -671,6 +772,9 @@ namespace OpenSim.Region.Framework.Scenes
671 772
672 ApplyPhysics(); 773 ApplyPhysics();
673 774
775 if (RootPart.PhysActor != null)
776 RootPart.Buoyancy = RootPart.Buoyancy;
777
674 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled 778 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled
675 // for the same object with very different properties. The caller must schedule the update. 779 // for the same object with very different properties. The caller must schedule the update.
676 //ScheduleGroupForFullUpdate(); 780 //ScheduleGroupForFullUpdate();
@@ -686,6 +790,10 @@ namespace OpenSim.Region.Framework.Scenes
686 EntityIntersection result = new EntityIntersection(); 790 EntityIntersection result = new EntityIntersection();
687 791
688 SceneObjectPart[] parts = m_parts.GetArray(); 792 SceneObjectPart[] parts = m_parts.GetArray();
793
794 // Find closest hit here
795 float idist = float.MaxValue;
796
689 for (int i = 0; i < parts.Length; i++) 797 for (int i = 0; i < parts.Length; i++)
690 { 798 {
691 SceneObjectPart part = parts[i]; 799 SceneObjectPart part = parts[i];
@@ -700,11 +808,6 @@ namespace OpenSim.Region.Framework.Scenes
700 808
701 EntityIntersection inter = part.TestIntersectionOBB(hRay, parentrotation, frontFacesOnly, faceCenters); 809 EntityIntersection inter = part.TestIntersectionOBB(hRay, parentrotation, frontFacesOnly, faceCenters);
702 810
703 // This may need to be updated to the maximum draw distance possible..
704 // We might (and probably will) be checking for prim creation from other sims
705 // when the camera crosses the border.
706 float idist = Constants.RegionSize;
707
708 if (inter.HitTF) 811 if (inter.HitTF)
709 { 812 {
710 // We need to find the closest prim to return to the testcaller along the ray 813 // We need to find the closest prim to return to the testcaller along the ray
@@ -715,10 +818,11 @@ namespace OpenSim.Region.Framework.Scenes
715 result.obj = part; 818 result.obj = part;
716 result.normal = inter.normal; 819 result.normal = inter.normal;
717 result.distance = inter.distance; 820 result.distance = inter.distance;
821
822 idist = inter.distance;
718 } 823 }
719 } 824 }
720 } 825 }
721
722 return result; 826 return result;
723 } 827 }
724 828
@@ -738,17 +842,19 @@ namespace OpenSim.Region.Framework.Scenes
738 minZ = 8192f; 842 minZ = 8192f;
739 843
740 SceneObjectPart[] parts = m_parts.GetArray(); 844 SceneObjectPart[] parts = m_parts.GetArray();
741 for (int i = 0; i < parts.Length; i++) 845 foreach (SceneObjectPart part in parts)
742 { 846 {
743 SceneObjectPart part = parts[i];
744
745 Vector3 worldPos = part.GetWorldPosition(); 847 Vector3 worldPos = part.GetWorldPosition();
746 Vector3 offset = worldPos - AbsolutePosition; 848 Vector3 offset = worldPos - AbsolutePosition;
747 Quaternion worldRot; 849 Quaternion worldRot;
748 if (part.ParentID == 0) 850 if (part.ParentID == 0)
851 {
749 worldRot = part.RotationOffset; 852 worldRot = part.RotationOffset;
853 }
750 else 854 else
855 {
751 worldRot = part.GetWorldRotation(); 856 worldRot = part.GetWorldRotation();
857 }
752 858
753 Vector3 frontTopLeft; 859 Vector3 frontTopLeft;
754 Vector3 frontTopRight; 860 Vector3 frontTopRight;
@@ -760,6 +866,8 @@ namespace OpenSim.Region.Framework.Scenes
760 Vector3 backBottomLeft; 866 Vector3 backBottomLeft;
761 Vector3 backBottomRight; 867 Vector3 backBottomRight;
762 868
869 // Vector3[] corners = new Vector3[8];
870
763 Vector3 orig = Vector3.Zero; 871 Vector3 orig = Vector3.Zero;
764 872
765 frontTopLeft.X = orig.X - (part.Scale.X / 2); 873 frontTopLeft.X = orig.X - (part.Scale.X / 2);
@@ -794,6 +902,38 @@ namespace OpenSim.Region.Framework.Scenes
794 backBottomRight.Y = orig.Y + (part.Scale.Y / 2); 902 backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
795 backBottomRight.Z = orig.Z - (part.Scale.Z / 2); 903 backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
796 904
905
906
907 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
908 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
909 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
910 //m_log.InfoFormat("pre corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
911 //m_log.InfoFormat("pre corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
912 //m_log.InfoFormat("pre corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
913 //m_log.InfoFormat("pre corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
914 //m_log.InfoFormat("pre corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
915
916 //for (int i = 0; i < 8; i++)
917 //{
918 // corners[i] = corners[i] * worldRot;
919 // corners[i] += offset;
920
921 // if (corners[i].X > maxX)
922 // maxX = corners[i].X;
923 // if (corners[i].X < minX)
924 // minX = corners[i].X;
925
926 // if (corners[i].Y > maxY)
927 // maxY = corners[i].Y;
928 // if (corners[i].Y < minY)
929 // minY = corners[i].Y;
930
931 // if (corners[i].Z > maxZ)
932 // maxZ = corners[i].Y;
933 // if (corners[i].Z < minZ)
934 // minZ = corners[i].Z;
935 //}
936
797 frontTopLeft = frontTopLeft * worldRot; 937 frontTopLeft = frontTopLeft * worldRot;
798 frontTopRight = frontTopRight * worldRot; 938 frontTopRight = frontTopRight * worldRot;
799 frontBottomLeft = frontBottomLeft * worldRot; 939 frontBottomLeft = frontBottomLeft * worldRot;
@@ -815,6 +955,15 @@ namespace OpenSim.Region.Framework.Scenes
815 backTopLeft += offset; 955 backTopLeft += offset;
816 backTopRight += offset; 956 backTopRight += offset;
817 957
958 //m_log.InfoFormat("corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
959 //m_log.InfoFormat("corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
960 //m_log.InfoFormat("corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
961 //m_log.InfoFormat("corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
962 //m_log.InfoFormat("corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
963 //m_log.InfoFormat("corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
964 //m_log.InfoFormat("corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
965 //m_log.InfoFormat("corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
966
818 if (frontTopRight.X > maxX) 967 if (frontTopRight.X > maxX)
819 maxX = frontTopRight.X; 968 maxX = frontTopRight.X;
820 if (frontTopLeft.X > maxX) 969 if (frontTopLeft.X > maxX)
@@ -960,15 +1109,20 @@ namespace OpenSim.Region.Framework.Scenes
960 1109
961 public void SaveScriptedState(XmlTextWriter writer) 1110 public void SaveScriptedState(XmlTextWriter writer)
962 { 1111 {
1112 SaveScriptedState(writer, false);
1113 }
1114
1115 public void SaveScriptedState(XmlTextWriter writer, bool oldIDs)
1116 {
963 XmlDocument doc = new XmlDocument(); 1117 XmlDocument doc = new XmlDocument();
964 Dictionary<UUID,string> states = new Dictionary<UUID,string>(); 1118 Dictionary<UUID,string> states = new Dictionary<UUID,string>();
965 1119
966 SceneObjectPart[] parts = m_parts.GetArray(); 1120 SceneObjectPart[] parts = m_parts.GetArray();
967 for (int i = 0; i < parts.Length; i++) 1121 for (int i = 0; i < parts.Length; i++)
968 { 1122 {
969 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(); 1123 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(oldIDs);
970 foreach (KeyValuePair<UUID, string> kvp in pstates) 1124 foreach (KeyValuePair<UUID, string> kvp in pstates)
971 states.Add(kvp.Key, kvp.Value); 1125 states[kvp.Key] = kvp.Value;
972 } 1126 }
973 1127
974 if (states.Count > 0) 1128 if (states.Count > 0)
@@ -988,6 +1142,168 @@ namespace OpenSim.Region.Framework.Scenes
988 } 1142 }
989 1143
990 /// <summary> 1144 /// <summary>
1145 /// Add the avatar to this linkset (avatar is sat).
1146 /// </summary>
1147 /// <param name="agentID"></param>
1148 public void AddAvatar(UUID agentID)
1149 {
1150 ScenePresence presence;
1151 if (m_scene.TryGetScenePresence(agentID, out presence))
1152 {
1153 if (!m_linkedAvatars.Contains(presence))
1154 {
1155 m_linkedAvatars.Add(presence);
1156 }
1157 }
1158 }
1159
1160 /// <summary>
1161 /// Delete the avatar from this linkset (avatar is unsat).
1162 /// </summary>
1163 /// <param name="agentID"></param>
1164 public void DeleteAvatar(UUID agentID)
1165 {
1166 ScenePresence presence;
1167 if (m_scene.TryGetScenePresence(agentID, out presence))
1168 {
1169 if (m_linkedAvatars.Contains(presence))
1170 {
1171 m_linkedAvatars.Remove(presence);
1172 }
1173 }
1174 }
1175
1176 /// <summary>
1177 /// Returns the list of linked presences (avatars sat on this group)
1178 /// </summary>
1179 /// <param name="agentID"></param>
1180 public List<ScenePresence> GetLinkedAvatars()
1181 {
1182 return m_linkedAvatars;
1183 }
1184
1185 /// <summary>
1186 /// Attach this scene object to the given avatar.
1187 /// </summary>
1188 /// <param name="agentID"></param>
1189 /// <param name="attachmentpoint"></param>
1190 /// <param name="AttachOffset"></param>
1191 private void AttachToAgent(
1192 ScenePresence avatar, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent)
1193 {
1194 if (avatar != null)
1195 {
1196 // don't attach attachments to child agents
1197 if (avatar.IsChildAgent) return;
1198
1199 // Remove from database and parcel prim count
1200 m_scene.DeleteFromStorage(so.UUID);
1201 m_scene.EventManager.TriggerParcelPrimCountTainted();
1202
1203 so.AttachedAvatar = avatar.UUID;
1204
1205 if (so.RootPart.PhysActor != null)
1206 {
1207 m_scene.PhysicsScene.RemovePrim(so.RootPart.PhysActor);
1208 so.RootPart.PhysActor = null;
1209 }
1210
1211 so.AbsolutePosition = attachOffset;
1212 so.RootPart.AttachedPos = attachOffset;
1213 so.IsAttachment = true;
1214 so.RootPart.SetParentLocalId(avatar.LocalId);
1215 so.AttachmentPoint = attachmentpoint;
1216
1217 avatar.AddAttachment(this);
1218
1219 if (!silent)
1220 {
1221 // Killing it here will cause the client to deselect it
1222 // It then reappears on the avatar, deselected
1223 // through the full update below
1224 //
1225 if (IsSelected)
1226 {
1227 m_scene.SendKillObject(new List<uint> { m_rootPart.LocalId });
1228 }
1229
1230 IsSelected = false; // fudge....
1231 ScheduleGroupForFullUpdate();
1232 }
1233 }
1234 else
1235 {
1236 m_log.WarnFormat(
1237 "[SOG]: Tried to add attachment {0} to avatar with UUID {1} in region {2} but the avatar is not present",
1238 UUID, avatar.ControllingClient.AgentId, Scene.RegionInfo.RegionName);
1239 }
1240 }
1241
1242 public byte GetAttachmentPoint()
1243 {
1244 return m_rootPart.Shape.State;
1245 }
1246
1247 public void DetachToGround()
1248 {
1249 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
1250 if (avatar == null)
1251 return;
1252
1253 avatar.RemoveAttachment(this);
1254
1255 Vector3 detachedpos = new Vector3(127f,127f,127f);
1256 if (avatar == null)
1257 return;
1258
1259 detachedpos = avatar.AbsolutePosition;
1260 RootPart.FromItemID = UUID.Zero;
1261
1262 AbsolutePosition = detachedpos;
1263 AttachedAvatar = UUID.Zero;
1264
1265 //SceneObjectPart[] parts = m_parts.GetArray();
1266 //for (int i = 0; i < parts.Length; i++)
1267 // parts[i].AttachedAvatar = UUID.Zero;
1268
1269 m_rootPart.SetParentLocalId(0);
1270 AttachmentPoint = (byte)0;
1271 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive);
1272 HasGroupChanged = true;
1273 RootPart.Rezzed = DateTime.Now;
1274 RootPart.RemFlag(PrimFlags.TemporaryOnRez);
1275 AttachToBackup();
1276 m_scene.EventManager.TriggerParcelPrimCountTainted();
1277 m_rootPart.ScheduleFullUpdate();
1278 m_rootPart.ClearUndoState();
1279 }
1280
1281 public void DetachToInventoryPrep()
1282 {
1283 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
1284 //Vector3 detachedpos = new Vector3(127f, 127f, 127f);
1285 if (avatar != null)
1286 {
1287 //detachedpos = avatar.AbsolutePosition;
1288 avatar.RemoveAttachment(this);
1289 }
1290
1291 AttachedAvatar = UUID.Zero;
1292
1293 /*SceneObjectPart[] parts = m_parts.GetArray();
1294 for (int i = 0; i < parts.Length; i++)
1295 parts[i].AttachedAvatar = UUID.Zero;*/
1296
1297 m_rootPart.SetParentLocalId(0);
1298 //m_rootPart.SetAttachmentPoint((byte)0);
1299 IsAttachment = false;
1300 AbsolutePosition = m_rootPart.AttachedPos;
1301 //m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_scene.m_physicalPrim);
1302 //AttachToBackup();
1303 //m_rootPart.ScheduleFullUpdate();
1304 }
1305
1306 /// <summary>
991 /// 1307 ///
992 /// </summary> 1308 /// </summary>
993 /// <param name="part"></param> 1309 /// <param name="part"></param>
@@ -1037,7 +1353,10 @@ namespace OpenSim.Region.Framework.Scenes
1037 public void AddPart(SceneObjectPart part) 1353 public void AddPart(SceneObjectPart part)
1038 { 1354 {
1039 part.SetParent(this); 1355 part.SetParent(this);
1040 part.LinkNum = m_parts.Add(part.UUID, part); 1356 m_parts.Add(part.UUID, part);
1357
1358 part.LinkNum = m_parts.Count;
1359
1041 if (part.LinkNum == 2) 1360 if (part.LinkNum == 2)
1042 RootPart.LinkNum = 1; 1361 RootPart.LinkNum = 1;
1043 } 1362 }
@@ -1145,6 +1464,11 @@ namespace OpenSim.Region.Framework.Scenes
1145 /// <param name="silent">If true then deletion is not broadcast to clients</param> 1464 /// <param name="silent">If true then deletion is not broadcast to clients</param>
1146 public void DeleteGroupFromScene(bool silent) 1465 public void DeleteGroupFromScene(bool silent)
1147 { 1466 {
1467 // We need to keep track of this state in case this group is still queued for backup.
1468 IsDeleted = true;
1469
1470 DetachFromBackup();
1471
1148 SceneObjectPart[] parts = m_parts.GetArray(); 1472 SceneObjectPart[] parts = m_parts.GetArray();
1149 for (int i = 0; i < parts.Length; i++) 1473 for (int i = 0; i < parts.Length; i++)
1150 { 1474 {
@@ -1167,6 +1491,8 @@ namespace OpenSim.Region.Framework.Scenes
1167 } 1491 }
1168 }); 1492 });
1169 } 1493 }
1494
1495
1170 } 1496 }
1171 1497
1172 public void AddScriptLPS(int count) 1498 public void AddScriptLPS(int count)
@@ -1262,7 +1588,12 @@ namespace OpenSim.Region.Framework.Scenes
1262 1588
1263 public void SetOwnerId(UUID userId) 1589 public void SetOwnerId(UUID userId)
1264 { 1590 {
1265 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); 1591 ForEachPart(delegate(SceneObjectPart part)
1592 {
1593
1594 part.OwnerID = userId;
1595
1596 });
1266 } 1597 }
1267 1598
1268 public void ForEachPart(Action<SceneObjectPart> whatToDo) 1599 public void ForEachPart(Action<SceneObjectPart> whatToDo)
@@ -1294,11 +1625,17 @@ namespace OpenSim.Region.Framework.Scenes
1294 return; 1625 return;
1295 } 1626 }
1296 1627
1628 if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
1629 return;
1630
1297 // Since this is the top of the section of call stack for backing up a particular scene object, don't let 1631 // Since this is the top of the section of call stack for backing up a particular scene object, don't let
1298 // any exception propogate upwards. 1632 // any exception propogate upwards.
1299 try 1633 try
1300 { 1634 {
1301 if (!m_scene.ShuttingDown) // if shutting down then there will be nothing to handle the return so leave till next restart 1635 if (!m_scene.ShuttingDown || // if shutting down then there will be nothing to handle the return so leave till next restart
1636 m_scene.LoginsDisabled || // We're starting up or doing maintenance, don't mess with things
1637 m_scene.LoadingPrims) // Land may not be valid yet
1638
1302 { 1639 {
1303 ILandObject parcel = m_scene.LandChannel.GetLandObject( 1640 ILandObject parcel = m_scene.LandChannel.GetLandObject(
1304 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y); 1641 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y);
@@ -1325,6 +1662,7 @@ namespace OpenSim.Region.Framework.Scenes
1325 } 1662 }
1326 } 1663 }
1327 } 1664 }
1665
1328 } 1666 }
1329 1667
1330 if (m_scene.UseBackup && HasGroupChanged) 1668 if (m_scene.UseBackup && HasGroupChanged)
@@ -1332,6 +1670,20 @@ namespace OpenSim.Region.Framework.Scenes
1332 // don't backup while it's selected or you're asking for changes mid stream. 1670 // don't backup while it's selected or you're asking for changes mid stream.
1333 if (isTimeToPersist() || forcedBackup) 1671 if (isTimeToPersist() || forcedBackup)
1334 { 1672 {
1673 if (m_rootPart.PhysActor != null &&
1674 (!m_rootPart.PhysActor.IsPhysical))
1675 {
1676 // Possible ghost prim
1677 if (m_rootPart.PhysActor.Position != m_rootPart.GroupPosition)
1678 {
1679 foreach (SceneObjectPart part in m_parts.GetArray())
1680 {
1681 // Re-set physics actor positions and
1682 // orientations
1683 part.GroupPosition = m_rootPart.GroupPosition;
1684 }
1685 }
1686 }
1335// m_log.DebugFormat( 1687// m_log.DebugFormat(
1336// "[SCENE]: Storing {0}, {1} in {2}", 1688// "[SCENE]: Storing {0}, {1} in {2}",
1337// Name, UUID, m_scene.RegionInfo.RegionName); 1689// Name, UUID, m_scene.RegionInfo.RegionName);
@@ -1415,7 +1767,7 @@ namespace OpenSim.Region.Framework.Scenes
1415 // This is only necessary when userExposed is false! 1767 // This is only necessary when userExposed is false!
1416 1768
1417 bool previousAttachmentStatus = dupe.IsAttachment; 1769 bool previousAttachmentStatus = dupe.IsAttachment;
1418 1770
1419 if (!userExposed) 1771 if (!userExposed)
1420 dupe.IsAttachment = true; 1772 dupe.IsAttachment = true;
1421 1773
@@ -1433,11 +1785,11 @@ namespace OpenSim.Region.Framework.Scenes
1433 dupe.m_rootPart.TrimPermissions(); 1785 dupe.m_rootPart.TrimPermissions();
1434 1786
1435 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray()); 1787 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray());
1436 1788
1437 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) 1789 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1438 { 1790 {
1439 return p1.LinkNum.CompareTo(p2.LinkNum); 1791 return p1.LinkNum.CompareTo(p2.LinkNum);
1440 } 1792 }
1441 ); 1793 );
1442 1794
1443 foreach (SceneObjectPart part in partList) 1795 foreach (SceneObjectPart part in partList)
@@ -1457,7 +1809,7 @@ namespace OpenSim.Region.Framework.Scenes
1457 if (part.PhysActor != null && userExposed) 1809 if (part.PhysActor != null && userExposed)
1458 { 1810 {
1459 PrimitiveBaseShape pbs = newPart.Shape; 1811 PrimitiveBaseShape pbs = newPart.Shape;
1460 1812
1461 newPart.PhysActor 1813 newPart.PhysActor
1462 = m_scene.PhysicsScene.AddPrimShape( 1814 = m_scene.PhysicsScene.AddPrimShape(
1463 string.Format("{0}/{1}", newPart.Name, newPart.UUID), 1815 string.Format("{0}/{1}", newPart.Name, newPart.UUID),
@@ -1467,11 +1819,11 @@ namespace OpenSim.Region.Framework.Scenes
1467 newPart.RotationOffset, 1819 newPart.RotationOffset,
1468 part.PhysActor.IsPhysical, 1820 part.PhysActor.IsPhysical,
1469 newPart.LocalId); 1821 newPart.LocalId);
1470 1822
1471 newPart.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true); 1823 newPart.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true);
1472 } 1824 }
1473 } 1825 }
1474 1826
1475 if (userExposed) 1827 if (userExposed)
1476 { 1828 {
1477 dupe.UpdateParentIDs(); 1829 dupe.UpdateParentIDs();
@@ -1586,6 +1938,7 @@ namespace OpenSim.Region.Framework.Scenes
1586 return Vector3.Zero; 1938 return Vector3.Zero;
1587 } 1939 }
1588 1940
1941 // This is used by both Double-Click Auto-Pilot and llMoveToTarget() in an attached object
1589 public void moveToTarget(Vector3 target, float tau) 1942 public void moveToTarget(Vector3 target, float tau)
1590 { 1943 {
1591 if (IsAttachment) 1944 if (IsAttachment)
@@ -1613,10 +1966,44 @@ namespace OpenSim.Region.Framework.Scenes
1613 RootPart.PhysActor.PIDActive = false; 1966 RootPart.PhysActor.PIDActive = false;
1614 } 1967 }
1615 1968
1969 public void rotLookAt(Quaternion target, float strength, float damping)
1970 {
1971 SceneObjectPart rootpart = m_rootPart;
1972 if (rootpart != null)
1973 {
1974 if (IsAttachment)
1975 {
1976 /*
1977 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
1978 if (avatar != null)
1979 {
1980 Rotate the Av?
1981 } */
1982 }
1983 else
1984 {
1985 if (rootpart.PhysActor != null)
1986 { // APID must be implemented in your physics system for this to function.
1987 rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W);
1988 rootpart.PhysActor.APIDStrength = strength;
1989 rootpart.PhysActor.APIDDamping = damping;
1990 rootpart.PhysActor.APIDActive = true;
1991 }
1992 }
1993 }
1994 }
1995
1616 public void stopLookAt() 1996 public void stopLookAt()
1617 { 1997 {
1618 if (RootPart.PhysActor != null) 1998 SceneObjectPart rootpart = m_rootPart;
1619 RootPart.PhysActor.APIDActive = false; 1999 if (rootpart != null)
2000 {
2001 if (rootpart.PhysActor != null)
2002 { // APID must be implemented in your physics system for this to function.
2003 rootpart.PhysActor.APIDActive = false;
2004 }
2005 }
2006
1620 } 2007 }
1621 2008
1622 /// <summary> 2009 /// <summary>
@@ -1674,6 +2061,8 @@ namespace OpenSim.Region.Framework.Scenes
1674 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) 2061 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
1675 { 2062 {
1676 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 2063 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
2064 newPart.SetParent(this);
2065
1677 AddPart(newPart); 2066 AddPart(newPart);
1678 2067
1679 SetPartAsNonRoot(newPart); 2068 SetPartAsNonRoot(newPart);
@@ -1802,11 +2191,11 @@ namespace OpenSim.Region.Framework.Scenes
1802 /// Immediately send a full update for this scene object. 2191 /// Immediately send a full update for this scene object.
1803 /// </summary> 2192 /// </summary>
1804 public void SendGroupFullUpdate() 2193 public void SendGroupFullUpdate()
1805 { 2194 {
1806 if (IsDeleted) 2195 if (IsDeleted)
1807 return; 2196 return;
1808 2197
1809// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); 2198// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID);
1810 2199
1811 RootPart.SendFullUpdateToAllClients(); 2200 RootPart.SendFullUpdateToAllClients();
1812 2201
@@ -2007,7 +2396,7 @@ namespace OpenSim.Region.Framework.Scenes
2007 objectGroup.IsDeleted = true; 2396 objectGroup.IsDeleted = true;
2008 2397
2009 objectGroup.m_parts.Clear(); 2398 objectGroup.m_parts.Clear();
2010 2399
2011 // Can't do this yet since backup still makes use of the root part without any synchronization 2400 // Can't do this yet since backup still makes use of the root part without any synchronization
2012// objectGroup.m_rootPart = null; 2401// objectGroup.m_rootPart = null;
2013 2402
@@ -2141,6 +2530,7 @@ namespace OpenSim.Region.Framework.Scenes
2141 /// <param name="objectGroup"></param> 2530 /// <param name="objectGroup"></param>
2142 public virtual void DetachFromBackup() 2531 public virtual void DetachFromBackup()
2143 { 2532 {
2533 m_scene.SceneGraph.FireDetachFromBackup(this);
2144 if (m_isBackedUp && Scene != null) 2534 if (m_isBackedUp && Scene != null)
2145 m_scene.EventManager.OnBackup -= ProcessBackup; 2535 m_scene.EventManager.OnBackup -= ProcessBackup;
2146 2536
@@ -2159,7 +2549,8 @@ namespace OpenSim.Region.Framework.Scenes
2159 2549
2160 axPos *= parentRot; 2550 axPos *= parentRot;
2161 part.OffsetPosition = axPos; 2551 part.OffsetPosition = axPos;
2162 part.GroupPosition = oldGroupPosition + part.OffsetPosition; 2552 Vector3 newPos = oldGroupPosition + part.OffsetPosition;
2553 part.GroupPosition = newPos;
2163 part.OffsetPosition = Vector3.Zero; 2554 part.OffsetPosition = Vector3.Zero;
2164 part.RotationOffset = worldRot; 2555 part.RotationOffset = worldRot;
2165 2556
@@ -2170,7 +2561,7 @@ namespace OpenSim.Region.Framework.Scenes
2170 2561
2171 part.LinkNum = linkNum; 2562 part.LinkNum = linkNum;
2172 2563
2173 part.OffsetPosition = part.GroupPosition - AbsolutePosition; 2564 part.OffsetPosition = newPos - AbsolutePosition;
2174 2565
2175 Quaternion rootRotation = m_rootPart.RotationOffset; 2566 Quaternion rootRotation = m_rootPart.RotationOffset;
2176 2567
@@ -2180,7 +2571,7 @@ namespace OpenSim.Region.Framework.Scenes
2180 2571
2181 parentRot = m_rootPart.RotationOffset; 2572 parentRot = m_rootPart.RotationOffset;
2182 oldRot = part.RotationOffset; 2573 oldRot = part.RotationOffset;
2183 Quaternion newRot = Quaternion.Inverse(parentRot) * oldRot; 2574 Quaternion newRot = Quaternion.Inverse(parentRot) * worldRot;
2184 part.RotationOffset = newRot; 2575 part.RotationOffset = newRot;
2185 } 2576 }
2186 2577
@@ -2427,8 +2818,12 @@ namespace OpenSim.Region.Framework.Scenes
2427 } 2818 }
2428 } 2819 }
2429 2820
2821 RootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect);
2430 for (int i = 0; i < parts.Length; i++) 2822 for (int i = 0; i < parts.Length; i++)
2431 parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect); 2823 {
2824 if (parts[i] != RootPart)
2825 parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect);
2826 }
2432 } 2827 }
2433 } 2828 }
2434 2829
@@ -2441,6 +2836,17 @@ namespace OpenSim.Region.Framework.Scenes
2441 } 2836 }
2442 } 2837 }
2443 2838
2839
2840
2841 /// <summary>
2842 /// Gets the number of parts
2843 /// </summary>
2844 /// <returns></returns>
2845 public int GetPartCount()
2846 {
2847 return Parts.Count();
2848 }
2849
2444 /// <summary> 2850 /// <summary>
2445 /// Update the texture entry for this part 2851 /// Update the texture entry for this part
2446 /// </summary> 2852 /// </summary>
@@ -2502,7 +2908,6 @@ namespace OpenSim.Region.Framework.Scenes
2502 { 2908 {
2503// m_log.DebugFormat( 2909// m_log.DebugFormat(
2504// "[SCENE OBJECT GROUP]: Group resizing {0} {1} from {2} to {3}", Name, LocalId, RootPart.Scale, scale); 2910// "[SCENE OBJECT GROUP]: Group resizing {0} {1} from {2} to {3}", Name, LocalId, RootPart.Scale, scale);
2505
2506 RootPart.StoreUndoState(true); 2911 RootPart.StoreUndoState(true);
2507 2912
2508 scale.X = Math.Min(scale.X, Scene.m_maxNonphys); 2913 scale.X = Math.Min(scale.X, Scene.m_maxNonphys);
@@ -2603,7 +3008,6 @@ namespace OpenSim.Region.Framework.Scenes
2603 prevScale.X *= x; 3008 prevScale.X *= x;
2604 prevScale.Y *= y; 3009 prevScale.Y *= y;
2605 prevScale.Z *= z; 3010 prevScale.Z *= z;
2606
2607// RootPart.IgnoreUndoUpdate = true; 3011// RootPart.IgnoreUndoUpdate = true;
2608 RootPart.Resize(prevScale); 3012 RootPart.Resize(prevScale);
2609// RootPart.IgnoreUndoUpdate = false; 3013// RootPart.IgnoreUndoUpdate = false;
@@ -2634,7 +3038,9 @@ namespace OpenSim.Region.Framework.Scenes
2634 } 3038 }
2635 3039
2636// obPart.IgnoreUndoUpdate = false; 3040// obPart.IgnoreUndoUpdate = false;
2637// obPart.StoreUndoState(); 3041 HasGroupChanged = true;
3042 m_rootPart.TriggerScriptChangedEvent(Changed.SCALE);
3043 ScheduleGroupForTerseUpdate();
2638 } 3044 }
2639 3045
2640// m_log.DebugFormat( 3046// m_log.DebugFormat(
@@ -2694,9 +3100,9 @@ namespace OpenSim.Region.Framework.Scenes
2694 { 3100 {
2695 SceneObjectPart part = GetChildPart(localID); 3101 SceneObjectPart part = GetChildPart(localID);
2696 3102
2697// SceneObjectPart[] parts = m_parts.GetArray(); 3103 SceneObjectPart[] parts = m_parts.GetArray();
2698// for (int i = 0; i < parts.Length; i++) 3104 for (int i = 0; i < parts.Length; i++)
2699// parts[i].StoreUndoState(); 3105 parts[i].StoreUndoState();
2700 3106
2701 if (part != null) 3107 if (part != null)
2702 { 3108 {
@@ -2752,10 +3158,27 @@ namespace OpenSim.Region.Framework.Scenes
2752 obPart.OffsetPosition = obPart.OffsetPosition + diff; 3158 obPart.OffsetPosition = obPart.OffsetPosition + diff;
2753 } 3159 }
2754 3160
2755 AbsolutePosition = newPos; 3161 //We have to set undoing here because otherwise an undo state will be saved
3162 if (!m_rootPart.Undoing)
3163 {
3164 m_rootPart.Undoing = true;
3165 AbsolutePosition = newPos;
3166 m_rootPart.Undoing = false;
3167 }
3168 else
3169 {
3170 AbsolutePosition = newPos;
3171 }
2756 3172
2757 HasGroupChanged = true; 3173 HasGroupChanged = true;
2758 ScheduleGroupForTerseUpdate(); 3174 if (m_rootPart.Undoing)
3175 {
3176 ScheduleGroupForFullUpdate();
3177 }
3178 else
3179 {
3180 ScheduleGroupForTerseUpdate();
3181 }
2759 } 3182 }
2760 3183
2761 #endregion 3184 #endregion
@@ -2832,10 +3255,7 @@ namespace OpenSim.Region.Framework.Scenes
2832 public void UpdateSingleRotation(Quaternion rot, uint localID) 3255 public void UpdateSingleRotation(Quaternion rot, uint localID)
2833 { 3256 {
2834 SceneObjectPart part = GetChildPart(localID); 3257 SceneObjectPart part = GetChildPart(localID);
2835
2836 SceneObjectPart[] parts = m_parts.GetArray(); 3258 SceneObjectPart[] parts = m_parts.GetArray();
2837 for (int i = 0; i < parts.Length; i++)
2838 parts[i].StoreUndoState();
2839 3259
2840 if (part != null) 3260 if (part != null)
2841 { 3261 {
@@ -2873,7 +3293,16 @@ namespace OpenSim.Region.Framework.Scenes
2873 if (part.UUID == m_rootPart.UUID) 3293 if (part.UUID == m_rootPart.UUID)
2874 { 3294 {
2875 UpdateRootRotation(rot); 3295 UpdateRootRotation(rot);
2876 AbsolutePosition = pos; 3296 if (!m_rootPart.Undoing)
3297 {
3298 m_rootPart.Undoing = true;
3299 AbsolutePosition = pos;
3300 m_rootPart.Undoing = false;
3301 }
3302 else
3303 {
3304 AbsolutePosition = pos;
3305 }
2877 } 3306 }
2878 else 3307 else
2879 { 3308 {
@@ -2897,9 +3326,10 @@ namespace OpenSim.Region.Framework.Scenes
2897 3326
2898 Quaternion axRot = rot; 3327 Quaternion axRot = rot;
2899 Quaternion oldParentRot = m_rootPart.RotationOffset; 3328 Quaternion oldParentRot = m_rootPart.RotationOffset;
2900
2901 m_rootPart.StoreUndoState(); 3329 m_rootPart.StoreUndoState();
2902 m_rootPart.UpdateRotation(rot); 3330
3331 //Don't use UpdateRotation because it schedules an update prematurely
3332 m_rootPart.RotationOffset = rot;
2903 if (m_rootPart.PhysActor != null) 3333 if (m_rootPart.PhysActor != null)
2904 { 3334 {
2905 m_rootPart.PhysActor.Orientation = m_rootPart.RotationOffset; 3335 m_rootPart.PhysActor.Orientation = m_rootPart.RotationOffset;
@@ -2913,15 +3343,17 @@ namespace OpenSim.Region.Framework.Scenes
2913 if (prim.UUID != m_rootPart.UUID) 3343 if (prim.UUID != m_rootPart.UUID)
2914 { 3344 {
2915 prim.IgnoreUndoUpdate = true; 3345 prim.IgnoreUndoUpdate = true;
3346
3347 Quaternion NewRot = oldParentRot * prim.RotationOffset;
3348 NewRot = Quaternion.Inverse(axRot) * NewRot;
3349 prim.RotationOffset = NewRot;
3350
2916 Vector3 axPos = prim.OffsetPosition; 3351 Vector3 axPos = prim.OffsetPosition;
3352
2917 axPos *= oldParentRot; 3353 axPos *= oldParentRot;
2918 axPos *= Quaternion.Inverse(axRot); 3354 axPos *= Quaternion.Inverse(axRot);
2919 prim.OffsetPosition = axPos; 3355 prim.OffsetPosition = axPos;
2920 Quaternion primsRot = prim.RotationOffset; 3356
2921 Quaternion newRot = oldParentRot * primsRot;
2922 newRot = Quaternion.Inverse(axRot) * newRot;
2923 prim.RotationOffset = newRot;
2924 prim.ScheduleTerseUpdate();
2925 prim.IgnoreUndoUpdate = false; 3357 prim.IgnoreUndoUpdate = false;
2926 } 3358 }
2927 } 3359 }
@@ -2935,8 +3367,8 @@ namespace OpenSim.Region.Framework.Scenes
2935//// childpart.StoreUndoState(); 3367//// childpart.StoreUndoState();
2936// } 3368// }
2937// } 3369// }
2938 3370 HasGroupChanged = true;
2939 m_rootPart.ScheduleTerseUpdate(); 3371 ScheduleGroupForFullUpdate();
2940 3372
2941// m_log.DebugFormat( 3373// m_log.DebugFormat(
2942// "[SCENE OBJECT GROUP]: Updated root rotation of {0} {1} to {2}", 3374// "[SCENE OBJECT GROUP]: Updated root rotation of {0} {1} to {2}",
@@ -3164,7 +3596,6 @@ namespace OpenSim.Region.Framework.Scenes
3164 public float GetMass() 3596 public float GetMass()
3165 { 3597 {
3166 float retmass = 0f; 3598 float retmass = 0f;
3167
3168 SceneObjectPart[] parts = m_parts.GetArray(); 3599 SceneObjectPart[] parts = m_parts.GetArray();
3169 for (int i = 0; i < parts.Length; i++) 3600 for (int i = 0; i < parts.Length; i++)
3170 retmass += parts[i].GetMass(); 3601 retmass += parts[i].GetMass();
@@ -3260,6 +3691,14 @@ namespace OpenSim.Region.Framework.Scenes
3260 SetFromItemID(uuid); 3691 SetFromItemID(uuid);
3261 } 3692 }
3262 3693
3694 public void ResetOwnerChangeFlag()
3695 {
3696 ForEachPart(delegate(SceneObjectPart part)
3697 {
3698 part.ResetOwnerChangeFlag();
3699 });
3700 }
3701
3263 #endregion 3702 #endregion
3264 } 3703 }
3265} 3704}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 51d3586..c45cfb8 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
@@ -252,6 +261,7 @@ namespace OpenSim.Region.Framework.Scenes
252 private Quaternion m_sitTargetOrientation = Quaternion.Identity; 261 private Quaternion m_sitTargetOrientation = Quaternion.Identity;
253 private Vector3 m_sitTargetPosition; 262 private Vector3 m_sitTargetPosition;
254 private string m_sitAnimation = "SIT"; 263 private string m_sitAnimation = "SIT";
264 private bool m_occupied; // KF if any av is sitting on this prim
255 private string m_text = String.Empty; 265 private string m_text = String.Empty;
256 private string m_touchName = String.Empty; 266 private string m_touchName = String.Empty;
257 private readonly Stack<UndoState> m_undo = new Stack<UndoState>(5); 267 private readonly Stack<UndoState> m_undo = new Stack<UndoState>(5);
@@ -284,6 +294,7 @@ namespace OpenSim.Region.Framework.Scenes
284 protected Vector3 m_lastAcceleration; 294 protected Vector3 m_lastAcceleration;
285 protected Vector3 m_lastAngularVelocity; 295 protected Vector3 m_lastAngularVelocity;
286 protected int m_lastTerseSent; 296 protected int m_lastTerseSent;
297 protected float m_buoyancy = 0.0f;
287 298
288 /// <summary> 299 /// <summary>
289 /// Stores media texture data 300 /// Stores media texture data
@@ -339,7 +350,7 @@ namespace OpenSim.Region.Framework.Scenes
339 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition, 350 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition,
340 Quaternion rotationOffset, Vector3 offsetPosition) : this() 351 Quaternion rotationOffset, Vector3 offsetPosition) : this()
341 { 352 {
342 m_name = "Primitive"; 353 m_name = "Object";
343 354
344 CreationDate = (int)Utils.DateTimeToUnixTime(Rezzed); 355 CreationDate = (int)Utils.DateTimeToUnixTime(Rezzed);
345 LastOwnerID = CreatorID = OwnerID = ownerID; 356 LastOwnerID = CreatorID = OwnerID = ownerID;
@@ -379,7 +390,7 @@ namespace OpenSim.Region.Framework.Scenes
379 private uint _ownerMask = (uint)PermissionMask.All; 390 private uint _ownerMask = (uint)PermissionMask.All;
380 private uint _groupMask = (uint)PermissionMask.None; 391 private uint _groupMask = (uint)PermissionMask.None;
381 private uint _everyoneMask = (uint)PermissionMask.None; 392 private uint _everyoneMask = (uint)PermissionMask.None;
382 private uint _nextOwnerMask = (uint)PermissionMask.All; 393 private uint _nextOwnerMask = (uint)(PermissionMask.Move | PermissionMask.Modify | PermissionMask.Transfer);
383 private PrimFlags _flags = PrimFlags.None; 394 private PrimFlags _flags = PrimFlags.None;
384 private DateTime m_expires; 395 private DateTime m_expires;
385 private DateTime m_rezzed; 396 private DateTime m_rezzed;
@@ -473,12 +484,16 @@ namespace OpenSim.Region.Framework.Scenes
473 } 484 }
474 485
475 /// <value> 486 /// <value>
476 /// Access should be via Inventory directly - this property temporarily remains for xml serialization purposes 487 /// Get the inventory list
477 /// </value> 488 /// </value>
478 public TaskInventoryDictionary TaskInventory 489 public TaskInventoryDictionary TaskInventory
479 { 490 {
480 get { return m_inventory.Items; } 491 get {
481 set { m_inventory.Items = value; } 492 return m_inventory.Items;
493 }
494 set {
495 m_inventory.Items = value;
496 }
482 } 497 }
483 498
484 /// <summary> 499 /// <summary>
@@ -623,14 +638,12 @@ namespace OpenSim.Region.Framework.Scenes
623 set { m_LoopSoundSlavePrims = value; } 638 set { m_LoopSoundSlavePrims = value; }
624 } 639 }
625 640
626
627 public Byte[] TextureAnimation 641 public Byte[] TextureAnimation
628 { 642 {
629 get { return m_TextureAnimation; } 643 get { return m_TextureAnimation; }
630 set { m_TextureAnimation = value; } 644 set { m_TextureAnimation = value; }
631 } 645 }
632 646
633
634 public Byte[] ParticleSystem 647 public Byte[] ParticleSystem
635 { 648 {
636 get { return m_particleSystem; } 649 get { return m_particleSystem; }
@@ -667,9 +680,11 @@ namespace OpenSim.Region.Framework.Scenes
667 { 680 {
668 // If this is a linkset, we don't want the physics engine mucking up our group position here. 681 // If this is a linkset, we don't want the physics engine mucking up our group position here.
669 PhysicsActor actor = PhysActor; 682 PhysicsActor actor = PhysActor;
670 if (actor != null && ParentID == 0) 683 if (ParentID == 0)
671 { 684 {
672 m_groupPosition = actor.Position; 685 if (actor != null)
686 m_groupPosition = actor.Position;
687 return m_groupPosition;
673 } 688 }
674 689
675 if (ParentGroup.IsAttachment) 690 if (ParentGroup.IsAttachment)
@@ -679,12 +694,14 @@ namespace OpenSim.Region.Framework.Scenes
679 return sp.AbsolutePosition; 694 return sp.AbsolutePosition;
680 } 695 }
681 696
697 // use root prim's group position. Physics may have updated it
698 if (ParentGroup.RootPart != this)
699 m_groupPosition = ParentGroup.RootPart.GroupPosition;
682 return m_groupPosition; 700 return m_groupPosition;
683 } 701 }
684 set 702 set
685 { 703 {
686 m_groupPosition = value; 704 m_groupPosition = value;
687
688 PhysicsActor actor = PhysActor; 705 PhysicsActor actor = PhysActor;
689 if (actor != null) 706 if (actor != null)
690 { 707 {
@@ -710,16 +727,6 @@ namespace OpenSim.Region.Framework.Scenes
710 m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message); 727 m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message);
711 } 728 }
712 } 729 }
713
714 // TODO if we decide to do sitting in a more SL compatible way (multiple avatars per prim), this has to be fixed, too
715 if (SitTargetAvatar != UUID.Zero)
716 {
717 ScenePresence avatar;
718 if (ParentGroup.Scene.TryGetScenePresence(SitTargetAvatar, out avatar))
719 {
720 avatar.ParentPosition = GetWorldPosition();
721 }
722 }
723 } 730 }
724 } 731 }
725 732
@@ -728,7 +735,7 @@ namespace OpenSim.Region.Framework.Scenes
728 get { return m_offsetPosition; } 735 get { return m_offsetPosition; }
729 set 736 set
730 { 737 {
731// StoreUndoState(); 738 Vector3 oldpos = m_offsetPosition;
732 m_offsetPosition = value; 739 m_offsetPosition = value;
733 740
734 if (ParentGroup != null && !ParentGroup.IsDeleted) 741 if (ParentGroup != null && !ParentGroup.IsDeleted)
@@ -743,7 +750,22 @@ namespace OpenSim.Region.Framework.Scenes
743 if (ParentGroup.Scene != null) 750 if (ParentGroup.Scene != null)
744 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 751 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
745 } 752 }
753
754 if (!m_parentGroup.m_dupeInProgress)
755 {
756 List<ScenePresence> avs = ParentGroup.GetLinkedAvatars();
757 foreach (ScenePresence av in avs)
758 {
759 if (av.ParentID == m_localId)
760 {
761 Vector3 offset = (m_offsetPosition - oldpos);
762 av.AbsolutePosition += offset;
763 av.SendAvatarDataToAllAgents();
764 }
765 }
766 }
746 } 767 }
768 TriggerScriptChangedEvent(Changed.POSITION);
747 } 769 }
748 } 770 }
749 771
@@ -892,7 +914,16 @@ namespace OpenSim.Region.Framework.Scenes
892 /// <summary></summary> 914 /// <summary></summary>
893 public Vector3 Acceleration 915 public Vector3 Acceleration
894 { 916 {
895 get { return m_acceleration; } 917 get
918 {
919 PhysicsActor actor = PhysActor;
920 if (actor != null)
921 {
922 m_acceleration = actor.Acceleration;
923 }
924 return m_acceleration;
925 }
926
896 set { m_acceleration = value; } 927 set { m_acceleration = value; }
897 } 928 }
898 929
@@ -1043,10 +1074,7 @@ namespace OpenSim.Region.Framework.Scenes
1043 { 1074 {
1044 get 1075 get
1045 { 1076 {
1046 if (ParentGroup.IsAttachment) 1077 return GroupPosition + (m_offsetPosition * ParentGroup.RootPart.RotationOffset);
1047 return GroupPosition;
1048
1049 return m_offsetPosition + m_groupPosition;
1050 } 1078 }
1051 } 1079 }
1052 1080
@@ -1216,6 +1244,13 @@ namespace OpenSim.Region.Framework.Scenes
1216 _flags = value; 1244 _flags = value;
1217 } 1245 }
1218 } 1246 }
1247
1248 [XmlIgnore]
1249 public bool IsOccupied // KF If an av is sittingon this prim
1250 {
1251 get { return m_occupied; }
1252 set { m_occupied = value; }
1253 }
1219 1254
1220 /// <summary> 1255 /// <summary>
1221 /// ID of the avatar that is sat on us. If there is no such avatar then is UUID.Zero 1256 /// ID of the avatar that is sat on us. If there is no such avatar then is UUID.Zero
@@ -1275,6 +1310,19 @@ namespace OpenSim.Region.Framework.Scenes
1275 set { m_collisionSoundVolume = value; } 1310 set { m_collisionSoundVolume = value; }
1276 } 1311 }
1277 1312
1313 public float Buoyancy
1314 {
1315 get { return m_buoyancy; }
1316 set
1317 {
1318 m_buoyancy = value;
1319 if (PhysActor != null)
1320 {
1321 PhysActor.Buoyancy = value;
1322 }
1323 }
1324 }
1325
1278 #endregion Public Properties with only Get 1326 #endregion Public Properties with only Get
1279 1327
1280 private uint ApplyMask(uint val, bool set, uint mask) 1328 private uint ApplyMask(uint val, bool set, uint mask)
@@ -1599,6 +1647,9 @@ namespace OpenSim.Region.Framework.Scenes
1599 1647
1600 // Move afterwards ResetIDs as it clears the localID 1648 // Move afterwards ResetIDs as it clears the localID
1601 dupe.LocalId = localID; 1649 dupe.LocalId = localID;
1650 if(dupe.PhysActor != null)
1651 dupe.PhysActor.LocalID = localID;
1652
1602 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated. 1653 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated.
1603 dupe.LastOwnerID = OwnerID; 1654 dupe.LastOwnerID = OwnerID;
1604 1655
@@ -2604,17 +2655,18 @@ namespace OpenSim.Region.Framework.Scenes
2604 //Trys to fetch sound id from prim's inventory. 2655 //Trys to fetch sound id from prim's inventory.
2605 //Prim's inventory doesn't support non script items yet 2656 //Prim's inventory doesn't support non script items yet
2606 2657
2607 lock (TaskInventory) 2658 TaskInventory.LockItemsForRead(true);
2659
2660 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2608 { 2661 {
2609 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 2662 if (item.Value.Name == sound)
2610 { 2663 {
2611 if (item.Value.Name == sound) 2664 soundID = item.Value.ItemID;
2612 { 2665 break;
2613 soundID = item.Value.ItemID;
2614 break;
2615 }
2616 } 2666 }
2617 } 2667 }
2668
2669 TaskInventory.LockItemsForRead(false);
2618 } 2670 }
2619 2671
2620 ParentGroup.Scene.ForEachRootScenePresence(delegate(ScenePresence sp) 2672 ParentGroup.Scene.ForEachRootScenePresence(delegate(ScenePresence sp)
@@ -2697,7 +2749,7 @@ namespace OpenSim.Region.Framework.Scenes
2697 2749
2698 public void RotLookAt(Quaternion target, float strength, float damping) 2750 public void RotLookAt(Quaternion target, float strength, float damping)
2699 { 2751 {
2700 rotLookAt(target, strength, damping); 2752 m_parentGroup.rotLookAt(target, strength, damping); // This calls method in SceneObjectGroup.
2701 } 2753 }
2702 2754
2703 public void rotLookAt(Quaternion target, float strength, float damping) 2755 public void rotLookAt(Quaternion target, float strength, float damping)
@@ -2923,8 +2975,8 @@ namespace OpenSim.Region.Framework.Scenes
2923 { 2975 {
2924 const float ROTATION_TOLERANCE = 0.01f; 2976 const float ROTATION_TOLERANCE = 0.01f;
2925 const float VELOCITY_TOLERANCE = 0.001f; 2977 const float VELOCITY_TOLERANCE = 0.001f;
2926 const float POSITION_TOLERANCE = 0.05f; 2978 const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary
2927 const int TIME_MS_TOLERANCE = 3000; 2979 const int TIME_MS_TOLERANCE = 200; //llSetPos has a 200ms delay. This should NOT be 3 seconds.
2928 2980
2929 switch (UpdateFlag) 2981 switch (UpdateFlag)
2930 { 2982 {
@@ -2986,17 +3038,16 @@ namespace OpenSim.Region.Framework.Scenes
2986 if (!UUID.TryParse(sound, out soundID)) 3038 if (!UUID.TryParse(sound, out soundID))
2987 { 3039 {
2988 // search sound file from inventory 3040 // search sound file from inventory
2989 lock (TaskInventory) 3041 TaskInventory.LockItemsForRead(true);
3042 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2990 { 3043 {
2991 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 3044 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound)
2992 { 3045 {
2993 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound) 3046 soundID = item.Value.ItemID;
2994 { 3047 break;
2995 soundID = item.Value.ItemID;
2996 break;
2997 }
2998 } 3048 }
2999 } 3049 }
3050 TaskInventory.LockItemsForRead(false);
3000 } 3051 }
3001 3052
3002 if (soundID == UUID.Zero) 3053 if (soundID == UUID.Zero)
@@ -3470,10 +3521,10 @@ namespace OpenSim.Region.Framework.Scenes
3470 // TODO: May need to fix for group comparison 3521 // TODO: May need to fix for group comparison
3471 if (last.Compare(this)) 3522 if (last.Compare(this))
3472 { 3523 {
3473 // m_log.DebugFormat( 3524 // m_log.DebugFormat(
3474 // "[SCENE OBJECT PART]: Not storing undo for {0} {1} since current state is same as last undo state, initial stack size {2}", 3525 // "[SCENE OBJECT PART]: Not storing undo for {0} {1} since current state is same as last undo state, initial stack size {2}",
3475 // Name, LocalId, m_undo.Count); 3526 // Name, LocalId, m_undo.Count);
3476 3527
3477 return; 3528 return;
3478 } 3529 }
3479 } 3530 }
@@ -3486,29 +3537,29 @@ namespace OpenSim.Region.Framework.Scenes
3486 if (ParentGroup.GetSceneMaxUndo() > 0) 3537 if (ParentGroup.GetSceneMaxUndo() > 0)
3487 { 3538 {
3488 UndoState nUndo = new UndoState(this, forGroup); 3539 UndoState nUndo = new UndoState(this, forGroup);
3489 3540
3490 m_undo.Push(nUndo); 3541 m_undo.Push(nUndo);
3491 3542
3492 if (m_redo.Count > 0) 3543 if (m_redo.Count > 0)
3493 m_redo.Clear(); 3544 m_redo.Clear();
3494 3545
3495 // m_log.DebugFormat( 3546 // m_log.DebugFormat(
3496 // "[SCENE OBJECT PART]: Stored undo state for {0} {1}, forGroup {2}, stack size now {3}", 3547 // "[SCENE OBJECT PART]: Stored undo state for {0} {1}, forGroup {2}, stack size now {3}",
3497 // Name, LocalId, forGroup, m_undo.Count); 3548 // Name, LocalId, forGroup, m_undo.Count);
3498 } 3549 }
3499 } 3550 }
3500 } 3551 }
3501 } 3552 }
3502// else 3553 // else
3503// { 3554 // {
3504// m_log.DebugFormat("[SCENE OBJECT PART]: Ignoring undo store for {0} {1}", Name, LocalId); 3555 // m_log.DebugFormat("[SCENE OBJECT PART]: Ignoring undo store for {0} {1}", Name, LocalId);
3505// } 3556 // }
3506 } 3557 }
3507// else 3558 // else
3508// { 3559 // {
3509// m_log.DebugFormat( 3560 // m_log.DebugFormat(
3510// "[SCENE OBJECT PART]: Ignoring undo store for {0} {1} since already undoing", Name, LocalId); 3561 // "[SCENE OBJECT PART]: Ignoring undo store for {0} {1} since already undoing", Name, LocalId);
3511// } 3562 // }
3512 } 3563 }
3513 3564
3514 /// <summary> 3565 /// <summary>
@@ -4239,6 +4290,9 @@ namespace OpenSim.Region.Framework.Scenes
4239 bool wasPhantom = ((Flags & PrimFlags.Phantom) != 0); 4290 bool wasPhantom = ((Flags & PrimFlags.Phantom) != 0);
4240 bool wasVD = VolumeDetectActive; 4291 bool wasVD = VolumeDetectActive;
4241 4292
4293// m_log.DebugFormat("[SOP]: Old states: phys: {0} temp: {1} phan: {2} vd: {3}", wasUsingPhysics, wasTemporary, wasPhantom, wasVD);
4294// m_log.DebugFormat("[SOP]: New states: phys: {0} temp: {1} phan: {2} vd: {3}", UsePhysics, SetTemporary, SetPhantom, SetVD);
4295
4242 if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD)) 4296 if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD))
4243 return; 4297 return;
4244 4298
@@ -4268,6 +4322,11 @@ namespace OpenSim.Region.Framework.Scenes
4268 SetPhantom = false; 4322 SetPhantom = false;
4269 } 4323 }
4270 } 4324 }
4325 else if (wasVD)
4326 {
4327 // Correspondingly, if VD is turned off, also turn off phantom
4328 SetPhantom = false;
4329 }
4271 4330
4272 if (UsePhysics && IsJoint()) 4331 if (UsePhysics && IsJoint())
4273 { 4332 {
@@ -4762,5 +4821,17 @@ namespace OpenSim.Region.Framework.Scenes
4762 Color color = Color; 4821 Color color = Color;
4763 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A)); 4822 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A));
4764 } 4823 }
4824
4825 public void ResetOwnerChangeFlag()
4826 {
4827 List<UUID> inv = Inventory.GetInventoryList();
4828
4829 foreach (UUID itemID in inv)
4830 {
4831 TaskInventoryItem item = Inventory.GetInventoryItem(itemID);
4832 item.OwnerChanged = false;
4833 Inventory.UpdateInventoryItem(item, false, false);
4834 }
4835 }
4765 } 4836 }
4766} 4837}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index daddb90..2335ad5 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
@@ -48,6 +48,9 @@ namespace OpenSim.Region.Framework.Scenes
48 private string m_inventoryFileName = String.Empty; 48 private string m_inventoryFileName = String.Empty;
49 private byte[] m_inventoryFileData = new byte[0]; 49 private byte[] m_inventoryFileData = new byte[0];
50 private uint m_inventoryFileNameSerial = 0; 50 private uint m_inventoryFileNameSerial = 0;
51 private bool m_inventoryPrivileged = false;
52
53 private Dictionary<UUID, ArrayList> m_scriptErrors = new Dictionary<UUID, ArrayList>();
51 54
52 /// <value> 55 /// <value>
53 /// The part to which the inventory belongs. 56 /// The part to which the inventory belongs.
@@ -84,11 +87,14 @@ namespace OpenSim.Region.Framework.Scenes
84 /// </value> 87 /// </value>
85 protected internal TaskInventoryDictionary Items 88 protected internal TaskInventoryDictionary Items
86 { 89 {
87 get { return m_items; } 90 get {
91 return m_items;
92 }
88 set 93 set
89 { 94 {
90 m_items = value; 95 m_items = value;
91 m_inventorySerial++; 96 m_inventorySerial++;
97 QueryScriptStates();
92 } 98 }
93 } 99 }
94 100
@@ -123,38 +129,45 @@ namespace OpenSim.Region.Framework.Scenes
123 public void ResetInventoryIDs() 129 public void ResetInventoryIDs()
124 { 130 {
125 if (null == m_part) 131 if (null == m_part)
126 return; 132 m_items.LockItemsForWrite(true);
127 133
128 lock (m_items) 134 if (Items.Count == 0)
129 { 135 {
130 if (0 == m_items.Count) 136 m_items.LockItemsForWrite(false);
131 return; 137 return;
138 }
132 139
133 IList<TaskInventoryItem> items = GetInventoryItems(); 140 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
134 m_items.Clear(); 141 Items.Clear();
135 142
136 foreach (TaskInventoryItem item in items) 143 foreach (TaskInventoryItem item in items)
137 { 144 {
138 item.ResetIDs(m_part.UUID); 145 item.ResetIDs(m_part.UUID);
139 m_items.Add(item.ItemID, item); 146 Items.Add(item.ItemID, item);
140 }
141 } 147 }
148 m_items.LockItemsForWrite(false);
142 } 149 }
143 150
144 public void ResetObjectID() 151 public void ResetObjectID()
145 { 152 {
146 lock (Items) 153 m_items.LockItemsForWrite(true);
154
155 if (Items.Count == 0)
147 { 156 {
148 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values); 157 m_items.LockItemsForWrite(false);
149 Items.Clear(); 158 return;
150
151 foreach (TaskInventoryItem item in items)
152 {
153 item.ParentPartID = m_part.UUID;
154 item.ParentID = m_part.UUID;
155 Items.Add(item.ItemID, item);
156 }
157 } 159 }
160
161 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
162 Items.Clear();
163
164 foreach (TaskInventoryItem item in items)
165 {
166 item.ParentPartID = m_part.UUID;
167 item.ParentID = m_part.UUID;
168 Items.Add(item.ItemID, item);
169 }
170 m_items.LockItemsForWrite(false);
158 } 171 }
159 172
160 /// <summary> 173 /// <summary>
@@ -163,12 +176,11 @@ namespace OpenSim.Region.Framework.Scenes
163 /// <param name="ownerId"></param> 176 /// <param name="ownerId"></param>
164 public void ChangeInventoryOwner(UUID ownerId) 177 public void ChangeInventoryOwner(UUID ownerId)
165 { 178 {
166 lock (Items) 179 m_items.LockItemsForWrite(true);
180 if (0 == Items.Count)
167 { 181 {
168 if (0 == Items.Count) 182 m_items.LockItemsForWrite(false);
169 { 183 return;
170 return;
171 }
172 } 184 }
173 185
174 HasInventoryChanged = true; 186 HasInventoryChanged = true;
@@ -184,6 +196,7 @@ namespace OpenSim.Region.Framework.Scenes
184 item.PermsGranter = UUID.Zero; 196 item.PermsGranter = UUID.Zero;
185 item.OwnerChanged = true; 197 item.OwnerChanged = true;
186 } 198 }
199 m_items.LockItemsForWrite(false);
187 } 200 }
188 201
189 /// <summary> 202 /// <summary>
@@ -192,12 +205,11 @@ namespace OpenSim.Region.Framework.Scenes
192 /// <param name="groupID"></param> 205 /// <param name="groupID"></param>
193 public void ChangeInventoryGroup(UUID groupID) 206 public void ChangeInventoryGroup(UUID groupID)
194 { 207 {
195 lock (Items) 208 m_items.LockItemsForWrite(true);
209 if (0 == Items.Count)
196 { 210 {
197 if (0 == Items.Count) 211 m_items.LockItemsForWrite(false);
198 { 212 return;
199 return;
200 }
201 } 213 }
202 214
203 // Don't let this set the HasGroupChanged flag for attachments 215 // Don't let this set the HasGroupChanged flag for attachments
@@ -209,12 +221,45 @@ namespace OpenSim.Region.Framework.Scenes
209 m_part.ParentGroup.HasGroupChanged = true; 221 m_part.ParentGroup.HasGroupChanged = true;
210 } 222 }
211 223
212 List<TaskInventoryItem> items = GetInventoryItems(); 224 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
213 foreach (TaskInventoryItem item in items) 225 foreach (TaskInventoryItem item in items)
214 { 226 {
215 if (groupID != item.GroupID) 227 if (groupID != item.GroupID)
228 {
216 item.GroupID = groupID; 229 item.GroupID = groupID;
230 }
231 }
232 m_items.LockItemsForWrite(false);
233 }
234
235 private void QueryScriptStates()
236 {
237 if (m_part == null || m_part.ParentGroup == null)
238 return;
239
240 IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>();
241 if (engines == null) // No engine at all
242 return;
243
244 Items.LockItemsForRead(true);
245 foreach (TaskInventoryItem item in Items.Values)
246 {
247 if (item.InvType == (int)InventoryType.LSL)
248 {
249 foreach (IScriptModule e in engines)
250 {
251 bool running;
252
253 if (e.HasScript(item.ItemID, out running))
254 {
255 item.ScriptRunning = running;
256 break;
257 }
258 }
259 }
217 } 260 }
261
262 Items.LockItemsForRead(false);
218 } 263 }
219 264
220 /// <summary> 265 /// <summary>
@@ -222,9 +267,14 @@ namespace OpenSim.Region.Framework.Scenes
222 /// </summary> 267 /// </summary>
223 public void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource) 268 public void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource)
224 { 269 {
225 List<TaskInventoryItem> scripts = GetInventoryScripts(); 270 Items.LockItemsForRead(true);
226 foreach (TaskInventoryItem item in scripts) 271 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
227 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource); 272 Items.LockItemsForRead(false);
273 foreach (TaskInventoryItem item in items)
274 {
275 if ((int)InventoryType.LSL == item.InvType)
276 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource);
277 }
228 } 278 }
229 279
230 public ArrayList GetScriptErrors(UUID itemID) 280 public ArrayList GetScriptErrors(UUID itemID)
@@ -255,9 +305,18 @@ namespace OpenSim.Region.Framework.Scenes
255 /// </param> 305 /// </param>
256 public void RemoveScriptInstances(bool sceneObjectBeingDeleted) 306 public void RemoveScriptInstances(bool sceneObjectBeingDeleted)
257 { 307 {
258 List<TaskInventoryItem> scripts = GetInventoryScripts(); 308 Items.LockItemsForRead(true);
259 foreach (TaskInventoryItem item in scripts) 309 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
260 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted); 310 Items.LockItemsForRead(false);
311
312 foreach (TaskInventoryItem item in items)
313 {
314 if ((int)InventoryType.LSL == item.InvType)
315 {
316 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted);
317 m_part.RemoveScriptEvents(item.ItemID);
318 }
319 }
261 } 320 }
262 321
263 /// <summary> 322 /// <summary>
@@ -273,7 +332,10 @@ namespace OpenSim.Region.Framework.Scenes
273 // item.Name, item.ItemID, Name, UUID); 332 // item.Name, item.ItemID, Name, UUID);
274 333
275 if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID)) 334 if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID))
335 {
336 StoreScriptError(item.ItemID, "no permission");
276 return; 337 return;
338 }
277 339
278 m_part.AddFlag(PrimFlags.Scripted); 340 m_part.AddFlag(PrimFlags.Scripted);
279 341
@@ -282,14 +344,13 @@ namespace OpenSim.Region.Framework.Scenes
282 if (stateSource == 2 && // Prim crossing 344 if (stateSource == 2 && // Prim crossing
283 m_part.ParentGroup.Scene.m_trustBinaries) 345 m_part.ParentGroup.Scene.m_trustBinaries)
284 { 346 {
285 lock (m_items) 347 m_items.LockItemsForWrite(true);
286 { 348 m_items[item.ItemID].PermsMask = 0;
287 m_items[item.ItemID].PermsMask = 0; 349 m_items[item.ItemID].PermsGranter = UUID.Zero;
288 m_items[item.ItemID].PermsGranter = UUID.Zero; 350 m_items.LockItemsForWrite(false);
289 }
290
291 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 351 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
292 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource); 352 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource);
353 StoreScriptErrors(item.ItemID, null);
293 m_part.ParentGroup.AddActiveScriptCount(1); 354 m_part.ParentGroup.AddActiveScriptCount(1);
294 m_part.ScheduleFullUpdate(); 355 m_part.ScheduleFullUpdate();
295 return; 356 return;
@@ -298,6 +359,8 @@ namespace OpenSim.Region.Framework.Scenes
298 AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString()); 359 AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString());
299 if (null == asset) 360 if (null == asset)
300 { 361 {
362 string msg = String.Format("asset ID {0} could not be found", item.AssetID);
363 StoreScriptError(item.ItemID, msg);
301 m_log.ErrorFormat( 364 m_log.ErrorFormat(
302 "[PRIM INVENTORY]: " + 365 "[PRIM INVENTORY]: " +
303 "Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found", 366 "Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found",
@@ -309,15 +372,20 @@ namespace OpenSim.Region.Framework.Scenes
309 if (m_part.ParentGroup.m_savedScriptState != null) 372 if (m_part.ParentGroup.m_savedScriptState != null)
310 RestoreSavedScriptState(item.OldItemID, item.ItemID); 373 RestoreSavedScriptState(item.OldItemID, item.ItemID);
311 374
312 lock (m_items) 375 m_items.LockItemsForWrite(true);
313 { 376
314 m_items[item.ItemID].PermsMask = 0; 377 m_items[item.ItemID].PermsMask = 0;
315 m_items[item.ItemID].PermsGranter = UUID.Zero; 378 m_items[item.ItemID].PermsGranter = UUID.Zero;
316 } 379
380 m_items.LockItemsForWrite(false);
317 381
318 string script = Utils.BytesToString(asset.Data); 382 string script = Utils.BytesToString(asset.Data);
319 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 383 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
320 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource); 384 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource);
385 StoreScriptErrors(item.ItemID, null);
386 if (!item.ScriptRunning)
387 m_part.ParentGroup.Scene.EventManager.TriggerStopScript(
388 m_part.LocalId, item.ItemID);
321 m_part.ParentGroup.AddActiveScriptCount(1); 389 m_part.ParentGroup.AddActiveScriptCount(1);
322 m_part.ScheduleFullUpdate(); 390 m_part.ScheduleFullUpdate();
323 } 391 }
@@ -383,21 +451,145 @@ namespace OpenSim.Region.Framework.Scenes
383 451
384 /// <summary> 452 /// <summary>
385 /// Start a script which is in this prim's inventory. 453 /// Start a script which is in this prim's inventory.
454 /// Some processing may occur in the background, but this routine returns asap.
386 /// </summary> 455 /// </summary>
387 /// <param name="itemId"> 456 /// <param name="itemId">
388 /// A <see cref="UUID"/> 457 /// A <see cref="UUID"/>
389 /// </param> 458 /// </param>
390 public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource) 459 public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
391 { 460 {
392 TaskInventoryItem item = GetInventoryItem(itemId); 461 lock (m_scriptErrors)
393 if (item != null) 462 {
394 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource); 463 // Indicate to CreateScriptInstanceInternal() we don't want it to wait for completion
464 m_scriptErrors.Remove(itemId);
465 }
466 CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
467 }
468
469 private void CreateScriptInstanceInternal(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
470 {
471 m_items.LockItemsForRead(true);
472 if (m_items.ContainsKey(itemId))
473 {
474 if (m_items.ContainsKey(itemId))
475 {
476 m_items.LockItemsForRead(false);
477 CreateScriptInstance(m_items[itemId], startParam, postOnRez, engine, stateSource);
478 }
479 else
480 {
481 m_items.LockItemsForRead(false);
482 string msg = String.Format("couldn't be found for prim {0}, {1} at {2} in {3}", m_part.Name, m_part.UUID,
483 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
484 StoreScriptError(itemId, msg);
485 m_log.ErrorFormat(
486 "[PRIM INVENTORY]: " +
487 "Couldn't start script with ID {0} since it {1}", itemId, msg);
488 }
489 }
395 else 490 else
491 {
492 m_items.LockItemsForRead(false);
493 string msg = String.Format("couldn't be found for prim {0}, {1}", m_part.Name, m_part.UUID);
494 StoreScriptError(itemId, msg);
396 m_log.ErrorFormat( 495 m_log.ErrorFormat(
397 "[PRIM INVENTORY]: " + 496 "[PRIM INVENTORY]: " +
398 "Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}", 497 "Couldn't start script with ID {0} since it {1}", itemId, msg);
399 itemId, m_part.Name, m_part.UUID, 498 }
400 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 499
500 }
501
502 /// <summary>
503 /// Start a script which is in this prim's inventory and return any compilation error messages.
504 /// </summary>
505 /// <param name="itemId">
506 /// A <see cref="UUID"/>
507 /// </param>
508 public ArrayList CreateScriptInstanceEr(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
509 {
510 ArrayList errors;
511
512 // Indicate to CreateScriptInstanceInternal() we want it to
513 // post any compilation/loading error messages
514 lock (m_scriptErrors)
515 {
516 m_scriptErrors[itemId] = null;
517 }
518
519 // Perform compilation/loading
520 CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
521
522 // Wait for and retrieve any errors
523 lock (m_scriptErrors)
524 {
525 while ((errors = m_scriptErrors[itemId]) == null)
526 {
527 if (!System.Threading.Monitor.Wait(m_scriptErrors, 15000))
528 {
529 m_log.ErrorFormat(
530 "[PRIM INVENTORY]: " +
531 "timedout waiting for script {0} errors", itemId);
532 errors = m_scriptErrors[itemId];
533 if (errors == null)
534 {
535 errors = new ArrayList(1);
536 errors.Add("timedout waiting for errors");
537 }
538 break;
539 }
540 }
541 m_scriptErrors.Remove(itemId);
542 }
543 return errors;
544 }
545
546 // Signal to CreateScriptInstanceEr() that compilation/loading is complete
547 private void StoreScriptErrors(UUID itemId, ArrayList errors)
548 {
549 lock (m_scriptErrors)
550 {
551 // If compilation/loading initiated via CreateScriptInstance(),
552 // it does not want the errors, so just get out
553 if (!m_scriptErrors.ContainsKey(itemId))
554 {
555 return;
556 }
557
558 // Initiated via CreateScriptInstanceEr(), if we know what the
559 // errors are, save them and wake CreateScriptInstanceEr().
560 if (errors != null)
561 {
562 m_scriptErrors[itemId] = errors;
563 System.Threading.Monitor.PulseAll(m_scriptErrors);
564 return;
565 }
566 }
567
568 // Initiated via CreateScriptInstanceEr() but we don't know what
569 // the errors are yet, so retrieve them from the script engine.
570 // This may involve some waiting internal to GetScriptErrors().
571 errors = GetScriptErrors(itemId);
572
573 // Get a default non-null value to indicate success.
574 if (errors == null)
575 {
576 errors = new ArrayList();
577 }
578
579 // Post to CreateScriptInstanceEr() and wake it up
580 lock (m_scriptErrors)
581 {
582 m_scriptErrors[itemId] = errors;
583 System.Threading.Monitor.PulseAll(m_scriptErrors);
584 }
585 }
586
587 // Like StoreScriptErrors(), but just posts a single string message
588 private void StoreScriptError(UUID itemId, string message)
589 {
590 ArrayList errors = new ArrayList(1);
591 errors.Add(message);
592 StoreScriptErrors(itemId, errors);
401 } 593 }
402 594
403 /// <summary> 595 /// <summary>
@@ -410,15 +602,7 @@ namespace OpenSim.Region.Framework.Scenes
410 /// </param> 602 /// </param>
411 public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted) 603 public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted)
412 { 604 {
413 bool scriptPresent = false; 605 if (m_items.ContainsKey(itemId))
414
415 lock (m_items)
416 {
417 if (m_items.ContainsKey(itemId))
418 scriptPresent = true;
419 }
420
421 if (scriptPresent)
422 { 606 {
423 if (!sceneObjectBeingDeleted) 607 if (!sceneObjectBeingDeleted)
424 m_part.RemoveScriptEvents(itemId); 608 m_part.RemoveScriptEvents(itemId);
@@ -443,14 +627,16 @@ namespace OpenSim.Region.Framework.Scenes
443 /// <returns></returns> 627 /// <returns></returns>
444 private bool InventoryContainsName(string name) 628 private bool InventoryContainsName(string name)
445 { 629 {
446 lock (m_items) 630 m_items.LockItemsForRead(true);
631 foreach (TaskInventoryItem item in m_items.Values)
447 { 632 {
448 foreach (TaskInventoryItem item in m_items.Values) 633 if (item.Name == name)
449 { 634 {
450 if (item.Name == name) 635 m_items.LockItemsForRead(false);
451 return true; 636 return true;
452 } 637 }
453 } 638 }
639 m_items.LockItemsForRead(false);
454 return false; 640 return false;
455 } 641 }
456 642
@@ -492,8 +678,9 @@ namespace OpenSim.Region.Framework.Scenes
492 /// <param name="item"></param> 678 /// <param name="item"></param>
493 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop) 679 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop)
494 { 680 {
495 List<TaskInventoryItem> il = GetInventoryItems(); 681 m_items.LockItemsForRead(true);
496 682 List<TaskInventoryItem> il = new List<TaskInventoryItem>(m_items.Values);
683 m_items.LockItemsForRead(false);
497 foreach (TaskInventoryItem i in il) 684 foreach (TaskInventoryItem i in il)
498 { 685 {
499 if (i.Name == item.Name) 686 if (i.Name == item.Name)
@@ -531,14 +718,14 @@ namespace OpenSim.Region.Framework.Scenes
531 item.Name = name; 718 item.Name = name;
532 item.GroupID = m_part.GroupID; 719 item.GroupID = m_part.GroupID;
533 720
534 lock (m_items) 721 m_items.LockItemsForWrite(true);
535 m_items.Add(item.ItemID, item); 722 m_items.Add(item.ItemID, item);
536 723 m_items.LockItemsForWrite(false);
537 if (allowedDrop) 724 if (allowedDrop)
538 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP); 725 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP);
539 else 726 else
540 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 727 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
541 728
542 m_inventorySerial++; 729 m_inventorySerial++;
543 //m_inventorySerial += 2; 730 //m_inventorySerial += 2;
544 HasInventoryChanged = true; 731 HasInventoryChanged = true;
@@ -554,15 +741,15 @@ namespace OpenSim.Region.Framework.Scenes
554 /// <param name="items"></param> 741 /// <param name="items"></param>
555 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items) 742 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items)
556 { 743 {
557 lock (m_items) 744 m_items.LockItemsForWrite(true);
745 foreach (TaskInventoryItem item in items)
558 { 746 {
559 foreach (TaskInventoryItem item in items) 747 m_items.Add(item.ItemID, item);
560 { 748// m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
561 m_items.Add(item.ItemID, item);
562// m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
563 }
564 m_inventorySerial++;
565 } 749 }
750 m_items.LockItemsForWrite(false);
751
752 m_inventorySerial++;
566 } 753 }
567 754
568 /// <summary> 755 /// <summary>
@@ -573,10 +760,9 @@ namespace OpenSim.Region.Framework.Scenes
573 public TaskInventoryItem GetInventoryItem(UUID itemId) 760 public TaskInventoryItem GetInventoryItem(UUID itemId)
574 { 761 {
575 TaskInventoryItem item; 762 TaskInventoryItem item;
576 763 m_items.LockItemsForRead(true);
577 lock (m_items) 764 m_items.TryGetValue(itemId, out item);
578 m_items.TryGetValue(itemId, out item); 765 m_items.LockItemsForRead(false);
579
580 return item; 766 return item;
581 } 767 }
582 768
@@ -592,15 +778,16 @@ namespace OpenSim.Region.Framework.Scenes
592 { 778 {
593 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(); 779 IList<TaskInventoryItem> items = new List<TaskInventoryItem>();
594 780
595 lock (m_items) 781 m_items.LockItemsForRead(true);
782
783 foreach (TaskInventoryItem item in m_items.Values)
596 { 784 {
597 foreach (TaskInventoryItem item in m_items.Values) 785 if (item.Name == name)
598 { 786 items.Add(item);
599 if (item.Name == name)
600 items.Add(item);
601 }
602 } 787 }
603 788
789 m_items.LockItemsForRead(false);
790
604 return items; 791 return items;
605 } 792 }
606 793
@@ -619,6 +806,9 @@ namespace OpenSim.Region.Framework.Scenes
619 string xmlData = Utils.BytesToString(rezAsset.Data); 806 string xmlData = Utils.BytesToString(rezAsset.Data);
620 SceneObjectGroup group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); 807 SceneObjectGroup group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
621 808
809 group.RootPart.AttachPoint = group.RootPart.Shape.State;
810 group.RootPart.AttachOffset = group.AbsolutePosition;
811
622 group.ResetIDs(); 812 group.ResetIDs();
623 813
624 SceneObjectPart rootPart = group.GetChildPart(group.UUID); 814 SceneObjectPart rootPart = group.GetChildPart(group.UUID);
@@ -693,8 +883,9 @@ namespace OpenSim.Region.Framework.Scenes
693 883
694 public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged) 884 public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged)
695 { 885 {
696 TaskInventoryItem it = GetInventoryItem(item.ItemID); 886 m_items.LockItemsForWrite(true);
697 if (it != null) 887
888 if (m_items.ContainsKey(item.ItemID))
698 { 889 {
699// m_log.DebugFormat("[PRIM INVENTORY]: Updating item {0} in {1}", item.Name, m_part.Name); 890// m_log.DebugFormat("[PRIM INVENTORY]: Updating item {0} in {1}", item.Name, m_part.Name);
700 891
@@ -707,14 +898,10 @@ namespace OpenSim.Region.Framework.Scenes
707 item.GroupID = m_part.GroupID; 898 item.GroupID = m_part.GroupID;
708 899
709 if (item.AssetID == UUID.Zero) 900 if (item.AssetID == UUID.Zero)
710 item.AssetID = it.AssetID; 901 item.AssetID = m_items[item.ItemID].AssetID;
711 902
712 lock (m_items) 903 m_items[item.ItemID] = item;
713 { 904 m_inventorySerial++;
714 m_items[item.ItemID] = item;
715 m_inventorySerial++;
716 }
717
718 if (fireScriptEvents) 905 if (fireScriptEvents)
719 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 906 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
720 907
@@ -723,7 +910,7 @@ namespace OpenSim.Region.Framework.Scenes
723 HasInventoryChanged = true; 910 HasInventoryChanged = true;
724 m_part.ParentGroup.HasGroupChanged = true; 911 m_part.ParentGroup.HasGroupChanged = true;
725 } 912 }
726 913 m_items.LockItemsForWrite(false);
727 return true; 914 return true;
728 } 915 }
729 else 916 else
@@ -734,8 +921,9 @@ namespace OpenSim.Region.Framework.Scenes
734 item.ItemID, m_part.Name, m_part.UUID, 921 item.ItemID, m_part.Name, m_part.UUID,
735 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 922 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
736 } 923 }
737 return false; 924 m_items.LockItemsForWrite(false);
738 925
926 return false;
739 } 927 }
740 928
741 /// <summary> 929 /// <summary>
@@ -746,43 +934,59 @@ namespace OpenSim.Region.Framework.Scenes
746 /// in this prim's inventory.</returns> 934 /// in this prim's inventory.</returns>
747 public int RemoveInventoryItem(UUID itemID) 935 public int RemoveInventoryItem(UUID itemID)
748 { 936 {
749 TaskInventoryItem item = GetInventoryItem(itemID); 937 m_items.LockItemsForRead(true);
750 if (item != null) 938
939 if (m_items.ContainsKey(itemID))
751 { 940 {
752 int type = m_items[itemID].InvType; 941 int type = m_items[itemID].InvType;
942 m_items.LockItemsForRead(false);
753 if (type == 10) // Script 943 if (type == 10) // Script
754 { 944 {
755 m_part.RemoveScriptEvents(itemID);
756 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID); 945 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID);
757 } 946 }
947 m_items.LockItemsForWrite(true);
758 m_items.Remove(itemID); 948 m_items.Remove(itemID);
949 m_items.LockItemsForWrite(false);
759 m_inventorySerial++; 950 m_inventorySerial++;
760 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 951 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
761 952
762 HasInventoryChanged = true; 953 HasInventoryChanged = true;
763 m_part.ParentGroup.HasGroupChanged = true; 954 m_part.ParentGroup.HasGroupChanged = true;
764 955
765 if (!ContainsScripts()) 956 int scriptcount = 0;
957 m_items.LockItemsForRead(true);
958 foreach (TaskInventoryItem item in m_items.Values)
959 {
960 if (item.Type == 10)
961 {
962 scriptcount++;
963 }
964 }
965 m_items.LockItemsForRead(false);
966
967
968 if (scriptcount <= 0)
969 {
766 m_part.RemFlag(PrimFlags.Scripted); 970 m_part.RemFlag(PrimFlags.Scripted);
971 }
767 972
768 m_part.ScheduleFullUpdate(); 973 m_part.ScheduleFullUpdate();
769 974
770 return type; 975 return type;
771
772 } 976 }
773 else 977 else
774 { 978 {
979 m_items.LockItemsForRead(false);
775 m_log.ErrorFormat( 980 m_log.ErrorFormat(
776 "[PRIM INVENTORY]: " + 981 "[PRIM INVENTORY]: " +
777 "Tried to remove item ID {0} from prim {1}, {2} at {3} in {4} but the item does not exist in this inventory", 982 "Tried to remove item ID {0} from prim {1}, {2} but the item does not exist in this inventory",
778 itemID, m_part.Name, m_part.UUID, 983 itemID, m_part.Name, m_part.UUID);
779 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
780 } 984 }
781 985
782 return -1; 986 return -1;
783 } 987 }
784 988
785 private bool CreateInventoryFile() 989 private bool CreateInventoryFileName()
786 { 990 {
787// m_log.DebugFormat( 991// m_log.DebugFormat(
788// "[PRIM INVENTORY]: Creating inventory file for {0} {1} {2}, serial {3}", 992// "[PRIM INVENTORY]: Creating inventory file for {0} {1} {2}, serial {3}",
@@ -791,116 +995,125 @@ namespace OpenSim.Region.Framework.Scenes
791 if (m_inventoryFileName == String.Empty || 995 if (m_inventoryFileName == String.Empty ||
792 m_inventoryFileNameSerial < m_inventorySerial) 996 m_inventoryFileNameSerial < m_inventorySerial)
793 { 997 {
794 // Something changed, we need to create a new file
795 m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp"; 998 m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp";
796 m_inventoryFileNameSerial = m_inventorySerial; 999 m_inventoryFileNameSerial = m_inventorySerial;
797 1000
798 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero); 1001 return true;
1002 }
1003
1004 return false;
1005 }
1006
1007 /// <summary>
1008 /// Serialize all the metadata for the items in this prim's inventory ready for sending to the client
1009 /// </summary>
1010 /// <param name="xferManager"></param>
1011 public void RequestInventoryFile(IClientAPI client, IXfer xferManager)
1012 {
1013 bool changed = CreateInventoryFileName();
1014
1015 bool includeAssets = false;
1016 if (m_part.ParentGroup.Scene.Permissions.CanEditObjectInventory(m_part.UUID, client.AgentId))
1017 includeAssets = true;
1018
1019 if (m_inventoryPrivileged != includeAssets)
1020 changed = true;
1021
1022 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero);
1023
1024 Items.LockItemsForRead(true);
1025
1026 if (m_inventorySerial == 0) // No inventory
1027 {
1028 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
1029 Items.LockItemsForRead(false);
1030 return;
1031 }
799 1032
800 lock (m_items) 1033 if (m_items.Count == 0) // No inventory
1034 {
1035 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
1036 Items.LockItemsForRead(false);
1037 return;
1038 }
1039
1040 if (!changed)
1041 {
1042 if (m_inventoryFileData.Length > 2)
801 { 1043 {
802 foreach (TaskInventoryItem item in m_items.Values) 1044 xferManager.AddNewFile(m_inventoryFileName,
803 { 1045 m_inventoryFileData);
804// m_log.DebugFormat( 1046 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
805// "[PRIM INVENTORY]: Adding item {0} {1} for serial {2} on prim {3} {4} {5}", 1047 Util.StringToBytes256(m_inventoryFileName));
806// item.Name, item.ItemID, m_inventorySerial, m_part.Name, m_part.UUID, m_part.LocalId);
807 1048
808 UUID ownerID = item.OwnerID; 1049 Items.LockItemsForRead(false);
809 uint everyoneMask = 0; 1050 return;
810 uint baseMask = item.BasePermissions; 1051 }
811 uint ownerMask = item.CurrentPermissions; 1052 }
812 uint groupMask = item.GroupPermissions;
813 1053
814 invString.AddItemStart(); 1054 m_inventoryPrivileged = includeAssets;
815 invString.AddNameValueLine("item_id", item.ItemID.ToString());
816 invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
817 1055
818 invString.AddPermissionsStart(); 1056 foreach (TaskInventoryItem item in m_items.Values)
1057 {
1058 UUID ownerID = item.OwnerID;
1059 uint everyoneMask = 0;
1060 uint baseMask = item.BasePermissions;
1061 uint ownerMask = item.CurrentPermissions;
1062 uint groupMask = item.GroupPermissions;
819 1063
820 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask)); 1064 invString.AddItemStart();
821 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask)); 1065 invString.AddNameValueLine("item_id", item.ItemID.ToString());
822 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask)); 1066 invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
823 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask));
824 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
825 1067
826 invString.AddNameValueLine("creator_id", item.CreatorID.ToString()); 1068 invString.AddPermissionsStart();
827 invString.AddNameValueLine("owner_id", ownerID.ToString());
828 1069
829 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString()); 1070 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask));
1071 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask));
1072 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask));
1073 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask));
1074 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
830 1075
831 invString.AddNameValueLine("group_id", item.GroupID.ToString()); 1076 invString.AddNameValueLine("creator_id", item.CreatorID.ToString());
832 invString.AddSectionEnd(); 1077 invString.AddNameValueLine("owner_id", ownerID.ToString());
833 1078
834 invString.AddNameValueLine("asset_id", item.AssetID.ToString()); 1079 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString());
835 invString.AddNameValueLine("type", Utils.AssetTypeToString((AssetType)item.Type));
836 invString.AddNameValueLine("inv_type", Utils.InventoryTypeToString((InventoryType)item.InvType));
837 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags));
838 1080
839 invString.AddSaleStart(); 1081 invString.AddNameValueLine("group_id", item.GroupID.ToString());
840 invString.AddNameValueLine("sale_type", "not"); 1082 invString.AddSectionEnd();
841 invString.AddNameValueLine("sale_price", "0");
842 invString.AddSectionEnd();
843 1083
844 invString.AddNameValueLine("name", item.Name + "|"); 1084 if (includeAssets)
845 invString.AddNameValueLine("desc", item.Description + "|"); 1085 invString.AddNameValueLine("asset_id", item.AssetID.ToString());
1086 else
1087 invString.AddNameValueLine("asset_id", UUID.Zero.ToString());
1088 invString.AddNameValueLine("type", Utils.AssetTypeToString((AssetType)item.Type));
1089 invString.AddNameValueLine("inv_type", Utils.InventoryTypeToString((InventoryType)item.InvType));
1090 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags));
846 1091
847 invString.AddNameValueLine("creation_date", item.CreationDate.ToString()); 1092 invString.AddSaleStart();
848 invString.AddSectionEnd(); 1093 invString.AddNameValueLine("sale_type", "not");
849 } 1094 invString.AddNameValueLine("sale_price", "0");
850 } 1095 invString.AddSectionEnd();
851 1096
852 m_inventoryFileData = Utils.StringToBytes(invString.BuildString); 1097 invString.AddNameValueLine("name", item.Name + "|");
1098 invString.AddNameValueLine("desc", item.Description + "|");
853 1099
854 return true; 1100 invString.AddNameValueLine("creation_date", item.CreationDate.ToString());
1101 invString.AddSectionEnd();
855 } 1102 }
856 1103
857 // No need to recreate, the existing file is fine 1104 Items.LockItemsForRead(false);
858 return false;
859 }
860 1105
861 /// <summary> 1106 m_inventoryFileData = Utils.StringToBytes(invString.BuildString);
862 /// Serialize all the metadata for the items in this prim's inventory ready for sending to the client
863 /// </summary>
864 /// <param name="xferManager"></param>
865 public void RequestInventoryFile(IClientAPI client, IXfer xferManager)
866 {
867 lock (m_items)
868 {
869 // Don't send a inventory xfer name if there are no items. Doing so causes viewer 3 to crash when rezzing
870 // a new script if any previous deletion has left the prim inventory empty.
871 if (m_items.Count == 0) // No inventory
872 {
873// m_log.DebugFormat(
874// "[PRIM INVENTORY]: Not sending inventory data for part {0} {1} {2} for {3} since no items",
875// m_part.Name, m_part.LocalId, m_part.UUID, client.Name);
876 1107
877 client.SendTaskInventory(m_part.UUID, 0, new byte[0]); 1108 if (m_inventoryFileData.Length > 2)
878 return; 1109 {
879 } 1110 xferManager.AddNewFile(m_inventoryFileName, m_inventoryFileData);
880 1111 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
881 CreateInventoryFile(); 1112 Util.StringToBytes256(m_inventoryFileName));
882 1113 return;
883 // In principle, we should only do the rest if the inventory changed;
884 // by sending m_inventorySerial to the client, it ought to know
885 // that nothing changed and that it doesn't need to request the file.
886 // Unfortunately, it doesn't look like the client optimizes this;
887 // the client seems to always come back and request the Xfer,
888 // no matter what value m_inventorySerial has.
889 // FIXME: Could probably be > 0 here rather than > 2
890 if (m_inventoryFileData.Length > 2)
891 {
892 // Add the file for Xfer
893 // m_log.DebugFormat(
894 // "[PRIM INVENTORY]: Adding inventory file {0} (length {1}) for transfer on {2} {3} {4}",
895 // m_inventoryFileName, m_inventoryFileData.Length, m_part.Name, m_part.UUID, m_part.LocalId);
896
897 xferManager.AddNewFile(m_inventoryFileName, m_inventoryFileData);
898 }
899
900 // Tell the client we're ready to Xfer the file
901 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
902 Util.StringToBytes256(m_inventoryFileName));
903 } 1114 }
1115
1116 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
904 } 1117 }
905 1118
906 /// <summary> 1119 /// <summary>
@@ -909,13 +1122,19 @@ namespace OpenSim.Region.Framework.Scenes
909 /// <param name="datastore"></param> 1122 /// <param name="datastore"></param>
910 public void ProcessInventoryBackup(ISimulationDataService datastore) 1123 public void ProcessInventoryBackup(ISimulationDataService datastore)
911 { 1124 {
912 if (HasInventoryChanged) 1125// Removed this because linking will cause an immediate delete of the new
913 { 1126// child prim from the database and the subsequent storing of the prim sees
914 HasInventoryChanged = false; 1127// the inventory of it as unchanged and doesn't store it at all. The overhead
915 List<TaskInventoryItem> items = GetInventoryItems(); 1128// of storing prim inventory needlessly is much less than the aggravation
916 datastore.StorePrimInventory(m_part.UUID, items); 1129// of prim inventory loss.
1130// if (HasInventoryChanged)
1131// {
1132 Items.LockItemsForRead(true);
1133 datastore.StorePrimInventory(m_part.UUID, Items.Values);
1134 Items.LockItemsForRead(false);
917 1135
918 } 1136 HasInventoryChanged = false;
1137// }
919 } 1138 }
920 1139
921 public class InventoryStringBuilder 1140 public class InventoryStringBuilder
@@ -981,82 +1200,63 @@ namespace OpenSim.Region.Framework.Scenes
981 { 1200 {
982 uint mask=0x7fffffff; 1201 uint mask=0x7fffffff;
983 1202
984 lock (m_items) 1203 foreach (TaskInventoryItem item in m_items.Values)
985 { 1204 {
986 foreach (TaskInventoryItem item in m_items.Values) 1205 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0)
1206 mask &= ~((uint)PermissionMask.Copy >> 13);
1207 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0)
1208 mask &= ~((uint)PermissionMask.Transfer >> 13);
1209 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0)
1210 mask &= ~((uint)PermissionMask.Modify >> 13);
1211
1212 if (item.InvType == (int)InventoryType.Object)
987 { 1213 {
988 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0) 1214 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
989 mask &= ~((uint)PermissionMask.Copy >> 13); 1215 mask &= ~((uint)PermissionMask.Copy >> 13);
990 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0) 1216 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
991 mask &= ~((uint)PermissionMask.Transfer >> 13); 1217 mask &= ~((uint)PermissionMask.Transfer >> 13);
992 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0) 1218 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
993 mask &= ~((uint)PermissionMask.Modify >> 13); 1219 mask &= ~((uint)PermissionMask.Modify >> 13);
994
995 if (item.InvType != (int)InventoryType.Object)
996 {
997 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0)
998 mask &= ~((uint)PermissionMask.Copy >> 13);
999 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0)
1000 mask &= ~((uint)PermissionMask.Transfer >> 13);
1001 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0)
1002 mask &= ~((uint)PermissionMask.Modify >> 13);
1003 }
1004 else
1005 {
1006 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
1007 mask &= ~((uint)PermissionMask.Copy >> 13);
1008 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
1009 mask &= ~((uint)PermissionMask.Transfer >> 13);
1010 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1011 mask &= ~((uint)PermissionMask.Modify >> 13);
1012 }
1013
1014 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
1015 mask &= ~(uint)PermissionMask.Copy;
1016 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
1017 mask &= ~(uint)PermissionMask.Transfer;
1018 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
1019 mask &= ~(uint)PermissionMask.Modify;
1020 } 1220 }
1221
1222 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
1223 mask &= ~(uint)PermissionMask.Copy;
1224 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
1225 mask &= ~(uint)PermissionMask.Transfer;
1226 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
1227 mask &= ~(uint)PermissionMask.Modify;
1021 } 1228 }
1022
1023 return mask; 1229 return mask;
1024 } 1230 }
1025 1231
1026 public void ApplyNextOwnerPermissions() 1232 public void ApplyNextOwnerPermissions()
1027 { 1233 {
1028 lock (m_items) 1234 foreach (TaskInventoryItem item in m_items.Values)
1029 { 1235 {
1030 foreach (TaskInventoryItem item in m_items.Values) 1236 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0)
1031 { 1237 {
1032 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0) 1238 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
1033 { 1239 item.CurrentPermissions &= ~(uint)PermissionMask.Copy;
1034 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0) 1240 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
1035 item.CurrentPermissions &= ~(uint)PermissionMask.Copy; 1241 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer;
1036 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0) 1242 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1037 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer; 1243 item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
1038 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1039 item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
1040 }
1041 item.CurrentPermissions &= item.NextPermissions;
1042 item.BasePermissions &= item.NextPermissions;
1043 item.EveryonePermissions &= item.NextPermissions;
1044 item.OwnerChanged = true;
1045 item.PermsMask = 0;
1046 item.PermsGranter = UUID.Zero;
1047 } 1244 }
1245 item.OwnerChanged = true;
1246 item.CurrentPermissions &= item.NextPermissions;
1247 item.BasePermissions &= item.NextPermissions;
1248 item.EveryonePermissions &= item.NextPermissions;
1249 item.PermsMask = 0;
1250 item.PermsGranter = UUID.Zero;
1048 } 1251 }
1049 } 1252 }
1050 1253
1051 public void ApplyGodPermissions(uint perms) 1254 public void ApplyGodPermissions(uint perms)
1052 { 1255 {
1053 lock (m_items) 1256 foreach (TaskInventoryItem item in m_items.Values)
1054 { 1257 {
1055 foreach (TaskInventoryItem item in m_items.Values) 1258 item.CurrentPermissions = perms;
1056 { 1259 item.BasePermissions = perms;
1057 item.CurrentPermissions = perms;
1058 item.BasePermissions = perms;
1059 }
1060 } 1260 }
1061 1261
1062 m_inventorySerial++; 1262 m_inventorySerial++;
@@ -1069,17 +1269,13 @@ namespace OpenSim.Region.Framework.Scenes
1069 /// <returns></returns> 1269 /// <returns></returns>
1070 public bool ContainsScripts() 1270 public bool ContainsScripts()
1071 { 1271 {
1072 lock (m_items) 1272 foreach (TaskInventoryItem item in m_items.Values)
1073 { 1273 {
1074 foreach (TaskInventoryItem item in m_items.Values) 1274 if (item.InvType == (int)InventoryType.LSL)
1075 { 1275 {
1076 if (item.InvType == (int)InventoryType.LSL) 1276 return true;
1077 {
1078 return true;
1079 }
1080 } 1277 }
1081 } 1278 }
1082
1083 return false; 1279 return false;
1084 } 1280 }
1085 1281
@@ -1087,11 +1283,8 @@ namespace OpenSim.Region.Framework.Scenes
1087 { 1283 {
1088 List<UUID> ret = new List<UUID>(); 1284 List<UUID> ret = new List<UUID>();
1089 1285
1090 lock (m_items) 1286 foreach (TaskInventoryItem item in m_items.Values)
1091 { 1287 ret.Add(item.ItemID);
1092 foreach (TaskInventoryItem item in m_items.Values)
1093 ret.Add(item.ItemID);
1094 }
1095 1288
1096 return ret; 1289 return ret;
1097 } 1290 }
@@ -1122,6 +1315,11 @@ namespace OpenSim.Region.Framework.Scenes
1122 1315
1123 public Dictionary<UUID, string> GetScriptStates() 1316 public Dictionary<UUID, string> GetScriptStates()
1124 { 1317 {
1318 return GetScriptStates(false);
1319 }
1320
1321 public Dictionary<UUID, string> GetScriptStates(bool oldIDs)
1322 {
1125 Dictionary<UUID, string> ret = new Dictionary<UUID, string>(); 1323 Dictionary<UUID, string> ret = new Dictionary<UUID, string>();
1126 1324
1127 if (m_part.ParentGroup.Scene == null) // Group not in a scene 1325 if (m_part.ParentGroup.Scene == null) // Group not in a scene
@@ -1132,25 +1330,35 @@ namespace OpenSim.Region.Framework.Scenes
1132 if (engines.Length == 0) // No engine at all 1330 if (engines.Length == 0) // No engine at all
1133 return ret; 1331 return ret;
1134 1332
1135 List<TaskInventoryItem> scripts = GetInventoryScripts(); 1333 Items.LockItemsForRead(true);
1136 1334 foreach (TaskInventoryItem item in m_items.Values)
1137 foreach (TaskInventoryItem item in scripts)
1138 { 1335 {
1139 foreach (IScriptModule e in engines) 1336 if (item.InvType == (int)InventoryType.LSL)
1140 { 1337 {
1141 if (e != null) 1338 foreach (IScriptModule e in engines)
1142 { 1339 {
1143 string n = e.GetXMLState(item.ItemID); 1340 if (e != null)
1144 if (n != String.Empty)
1145 { 1341 {
1146 if (!ret.ContainsKey(item.ItemID)) 1342 string n = e.GetXMLState(item.ItemID);
1147 ret[item.ItemID] = n; 1343 if (n != String.Empty)
1148 break; 1344 {
1345 if (oldIDs)
1346 {
1347 if (!ret.ContainsKey(item.OldItemID))
1348 ret[item.OldItemID] = n;
1349 }
1350 else
1351 {
1352 if (!ret.ContainsKey(item.ItemID))
1353 ret[item.ItemID] = n;
1354 }
1355 break;
1356 }
1149 } 1357 }
1150 } 1358 }
1151 } 1359 }
1152 } 1360 }
1153 1361 Items.LockItemsForRead(false);
1154 return ret; 1362 return ret;
1155 } 1363 }
1156 1364
@@ -1160,21 +1368,27 @@ namespace OpenSim.Region.Framework.Scenes
1160 if (engines.Length == 0) 1368 if (engines.Length == 0)
1161 return; 1369 return;
1162 1370
1163 List<TaskInventoryItem> scripts = GetInventoryScripts();
1164 1371
1165 foreach (TaskInventoryItem item in scripts) 1372 Items.LockItemsForRead(true);
1373
1374 foreach (TaskInventoryItem item in m_items.Values)
1166 { 1375 {
1167 foreach (IScriptModule engine in engines) 1376 if (item.InvType == (int)InventoryType.LSL)
1168 { 1377 {
1169 if (engine != null) 1378 foreach (IScriptModule engine in engines)
1170 { 1379 {
1171 if (item.OwnerChanged) 1380 if (engine != null)
1172 engine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.OWNER }); 1381 {
1173 item.OwnerChanged = false; 1382 if (item.OwnerChanged)
1174 engine.ResumeScript(item.ItemID); 1383 engine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.OWNER });
1384 item.OwnerChanged = false;
1385 engine.ResumeScript(item.ItemID);
1386 }
1175 } 1387 }
1176 } 1388 }
1177 } 1389 }
1390
1391 Items.LockItemsForRead(false);
1178 } 1392 }
1179 } 1393 }
1180} 1394}
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 8a49f2c..635bca7 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -167,6 +167,7 @@ namespace OpenSim.Region.Framework.Scenes
167// private int m_lastColCount = -1; //KF: Look for Collision chnages 167// private int m_lastColCount = -1; //KF: Look for Collision chnages
168// private int m_updateCount = 0; //KF: Update Anims for a while 168// private int m_updateCount = 0; //KF: Update Anims for a while
169// private static readonly int UPDATE_COUNT = 10; // how many frames to update for 169// private static readonly int UPDATE_COUNT = 10; // how many frames to update for
170 private List<uint> m_lastColliders = new List<uint>();
170 171
171 private TeleportFlags m_teleportFlags; 172 private TeleportFlags m_teleportFlags;
172 public TeleportFlags TeleportFlags 173 public TeleportFlags TeleportFlags
@@ -228,6 +229,9 @@ namespace OpenSim.Region.Framework.Scenes
228 //private int m_moveToPositionStateStatus; 229 //private int m_moveToPositionStateStatus;
229 //***************************************************** 230 //*****************************************************
230 231
232 private bool m_collisionEventFlag = false;
233 private object m_collisionEventLock = new Object();
234
231 protected AvatarAppearance m_appearance; 235 protected AvatarAppearance m_appearance;
232 236
233 public AvatarAppearance Appearance 237 public AvatarAppearance Appearance
@@ -1836,6 +1840,7 @@ namespace OpenSim.Region.Framework.Scenes
1836 if (part.SitTargetAvatar == UUID) 1840 if (part.SitTargetAvatar == UUID)
1837 part.SitTargetAvatar = UUID.Zero; 1841 part.SitTargetAvatar = UUID.Zero;
1838 1842
1843 part.ParentGroup.DeleteAvatar(UUID);
1839 ParentPosition = part.GetWorldPosition(); 1844 ParentPosition = part.GetWorldPosition();
1840 ControllingClient.SendClearFollowCamProperties(part.ParentUUID); 1845 ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
1841 } 1846 }
@@ -1974,7 +1979,7 @@ namespace OpenSim.Region.Framework.Scenes
1974 forceMouselook = part.GetForceMouselook(); 1979 forceMouselook = part.GetForceMouselook();
1975 1980
1976 ControllingClient.SendSitResponse( 1981 ControllingClient.SendSitResponse(
1977 targetID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook); 1982 part.UUID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook);
1978 1983
1979 m_requestedSitTargetUUID = targetID; 1984 m_requestedSitTargetUUID = targetID;
1980 1985
@@ -2259,11 +2264,13 @@ namespace OpenSim.Region.Framework.Scenes
2259 m_pos = sitTargetPos + SIT_TARGET_ADJUSTMENT; 2264 m_pos = sitTargetPos + SIT_TARGET_ADJUSTMENT;
2260 Rotation = sitTargetOrient; 2265 Rotation = sitTargetOrient;
2261 ParentPosition = part.AbsolutePosition; 2266 ParentPosition = part.AbsolutePosition;
2267 part.ParentGroup.AddAvatar(UUID);
2262 } 2268 }
2263 else 2269 else
2264 { 2270 {
2265 m_pos -= part.AbsolutePosition; 2271 m_pos -= part.AbsolutePosition;
2266 ParentPosition = part.AbsolutePosition; 2272 ParentPosition = part.AbsolutePosition;
2273 part.ParentGroup.AddAvatar(UUID);
2267 2274
2268// m_log.DebugFormat( 2275// m_log.DebugFormat(
2269// "[SCENE PRESENCE]: Sitting {0} at position {1} ({2} + {3}) on part {4} {5} without sit target", 2276// "[SCENE PRESENCE]: Sitting {0} at position {1} ({2} + {3}) on part {4} {5} without sit target",
@@ -3369,6 +3376,8 @@ namespace OpenSim.Region.Framework.Scenes
3369 } 3376 }
3370 } 3377 }
3371 3378
3379 RaiseCollisionScriptEvents(coldata);
3380
3372 if (Invulnerable) 3381 if (Invulnerable)
3373 return; 3382 return;
3374 3383
@@ -3879,9 +3888,171 @@ namespace OpenSim.Region.Framework.Scenes
3879 pos = land.LandData.UserLocation; 3888 pos = land.LandData.UserLocation;
3880 } 3889 }
3881 } 3890 }
3882 3891
3883 land.SendLandUpdateToClient(ControllingClient); 3892 land.SendLandUpdateToClient(ControllingClient);
3884 } 3893 }
3885 } 3894 }
3895
3896 private void RaiseCollisionScriptEvents(Dictionary<uint, ContactPoint> coldata)
3897 {
3898 lock(m_collisionEventLock)
3899 {
3900 if (m_collisionEventFlag)
3901 return;
3902 m_collisionEventFlag = true;
3903 }
3904
3905 Util.FireAndForget(delegate(object x)
3906 {
3907 try
3908 {
3909 List<uint> thisHitColliders = new List<uint>();
3910 List<uint> endedColliders = new List<uint>();
3911 List<uint> startedColliders = new List<uint>();
3912
3913 foreach (uint localid in coldata.Keys)
3914 {
3915 thisHitColliders.Add(localid);
3916 if (!m_lastColliders.Contains(localid))
3917 {
3918 startedColliders.Add(localid);
3919 }
3920 //m_log.Debug("[SCENE PRESENCE]: Collided with:" + localid.ToString() + " at depth of: " + collissionswith[localid].ToString());
3921 }
3922
3923 // calculate things that ended colliding
3924 foreach (uint localID in m_lastColliders)
3925 {
3926 if (!thisHitColliders.Contains(localID))
3927 {
3928 endedColliders.Add(localID);
3929 }
3930 }
3931 //add the items that started colliding this time to the last colliders list.
3932 foreach (uint localID in startedColliders)
3933 {
3934 m_lastColliders.Add(localID);
3935 }
3936 // remove things that ended colliding from the last colliders list
3937 foreach (uint localID in endedColliders)
3938 {
3939 m_lastColliders.Remove(localID);
3940 }
3941
3942 // do event notification
3943 if (startedColliders.Count > 0)
3944 {
3945 ColliderArgs StartCollidingMessage = new ColliderArgs();
3946 List<DetectedObject> colliding = new List<DetectedObject>();
3947 foreach (uint localId in startedColliders)
3948 {
3949 if (localId == 0)
3950 continue;
3951
3952 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
3953 string data = "";
3954 if (obj != null)
3955 {
3956 DetectedObject detobj = new DetectedObject();
3957 detobj.keyUUID = obj.UUID;
3958 detobj.nameStr = obj.Name;
3959 detobj.ownerUUID = obj.OwnerID;
3960 detobj.posVector = obj.AbsolutePosition;
3961 detobj.rotQuat = obj.GetWorldRotation();
3962 detobj.velVector = obj.Velocity;
3963 detobj.colliderType = 0;
3964 detobj.groupUUID = obj.GroupID;
3965 colliding.Add(detobj);
3966 }
3967 }
3968
3969 if (colliding.Count > 0)
3970 {
3971 StartCollidingMessage.Colliders = colliding;
3972
3973 foreach (SceneObjectGroup att in GetAttachments())
3974 Scene.EventManager.TriggerScriptCollidingStart(att.LocalId, StartCollidingMessage);
3975 }
3976 }
3977
3978 if (endedColliders.Count > 0)
3979 {
3980 ColliderArgs EndCollidingMessage = new ColliderArgs();
3981 List<DetectedObject> colliding = new List<DetectedObject>();
3982 foreach (uint localId in endedColliders)
3983 {
3984 if (localId == 0)
3985 continue;
3986
3987 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
3988 string data = "";
3989 if (obj != null)
3990 {
3991 DetectedObject detobj = new DetectedObject();
3992 detobj.keyUUID = obj.UUID;
3993 detobj.nameStr = obj.Name;
3994 detobj.ownerUUID = obj.OwnerID;
3995 detobj.posVector = obj.AbsolutePosition;
3996 detobj.rotQuat = obj.GetWorldRotation();
3997 detobj.velVector = obj.Velocity;
3998 detobj.colliderType = 0;
3999 detobj.groupUUID = obj.GroupID;
4000 colliding.Add(detobj);
4001 }
4002 }
4003
4004 if (colliding.Count > 0)
4005 {
4006 EndCollidingMessage.Colliders = colliding;
4007
4008 foreach (SceneObjectGroup att in GetAttachments())
4009 Scene.EventManager.TriggerScriptCollidingEnd(att.LocalId, EndCollidingMessage);
4010 }
4011 }
4012
4013 if (thisHitColliders.Count > 0)
4014 {
4015 ColliderArgs CollidingMessage = new ColliderArgs();
4016 List<DetectedObject> colliding = new List<DetectedObject>();
4017 foreach (uint localId in thisHitColliders)
4018 {
4019 if (localId == 0)
4020 continue;
4021
4022 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
4023 string data = "";
4024 if (obj != null)
4025 {
4026 DetectedObject detobj = new DetectedObject();
4027 detobj.keyUUID = obj.UUID;
4028 detobj.nameStr = obj.Name;
4029 detobj.ownerUUID = obj.OwnerID;
4030 detobj.posVector = obj.AbsolutePosition;
4031 detobj.rotQuat = obj.GetWorldRotation();
4032 detobj.velVector = obj.Velocity;
4033 detobj.colliderType = 0;
4034 detobj.groupUUID = obj.GroupID;
4035 colliding.Add(detobj);
4036 }
4037 }
4038
4039 if (colliding.Count > 0)
4040 {
4041 CollidingMessage.Colliders = colliding;
4042
4043 lock (m_attachments)
4044 {
4045 foreach (SceneObjectGroup att in m_attachments)
4046 Scene.EventManager.TriggerScriptColliding(att.LocalId, CollidingMessage);
4047 }
4048 }
4049 }
4050 }
4051 finally
4052 {
4053 m_collisionEventFlag = false;
4054 }
4055 });
4056 }
3886 } 4057 }
3887} 4058}
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
index bca49f7..3f24991 100644
--- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
+++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
@@ -345,6 +345,9 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
345 m_SOPXmlProcessors.Add("PayPrice2", ProcessPayPrice2); 345 m_SOPXmlProcessors.Add("PayPrice2", ProcessPayPrice2);
346 m_SOPXmlProcessors.Add("PayPrice3", ProcessPayPrice3); 346 m_SOPXmlProcessors.Add("PayPrice3", ProcessPayPrice3);
347 m_SOPXmlProcessors.Add("PayPrice4", ProcessPayPrice4); 347 m_SOPXmlProcessors.Add("PayPrice4", ProcessPayPrice4);
348
349 m_SOPXmlProcessors.Add("Buoyancy", ProcessBuoyancy);
350 m_SOPXmlProcessors.Add("VolumeDetectActive", ProcessVolumeDetectActive);
348 #endregion 351 #endregion
349 352
350 #region TaskInventoryXmlProcessors initialization 353 #region TaskInventoryXmlProcessors initialization
@@ -729,6 +732,16 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
729 obj.PayPrice[4] = (int)reader.ReadElementContentAsInt("PayPrice4", String.Empty); 732 obj.PayPrice[4] = (int)reader.ReadElementContentAsInt("PayPrice4", String.Empty);
730 } 733 }
731 734
735 private static void ProcessBuoyancy(SceneObjectPart obj, XmlTextReader reader)
736 {
737 obj.Buoyancy = (int)reader.ReadElementContentAsFloat("Buoyancy", String.Empty);
738 }
739
740 private static void ProcessVolumeDetectActive(SceneObjectPart obj, XmlTextReader reader)
741 {
742 obj.VolumeDetectActive = Util.ReadBoolean(reader);
743 }
744
732 #endregion 745 #endregion
733 746
734 #region TaskInventoryXmlProcessors 747 #region TaskInventoryXmlProcessors
@@ -1212,6 +1225,9 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1212 writer.WriteElementString("PayPrice3", sop.PayPrice[3].ToString()); 1225 writer.WriteElementString("PayPrice3", sop.PayPrice[3].ToString());
1213 writer.WriteElementString("PayPrice4", sop.PayPrice[4].ToString()); 1226 writer.WriteElementString("PayPrice4", sop.PayPrice[4].ToString());
1214 1227
1228 writer.WriteElementString("Buoyancy", sop.Buoyancy.ToString());
1229 writer.WriteElementString("VolumeDetectActive", sop.VolumeDetectActive.ToString().ToLower());
1230
1215 writer.WriteEndElement(); 1231 writer.WriteEndElement();
1216 } 1232 }
1217 1233
@@ -1496,12 +1512,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1496 { 1512 {
1497 TaskInventoryDictionary tinv = new TaskInventoryDictionary(); 1513 TaskInventoryDictionary tinv = new TaskInventoryDictionary();
1498 1514
1499 if (reader.IsEmptyElement)
1500 {
1501 reader.Read();
1502 return tinv;
1503 }
1504
1505 reader.ReadStartElement(name, String.Empty); 1515 reader.ReadStartElement(name, String.Empty);
1506 1516
1507 while (reader.Name == "TaskInventoryItem") 1517 while (reader.Name == "TaskInventoryItem")
@@ -1544,12 +1554,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1544 1554
1545 PrimitiveBaseShape shape = new PrimitiveBaseShape(); 1555 PrimitiveBaseShape shape = new PrimitiveBaseShape();
1546 1556
1547 if (reader.IsEmptyElement)
1548 {
1549 reader.Read();
1550 return shape;
1551 }
1552
1553 reader.ReadStartElement(name, String.Empty); // Shape 1557 reader.ReadStartElement(name, String.Empty); // Shape
1554 1558
1555 string nodeName = string.Empty; 1559 string nodeName = string.Empty;
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;