aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework')
-rw-r--r--OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs6
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEntityInventory.cs3
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs4
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEstateModule.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/IInterregionComms.cs8
-rw-r--r--OpenSim/Region/Framework/Interfaces/IScriptModule.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/ISnmpModule.cs27
-rw-r--r--OpenSim/Region/Framework/Interfaces/IUserAccountCacheModule.cs13
-rw-r--r--OpenSim/Region/Framework/ModuleLoader.cs3
-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.cs344
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs3
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs489
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneBase.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs37
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs230
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneManager.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs17
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs569
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs199
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs806
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs188
-rw-r--r--OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs28
-rw-r--r--OpenSim/Region/Framework/Scenes/UndoState.cs87
-rw-r--r--OpenSim/Region/Framework/Scenes/UuidGatherer.cs4
26 files changed, 2352 insertions, 749 deletions
diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
index e668dae..a7770ad 100644
--- a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Xml;
29using System.Collections.Generic; 30using System.Collections.Generic;
30using OpenMetaverse; 31using OpenMetaverse;
31using OpenSim.Framework; 32using OpenSim.Framework;
@@ -75,6 +76,10 @@ namespace OpenSim.Region.Framework.Interfaces
75 /// <returns>The scene object that was attached. Null if the scene object could not be found</returns> 76 /// <returns>The scene object that was attached. Null if the scene object could not be found</returns>
76 ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt); 77 ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt);
77 78
79 // Same as above, but also load script states from a separate doc
80 ISceneEntity RezSingleAttachmentFromInventory(
81 IScenePresence presence, UUID itemID, uint AttachmentPt, bool updateInventoryStatus, XmlDocument doc);
82
78 /// <summary> 83 /// <summary>
79 /// Rez multiple attachments from a user's inventory 84 /// Rez multiple attachments from a user's inventory
80 /// </summary> 85 /// </summary>
@@ -96,7 +101,6 @@ namespace OpenSim.Region.Framework.Interfaces
96 /// <param name="itemID"></param> 101 /// <param name="itemID"></param>
97 void DetachSingleAttachmentToInv(IScenePresence sp, UUID itemID); 102 void DetachSingleAttachmentToInv(IScenePresence sp, UUID itemID);
98 103
99 /// <summary>
100 /// Update the position of an attachment. 104 /// Update the position of an attachment.
101 /// </summary> 105 /// </summary>
102 /// <param name="sog"></param> 106 /// <param name="sog"></param>
diff --git a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
index 15060fd..4b17b9a 100644
--- a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
@@ -115,6 +115,8 @@ namespace OpenSim.Region.Framework.Interfaces
115 /// <param name="stateSource"></param> 115 /// <param name="stateSource"></param>
116 void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource); 116 void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource);
117 117
118 ArrayList CreateScriptInstanceEr(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource);
119
118 /// <summary> 120 /// <summary>
119 /// Stop a script which is in this prim's inventory. 121 /// Stop a script which is in this prim's inventory.
120 /// </summary> 122 /// </summary>
@@ -229,5 +231,6 @@ namespace OpenSim.Region.Framework.Interfaces
229 /// A <see cref="Dictionary`2"/> 231 /// A <see cref="Dictionary`2"/>
230 /// </returns> 232 /// </returns>
231 Dictionary<UUID, string> GetScriptStates(); 233 Dictionary<UUID, string> GetScriptStates();
234 Dictionary<UUID, string> GetScriptStates(bool oldIDs);
232 } 235 }
233} 236}
diff --git a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
index 07e97d5..c38ecd9 100644
--- a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
@@ -40,11 +40,11 @@ namespace OpenSim.Region.Framework.Interfaces
40 void Teleport(ScenePresence agent, ulong regionHandle, Vector3 position, 40 void Teleport(ScenePresence agent, ulong regionHandle, Vector3 position,
41 Vector3 lookAt, uint teleportFlags); 41 Vector3 lookAt, uint teleportFlags);
42 42
43 bool TeleportHome(UUID id, IClientAPI client);
44
43 void DoTeleport(ScenePresence sp, GridRegion reg, GridRegion finalDestination, 45 void DoTeleport(ScenePresence sp, GridRegion reg, GridRegion finalDestination,
44 Vector3 position, Vector3 lookAt, uint teleportFlags, IEventQueue eq); 46 Vector3 position, Vector3 lookAt, uint teleportFlags, IEventQueue eq);
45 47
46 void TeleportHome(UUID id, IClientAPI client);
47
48 bool Cross(ScenePresence agent, bool isFlying); 48 bool Cross(ScenePresence agent, bool isFlying);
49 49
50 void AgentArrivedAtDestination(UUID agent); 50 void AgentArrivedAtDestination(UUID agent);
diff --git a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs
index 721f0ee..72e79ed 100644
--- a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs
@@ -45,5 +45,7 @@ namespace OpenSim.Region.Framework.Interfaces
45 /// Tell all clients about the current state of the region (terrain textures, water height, etc.). 45 /// Tell all clients about the current state of the region (terrain textures, water height, etc.).
46 /// </summary> 46 /// </summary>
47 void sendRegionHandshakeToAll(); 47 void sendRegionHandshakeToAll();
48 void TriggerEstateInfoChange();
49 void TriggerRegionInfoChange();
48 } 50 }
49} 51}
diff --git a/OpenSim/Region/Framework/Interfaces/IInterregionComms.cs b/OpenSim/Region/Framework/Interfaces/IInterregionComms.cs
index 2d6287f..67a500f 100644
--- a/OpenSim/Region/Framework/Interfaces/IInterregionComms.cs
+++ b/OpenSim/Region/Framework/Interfaces/IInterregionComms.cs
@@ -68,6 +68,14 @@ namespace OpenSim.Region.Framework.Interfaces
68 bool SendReleaseAgent(ulong regionHandle, UUID id, string uri); 68 bool SendReleaseAgent(ulong regionHandle, UUID id, string uri);
69 69
70 /// <summary> 70 /// <summary>
71 /// Close chid agent.
72 /// </summary>
73 /// <param name="regionHandle"></param>
74 /// <param name="id"></param>
75 /// <returns></returns>
76 bool SendCloseChildAgent(ulong regionHandle, UUID id);
77
78 /// <summary>
71 /// Close agent. 79 /// Close agent.
72 /// </summary> 80 /// </summary>
73 /// <param name="regionHandle"></param> 81 /// <param name="regionHandle"></param>
diff --git a/OpenSim/Region/Framework/Interfaces/IScriptModule.cs b/OpenSim/Region/Framework/Interfaces/IScriptModule.cs
index 18c45dd..2d6758b 100644
--- a/OpenSim/Region/Framework/Interfaces/IScriptModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IScriptModule.cs
@@ -68,6 +68,8 @@ namespace OpenSim.Region.Framework.Interfaces
68 68
69 ArrayList GetScriptErrors(UUID itemID); 69 ArrayList GetScriptErrors(UUID itemID);
70 70
71 bool HasScript(UUID itemID, out bool running);
72
71 void SaveAllState(); 73 void SaveAllState();
72 74
73 /// <summary> 75 /// <summary>
diff --git a/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs b/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs
new file mode 100644
index 0000000..e01f649
--- /dev/null
+++ b/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs
@@ -0,0 +1,27 @@
1///////////////////////////////////////////////////////////////////
2//
3// (c) Careminster LImited, Melanie Thielker and the Meta7 Team
4//
5// This file is not open source. All rights reserved
6// Mod 2
7
8using OpenSim.Region.Framework.Scenes;
9
10public interface ISnmpModule
11{
12 void Trap(int code, string Message, Scene scene);
13 void Critical(string Message, Scene scene);
14 void Warning(string Message, Scene scene);
15 void Major(string Message, Scene scene);
16 void ColdStart(int step , Scene scene);
17 void Shutdown(int step , Scene scene);
18 //
19 // Node Start/stop events
20 //
21 void LinkUp(Scene scene);
22 void LinkDown(Scene scene);
23 void BootInfo(string data, Scene scene);
24 void trapDebug(string Module,string data, Scene scene);
25 void trapXMRE(int data, string Message, Scene scene);
26
27}
diff --git a/OpenSim/Region/Framework/Interfaces/IUserAccountCacheModule.cs b/OpenSim/Region/Framework/Interfaces/IUserAccountCacheModule.cs
new file mode 100644
index 0000000..d1a4d8e
--- /dev/null
+++ b/OpenSim/Region/Framework/Interfaces/IUserAccountCacheModule.cs
@@ -0,0 +1,13 @@
1///////////////////////////////////////////////////////////////////
2//
3// (c) Careminster Limited, Melanie Thielker and the Meta7 Team
4//
5// This file is not open source. All rights reserved
6//
7
8using OpenSim.Region.Framework.Scenes;
9
10public interface IUserAccountCacheModule
11{
12 void Remove(string name);
13}
diff --git a/OpenSim/Region/Framework/ModuleLoader.cs b/OpenSim/Region/Framework/ModuleLoader.cs
index 14ecd44..32ee674 100644
--- a/OpenSim/Region/Framework/ModuleLoader.cs
+++ b/OpenSim/Region/Framework/ModuleLoader.cs
@@ -227,7 +227,8 @@ namespace OpenSim.Region.Framework
227 pluginAssembly.FullName, e.Message, e.StackTrace); 227 pluginAssembly.FullName, e.Message, e.StackTrace);
228 228
229 // justincc: Right now this is fatal to really get the user's attention 229 // justincc: Right now this is fatal to really get the user's attention
230 throw e; 230 // TomMeta: WTF? No, how about we /don't/ throw a fatal exception when there's no need to?
231 //throw e;
231 } 232 }
232 } 233 }
233 234
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 dd3208a..817736f 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 {
125// m_log.DebugFormat(
126// "[LOCAL INVENTORY SERVICES CONNECTOR]: Found folder {0} type {1} for item {2}",
127// f.Name, (AssetType)f.Type, item.Name);
128
129 item.Folder = f.ID;
130 }
131 else
132 { 126 {
133 f = InventoryService.GetRootFolder(item.Owner); 127 folder = InventoryService.GetRootFolder(item.Owner);
134 if (f != null) 128
135 { 129 if (folder == null)
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();
@@ -1472,28 +1491,12 @@ namespace OpenSim.Region.Framework.Scenes
1472// m_log.DebugFormat( 1491// m_log.DebugFormat(
1473// "[PRIM INVENTORY]: Updating item {0} in {1} for UpdateTaskInventory()", 1492// "[PRIM INVENTORY]: Updating item {0} in {1} for UpdateTaskInventory()",
1474// currentItem.Name, part.Name); 1493// currentItem.Name, part.Name);
1475 1494 IAgentAssetTransactions agentTransactions = this.RequestModuleInterface<IAgentAssetTransactions>();
1476 // Viewers from at least Linden Lab 1.23 onwards use a capability to update script contents rather 1495 if (agentTransactions != null)
1477 // than UDP. With viewers from at least 1.23 onwards, changing properties on scripts (e.g. renaming) causes 1496 {
1478 // this to spew spurious errors and "thing saved" messages. 1497 agentTransactions.HandleTaskItemUpdateFromTransaction(
1479 // Rather than retaining complexity in the code and removing useful error messages, I'm going to 1498 remoteClient, part, transactionID, currentItem);
1480 // comment this section out. If this was still working for very old viewers and there is 1499 }
1481 // a large population using them which cannot upgrade to 1.23 or derivatives then we can revisit
1482 // this - justincc
1483// IAgentAssetTransactions agentTransactions = this.RequestModuleInterface<IAgentAssetTransactions>();
1484// if (agentTransactions != null)
1485// {
1486// agentTransactions.HandleTaskItemUpdateFromTransaction(
1487// remoteClient, part, transactionID, currentItem);
1488//
1489// if ((InventoryType)itemInfo.InvType == InventoryType.Notecard)
1490// remoteClient.SendAgentAlertMessage("Notecard saved", false);
1491// else if ((InventoryType)itemInfo.InvType == InventoryType.LSL)
1492// remoteClient.SendAgentAlertMessage("Script saved", false);
1493// else
1494// remoteClient.SendAgentAlertMessage("Item saved", false);
1495// }
1496
1497 // Base ALWAYS has move 1500 // Base ALWAYS has move
1498 currentItem.BasePermissions |= (uint)PermissionMask.Move; 1501 currentItem.BasePermissions |= (uint)PermissionMask.Move;
1499 1502
@@ -1670,7 +1673,7 @@ namespace OpenSim.Region.Framework.Scenes
1670 } 1673 }
1671 1674
1672 AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType, 1675 AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType,
1673 Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n}"), 1676 Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n\n touch_start(integer num)\n {\n }\n}"),
1674 agentID); 1677 agentID);
1675 AssetService.Store(asset); 1678 AssetService.Store(asset);
1676 1679
@@ -1822,23 +1825,32 @@ namespace OpenSim.Region.Framework.Scenes
1822 // build a list of eligible objects 1825 // build a list of eligible objects
1823 List<uint> deleteIDs = new List<uint>(); 1826 List<uint> deleteIDs = new List<uint>();
1824 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>(); 1827 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>();
1825 1828 List<SceneObjectGroup> takeGroups = new List<SceneObjectGroup>();
1826 // Start with true for both, then remove the flags if objects
1827 // that we can't derez are part of the selection
1828 bool permissionToTake = true;
1829 bool permissionToTakeCopy = true;
1830 bool permissionToDelete = true;
1831 1829
1832 foreach (uint localID in localIDs) 1830 foreach (uint localID in localIDs)
1833 { 1831 {
1832 // Start with true for both, then remove the flags if objects
1833 // that we can't derez are part of the selection
1834 bool permissionToTake = true;
1835 bool permissionToTakeCopy = true;
1836 bool permissionToDelete = true;
1837
1834 // Invalid id 1838 // Invalid id
1835 SceneObjectPart part = GetSceneObjectPart(localID); 1839 SceneObjectPart part = GetSceneObjectPart(localID);
1836 if (part == null) 1840 if (part == null)
1841 {
1842 //Client still thinks the object exists, kill it
1843 deleteIDs.Add(localID);
1837 continue; 1844 continue;
1845 }
1838 1846
1839 // Already deleted by someone else 1847 // Already deleted by someone else
1840 if (part.ParentGroup.IsDeleted) 1848 if (part.ParentGroup.IsDeleted)
1849 {
1850 //Client still thinks the object exists, kill it
1851 deleteIDs.Add(localID);
1841 continue; 1852 continue;
1853 }
1842 1854
1843 // Can't delete child prims 1855 // Can't delete child prims
1844 if (part != part.ParentGroup.RootPart) 1856 if (part != part.ParentGroup.RootPart)
@@ -1846,9 +1858,6 @@ namespace OpenSim.Region.Framework.Scenes
1846 1858
1847 SceneObjectGroup grp = part.ParentGroup; 1859 SceneObjectGroup grp = part.ParentGroup;
1848 1860
1849 deleteIDs.Add(localID);
1850 deleteGroups.Add(grp);
1851
1852 if (remoteClient == null) 1861 if (remoteClient == null)
1853 { 1862 {
1854 // Autoreturn has a null client. Nothing else does. So 1863 // Autoreturn has a null client. Nothing else does. So
@@ -1865,81 +1874,193 @@ namespace OpenSim.Region.Framework.Scenes
1865 } 1874 }
1866 else 1875 else
1867 { 1876 {
1868 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId)) 1877 if (action == DeRezAction.TakeCopy)
1878 {
1879 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId))
1880 permissionToTakeCopy = false;
1881 }
1882 else
1883 {
1869 permissionToTakeCopy = false; 1884 permissionToTakeCopy = false;
1870 1885 }
1871 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId)) 1886 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId))
1872 permissionToTake = false; 1887 permissionToTake = false;
1873 1888
1874 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId)) 1889 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId))
1875 permissionToDelete = false; 1890 permissionToDelete = false;
1876 } 1891 }
1877 }
1878 1892
1879 // Handle god perms 1893 // Handle god perms
1880 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId)) 1894 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId))
1881 { 1895 {
1882 permissionToTake = true; 1896 permissionToTake = true;
1883 permissionToTakeCopy = true; 1897 permissionToTakeCopy = true;
1884 permissionToDelete = true; 1898 permissionToDelete = true;
1885 } 1899 }
1886 1900
1887 // If we're re-saving, we don't even want to delete 1901 // If we're re-saving, we don't even want to delete
1888 if (action == DeRezAction.SaveToExistingUserInventoryItem) 1902 if (action == DeRezAction.SaveToExistingUserInventoryItem)
1889 permissionToDelete = false; 1903 permissionToDelete = false;
1890 1904
1891 // if we want to take a copy, we also don't want to delete 1905 // if we want to take a copy, we also don't want to delete
1892 // Note: after this point, the permissionToTakeCopy flag 1906 // Note: after this point, the permissionToTakeCopy flag
1893 // becomes irrelevant. It already includes the permissionToTake 1907 // becomes irrelevant. It already includes the permissionToTake
1894 // permission and after excluding no copy items here, we can 1908 // permission and after excluding no copy items here, we can
1895 // just use that. 1909 // just use that.
1896 if (action == DeRezAction.TakeCopy) 1910 if (action == DeRezAction.TakeCopy)
1897 { 1911 {
1898 // If we don't have permission, stop right here 1912 // If we don't have permission, stop right here
1899 if (!permissionToTakeCopy) 1913 if (!permissionToTakeCopy)
1900 return; 1914 return;
1901 1915
1902 permissionToTake = true; 1916 permissionToTake = true;
1903 // Don't delete 1917 // Don't delete
1904 permissionToDelete = false; 1918 permissionToDelete = false;
1905 } 1919 }
1906 1920
1907 if (action == DeRezAction.Return) 1921 if (action == DeRezAction.Return)
1908 {
1909 if (remoteClient != null)
1910 { 1922 {
1911 if (Permissions.CanReturnObjects( 1923 if (remoteClient != null)
1912 null,
1913 remoteClient.AgentId,
1914 deleteGroups))
1915 { 1924 {
1916 permissionToTake = true; 1925 if (Permissions.CanReturnObjects(
1917 permissionToDelete = true; 1926 null,
1918 1927 remoteClient.AgentId,
1919 foreach (SceneObjectGroup g in deleteGroups) 1928 deleteGroups))
1920 { 1929 {
1921 AddReturn(g.OwnerID, g.Name, g.AbsolutePosition, "parcel owner return"); 1930 permissionToTake = true;
1931 permissionToDelete = true;
1932
1933 AddReturn(grp.OwnerID, grp.Name, grp.AbsolutePosition, "parcel owner return");
1922 } 1934 }
1923 } 1935 }
1936 else // Auto return passes through here with null agent
1937 {
1938 permissionToTake = true;
1939 permissionToDelete = true;
1940 }
1924 } 1941 }
1925 else // Auto return passes through here with null agent 1942
1943 if (permissionToTake && (!permissionToDelete))
1944 takeGroups.Add(grp);
1945
1946 if (permissionToDelete)
1926 { 1947 {
1927 permissionToTake = true; 1948 if (permissionToTake)
1928 permissionToDelete = true; 1949 deleteGroups.Add(grp);
1950 deleteIDs.Add(grp.LocalId);
1929 } 1951 }
1930 } 1952 }
1931 1953
1932 if (permissionToTake) 1954 SendKillObject(deleteIDs);
1955
1956 if (deleteGroups.Count > 0)
1933 { 1957 {
1958 foreach (SceneObjectGroup g in deleteGroups)
1959 deleteIDs.Remove(g.LocalId);
1960
1934 m_asyncSceneObjectDeleter.DeleteToInventory( 1961 m_asyncSceneObjectDeleter.DeleteToInventory(
1935 action, destinationID, deleteGroups, remoteClient, 1962 action, destinationID, deleteGroups, remoteClient,
1936 permissionToDelete); 1963 true);
1937 } 1964 }
1938 else if (permissionToDelete) 1965 if (takeGroups.Count > 0)
1966 {
1967 m_asyncSceneObjectDeleter.DeleteToInventory(
1968 action, destinationID, takeGroups, remoteClient,
1969 false);
1970 }
1971 if (deleteIDs.Count > 0)
1939 { 1972 {
1940 foreach (SceneObjectGroup g in deleteGroups) 1973 foreach (SceneObjectGroup g in deleteGroups)
1941 DeleteSceneObject(g, false); 1974 DeleteSceneObject(g, true);
1975 }
1976 }
1977
1978 public UUID attachObjectAssetStore(IClientAPI remoteClient, SceneObjectGroup grp, UUID AgentId, out UUID itemID)
1979 {
1980 itemID = UUID.Zero;
1981 if (grp != null)
1982 {
1983 Vector3 inventoryStoredPosition = new Vector3
1984 (((grp.AbsolutePosition.X > (int)Constants.RegionSize)
1985 ? 250
1986 : grp.AbsolutePosition.X)
1987 ,
1988 (grp.AbsolutePosition.X > (int)Constants.RegionSize)
1989 ? 250
1990 : grp.AbsolutePosition.X,
1991 grp.AbsolutePosition.Z);
1992
1993 Vector3 originalPosition = grp.AbsolutePosition;
1994
1995 grp.AbsolutePosition = inventoryStoredPosition;
1996
1997 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp);
1998
1999 grp.AbsolutePosition = originalPosition;
2000
2001 AssetBase asset = CreateAsset(
2002 grp.GetPartName(grp.LocalId),
2003 grp.GetPartDescription(grp.LocalId),
2004 (sbyte)AssetType.Object,
2005 Utils.StringToBytes(sceneObjectXml),
2006 remoteClient.AgentId);
2007 AssetService.Store(asset);
2008
2009 InventoryItemBase item = new InventoryItemBase();
2010 item.CreatorId = grp.RootPart.CreatorID.ToString();
2011 item.CreatorData = grp.RootPart.CreatorData;
2012 item.Owner = remoteClient.AgentId;
2013 item.ID = UUID.Random();
2014 item.AssetID = asset.FullID;
2015 item.Description = asset.Description;
2016 item.Name = asset.Name;
2017 item.AssetType = asset.Type;
2018 item.InvType = (int)InventoryType.Object;
2019
2020 InventoryFolderBase folder = InventoryService.GetFolderForType(remoteClient.AgentId, AssetType.Object);
2021 if (folder != null)
2022 item.Folder = folder.ID;
2023 else // oopsies
2024 item.Folder = UUID.Zero;
2025
2026 // Set up base perms properly
2027 uint permsBase = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify);
2028 permsBase &= grp.RootPart.BaseMask;
2029 permsBase |= (uint)PermissionMask.Move;
2030
2031 // Make sure we don't lock it
2032 grp.RootPart.NextOwnerMask |= (uint)PermissionMask.Move;
2033
2034 if ((remoteClient.AgentId != grp.RootPart.OwnerID) && Permissions.PropagatePermissions())
2035 {
2036 item.BasePermissions = permsBase & grp.RootPart.NextOwnerMask;
2037 item.CurrentPermissions = permsBase & grp.RootPart.NextOwnerMask;
2038 item.NextPermissions = permsBase & grp.RootPart.NextOwnerMask;
2039 item.EveryOnePermissions = permsBase & grp.RootPart.EveryoneMask & grp.RootPart.NextOwnerMask;
2040 item.GroupPermissions = permsBase & grp.RootPart.GroupMask & grp.RootPart.NextOwnerMask;
2041 }
2042 else
2043 {
2044 item.BasePermissions = permsBase;
2045 item.CurrentPermissions = permsBase & grp.RootPart.OwnerMask;
2046 item.NextPermissions = permsBase & grp.RootPart.NextOwnerMask;
2047 item.EveryOnePermissions = permsBase & grp.RootPart.EveryoneMask;
2048 item.GroupPermissions = permsBase & grp.RootPart.GroupMask;
2049 }
2050 item.CreationDate = Util.UnixTimeSinceEpoch();
2051
2052 // sets itemID so client can show item as 'attached' in inventory
2053 grp.SetFromItemID(item.ID);
2054
2055 if (AddInventoryItem(item))
2056 remoteClient.SendInventoryItemCreateUpdate(item, 0);
2057 else
2058 m_dialogModule.SendAlertToUser(remoteClient, "Operation failed");
2059
2060 itemID = item.ID;
2061 return item.AssetID;
1942 } 2062 }
2063 return UUID.Zero;
1943 } 2064 }
1944 2065
1945 /// <summary> 2066 /// <summary>
@@ -2068,6 +2189,9 @@ namespace OpenSim.Region.Framework.Scenes
2068 2189
2069 public void SetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID, bool running) 2190 public void SetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID, bool running)
2070 { 2191 {
2192 if (!Permissions.CanEditScript(itemID, objectID, controllingClient.AgentId))
2193 return;
2194
2071 SceneObjectPart part = GetSceneObjectPart(objectID); 2195 SceneObjectPart part = GetSceneObjectPart(objectID);
2072 if (part == null) 2196 if (part == null)
2073 return; 2197 return;
diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
index 3355ebe..bf2e775 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
@@ -346,7 +346,10 @@ namespace OpenSim.Region.Framework.Scenes
346 List<UserAccount> accounts = UserAccountService.GetUserAccounts(RegionInfo.ScopeID, query); 346 List<UserAccount> accounts = UserAccountService.GetUserAccounts(RegionInfo.ScopeID, query);
347 347
348 if (accounts == null) 348 if (accounts == null)
349 {
350 m_log.DebugFormat("[LLCIENT]: ProcessAvatarPickerRequest: returned null result");
349 return; 351 return;
352 }
350 353
351 AvatarPickerReplyPacket replyPacket = (AvatarPickerReplyPacket) PacketPool.Instance.GetPacket(PacketType.AvatarPickerReply); 354 AvatarPickerReplyPacket replyPacket = (AvatarPickerReplyPacket) PacketPool.Instance.GetPacket(PacketType.AvatarPickerReply);
352 // TODO: don't create new blocks if recycling an old packet 355 // TODO: don't create new blocks if recycling an old packet
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 975d769..9b31fac 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -104,6 +104,7 @@ namespace OpenSim.Region.Framework.Scenes
104 // TODO: need to figure out how allow client agents but deny 104 // TODO: need to figure out how allow client agents but deny
105 // root agents when ACL denies access to root agent 105 // root agents when ACL denies access to root agent
106 public bool m_strictAccessControl = true; 106 public bool m_strictAccessControl = true;
107 public bool m_seeIntoBannedRegion = false;
107 public int MaxUndoCount = 5; 108 public int MaxUndoCount = 5;
108 // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet; 109 // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet;
109 public bool LoginLock = false; 110 public bool LoginLock = false;
@@ -119,12 +120,14 @@ namespace OpenSim.Region.Framework.Scenes
119 120
120 protected int m_splitRegionID; 121 protected int m_splitRegionID;
121 protected Timer m_restartWaitTimer = new Timer(); 122 protected Timer m_restartWaitTimer = new Timer();
123 protected Timer m_timerWatchdog = new Timer();
122 protected List<RegionInfo> m_regionRestartNotifyList = new List<RegionInfo>(); 124 protected List<RegionInfo> m_regionRestartNotifyList = new List<RegionInfo>();
123 protected List<RegionInfo> m_neighbours = new List<RegionInfo>(); 125 protected List<RegionInfo> m_neighbours = new List<RegionInfo>();
124 protected string m_simulatorVersion = "OpenSimulator Server"; 126 protected string m_simulatorVersion = "OpenSimulator Server";
125 protected ModuleLoader m_moduleLoader; 127 protected ModuleLoader m_moduleLoader;
126 protected AgentCircuitManager m_authenticateHandler; 128 protected AgentCircuitManager m_authenticateHandler;
127 protected SceneCommunicationService m_sceneGridService; 129 protected SceneCommunicationService m_sceneGridService;
130 protected ISnmpModule m_snmpService = null;
128 131
129 protected ISimulationDataService m_SimulationDataService; 132 protected ISimulationDataService m_SimulationDataService;
130 protected IEstateDataService m_EstateDataService; 133 protected IEstateDataService m_EstateDataService;
@@ -177,7 +180,7 @@ namespace OpenSim.Region.Framework.Scenes
177 private int m_update_events = 1; 180 private int m_update_events = 1;
178 private int m_update_backup = 200; 181 private int m_update_backup = 200;
179 private int m_update_terrain = 50; 182 private int m_update_terrain = 50;
180// private int m_update_land = 1; 183 private int m_update_land = 10;
181 private int m_update_coarse_locations = 50; 184 private int m_update_coarse_locations = 50;
182 185
183 private int agentMS; 186 private int agentMS;
@@ -192,6 +195,7 @@ namespace OpenSim.Region.Framework.Scenes
192 private int landMS; 195 private int landMS;
193 private int lastCompletedFrame; 196 private int lastCompletedFrame;
194 197
198 public bool CombineRegions = false;
195 /// <summary> 199 /// <summary>
196 /// Signals whether temporary objects are currently being cleaned up. Needed because this is launched 200 /// Signals whether temporary objects are currently being cleaned up. Needed because this is launched
197 /// asynchronously from the update loop. 201 /// asynchronously from the update loop.
@@ -214,11 +218,14 @@ namespace OpenSim.Region.Framework.Scenes
214 private bool m_scripts_enabled = true; 218 private bool m_scripts_enabled = true;
215 private string m_defaultScriptEngine; 219 private string m_defaultScriptEngine;
216 private int m_LastLogin; 220 private int m_LastLogin;
217 private Thread HeartbeatThread; 221 private Thread HeartbeatThread = null;
218 private volatile bool shuttingdown; 222 private volatile bool shuttingdown;
219 223
220 private int m_lastUpdate; 224 private int m_lastUpdate;
225 private int m_lastIncoming;
226 private int m_lastOutgoing;
221 private bool m_firstHeartbeat = true; 227 private bool m_firstHeartbeat = true;
228 private int m_hbRestarts = 0;
222 229
223 private object m_deleting_scene_object = new object(); 230 private object m_deleting_scene_object = new object();
224 231
@@ -265,6 +272,19 @@ namespace OpenSim.Region.Framework.Scenes
265 get { return m_sceneGridService; } 272 get { return m_sceneGridService; }
266 } 273 }
267 274
275 public ISnmpModule SnmpService
276 {
277 get
278 {
279 if (m_snmpService == null)
280 {
281 m_snmpService = RequestModuleInterface<ISnmpModule>();
282 }
283
284 return m_snmpService;
285 }
286 }
287
268 public ISimulationDataService SimulationDataService 288 public ISimulationDataService SimulationDataService
269 { 289 {
270 get 290 get
@@ -546,6 +566,9 @@ namespace OpenSim.Region.Framework.Scenes
546 m_EstateDataService = estateDataService; 566 m_EstateDataService = estateDataService;
547 m_regionHandle = m_regInfo.RegionHandle; 567 m_regionHandle = m_regInfo.RegionHandle;
548 m_regionName = m_regInfo.RegionName; 568 m_regionName = m_regInfo.RegionName;
569 m_lastUpdate = Util.EnvironmentTickCount();
570 m_lastIncoming = 0;
571 m_lastOutgoing = 0;
549 572
550 m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this); 573 m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this);
551 m_asyncSceneObjectDeleter.Enabled = true; 574 m_asyncSceneObjectDeleter.Enabled = true;
@@ -663,6 +686,7 @@ namespace OpenSim.Region.Framework.Scenes
663 CollidablePrims = startupConfig.GetBoolean("collidable_prim", true); 686 CollidablePrims = startupConfig.GetBoolean("collidable_prim", true);
664 687
665 m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys); 688 m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys);
689
666 if (RegionInfo.NonphysPrimMax > 0) 690 if (RegionInfo.NonphysPrimMax > 0)
667 { 691 {
668 m_maxNonphys = RegionInfo.NonphysPrimMax; 692 m_maxNonphys = RegionInfo.NonphysPrimMax;
@@ -694,6 +718,7 @@ namespace OpenSim.Region.Framework.Scenes
694 m_persistAfter *= 10000000; 718 m_persistAfter *= 10000000;
695 719
696 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine"); 720 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine");
721 m_log.InfoFormat("[SCENE]: Default script engine {0}", m_defaultScriptEngine);
697 722
698 IConfig packetConfig = m_config.Configs["PacketPool"]; 723 IConfig packetConfig = m_config.Configs["PacketPool"];
699 if (packetConfig != null) 724 if (packetConfig != null)
@@ -703,6 +728,8 @@ namespace OpenSim.Region.Framework.Scenes
703 } 728 }
704 729
705 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl); 730 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl);
731 m_seeIntoBannedRegion = startupConfig.GetBoolean("SeeIntoBannedRegion", m_seeIntoBannedRegion);
732 CombineRegions = startupConfig.GetBoolean("CombineContiguousRegions", false);
706 733
707 m_generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", true); 734 m_generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", true);
708 if (m_generateMaptiles) 735 if (m_generateMaptiles)
@@ -738,9 +765,9 @@ namespace OpenSim.Region.Framework.Scenes
738 m_update_terrain = startupConfig.GetInt( "UpdateTerrainEveryNFrames", m_update_terrain); 765 m_update_terrain = startupConfig.GetInt( "UpdateTerrainEveryNFrames", m_update_terrain);
739 m_update_temp_cleaning = startupConfig.GetInt( "UpdateTempCleaningEveryNFrames", m_update_temp_cleaning); 766 m_update_temp_cleaning = startupConfig.GetInt( "UpdateTempCleaningEveryNFrames", m_update_temp_cleaning);
740 } 767 }
741 catch 768 catch (Exception e)
742 { 769 {
743 m_log.Warn("[SCENE]: Failed to load StartupConfig"); 770 m_log.Error("[SCENE]: Failed to load StartupConfig: " + e.ToString());
744 } 771 }
745 772
746 #endregion Region Config 773 #endregion Region Config
@@ -1151,7 +1178,22 @@ namespace OpenSim.Region.Framework.Scenes
1151 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat); 1178 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat);
1152 if (HeartbeatThread != null) 1179 if (HeartbeatThread != null)
1153 { 1180 {
1181 m_hbRestarts++;
1182 if(m_hbRestarts > 10)
1183 Environment.Exit(1);
1184 m_log.ErrorFormat("[SCENE]: Restarting heartbeat thread because it hasn't reported in in region {0}", RegionInfo.RegionName);
1185
1186//int pid = System.Diagnostics.Process.GetCurrentProcess().Id;
1187//System.Diagnostics.Process proc = new System.Diagnostics.Process();
1188//proc.EnableRaisingEvents=false;
1189//proc.StartInfo.FileName = "/bin/kill";
1190//proc.StartInfo.Arguments = "-QUIT " + pid.ToString();
1191//proc.Start();
1192//proc.WaitForExit();
1193//Thread.Sleep(1000);
1194//Environment.Exit(1);
1154 HeartbeatThread.Abort(); 1195 HeartbeatThread.Abort();
1196 Watchdog.AbortThread(HeartbeatThread.ManagedThreadId);
1155 HeartbeatThread = null; 1197 HeartbeatThread = null;
1156 } 1198 }
1157 m_lastUpdate = Util.EnvironmentTickCount(); 1199 m_lastUpdate = Util.EnvironmentTickCount();
@@ -1198,9 +1240,6 @@ namespace OpenSim.Region.Framework.Scenes
1198 m_eventManager.TriggerOnRegionStarted(this); 1240 m_eventManager.TriggerOnRegionStarted(this);
1199 while (!shuttingdown) 1241 while (!shuttingdown)
1200 Update(); 1242 Update();
1201
1202 m_lastUpdate = Util.EnvironmentTickCount();
1203 m_firstHeartbeat = false;
1204 } 1243 }
1205 catch (ThreadAbortException) 1244 catch (ThreadAbortException)
1206 { 1245 {
@@ -1298,6 +1337,13 @@ namespace OpenSim.Region.Framework.Scenes
1298 eventMS = Util.EnvironmentTickCountSubtract(evMS); ; 1337 eventMS = Util.EnvironmentTickCountSubtract(evMS); ;
1299 } 1338 }
1300 1339
1340 // if (Frame % m_update_land == 0)
1341 // {
1342 // int ldMS = Util.EnvironmentTickCount();
1343 // UpdateLand();
1344 // landMS = Util.EnvironmentTickCountSubtract(ldMS);
1345 // }
1346
1301 if (Frame % m_update_backup == 0) 1347 if (Frame % m_update_backup == 0)
1302 { 1348 {
1303 int backMS = Util.EnvironmentTickCount(); 1349 int backMS = Util.EnvironmentTickCount();
@@ -1405,12 +1451,16 @@ namespace OpenSim.Region.Framework.Scenes
1405 maintc = Util.EnvironmentTickCountSubtract(maintc); 1451 maintc = Util.EnvironmentTickCountSubtract(maintc);
1406 maintc = (int)(MinFrameTime * 1000) - maintc; 1452 maintc = (int)(MinFrameTime * 1000) - maintc;
1407 1453
1454
1455 m_lastUpdate = Util.EnvironmentTickCount();
1456 m_firstHeartbeat = false;
1457
1408 if (maintc > 0) 1458 if (maintc > 0)
1409 Thread.Sleep(maintc); 1459 Thread.Sleep(maintc);
1410 1460
1411 // Tell the watchdog that this thread is still alive 1461 // Tell the watchdog that this thread is still alive
1412 Watchdog.UpdateThread(); 1462 Watchdog.UpdateThread();
1413 } 1463 }
1414 1464
1415 public void AddGroupTarget(SceneObjectGroup grp) 1465 public void AddGroupTarget(SceneObjectGroup grp)
1416 { 1466 {
@@ -1426,9 +1476,9 @@ namespace OpenSim.Region.Framework.Scenes
1426 1476
1427 private void CheckAtTargets() 1477 private void CheckAtTargets()
1428 { 1478 {
1429 Dictionary<UUID, SceneObjectGroup>.ValueCollection objs; 1479 List<SceneObjectGroup> objs = new List<SceneObjectGroup>();
1430 lock (m_groupsWithTargets) 1480 lock (m_groupsWithTargets)
1431 objs = m_groupsWithTargets.Values; 1481 objs = new List<SceneObjectGroup>(m_groupsWithTargets.Values);
1432 1482
1433 foreach (SceneObjectGroup entry in objs) 1483 foreach (SceneObjectGroup entry in objs)
1434 entry.checkAtTargets(); 1484 entry.checkAtTargets();
@@ -1510,7 +1560,7 @@ namespace OpenSim.Region.Framework.Scenes
1510 msg.fromAgentName = "Server"; 1560 msg.fromAgentName = "Server";
1511 msg.dialog = (byte)19; // Object msg 1561 msg.dialog = (byte)19; // Object msg
1512 msg.fromGroup = false; 1562 msg.fromGroup = false;
1513 msg.offline = (byte)0; 1563 msg.offline = (byte)1;
1514 msg.ParentEstateID = RegionInfo.EstateSettings.ParentEstateID; 1564 msg.ParentEstateID = RegionInfo.EstateSettings.ParentEstateID;
1515 msg.Position = Vector3.Zero; 1565 msg.Position = Vector3.Zero;
1516 msg.RegionID = RegionInfo.RegionID.Guid; 1566 msg.RegionID = RegionInfo.RegionID.Guid;
@@ -1741,14 +1791,24 @@ namespace OpenSim.Region.Framework.Scenes
1741 /// <returns></returns> 1791 /// <returns></returns>
1742 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter) 1792 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter)
1743 { 1793 {
1794
1795 float wheight = (float)RegionInfo.RegionSettings.WaterHeight;
1796 Vector3 wpos = Vector3.Zero;
1797 // Check for water surface intersection from above
1798 if ( (RayStart.Z > wheight) && (RayEnd.Z < wheight) )
1799 {
1800 float ratio = (RayStart.Z - wheight) / (RayStart.Z - RayEnd.Z);
1801 wpos.X = RayStart.X - (ratio * (RayStart.X - RayEnd.X));
1802 wpos.Y = RayStart.Y - (ratio * (RayStart.Y - RayEnd.Y));
1803 wpos.Z = wheight;
1804 }
1805
1744 Vector3 pos = Vector3.Zero; 1806 Vector3 pos = Vector3.Zero;
1745 if (RayEndIsIntersection == (byte)1) 1807 if (RayEndIsIntersection == (byte)1)
1746 { 1808 {
1747 pos = RayEnd; 1809 pos = RayEnd;
1748 return pos;
1749 } 1810 }
1750 1811 else if (RayTargetID != UUID.Zero)
1751 if (RayTargetID != UUID.Zero)
1752 { 1812 {
1753 SceneObjectPart target = GetSceneObjectPart(RayTargetID); 1813 SceneObjectPart target = GetSceneObjectPart(RayTargetID);
1754 1814
@@ -1770,7 +1830,7 @@ namespace OpenSim.Region.Framework.Scenes
1770 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter); 1830 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter);
1771 1831
1772 // Un-comment out the following line to Get Raytrace results printed to the console. 1832 // Un-comment out the following line to Get Raytrace results printed to the console.
1773 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString()); 1833 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
1774 float ScaleOffset = 0.5f; 1834 float ScaleOffset = 0.5f;
1775 1835
1776 // If we hit something 1836 // If we hit something
@@ -1793,13 +1853,10 @@ namespace OpenSim.Region.Framework.Scenes
1793 //pos.Z -= 0.25F; 1853 //pos.Z -= 0.25F;
1794 1854
1795 } 1855 }
1796
1797 return pos;
1798 } 1856 }
1799 else 1857 else
1800 { 1858 {
1801 // We don't have a target here, so we're going to raytrace all the objects in the scene. 1859 // We don't have a target here, so we're going to raytrace all the objects in the scene.
1802
1803 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false); 1860 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false);
1804 1861
1805 // Un-comment the following line to print the raytrace results to the console. 1862 // Un-comment the following line to print the raytrace results to the console.
@@ -1808,13 +1865,12 @@ namespace OpenSim.Region.Framework.Scenes
1808 if (ei.HitTF) 1865 if (ei.HitTF)
1809 { 1866 {
1810 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z); 1867 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z);
1811 } else 1868 }
1869 else
1812 { 1870 {
1813 // fall back to our stupid functionality 1871 // fall back to our stupid functionality
1814 pos = RayEnd; 1872 pos = RayEnd;
1815 } 1873 }
1816
1817 return pos;
1818 } 1874 }
1819 } 1875 }
1820 else 1876 else
@@ -1825,8 +1881,12 @@ namespace OpenSim.Region.Framework.Scenes
1825 //increase height so its above the ground. 1881 //increase height so its above the ground.
1826 //should be getting the normal of the ground at the rez point and using that? 1882 //should be getting the normal of the ground at the rez point and using that?
1827 pos.Z += scale.Z / 2f; 1883 pos.Z += scale.Z / 2f;
1828 return pos; 1884// return pos;
1829 } 1885 }
1886
1887 // check against posible water intercept
1888 if (wpos.Z > pos.Z) pos = wpos;
1889 return pos;
1830 } 1890 }
1831 1891
1832 1892
@@ -1910,7 +1970,10 @@ namespace OpenSim.Region.Framework.Scenes
1910 public bool AddRestoredSceneObject( 1970 public bool AddRestoredSceneObject(
1911 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 1971 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
1912 { 1972 {
1913 return m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates); 1973 bool result = m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates);
1974 if (result)
1975 sceneObject.IsDeleted = false;
1976 return result;
1914 } 1977 }
1915 1978
1916 /// <summary> 1979 /// <summary>
@@ -2002,6 +2065,15 @@ namespace OpenSim.Region.Framework.Scenes
2002 /// </summary> 2065 /// </summary>
2003 public void DeleteAllSceneObjects() 2066 public void DeleteAllSceneObjects()
2004 { 2067 {
2068 DeleteAllSceneObjects(false);
2069 }
2070
2071 /// <summary>
2072 /// Delete every object from the scene. This does not include attachments worn by avatars.
2073 /// </summary>
2074 public void DeleteAllSceneObjects(bool exceptNoCopy)
2075 {
2076 List<SceneObjectGroup> toReturn = new List<SceneObjectGroup>();
2005 lock (Entities) 2077 lock (Entities)
2006 { 2078 {
2007 EntityBase[] entities = Entities.GetEntities(); 2079 EntityBase[] entities = Entities.GetEntities();
@@ -2010,11 +2082,24 @@ namespace OpenSim.Region.Framework.Scenes
2010 if (e is SceneObjectGroup) 2082 if (e is SceneObjectGroup)
2011 { 2083 {
2012 SceneObjectGroup sog = (SceneObjectGroup)e; 2084 SceneObjectGroup sog = (SceneObjectGroup)e;
2013 if (!sog.IsAttachment) 2085 if (sog != null && !sog.IsAttachment)
2014 DeleteSceneObject((SceneObjectGroup)e, false); 2086 {
2087 if (!exceptNoCopy || ((sog.GetEffectivePermissions() & (uint)PermissionMask.Copy) != 0))
2088 {
2089 DeleteSceneObject((SceneObjectGroup)e, false);
2090 }
2091 else
2092 {
2093 toReturn.Add((SceneObjectGroup)e);
2094 }
2095 }
2015 } 2096 }
2016 } 2097 }
2017 } 2098 }
2099 if (toReturn.Count > 0)
2100 {
2101 returnObjects(toReturn.ToArray(), UUID.Zero);
2102 }
2018 } 2103 }
2019 2104
2020 /// <summary> 2105 /// <summary>
@@ -2062,6 +2147,8 @@ namespace OpenSim.Region.Framework.Scenes
2062 } 2147 }
2063 2148
2064 group.DeleteGroupFromScene(silent); 2149 group.DeleteGroupFromScene(silent);
2150 if (!silent)
2151 SendKillObject(new List<uint>() { group.LocalId });
2065 2152
2066// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID); 2153// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID);
2067 } 2154 }
@@ -2416,10 +2503,17 @@ namespace OpenSim.Region.Framework.Scenes
2416 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns> 2503 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns>
2417 public bool AddSceneObject(SceneObjectGroup sceneObject) 2504 public bool AddSceneObject(SceneObjectGroup sceneObject)
2418 { 2505 {
2506 if (sceneObject.OwnerID == UUID.Zero)
2507 {
2508 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero", sceneObject.UUID);
2509 return false;
2510 }
2511
2419 // If the user is banned, we won't let any of their objects 2512 // If the user is banned, we won't let any of their objects
2420 // enter. Period. 2513 // enter. Period.
2421 // 2514 //
2422 if (m_regInfo.EstateSettings.IsBanned(sceneObject.OwnerID)) 2515 int flags = GetUserFlags(sceneObject.OwnerID);
2516 if (m_regInfo.EstateSettings.IsBanned(sceneObject.OwnerID, flags))
2423 { 2517 {
2424 m_log.InfoFormat("[INTERREGION]: Denied prim crossing for banned avatar {0}", sceneObject.OwnerID); 2518 m_log.InfoFormat("[INTERREGION]: Denied prim crossing for banned avatar {0}", sceneObject.OwnerID);
2425 2519
@@ -2465,12 +2559,23 @@ namespace OpenSim.Region.Framework.Scenes
2465 } 2559 }
2466 else 2560 else
2467 { 2561 {
2562 m_log.DebugFormat("[SCENE]: Attachment {0} arrived and scene presence was not found, setting to temp", sceneObject.UUID);
2468 RootPrim.RemFlag(PrimFlags.TemporaryOnRez); 2563 RootPrim.RemFlag(PrimFlags.TemporaryOnRez);
2469 RootPrim.AddFlag(PrimFlags.TemporaryOnRez); 2564 RootPrim.AddFlag(PrimFlags.TemporaryOnRez);
2470 } 2565 }
2566 if (sceneObject.OwnerID == UUID.Zero)
2567 {
2568 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero after attachment processing. BUG!", sceneObject.UUID);
2569 return false;
2570 }
2471 } 2571 }
2472 else 2572 else
2473 { 2573 {
2574 if (sceneObject.OwnerID == UUID.Zero)
2575 {
2576 m_log.ErrorFormat("[SCENE]: Owner ID for non-attachment {0} was zero", sceneObject.UUID);
2577 return false;
2578 }
2474 AddRestoredSceneObject(sceneObject, true, false); 2579 AddRestoredSceneObject(sceneObject, true, false);
2475 2580
2476 if (!Permissions.CanObjectEntry(sceneObject.UUID, 2581 if (!Permissions.CanObjectEntry(sceneObject.UUID,
@@ -2499,6 +2604,24 @@ namespace OpenSim.Region.Framework.Scenes
2499 return 2; // StateSource.PrimCrossing 2604 return 2; // StateSource.PrimCrossing
2500 } 2605 }
2501 2606
2607 public int GetUserFlags(UUID user)
2608 {
2609 //Unfortunately the SP approach means that the value is cached until region is restarted
2610 /*
2611 ScenePresence sp;
2612 if (TryGetScenePresence(user, out sp))
2613 {
2614 return sp.UserFlags;
2615 }
2616 else
2617 {
2618 */
2619 UserAccount uac = UserAccountService.GetUserAccount(RegionInfo.ScopeID, user);
2620 if (uac == null)
2621 return 0;
2622 return uac.UserFlags;
2623 //}
2624 }
2502 #endregion 2625 #endregion
2503 2626
2504 #region Add/Remove Avatar Methods 2627 #region Add/Remove Avatar Methods
@@ -2513,6 +2636,7 @@ namespace OpenSim.Region.Framework.Scenes
2513 || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; 2636 || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0;
2514 2637
2515 CheckHeartbeat(); 2638 CheckHeartbeat();
2639 ScenePresence presence;
2516 2640
2517 ScenePresence sp = GetScenePresence(client.AgentId); 2641 ScenePresence sp = GetScenePresence(client.AgentId);
2518 2642
@@ -2561,7 +2685,13 @@ namespace OpenSim.Region.Framework.Scenes
2561 2685
2562 EventManager.TriggerOnNewClient(client); 2686 EventManager.TriggerOnNewClient(client);
2563 if (vialogin) 2687 if (vialogin)
2688 {
2564 EventManager.TriggerOnClientLogin(client); 2689 EventManager.TriggerOnClientLogin(client);
2690 // Send initial parcel data
2691 Vector3 pos = sp.AbsolutePosition;
2692 ILandObject land = LandChannel.GetLandObject(pos.X, pos.Y);
2693 land.SendLandUpdateToClient(client);
2694 }
2565 2695
2566 return sp; 2696 return sp;
2567 } 2697 }
@@ -2651,19 +2781,12 @@ namespace OpenSim.Region.Framework.Scenes
2651 // and the scene presence and the client, if they exist 2781 // and the scene presence and the client, if they exist
2652 try 2782 try
2653 { 2783 {
2654 // We need to wait for the client to make UDP contact first. 2784 ScenePresence sp = GetScenePresence(agentID);
2655 // It's the UDP contact that creates the scene presence 2785 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
2656 ScenePresence sp = WaitGetScenePresence(agentID); 2786
2657 if (sp != null) 2787 if (sp != null)
2658 {
2659 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
2660
2661 sp.ControllingClient.Close(); 2788 sp.ControllingClient.Close();
2662 } 2789
2663 else
2664 {
2665 m_log.WarnFormat("[SCENE]: Could not find scene presence for {0}", agentID);
2666 }
2667 // BANG! SLASH! 2790 // BANG! SLASH!
2668 m_authenticateHandler.RemoveCircuit(agentID); 2791 m_authenticateHandler.RemoveCircuit(agentID);
2669 2792
@@ -2764,6 +2887,7 @@ namespace OpenSim.Region.Framework.Scenes
2764 client.OnFetchInventory += m_asyncInventorySender.HandleFetchInventory; 2887 client.OnFetchInventory += m_asyncInventorySender.HandleFetchInventory;
2765 client.OnUpdateInventoryItem += UpdateInventoryItemAsset; 2888 client.OnUpdateInventoryItem += UpdateInventoryItemAsset;
2766 client.OnCopyInventoryItem += CopyInventoryItem; 2889 client.OnCopyInventoryItem += CopyInventoryItem;
2890 client.OnMoveItemsAndLeaveCopy += MoveInventoryItemsLeaveCopy;
2767 client.OnMoveInventoryItem += MoveInventoryItem; 2891 client.OnMoveInventoryItem += MoveInventoryItem;
2768 client.OnRemoveInventoryItem += RemoveInventoryItem; 2892 client.OnRemoveInventoryItem += RemoveInventoryItem;
2769 client.OnRemoveInventoryFolder += RemoveInventoryFolder; 2893 client.OnRemoveInventoryFolder += RemoveInventoryFolder;
@@ -2939,15 +3063,16 @@ namespace OpenSim.Region.Framework.Scenes
2939 /// </summary> 3063 /// </summary>
2940 /// <param name="agentId">The avatar's Unique ID</param> 3064 /// <param name="agentId">The avatar's Unique ID</param>
2941 /// <param name="client">The IClientAPI for the client</param> 3065 /// <param name="client">The IClientAPI for the client</param>
2942 public virtual void TeleportClientHome(UUID agentId, IClientAPI client) 3066 public virtual bool TeleportClientHome(UUID agentId, IClientAPI client)
2943 { 3067 {
2944 if (m_teleportModule != null) 3068 if (m_teleportModule != null)
2945 m_teleportModule.TeleportHome(agentId, client); 3069 return m_teleportModule.TeleportHome(agentId, client);
2946 else 3070 else
2947 { 3071 {
2948 m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active"); 3072 m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active");
2949 client.SendTeleportFailed("Unable to perform teleports on this simulator."); 3073 client.SendTeleportFailed("Unable to perform teleports on this simulator.");
2950 } 3074 }
3075 return false;
2951 } 3076 }
2952 3077
2953 /// <summary> 3078 /// <summary>
@@ -3039,6 +3164,16 @@ namespace OpenSim.Region.Framework.Scenes
3039 /// <param name="flags"></param> 3164 /// <param name="flags"></param>
3040 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags) 3165 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags)
3041 { 3166 {
3167 //Add half the avatar's height so that the user doesn't fall through prims
3168 ScenePresence presence;
3169 if (TryGetScenePresence(remoteClient.AgentId, out presence))
3170 {
3171 if (presence.Appearance != null)
3172 {
3173 position.Z = position.Z + (presence.Appearance.AvatarHeight / 2);
3174 }
3175 }
3176
3042 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt)) 3177 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt))
3043 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot. 3178 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot.
3044 m_dialogModule.SendAlertToUser(remoteClient, "Home position set."); 3179 m_dialogModule.SendAlertToUser(remoteClient, "Home position set.");
@@ -3107,8 +3242,9 @@ namespace OpenSim.Region.Framework.Scenes
3107 regions.Remove(RegionInfo.RegionHandle); 3242 regions.Remove(RegionInfo.RegionHandle);
3108 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); 3243 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions);
3109 } 3244 }
3110 3245 m_log.Debug("[Scene] Beginning ClientClosed");
3111 m_eventManager.TriggerClientClosed(agentID, this); 3246 m_eventManager.TriggerClientClosed(agentID, this);
3247 m_log.Debug("[Scene] Finished ClientClosed");
3112 } 3248 }
3113 catch (NullReferenceException) 3249 catch (NullReferenceException)
3114 { 3250 {
@@ -3160,9 +3296,10 @@ namespace OpenSim.Region.Framework.Scenes
3160 { 3296 {
3161 m_log.ErrorFormat("[SCENE] Scene.cs:RemoveClient exception {0}{1}", e.Message, e.StackTrace); 3297 m_log.ErrorFormat("[SCENE] Scene.cs:RemoveClient exception {0}{1}", e.Message, e.StackTrace);
3162 } 3298 }
3163 3299 m_log.Debug("[Scene] Done. Firing RemoveCircuit");
3164 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode); 3300 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode);
3165// CleanDroppedAttachments(); 3301// CleanDroppedAttachments();
3302 m_log.Debug("[Scene] The avatar has left the building");
3166 //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false)); 3303 //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false));
3167 //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true)); 3304 //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true));
3168 } 3305 }
@@ -3281,13 +3418,16 @@ namespace OpenSim.Region.Framework.Scenes
3281 sp = null; 3418 sp = null;
3282 } 3419 }
3283 3420
3284 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3285 3421
3286 //On login test land permisions 3422 //On login test land permisions
3287 if (vialogin) 3423 if (vialogin)
3288 { 3424 {
3289 if (land != null && !TestLandRestrictions(agent, land, out reason)) 3425 IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>();
3426 if (cache != null)
3427 cache.Remove(agent.firstname + " " + agent.lastname);
3428 if (!TestLandRestrictions(agent.AgentID, out reason, ref agent.startpos.X, ref agent.startpos.Y))
3290 { 3429 {
3430 m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString());
3291 return false; 3431 return false;
3292 } 3432 }
3293 } 3433 }
@@ -3311,8 +3451,13 @@ namespace OpenSim.Region.Framework.Scenes
3311 3451
3312 try 3452 try
3313 { 3453 {
3314 if (!AuthorizeUser(agent, out reason)) 3454 // Always check estate if this is a login. Always
3315 return false; 3455 // check if banned regions are to be blacked out.
3456 if (vialogin || (!m_seeIntoBannedRegion))
3457 {
3458 if (!AuthorizeUser(agent, out reason))
3459 return false;
3460 }
3316 } 3461 }
3317 catch (Exception e) 3462 catch (Exception e)
3318 { 3463 {
@@ -3415,6 +3560,8 @@ namespace OpenSim.Region.Framework.Scenes
3415 } 3560 }
3416 } 3561 }
3417 // Honor parcel landing type and position. 3562 // Honor parcel landing type and position.
3563 /*
3564 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3418 if (land != null) 3565 if (land != null)
3419 { 3566 {
3420 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) 3567 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero)
@@ -3422,26 +3569,34 @@ namespace OpenSim.Region.Framework.Scenes
3422 agent.startpos = land.LandData.UserLocation; 3569 agent.startpos = land.LandData.UserLocation;
3423 } 3570 }
3424 } 3571 }
3572 */// This is now handled properly in ScenePresence.MakeRootAgent
3425 } 3573 }
3426 3574
3427 return true; 3575 return true;
3428 } 3576 }
3429 3577
3430 private bool TestLandRestrictions(AgentCircuitData agent, ILandObject land, out string reason) 3578 public bool TestLandRestrictions(UUID agentID, out string reason, ref float posX, ref float posY)
3431 { 3579 {
3432 3580 reason = String.Empty;
3433 bool banned = land.IsBannedFromLand(agent.AgentID); 3581 if (Permissions.IsGod(agentID))
3434 bool restricted = land.IsRestrictedFromLand(agent.AgentID); 3582 return true;
3583
3584 ILandObject land = LandChannel.GetLandObject(posX, posY);
3585 if (land == null)
3586 return false;
3587
3588 bool banned = land.IsBannedFromLand(agentID);
3589 bool restricted = land.IsRestrictedFromLand(agentID);
3435 3590
3436 if (banned || restricted) 3591 if (banned || restricted)
3437 { 3592 {
3438 ILandObject nearestParcel = GetNearestAllowedParcel(agent.AgentID, agent.startpos.X, agent.startpos.Y); 3593 ILandObject nearestParcel = GetNearestAllowedParcel(agentID, posX, posY);
3439 if (nearestParcel != null) 3594 if (nearestParcel != null)
3440 { 3595 {
3441 //Move agent to nearest allowed 3596 //Move agent to nearest allowed
3442 Vector3 newPosition = GetParcelCenterAtGround(nearestParcel); 3597 Vector3 newPosition = GetParcelCenterAtGround(nearestParcel);
3443 agent.startpos.X = newPosition.X; 3598 posX = newPosition.X;
3444 agent.startpos.Y = newPosition.Y; 3599 posY = newPosition.Y;
3445 } 3600 }
3446 else 3601 else
3447 { 3602 {
@@ -3503,7 +3658,7 @@ namespace OpenSim.Region.Framework.Scenes
3503 3658
3504 if (!m_strictAccessControl) return true; 3659 if (!m_strictAccessControl) return true;
3505 if (Permissions.IsGod(agent.AgentID)) return true; 3660 if (Permissions.IsGod(agent.AgentID)) return true;
3506 3661
3507 if (AuthorizationService != null) 3662 if (AuthorizationService != null)
3508 { 3663 {
3509 if (!AuthorizationService.IsAuthorizedForRegion( 3664 if (!AuthorizationService.IsAuthorizedForRegion(
@@ -3511,14 +3666,14 @@ namespace OpenSim.Region.Framework.Scenes
3511 { 3666 {
3512 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the region", 3667 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the region",
3513 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 3668 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
3514 3669
3515 return false; 3670 return false;
3516 } 3671 }
3517 } 3672 }
3518 3673
3519 if (m_regInfo.EstateSettings != null) 3674 if (m_regInfo.EstateSettings != null)
3520 { 3675 {
3521 if (m_regInfo.EstateSettings.IsBanned(agent.AgentID)) 3676 if (m_regInfo.EstateSettings.IsBanned(agent.AgentID,0))
3522 { 3677 {
3523 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist", 3678 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist",
3524 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 3679 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
@@ -3710,6 +3865,13 @@ namespace OpenSim.Region.Framework.Scenes
3710 3865
3711 // We have to wait until the viewer contacts this region after receiving EAC. 3866 // We have to wait until the viewer contacts this region after receiving EAC.
3712 // That calls AddNewClient, which finally creates the ScenePresence 3867 // That calls AddNewClient, which finally creates the ScenePresence
3868 int flags = GetUserFlags(cAgentData.AgentID);
3869 if (m_regInfo.EstateSettings.IsBanned(cAgentData.AgentID, flags))
3870 {
3871 m_log.DebugFormat("[SCENE]: Denying root agent entry to {0}: banned", cAgentData.AgentID);
3872 return false;
3873 }
3874
3713 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2); 3875 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2);
3714 if (nearestParcel == null) 3876 if (nearestParcel == null)
3715 { 3877 {
@@ -3791,12 +3953,22 @@ namespace OpenSim.Region.Framework.Scenes
3791 return false; 3953 return false;
3792 } 3954 }
3793 3955
3956 public bool IncomingCloseAgent(UUID agentID)
3957 {
3958 return IncomingCloseAgent(agentID, false);
3959 }
3960
3961 public bool IncomingCloseChildAgent(UUID agentID)
3962 {
3963 return IncomingCloseAgent(agentID, true);
3964 }
3965
3794 /// <summary> 3966 /// <summary>
3795 /// Tell a single agent to disconnect from the region. 3967 /// Tell a single agent to disconnect from the region.
3796 /// </summary> 3968 /// </summary>
3797 /// <param name="regionHandle"></param>
3798 /// <param name="agentID"></param> 3969 /// <param name="agentID"></param>
3799 public bool IncomingCloseAgent(UUID agentID) 3970 /// <param name="childOnly"></param>
3971 public bool IncomingCloseAgent(UUID agentID, bool childOnly)
3800 { 3972 {
3801 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); 3973 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID);
3802 3974
@@ -3808,7 +3980,7 @@ namespace OpenSim.Region.Framework.Scenes
3808 { 3980 {
3809 m_sceneGraph.removeUserCount(false); 3981 m_sceneGraph.removeUserCount(false);
3810 } 3982 }
3811 else 3983 else if (!childOnly)
3812 { 3984 {
3813 m_sceneGraph.removeUserCount(true); 3985 m_sceneGraph.removeUserCount(true);
3814 } 3986 }
@@ -3824,9 +3996,12 @@ namespace OpenSim.Region.Framework.Scenes
3824 } 3996 }
3825 else 3997 else
3826 presence.ControllingClient.SendShutdownConnectionNotice(); 3998 presence.ControllingClient.SendShutdownConnectionNotice();
3999 presence.ControllingClient.Close(false);
4000 }
4001 else if (!childOnly)
4002 {
4003 presence.ControllingClient.Close(true);
3827 } 4004 }
3828
3829 presence.ControllingClient.Close();
3830 return true; 4005 return true;
3831 } 4006 }
3832 4007
@@ -4409,34 +4584,78 @@ namespace OpenSim.Region.Framework.Scenes
4409 SimulationDataService.RemoveObject(uuid, m_regInfo.RegionID); 4584 SimulationDataService.RemoveObject(uuid, m_regInfo.RegionID);
4410 } 4585 }
4411 4586
4412 public int GetHealth() 4587 public int GetHealth(out int flags, out string message)
4413 { 4588 {
4414 // Returns: 4589 // Returns:
4415 // 1 = sim is up and accepting http requests. The heartbeat has 4590 // 1 = sim is up and accepting http requests. The heartbeat has
4416 // stopped and the sim is probably locked up, but a remote 4591 // stopped and the sim is probably locked up, but a remote
4417 // admin restart may succeed 4592 // admin restart may succeed
4418 // 4593 //
4419 // 2 = Sim is up and the heartbeat is running. The sim is likely 4594 // 2 = Sim is up and the heartbeat is running. The sim is likely
4420 // usable for people within and logins _may_ work 4595 // usable for people within
4596 //
4597 // 3 = Sim is up and one packet thread is running. Sim is
4598 // unstable and will not accept new logins
4421 // 4599 //
4422 // 3 = We have seen a new user enter within the past 4 minutes 4600 // 4 = Sim is up and both packet threads are running. Sim is
4601 // likely usable
4602 //
4603 // 5 = We have seen a new user enter within the past 4 minutes
4423 // which can be seen as positive confirmation of sim health 4604 // which can be seen as positive confirmation of sim health
4424 // 4605 //
4606
4607 flags = 0;
4608 message = String.Empty;
4609
4610 CheckHeartbeat();
4611
4612 if (m_firstHeartbeat || (m_lastIncoming == 0 && m_lastOutgoing == 0))
4613 {
4614 // We're still starting
4615 // 0 means "in startup", it can't happen another way, since
4616 // to get here, we must be able to accept http connections
4617 return 0;
4618 }
4619
4425 int health=1; // Start at 1, means we're up 4620 int health=1; // Start at 1, means we're up
4426 4621
4427 if ((Util.EnvironmentTickCountSubtract(m_lastUpdate)) < 1000) 4622 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) < 1000)
4623 {
4428 health+=1; 4624 health+=1;
4625 flags |= 1;
4626 }
4627
4628 if (Util.EnvironmentTickCountSubtract(m_lastIncoming) < 1000)
4629 {
4630 health+=1;
4631 flags |= 2;
4632 }
4633
4634 if (Util.EnvironmentTickCountSubtract(m_lastOutgoing) < 1000)
4635 {
4636 health+=1;
4637 flags |= 4;
4638 }
4429 else 4639 else
4640 {
4641int pid = System.Diagnostics.Process.GetCurrentProcess().Id;
4642System.Diagnostics.Process proc = new System.Diagnostics.Process();
4643proc.EnableRaisingEvents=false;
4644proc.StartInfo.FileName = "/bin/kill";
4645proc.StartInfo.Arguments = "-QUIT " + pid.ToString();
4646proc.Start();
4647proc.WaitForExit();
4648Thread.Sleep(1000);
4649Environment.Exit(1);
4650 }
4651
4652 if (flags != 7)
4430 return health; 4653 return health;
4431 4654
4432 // A login in the last 4 mins? We can't be doing too badly 4655 // A login in the last 4 mins? We can't be doing too badly
4433 // 4656 //
4434 if ((Util.EnvironmentTickCountSubtract(m_LastLogin)) < 240000) 4657 if (Util.EnvironmentTickCountSubtract(m_LastLogin) < 240000)
4435 health++; 4658 health++;
4436 else
4437 return health;
4438
4439 CheckHeartbeat();
4440 4659
4441 return health; 4660 return health;
4442 } 4661 }
@@ -4629,7 +4848,7 @@ namespace OpenSim.Region.Framework.Scenes
4629 if (m_firstHeartbeat) 4848 if (m_firstHeartbeat)
4630 return; 4849 return;
4631 4850
4632 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) > 2000) 4851 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) > 5000)
4633 StartTimer(); 4852 StartTimer();
4634 } 4853 }
4635 4854
@@ -5039,7 +5258,55 @@ namespace OpenSim.Region.Framework.Scenes
5039 mapModule.GenerateMaptile(); 5258 mapModule.GenerateMaptile();
5040 } 5259 }
5041 5260
5042 private void RegenerateMaptileAndReregister(object sender, ElapsedEventArgs e) 5261// public void CleanDroppedAttachments()
5262// {
5263// List<SceneObjectGroup> objectsToDelete =
5264// new List<SceneObjectGroup>();
5265//
5266// lock (m_cleaningAttachments)
5267// {
5268// ForEachSOG(delegate (SceneObjectGroup grp)
5269// {
5270// if (grp.RootPart.Shape.PCode == 0 && grp.RootPart.Shape.State != 0 && (!objectsToDelete.Contains(grp)))
5271// {
5272// UUID agentID = grp.OwnerID;
5273// if (agentID == UUID.Zero)
5274// {
5275// objectsToDelete.Add(grp);
5276// return;
5277// }
5278//
5279// ScenePresence sp = GetScenePresence(agentID);
5280// if (sp == null)
5281// {
5282// objectsToDelete.Add(grp);
5283// return;
5284// }
5285// }
5286// });
5287// }
5288//
5289// foreach (SceneObjectGroup grp in objectsToDelete)
5290// {
5291// m_log.InfoFormat("[SCENE]: Deleting dropped attachment {0} of user {1}", grp.UUID, grp.OwnerID);
5292// DeleteSceneObject(grp, true);
5293// }
5294// }
5295
5296 public void ThreadAlive(int threadCode)
5297 {
5298 switch(threadCode)
5299 {
5300 case 1: // Incoming
5301 m_lastIncoming = Util.EnvironmentTickCount();
5302 break;
5303 case 2: // Incoming
5304 m_lastOutgoing = Util.EnvironmentTickCount();
5305 break;
5306 }
5307 }
5308
5309 public void RegenerateMaptileAndReregister(object sender, ElapsedEventArgs e)
5043 { 5310 {
5044 RegenerateMaptile(); 5311 RegenerateMaptile();
5045 5312
@@ -5058,6 +5325,14 @@ namespace OpenSim.Region.Framework.Scenes
5058 // child agent creation, thereby emulating the SL behavior. 5325 // child agent creation, thereby emulating the SL behavior.
5059 public bool QueryAccess(UUID agentID, Vector3 position, out string reason) 5326 public bool QueryAccess(UUID agentID, Vector3 position, out string reason)
5060 { 5327 {
5328 reason = "You are banned from the region";
5329
5330 if (Permissions.IsGod(agentID))
5331 {
5332 reason = String.Empty;
5333 return true;
5334 }
5335
5061 int num = m_sceneGraph.GetNumberOfScenePresences(); 5336 int num = m_sceneGraph.GetNumberOfScenePresences();
5062 5337
5063 if (num >= RegionInfo.RegionSettings.AgentLimit) 5338 if (num >= RegionInfo.RegionSettings.AgentLimit)
@@ -5069,6 +5344,41 @@ namespace OpenSim.Region.Framework.Scenes
5069 } 5344 }
5070 } 5345 }
5071 5346
5347 ScenePresence presence = GetScenePresence(agentID);
5348 IClientAPI client = null;
5349 AgentCircuitData aCircuit = null;
5350
5351 if (presence != null)
5352 {
5353 client = presence.ControllingClient;
5354 if (client != null)
5355 aCircuit = client.RequestClientInfo();
5356 }
5357
5358 // We may be called before there is a presence or a client.
5359 // Fake AgentCircuitData to keep IAuthorizationModule smiling
5360 if (client == null)
5361 {
5362 aCircuit = new AgentCircuitData();
5363 aCircuit.AgentID = agentID;
5364 aCircuit.firstname = String.Empty;
5365 aCircuit.lastname = String.Empty;
5366 }
5367
5368 try
5369 {
5370 if (!AuthorizeUser(aCircuit, out reason))
5371 {
5372 // m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID);
5373 return false;
5374 }
5375 }
5376 catch (Exception e)
5377 {
5378 m_log.DebugFormat("[SCENE]: Exception authorizing agent: {0} "+ e.StackTrace, e.Message);
5379 return false;
5380 }
5381
5072 if (position == Vector3.Zero) // Teleport 5382 if (position == Vector3.Zero) // Teleport
5073 { 5383 {
5074 if (!RegionInfo.EstateSettings.AllowDirectTeleport) 5384 if (!RegionInfo.EstateSettings.AllowDirectTeleport)
@@ -5097,13 +5407,46 @@ namespace OpenSim.Region.Framework.Scenes
5097 } 5407 }
5098 } 5408 }
5099 } 5409 }
5410
5411 float posX = 128.0f;
5412 float posY = 128.0f;
5413
5414 if (!TestLandRestrictions(agentID, out reason, ref posX, ref posY))
5415 {
5416 // m_log.DebugFormat("[SCENE]: Denying {0} because they are banned on all parcels", agentID);
5417 return false;
5418 }
5419 }
5420 else // Walking
5421 {
5422 ILandObject land = LandChannel.GetLandObject(position.X, position.Y);
5423 if (land == null)
5424 return false;
5425
5426 bool banned = land.IsBannedFromLand(agentID);
5427 bool restricted = land.IsRestrictedFromLand(agentID);
5428
5429 if (banned || restricted)
5430 return false;
5100 } 5431 }
5101 5432
5102 reason = String.Empty; 5433 reason = String.Empty;
5103 return true; 5434 return true;
5104 } 5435 }
5105 5436
5106 /// <summary> 5437 public void StartTimerWatchdog()
5438 {
5439 m_timerWatchdog.Interval = 1000;
5440 m_timerWatchdog.Elapsed += TimerWatchdog;
5441 m_timerWatchdog.AutoReset = true;
5442 m_timerWatchdog.Start();
5443 }
5444
5445 public void TimerWatchdog(object sender, ElapsedEventArgs e)
5446 {
5447 CheckHeartbeat();
5448 }
5449
5107 /// This method deals with movement when an avatar is automatically moving (but this is distinct from the 5450 /// This method deals with movement when an avatar is automatically moving (but this is distinct from the
5108 /// autopilot that moves an avatar to a sit target!. 5451 /// autopilot that moves an avatar to a sit target!.
5109 /// </summary> 5452 /// </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 06de72f..aecca27 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -41,6 +41,12 @@ namespace OpenSim.Region.Framework.Scenes
41{ 41{
42 public delegate void PhysicsCrash(); 42 public delegate void PhysicsCrash();
43 43
44 public delegate void AttachToBackupDelegate(SceneObjectGroup sog);
45
46 public delegate void DetachFromBackupDelegate(SceneObjectGroup sog);
47
48 public delegate void ChangedBackupDelegate(SceneObjectGroup sog);
49
44 /// <summary> 50 /// <summary>
45 /// This class used to be called InnerScene and may not yet truly be a SceneGraph. The non scene graph components 51 /// This class used to be called InnerScene and may not yet truly be a SceneGraph. The non scene graph components
46 /// should be migrated out over time. 52 /// should be migrated out over time.
@@ -54,11 +60,15 @@ namespace OpenSim.Region.Framework.Scenes
54 protected internal event PhysicsCrash UnRecoverableError; 60 protected internal event PhysicsCrash UnRecoverableError;
55 private PhysicsCrash handlerPhysicsCrash = null; 61 private PhysicsCrash handlerPhysicsCrash = null;
56 62
63 public event AttachToBackupDelegate OnAttachToBackup;
64 public event DetachFromBackupDelegate OnDetachFromBackup;
65 public event ChangedBackupDelegate OnChangeBackup;
66
57 #endregion 67 #endregion
58 68
59 #region Fields 69 #region Fields
60 70
61 protected object m_presenceLock = new object(); 71 protected OpenMetaverse.ReaderWriterLockSlim m_scenePresencesLock = new OpenMetaverse.ReaderWriterLockSlim();
62 protected Dictionary<UUID, ScenePresence> m_scenePresenceMap = new Dictionary<UUID, ScenePresence>(); 72 protected Dictionary<UUID, ScenePresence> m_scenePresenceMap = new Dictionary<UUID, ScenePresence>();
63 protected List<ScenePresence> m_scenePresenceArray = new List<ScenePresence>(); 73 protected List<ScenePresence> m_scenePresenceArray = new List<ScenePresence>();
64 74
@@ -120,13 +130,18 @@ namespace OpenSim.Region.Framework.Scenes
120 130
121 protected internal void Close() 131 protected internal void Close()
122 { 132 {
123 lock (m_presenceLock) 133 m_scenePresencesLock.EnterWriteLock();
134 try
124 { 135 {
125 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(); 136 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>();
126 List<ScenePresence> newlist = new List<ScenePresence>(); 137 List<ScenePresence> newlist = new List<ScenePresence>();
127 m_scenePresenceMap = newmap; 138 m_scenePresenceMap = newmap;
128 m_scenePresenceArray = newlist; 139 m_scenePresenceArray = newlist;
129 } 140 }
141 finally
142 {
143 m_scenePresencesLock.ExitWriteLock();
144 }
130 145
131 lock (SceneObjectGroupsByFullID) 146 lock (SceneObjectGroupsByFullID)
132 SceneObjectGroupsByFullID.Clear(); 147 SceneObjectGroupsByFullID.Clear();
@@ -265,6 +280,33 @@ namespace OpenSim.Region.Framework.Scenes
265 protected internal bool AddRestoredSceneObject( 280 protected internal bool AddRestoredSceneObject(
266 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 281 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
267 { 282 {
283 if (!m_parentScene.CombineRegions)
284 {
285 // KF: Check for out-of-region, move inside and make static.
286 Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X,
287 sceneObject.RootPart.GroupPosition.Y,
288 sceneObject.RootPart.GroupPosition.Z);
289 if (!(((sceneObject.RootPart.Shape.PCode == (byte)PCode.Prim) && (sceneObject.RootPart.Shape.State != 0))) && (npos.X < 0.0 || npos.Y < 0.0 || npos.Z < 0.0 ||
290 npos.X > Constants.RegionSize ||
291 npos.Y > Constants.RegionSize))
292 {
293 if (npos.X < 0.0) npos.X = 1.0f;
294 if (npos.Y < 0.0) npos.Y = 1.0f;
295 if (npos.Z < 0.0) npos.Z = 0.0f;
296 if (npos.X > Constants.RegionSize) npos.X = Constants.RegionSize - 1.0f;
297 if (npos.Y > Constants.RegionSize) npos.Y = Constants.RegionSize - 1.0f;
298
299 foreach (SceneObjectPart part in sceneObject.Parts)
300 {
301 part.GroupPosition = npos;
302 }
303 sceneObject.RootPart.Velocity = Vector3.Zero;
304 sceneObject.RootPart.AngularVelocity = Vector3.Zero;
305 sceneObject.RootPart.Acceleration = Vector3.Zero;
306 sceneObject.RootPart.Velocity = Vector3.Zero;
307 }
308 }
309
268 if (attachToBackup && (!alreadyPersisted)) 310 if (attachToBackup && (!alreadyPersisted))
269 { 311 {
270 sceneObject.ForceInventoryPersistence(); 312 sceneObject.ForceInventoryPersistence();
@@ -353,6 +395,11 @@ namespace OpenSim.Region.Framework.Scenes
353 /// </returns> 395 /// </returns>
354 protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) 396 protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates)
355 { 397 {
398 if (sceneObject == null)
399 {
400 m_log.ErrorFormat("[SCENEGRAPH]: Tried to add null scene object");
401 return false;
402 }
356 if (sceneObject.UUID == UUID.Zero) 403 if (sceneObject.UUID == UUID.Zero)
357 { 404 {
358 m_log.ErrorFormat( 405 m_log.ErrorFormat(
@@ -487,6 +534,30 @@ namespace OpenSim.Region.Framework.Scenes
487 m_updateList[obj.UUID] = obj; 534 m_updateList[obj.UUID] = obj;
488 } 535 }
489 536
537 public void FireAttachToBackup(SceneObjectGroup obj)
538 {
539 if (OnAttachToBackup != null)
540 {
541 OnAttachToBackup(obj);
542 }
543 }
544
545 public void FireDetachFromBackup(SceneObjectGroup obj)
546 {
547 if (OnDetachFromBackup != null)
548 {
549 OnDetachFromBackup(obj);
550 }
551 }
552
553 public void FireChangeBackup(SceneObjectGroup obj)
554 {
555 if (OnChangeBackup != null)
556 {
557 OnChangeBackup(obj);
558 }
559 }
560
490 /// <summary> 561 /// <summary>
491 /// Process all pending updates 562 /// Process all pending updates
492 /// </summary> 563 /// </summary>
@@ -604,7 +675,8 @@ namespace OpenSim.Region.Framework.Scenes
604 675
605 Entities[presence.UUID] = presence; 676 Entities[presence.UUID] = presence;
606 677
607 lock (m_presenceLock) 678 m_scenePresencesLock.EnterWriteLock();
679 try
608 { 680 {
609 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 681 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
610 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 682 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -628,6 +700,10 @@ namespace OpenSim.Region.Framework.Scenes
628 m_scenePresenceMap = newmap; 700 m_scenePresenceMap = newmap;
629 m_scenePresenceArray = newlist; 701 m_scenePresenceArray = newlist;
630 } 702 }
703 finally
704 {
705 m_scenePresencesLock.ExitWriteLock();
706 }
631 } 707 }
632 708
633 /// <summary> 709 /// <summary>
@@ -642,7 +718,8 @@ namespace OpenSim.Region.Framework.Scenes
642 agentID); 718 agentID);
643 } 719 }
644 720
645 lock (m_presenceLock) 721 m_scenePresencesLock.EnterWriteLock();
722 try
646 { 723 {
647 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 724 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
648 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 725 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -664,6 +741,10 @@ namespace OpenSim.Region.Framework.Scenes
664 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); 741 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID);
665 } 742 }
666 } 743 }
744 finally
745 {
746 m_scenePresencesLock.ExitWriteLock();
747 }
667 } 748 }
668 749
669 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) 750 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F)
@@ -1379,8 +1460,13 @@ namespace OpenSim.Region.Framework.Scenes
1379 { 1460 {
1380 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) 1461 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0))
1381 { 1462 {
1382 if (m_parentScene.AttachmentsModule != null) 1463 // Set the new attachment point data in the object
1383 m_parentScene.AttachmentsModule.UpdateAttachmentPosition(group, pos); 1464 byte attachmentPoint = group.GetAttachmentPoint();
1465 group.UpdateGroupPosition(pos);
1466 group.IsAttachment = false;
1467 group.AbsolutePosition = group.RootPart.AttachedPos;
1468 group.AttachmentPoint = attachmentPoint;
1469 group.HasGroupChanged = true;
1384 } 1470 }
1385 else 1471 else
1386 { 1472 {
@@ -1652,8 +1738,11 @@ namespace OpenSim.Region.Framework.Scenes
1652 return; 1738 return;
1653 1739
1654 Monitor.Enter(m_updateLock); 1740 Monitor.Enter(m_updateLock);
1741
1655 try 1742 try
1656 { 1743 {
1744 parentGroup.areUpdatesSuspended = true;
1745
1657 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); 1746 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
1658 1747
1659 // We do this in reverse to get the link order of the prims correct 1748 // We do this in reverse to get the link order of the prims correct
@@ -1664,9 +1753,13 @@ namespace OpenSim.Region.Framework.Scenes
1664 // Make sure no child prim is set for sale 1753 // Make sure no child prim is set for sale
1665 // So that, on delink, no prims are unwittingly 1754 // So that, on delink, no prims are unwittingly
1666 // left for sale and sold off 1755 // left for sale and sold off
1667 child.RootPart.ObjectSaleType = 0; 1756
1668 child.RootPart.SalePrice = 10; 1757 if (child != null)
1669 childGroups.Add(child); 1758 {
1759 child.RootPart.ObjectSaleType = 0;
1760 child.RootPart.SalePrice = 10;
1761 childGroups.Add(child);
1762 }
1670 } 1763 }
1671 1764
1672 foreach (SceneObjectGroup child in childGroups) 1765 foreach (SceneObjectGroup child in childGroups)
@@ -1685,12 +1778,19 @@ namespace OpenSim.Region.Framework.Scenes
1685 // occur on link to invoke this elsewhere (such as object selection) 1778 // occur on link to invoke this elsewhere (such as object selection)
1686 parentGroup.RootPart.CreateSelected = true; 1779 parentGroup.RootPart.CreateSelected = true;
1687 parentGroup.TriggerScriptChangedEvent(Changed.LINK); 1780 parentGroup.TriggerScriptChangedEvent(Changed.LINK);
1688 parentGroup.HasGroupChanged = true;
1689 parentGroup.ScheduleGroupForFullUpdate();
1690
1691 } 1781 }
1692 finally 1782 finally
1693 { 1783 {
1784 lock (SceneObjectGroupsByLocalPartID)
1785 {
1786 foreach (SceneObjectPart part in parentGroup.Parts)
1787 SceneObjectGroupsByLocalPartID[part.LocalId] = parentGroup;
1788 }
1789
1790 parentGroup.areUpdatesSuspended = false;
1791 parentGroup.HasGroupChanged = true;
1792 parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true);
1793 parentGroup.ScheduleGroupForFullUpdate();
1694 Monitor.Exit(m_updateLock); 1794 Monitor.Exit(m_updateLock);
1695 } 1795 }
1696 } 1796 }
@@ -1727,21 +1827,24 @@ namespace OpenSim.Region.Framework.Scenes
1727 1827
1728 SceneObjectGroup group = part.ParentGroup; 1828 SceneObjectGroup group = part.ParentGroup;
1729 if (!affectedGroups.Contains(group)) 1829 if (!affectedGroups.Contains(group))
1830 {
1831 group.areUpdatesSuspended = true;
1730 affectedGroups.Add(group); 1832 affectedGroups.Add(group);
1833 }
1731 } 1834 }
1732 } 1835 }
1733 } 1836 }
1734 1837
1735 foreach (SceneObjectPart child in childParts) 1838 if (childParts.Count > 0)
1736 { 1839 {
1737 // Unlink all child parts from their groups 1840 foreach (SceneObjectPart child in childParts)
1738 // 1841 {
1739 child.ParentGroup.DelinkFromGroup(child, true); 1842 // Unlink all child parts from their groups
1740 1843 //
1741 // These are not in affected groups and will not be 1844 child.ParentGroup.DelinkFromGroup(child, true);
1742 // handled further. Do the honors here. 1845 child.ParentGroup.HasGroupChanged = true;
1743 child.ParentGroup.HasGroupChanged = true; 1846 child.ParentGroup.ScheduleGroupForFullUpdate();
1744 child.ParentGroup.ScheduleGroupForFullUpdate(); 1847 }
1745 } 1848 }
1746 1849
1747 foreach (SceneObjectPart root in rootParts) 1850 foreach (SceneObjectPart root in rootParts)
@@ -1751,56 +1854,68 @@ namespace OpenSim.Region.Framework.Scenes
1751 // However, editing linked parts and unlinking may be different 1854 // However, editing linked parts and unlinking may be different
1752 // 1855 //
1753 SceneObjectGroup group = root.ParentGroup; 1856 SceneObjectGroup group = root.ParentGroup;
1857 group.areUpdatesSuspended = true;
1754 1858
1755 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); 1859 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts);
1756 int numChildren = newSet.Count; 1860 int numChildren = newSet.Count;
1757 1861
1862 if (numChildren == 1)
1863 break;
1864
1758 // If there are prims left in a link set, but the root is 1865 // If there are prims left in a link set, but the root is
1759 // slated for unlink, we need to do this 1866 // slated for unlink, we need to do this
1867 // Unlink the remaining set
1760 // 1868 //
1761 if (numChildren != 1) 1869 bool sendEventsToRemainder = true;
1762 { 1870 if (numChildren > 1)
1763 // Unlink the remaining set 1871 sendEventsToRemainder = false;
1764 //
1765 bool sendEventsToRemainder = true;
1766 if (numChildren > 1)
1767 sendEventsToRemainder = false;
1768 1872
1769 foreach (SceneObjectPart p in newSet) 1873 foreach (SceneObjectPart p in newSet)
1874 {
1875 if (p != group.RootPart)
1770 { 1876 {
1771 if (p != group.RootPart) 1877 group.DelinkFromGroup(p, sendEventsToRemainder);
1772 group.DelinkFromGroup(p, sendEventsToRemainder); 1878 if (numChildren > 2)
1879 {
1880 p.ParentGroup.areUpdatesSuspended = true;
1881 }
1882 else
1883 {
1884 p.ParentGroup.HasGroupChanged = true;
1885 p.ParentGroup.ScheduleGroupForFullUpdate();
1886 }
1773 } 1887 }
1888 }
1889
1890 // If there is more than one prim remaining, we
1891 // need to re-link
1892 //
1893 if (numChildren > 2)
1894 {
1895 // Remove old root
1896 //
1897 if (newSet.Contains(root))
1898 newSet.Remove(root);
1774 1899
1775 // If there is more than one prim remaining, we 1900 // Preserve link ordering
1776 // need to re-link
1777 // 1901 //
1778 if (numChildren > 2) 1902 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1779 { 1903 {
1780 // Remove old root 1904 return a.LinkNum.CompareTo(b.LinkNum);
1781 // 1905 });
1782 if (newSet.Contains(root))
1783 newSet.Remove(root);
1784
1785 // Preserve link ordering
1786 //
1787 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1788 {
1789 return a.LinkNum.CompareTo(b.LinkNum);
1790 });
1791 1906
1792 // Determine new root 1907 // Determine new root
1793 // 1908 //
1794 SceneObjectPart newRoot = newSet[0]; 1909 SceneObjectPart newRoot = newSet[0];
1795 newSet.RemoveAt(0); 1910 newSet.RemoveAt(0);
1796 1911
1797 foreach (SceneObjectPart newChild in newSet) 1912 foreach (SceneObjectPart newChild in newSet)
1798 newChild.ClearUpdateSchedule(); 1913 newChild.ClearUpdateSchedule();
1799 1914
1800 LinkObjects(newRoot, newSet); 1915 newRoot.ParentGroup.areUpdatesSuspended = true;
1801 if (!affectedGroups.Contains(newRoot.ParentGroup)) 1916 LinkObjects(newRoot, newSet);
1802 affectedGroups.Add(newRoot.ParentGroup); 1917 if (!affectedGroups.Contains(newRoot.ParentGroup))
1803 } 1918 affectedGroups.Add(newRoot.ParentGroup);
1804 } 1919 }
1805 } 1920 }
1806 1921
@@ -1808,8 +1923,14 @@ namespace OpenSim.Region.Framework.Scenes
1808 // 1923 //
1809 foreach (SceneObjectGroup g in affectedGroups) 1924 foreach (SceneObjectGroup g in affectedGroups)
1810 { 1925 {
1926 // Child prims that have been unlinked and deleted will
1927 // return unless the root is deleted. This will remove them
1928 // from the database. They will be rewritten immediately,
1929 // minus the rows for the unlinked child prims.
1930 m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID);
1811 g.TriggerScriptChangedEvent(Changed.LINK); 1931 g.TriggerScriptChangedEvent(Changed.LINK);
1812 g.HasGroupChanged = true; // Persist 1932 g.HasGroupChanged = true; // Persist
1933 g.areUpdatesSuspended = false;
1813 g.ScheduleGroupForFullUpdate(); 1934 g.ScheduleGroupForFullUpdate();
1814 } 1935 }
1815 } 1936 }
@@ -1927,9 +2048,6 @@ namespace OpenSim.Region.Framework.Scenes
1927 child.ApplyNextOwnerPermissions(); 2048 child.ApplyNextOwnerPermissions();
1928 } 2049 }
1929 } 2050 }
1930
1931 copy.RootPart.ObjectSaleType = 0;
1932 copy.RootPart.SalePrice = 10;
1933 } 2051 }
1934 2052
1935 // FIXME: This section needs to be refactored so that it just calls AddSceneObject() 2053 // FIXME: This section needs to be refactored so that it just calls AddSceneObject()
diff --git a/OpenSim/Region/Framework/Scenes/SceneManager.cs b/OpenSim/Region/Framework/Scenes/SceneManager.cs
index d73a959..e4eaf3a 100644
--- a/OpenSim/Region/Framework/Scenes/SceneManager.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneManager.cs
@@ -356,7 +356,7 @@ namespace OpenSim.Region.Framework.Scenes
356 356
357 public bool TrySetCurrentScene(UUID regionID) 357 public bool TrySetCurrentScene(UUID regionID)
358 { 358 {
359 m_log.Debug("Searching for Region: '" + regionID + "'"); 359// m_log.Debug("Searching for Region: '" + regionID + "'");
360 360
361 lock (m_localScenes) 361 lock (m_localScenes)
362 { 362 {
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
index f173c95..b56d3fc 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
@@ -69,10 +69,6 @@ namespace OpenSim.Region.Framework.Scenes
69 /// <summary> 69 /// <summary>
70 /// Stop the scripts contained in all the prims in this group 70 /// Stop the scripts contained in all the prims in this group
71 /// </summary> 71 /// </summary>
72 /// <param name="sceneObjectBeingDeleted">
73 /// Should be true if these scripts are being removed because the scene
74 /// object is being deleted. This will prevent spurious updates to the client.
75 /// </param>
76 public void RemoveScriptInstances(bool sceneObjectBeingDeleted) 72 public void RemoveScriptInstances(bool sceneObjectBeingDeleted)
77 { 73 {
78 SceneObjectPart[] parts = m_parts.GetArray(); 74 SceneObjectPart[] parts = m_parts.GetArray();
@@ -227,6 +223,11 @@ namespace OpenSim.Region.Framework.Scenes
227 223
228 public uint GetEffectivePermissions() 224 public uint GetEffectivePermissions()
229 { 225 {
226 return GetEffectivePermissions(false);
227 }
228
229 public uint GetEffectivePermissions(bool useBase)
230 {
230 uint perms=(uint)(PermissionMask.Modify | 231 uint perms=(uint)(PermissionMask.Modify |
231 PermissionMask.Copy | 232 PermissionMask.Copy |
232 PermissionMask.Move | 233 PermissionMask.Move |
@@ -238,7 +239,10 @@ namespace OpenSim.Region.Framework.Scenes
238 for (int i = 0; i < parts.Length; i++) 239 for (int i = 0; i < parts.Length; i++)
239 { 240 {
240 SceneObjectPart part = parts[i]; 241 SceneObjectPart part = parts[i];
241 ownerMask &= part.OwnerMask; 242 if (useBase)
243 ownerMask &= part.BaseMask;
244 else
245 ownerMask &= part.OwnerMask;
242 perms &= part.Inventory.MaskEffectivePermissions(); 246 perms &= part.Inventory.MaskEffectivePermissions();
243 } 247 }
244 248
@@ -378,6 +382,9 @@ namespace OpenSim.Region.Framework.Scenes
378 382
379 public void ResumeScripts() 383 public void ResumeScripts()
380 { 384 {
385 if (m_scene.RegionInfo.RegionSettings.DisableScripts)
386 return;
387
381 SceneObjectPart[] parts = m_parts.GetArray(); 388 SceneObjectPart[] parts = m_parts.GetArray();
382 for (int i = 0; i < parts.Length; i++) 389 for (int i = 0; i < parts.Length; i++)
383 parts[i].Inventory.ResumeScripts(); 390 parts[i].Inventory.ResumeScripts();
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 739c5fa..cf7bf16 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 //{
@@ -571,6 +668,7 @@ namespace OpenSim.Region.Framework.Scenes
571 /// </summary> 668 /// </summary>
572 public SceneObjectGroup() 669 public SceneObjectGroup()
573 { 670 {
671
574 } 672 }
575 673
576 /// <summary> 674 /// <summary>
@@ -587,7 +685,7 @@ namespace OpenSim.Region.Framework.Scenes
587 /// Constructor. This object is added to the scene later via AttachToScene() 685 /// Constructor. This object is added to the scene later via AttachToScene()
588 /// </summary> 686 /// </summary>
589 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) 687 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape)
590 { 688 {
591 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero)); 689 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero));
592 } 690 }
593 691
@@ -635,6 +733,9 @@ namespace OpenSim.Region.Framework.Scenes
635 /// </summary> 733 /// </summary>
636 public virtual void AttachToBackup() 734 public virtual void AttachToBackup()
637 { 735 {
736 if (IsAttachment) return;
737 m_scene.SceneGraph.FireAttachToBackup(this);
738
638 if (InSceneBackup) 739 if (InSceneBackup)
639 { 740 {
640 //m_log.DebugFormat( 741 //m_log.DebugFormat(
@@ -677,6 +778,9 @@ namespace OpenSim.Region.Framework.Scenes
677 778
678 ApplyPhysics(); 779 ApplyPhysics();
679 780
781 if (RootPart.PhysActor != null)
782 RootPart.Buoyancy = RootPart.Buoyancy;
783
680 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled 784 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled
681 // for the same object with very different properties. The caller must schedule the update. 785 // for the same object with very different properties. The caller must schedule the update.
682 //ScheduleGroupForFullUpdate(); 786 //ScheduleGroupForFullUpdate();
@@ -692,6 +796,10 @@ namespace OpenSim.Region.Framework.Scenes
692 EntityIntersection result = new EntityIntersection(); 796 EntityIntersection result = new EntityIntersection();
693 797
694 SceneObjectPart[] parts = m_parts.GetArray(); 798 SceneObjectPart[] parts = m_parts.GetArray();
799
800 // Find closest hit here
801 float idist = float.MaxValue;
802
695 for (int i = 0; i < parts.Length; i++) 803 for (int i = 0; i < parts.Length; i++)
696 { 804 {
697 SceneObjectPart part = parts[i]; 805 SceneObjectPart part = parts[i];
@@ -706,11 +814,6 @@ namespace OpenSim.Region.Framework.Scenes
706 814
707 EntityIntersection inter = part.TestIntersectionOBB(hRay, parentrotation, frontFacesOnly, faceCenters); 815 EntityIntersection inter = part.TestIntersectionOBB(hRay, parentrotation, frontFacesOnly, faceCenters);
708 816
709 // This may need to be updated to the maximum draw distance possible..
710 // We might (and probably will) be checking for prim creation from other sims
711 // when the camera crosses the border.
712 float idist = Constants.RegionSize;
713
714 if (inter.HitTF) 817 if (inter.HitTF)
715 { 818 {
716 // We need to find the closest prim to return to the testcaller along the ray 819 // We need to find the closest prim to return to the testcaller along the ray
@@ -721,10 +824,11 @@ namespace OpenSim.Region.Framework.Scenes
721 result.obj = part; 824 result.obj = part;
722 result.normal = inter.normal; 825 result.normal = inter.normal;
723 result.distance = inter.distance; 826 result.distance = inter.distance;
827
828 idist = inter.distance;
724 } 829 }
725 } 830 }
726 } 831 }
727
728 return result; 832 return result;
729 } 833 }
730 834
@@ -744,17 +848,19 @@ namespace OpenSim.Region.Framework.Scenes
744 minZ = 8192f; 848 minZ = 8192f;
745 849
746 SceneObjectPart[] parts = m_parts.GetArray(); 850 SceneObjectPart[] parts = m_parts.GetArray();
747 for (int i = 0; i < parts.Length; i++) 851 foreach (SceneObjectPart part in parts)
748 { 852 {
749 SceneObjectPart part = parts[i];
750
751 Vector3 worldPos = part.GetWorldPosition(); 853 Vector3 worldPos = part.GetWorldPosition();
752 Vector3 offset = worldPos - AbsolutePosition; 854 Vector3 offset = worldPos - AbsolutePosition;
753 Quaternion worldRot; 855 Quaternion worldRot;
754 if (part.ParentID == 0) 856 if (part.ParentID == 0)
857 {
755 worldRot = part.RotationOffset; 858 worldRot = part.RotationOffset;
859 }
756 else 860 else
861 {
757 worldRot = part.GetWorldRotation(); 862 worldRot = part.GetWorldRotation();
863 }
758 864
759 Vector3 frontTopLeft; 865 Vector3 frontTopLeft;
760 Vector3 frontTopRight; 866 Vector3 frontTopRight;
@@ -766,6 +872,8 @@ namespace OpenSim.Region.Framework.Scenes
766 Vector3 backBottomLeft; 872 Vector3 backBottomLeft;
767 Vector3 backBottomRight; 873 Vector3 backBottomRight;
768 874
875 // Vector3[] corners = new Vector3[8];
876
769 Vector3 orig = Vector3.Zero; 877 Vector3 orig = Vector3.Zero;
770 878
771 frontTopLeft.X = orig.X - (part.Scale.X / 2); 879 frontTopLeft.X = orig.X - (part.Scale.X / 2);
@@ -800,6 +908,38 @@ namespace OpenSim.Region.Framework.Scenes
800 backBottomRight.Y = orig.Y + (part.Scale.Y / 2); 908 backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
801 backBottomRight.Z = orig.Z - (part.Scale.Z / 2); 909 backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
802 910
911
912
913 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
914 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
915 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
916 //m_log.InfoFormat("pre corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
917 //m_log.InfoFormat("pre corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
918 //m_log.InfoFormat("pre corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
919 //m_log.InfoFormat("pre corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
920 //m_log.InfoFormat("pre corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
921
922 //for (int i = 0; i < 8; i++)
923 //{
924 // corners[i] = corners[i] * worldRot;
925 // corners[i] += offset;
926
927 // if (corners[i].X > maxX)
928 // maxX = corners[i].X;
929 // if (corners[i].X < minX)
930 // minX = corners[i].X;
931
932 // if (corners[i].Y > maxY)
933 // maxY = corners[i].Y;
934 // if (corners[i].Y < minY)
935 // minY = corners[i].Y;
936
937 // if (corners[i].Z > maxZ)
938 // maxZ = corners[i].Y;
939 // if (corners[i].Z < minZ)
940 // minZ = corners[i].Z;
941 //}
942
803 frontTopLeft = frontTopLeft * worldRot; 943 frontTopLeft = frontTopLeft * worldRot;
804 frontTopRight = frontTopRight * worldRot; 944 frontTopRight = frontTopRight * worldRot;
805 frontBottomLeft = frontBottomLeft * worldRot; 945 frontBottomLeft = frontBottomLeft * worldRot;
@@ -821,6 +961,15 @@ namespace OpenSim.Region.Framework.Scenes
821 backTopLeft += offset; 961 backTopLeft += offset;
822 backTopRight += offset; 962 backTopRight += offset;
823 963
964 //m_log.InfoFormat("corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
965 //m_log.InfoFormat("corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
966 //m_log.InfoFormat("corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
967 //m_log.InfoFormat("corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
968 //m_log.InfoFormat("corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
969 //m_log.InfoFormat("corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
970 //m_log.InfoFormat("corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
971 //m_log.InfoFormat("corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
972
824 if (frontTopRight.X > maxX) 973 if (frontTopRight.X > maxX)
825 maxX = frontTopRight.X; 974 maxX = frontTopRight.X;
826 if (frontTopLeft.X > maxX) 975 if (frontTopLeft.X > maxX)
@@ -966,15 +1115,20 @@ namespace OpenSim.Region.Framework.Scenes
966 1115
967 public void SaveScriptedState(XmlTextWriter writer) 1116 public void SaveScriptedState(XmlTextWriter writer)
968 { 1117 {
1118 SaveScriptedState(writer, false);
1119 }
1120
1121 public void SaveScriptedState(XmlTextWriter writer, bool oldIDs)
1122 {
969 XmlDocument doc = new XmlDocument(); 1123 XmlDocument doc = new XmlDocument();
970 Dictionary<UUID,string> states = new Dictionary<UUID,string>(); 1124 Dictionary<UUID,string> states = new Dictionary<UUID,string>();
971 1125
972 SceneObjectPart[] parts = m_parts.GetArray(); 1126 SceneObjectPart[] parts = m_parts.GetArray();
973 for (int i = 0; i < parts.Length; i++) 1127 for (int i = 0; i < parts.Length; i++)
974 { 1128 {
975 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(); 1129 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(oldIDs);
976 foreach (KeyValuePair<UUID, string> kvp in pstates) 1130 foreach (KeyValuePair<UUID, string> kvp in pstates)
977 states.Add(kvp.Key, kvp.Value); 1131 states[kvp.Key] = kvp.Value;
978 } 1132 }
979 1133
980 if (states.Count > 0) 1134 if (states.Count > 0)
@@ -994,6 +1148,168 @@ namespace OpenSim.Region.Framework.Scenes
994 } 1148 }
995 1149
996 /// <summary> 1150 /// <summary>
1151 /// Add the avatar to this linkset (avatar is sat).
1152 /// </summary>
1153 /// <param name="agentID"></param>
1154 public void AddAvatar(UUID agentID)
1155 {
1156 ScenePresence presence;
1157 if (m_scene.TryGetScenePresence(agentID, out presence))
1158 {
1159 if (!m_linkedAvatars.Contains(presence))
1160 {
1161 m_linkedAvatars.Add(presence);
1162 }
1163 }
1164 }
1165
1166 /// <summary>
1167 /// Delete the avatar from this linkset (avatar is unsat).
1168 /// </summary>
1169 /// <param name="agentID"></param>
1170 public void DeleteAvatar(UUID agentID)
1171 {
1172 ScenePresence presence;
1173 if (m_scene.TryGetScenePresence(agentID, out presence))
1174 {
1175 if (m_linkedAvatars.Contains(presence))
1176 {
1177 m_linkedAvatars.Remove(presence);
1178 }
1179 }
1180 }
1181
1182 /// <summary>
1183 /// Returns the list of linked presences (avatars sat on this group)
1184 /// </summary>
1185 /// <param name="agentID"></param>
1186 public List<ScenePresence> GetLinkedAvatars()
1187 {
1188 return m_linkedAvatars;
1189 }
1190
1191 /// <summary>
1192 /// Attach this scene object to the given avatar.
1193 /// </summary>
1194 /// <param name="agentID"></param>
1195 /// <param name="attachmentpoint"></param>
1196 /// <param name="AttachOffset"></param>
1197 private void AttachToAgent(
1198 ScenePresence avatar, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent)
1199 {
1200 if (avatar != null)
1201 {
1202 // don't attach attachments to child agents
1203 if (avatar.IsChildAgent) return;
1204
1205 // Remove from database and parcel prim count
1206 m_scene.DeleteFromStorage(so.UUID);
1207 m_scene.EventManager.TriggerParcelPrimCountTainted();
1208
1209 so.AttachedAvatar = avatar.UUID;
1210
1211 if (so.RootPart.PhysActor != null)
1212 {
1213 m_scene.PhysicsScene.RemovePrim(so.RootPart.PhysActor);
1214 so.RootPart.PhysActor = null;
1215 }
1216
1217 so.AbsolutePosition = attachOffset;
1218 so.RootPart.AttachedPos = attachOffset;
1219 so.IsAttachment = true;
1220 so.RootPart.SetParentLocalId(avatar.LocalId);
1221 so.AttachmentPoint = attachmentpoint;
1222
1223 avatar.AddAttachment(this);
1224
1225 if (!silent)
1226 {
1227 // Killing it here will cause the client to deselect it
1228 // It then reappears on the avatar, deselected
1229 // through the full update below
1230 //
1231 if (IsSelected)
1232 {
1233 m_scene.SendKillObject(new List<uint> { m_rootPart.LocalId });
1234 }
1235
1236 IsSelected = false; // fudge....
1237 ScheduleGroupForFullUpdate();
1238 }
1239 }
1240 else
1241 {
1242 m_log.WarnFormat(
1243 "[SOG]: Tried to add attachment {0} to avatar with UUID {1} in region {2} but the avatar is not present",
1244 UUID, avatar.ControllingClient.AgentId, Scene.RegionInfo.RegionName);
1245 }
1246 }
1247
1248 public byte GetAttachmentPoint()
1249 {
1250 return m_rootPart.Shape.State;
1251 }
1252
1253 public void DetachToGround()
1254 {
1255 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
1256 if (avatar == null)
1257 return;
1258
1259 avatar.RemoveAttachment(this);
1260
1261 Vector3 detachedpos = new Vector3(127f,127f,127f);
1262 if (avatar == null)
1263 return;
1264
1265 detachedpos = avatar.AbsolutePosition;
1266 RootPart.FromItemID = UUID.Zero;
1267
1268 AbsolutePosition = detachedpos;
1269 AttachedAvatar = UUID.Zero;
1270
1271 //SceneObjectPart[] parts = m_parts.GetArray();
1272 //for (int i = 0; i < parts.Length; i++)
1273 // parts[i].AttachedAvatar = UUID.Zero;
1274
1275 m_rootPart.SetParentLocalId(0);
1276 AttachmentPoint = (byte)0;
1277 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive);
1278 HasGroupChanged = true;
1279 RootPart.Rezzed = DateTime.Now;
1280 RootPart.RemFlag(PrimFlags.TemporaryOnRez);
1281 AttachToBackup();
1282 m_scene.EventManager.TriggerParcelPrimCountTainted();
1283 m_rootPart.ScheduleFullUpdate();
1284 m_rootPart.ClearUndoState();
1285 }
1286
1287 public void DetachToInventoryPrep()
1288 {
1289 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
1290 //Vector3 detachedpos = new Vector3(127f, 127f, 127f);
1291 if (avatar != null)
1292 {
1293 //detachedpos = avatar.AbsolutePosition;
1294 avatar.RemoveAttachment(this);
1295 }
1296
1297 AttachedAvatar = UUID.Zero;
1298
1299 /*SceneObjectPart[] parts = m_parts.GetArray();
1300 for (int i = 0; i < parts.Length; i++)
1301 parts[i].AttachedAvatar = UUID.Zero;*/
1302
1303 m_rootPart.SetParentLocalId(0);
1304 //m_rootPart.SetAttachmentPoint((byte)0);
1305 IsAttachment = false;
1306 AbsolutePosition = m_rootPart.AttachedPos;
1307 //m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_scene.m_physicalPrim);
1308 //AttachToBackup();
1309 //m_rootPart.ScheduleFullUpdate();
1310 }
1311
1312 /// <summary>
997 /// 1313 ///
998 /// </summary> 1314 /// </summary>
999 /// <param name="part"></param> 1315 /// <param name="part"></param>
@@ -1043,7 +1359,10 @@ namespace OpenSim.Region.Framework.Scenes
1043 public void AddPart(SceneObjectPart part) 1359 public void AddPart(SceneObjectPart part)
1044 { 1360 {
1045 part.SetParent(this); 1361 part.SetParent(this);
1046 part.LinkNum = m_parts.Add(part.UUID, part); 1362 m_parts.Add(part.UUID, part);
1363
1364 part.LinkNum = m_parts.Count;
1365
1047 if (part.LinkNum == 2) 1366 if (part.LinkNum == 2)
1048 RootPart.LinkNum = 1; 1367 RootPart.LinkNum = 1;
1049 } 1368 }
@@ -1151,6 +1470,11 @@ namespace OpenSim.Region.Framework.Scenes
1151 /// <param name="silent">If true then deletion is not broadcast to clients</param> 1470 /// <param name="silent">If true then deletion is not broadcast to clients</param>
1152 public void DeleteGroupFromScene(bool silent) 1471 public void DeleteGroupFromScene(bool silent)
1153 { 1472 {
1473 // We need to keep track of this state in case this group is still queued for backup.
1474 IsDeleted = true;
1475
1476 DetachFromBackup();
1477
1154 SceneObjectPart[] parts = m_parts.GetArray(); 1478 SceneObjectPart[] parts = m_parts.GetArray();
1155 for (int i = 0; i < parts.Length; i++) 1479 for (int i = 0; i < parts.Length; i++)
1156 { 1480 {
@@ -1173,6 +1497,8 @@ namespace OpenSim.Region.Framework.Scenes
1173 } 1497 }
1174 }); 1498 });
1175 } 1499 }
1500
1501
1176 } 1502 }
1177 1503
1178 public void AddScriptLPS(int count) 1504 public void AddScriptLPS(int count)
@@ -1268,7 +1594,12 @@ namespace OpenSim.Region.Framework.Scenes
1268 1594
1269 public void SetOwnerId(UUID userId) 1595 public void SetOwnerId(UUID userId)
1270 { 1596 {
1271 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); 1597 ForEachPart(delegate(SceneObjectPart part)
1598 {
1599
1600 part.OwnerID = userId;
1601
1602 });
1272 } 1603 }
1273 1604
1274 public void ForEachPart(Action<SceneObjectPart> whatToDo) 1605 public void ForEachPart(Action<SceneObjectPart> whatToDo)
@@ -1300,11 +1631,17 @@ namespace OpenSim.Region.Framework.Scenes
1300 return; 1631 return;
1301 } 1632 }
1302 1633
1634 if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
1635 return;
1636
1303 // Since this is the top of the section of call stack for backing up a particular scene object, don't let 1637 // Since this is the top of the section of call stack for backing up a particular scene object, don't let
1304 // any exception propogate upwards. 1638 // any exception propogate upwards.
1305 try 1639 try
1306 { 1640 {
1307 if (!m_scene.ShuttingDown) // if shutting down then there will be nothing to handle the return so leave till next restart 1641 if (!m_scene.ShuttingDown || // if shutting down then there will be nothing to handle the return so leave till next restart
1642 m_scene.LoginsDisabled || // We're starting up or doing maintenance, don't mess with things
1643 m_scene.LoadingPrims) // Land may not be valid yet
1644
1308 { 1645 {
1309 ILandObject parcel = m_scene.LandChannel.GetLandObject( 1646 ILandObject parcel = m_scene.LandChannel.GetLandObject(
1310 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y); 1647 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y);
@@ -1331,6 +1668,7 @@ namespace OpenSim.Region.Framework.Scenes
1331 } 1668 }
1332 } 1669 }
1333 } 1670 }
1671
1334 } 1672 }
1335 1673
1336 if (m_scene.UseBackup && HasGroupChanged) 1674 if (m_scene.UseBackup && HasGroupChanged)
@@ -1338,6 +1676,20 @@ namespace OpenSim.Region.Framework.Scenes
1338 // don't backup while it's selected or you're asking for changes mid stream. 1676 // don't backup while it's selected or you're asking for changes mid stream.
1339 if (isTimeToPersist() || forcedBackup) 1677 if (isTimeToPersist() || forcedBackup)
1340 { 1678 {
1679 if (m_rootPart.PhysActor != null &&
1680 (!m_rootPart.PhysActor.IsPhysical))
1681 {
1682 // Possible ghost prim
1683 if (m_rootPart.PhysActor.Position != m_rootPart.GroupPosition)
1684 {
1685 foreach (SceneObjectPart part in m_parts.GetArray())
1686 {
1687 // Re-set physics actor positions and
1688 // orientations
1689 part.GroupPosition = m_rootPart.GroupPosition;
1690 }
1691 }
1692 }
1341// m_log.DebugFormat( 1693// m_log.DebugFormat(
1342// "[SCENE]: Storing {0}, {1} in {2}", 1694// "[SCENE]: Storing {0}, {1} in {2}",
1343// Name, UUID, m_scene.RegionInfo.RegionName); 1695// Name, UUID, m_scene.RegionInfo.RegionName);
@@ -1421,7 +1773,7 @@ namespace OpenSim.Region.Framework.Scenes
1421 // This is only necessary when userExposed is false! 1773 // This is only necessary when userExposed is false!
1422 1774
1423 bool previousAttachmentStatus = dupe.IsAttachment; 1775 bool previousAttachmentStatus = dupe.IsAttachment;
1424 1776
1425 if (!userExposed) 1777 if (!userExposed)
1426 dupe.IsAttachment = true; 1778 dupe.IsAttachment = true;
1427 1779
@@ -1439,11 +1791,11 @@ namespace OpenSim.Region.Framework.Scenes
1439 dupe.m_rootPart.TrimPermissions(); 1791 dupe.m_rootPart.TrimPermissions();
1440 1792
1441 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray()); 1793 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray());
1442 1794
1443 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) 1795 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1444 { 1796 {
1445 return p1.LinkNum.CompareTo(p2.LinkNum); 1797 return p1.LinkNum.CompareTo(p2.LinkNum);
1446 } 1798 }
1447 ); 1799 );
1448 1800
1449 foreach (SceneObjectPart part in partList) 1801 foreach (SceneObjectPart part in partList)
@@ -1463,7 +1815,7 @@ namespace OpenSim.Region.Framework.Scenes
1463 if (part.PhysActor != null && userExposed) 1815 if (part.PhysActor != null && userExposed)
1464 { 1816 {
1465 PrimitiveBaseShape pbs = newPart.Shape; 1817 PrimitiveBaseShape pbs = newPart.Shape;
1466 1818
1467 newPart.PhysActor 1819 newPart.PhysActor
1468 = m_scene.PhysicsScene.AddPrimShape( 1820 = m_scene.PhysicsScene.AddPrimShape(
1469 string.Format("{0}/{1}", newPart.Name, newPart.UUID), 1821 string.Format("{0}/{1}", newPart.Name, newPart.UUID),
@@ -1473,11 +1825,11 @@ namespace OpenSim.Region.Framework.Scenes
1473 newPart.RotationOffset, 1825 newPart.RotationOffset,
1474 part.PhysActor.IsPhysical, 1826 part.PhysActor.IsPhysical,
1475 newPart.LocalId); 1827 newPart.LocalId);
1476 1828
1477 newPart.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true); 1829 newPart.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true);
1478 } 1830 }
1479 } 1831 }
1480 1832
1481 if (userExposed) 1833 if (userExposed)
1482 { 1834 {
1483 dupe.UpdateParentIDs(); 1835 dupe.UpdateParentIDs();
@@ -1592,6 +1944,7 @@ namespace OpenSim.Region.Framework.Scenes
1592 return Vector3.Zero; 1944 return Vector3.Zero;
1593 } 1945 }
1594 1946
1947 // This is used by both Double-Click Auto-Pilot and llMoveToTarget() in an attached object
1595 public void moveToTarget(Vector3 target, float tau) 1948 public void moveToTarget(Vector3 target, float tau)
1596 { 1949 {
1597 if (IsAttachment) 1950 if (IsAttachment)
@@ -1619,6 +1972,46 @@ namespace OpenSim.Region.Framework.Scenes
1619 RootPart.PhysActor.PIDActive = false; 1972 RootPart.PhysActor.PIDActive = false;
1620 } 1973 }
1621 1974
1975 public void rotLookAt(Quaternion target, float strength, float damping)
1976 {
1977 SceneObjectPart rootpart = m_rootPart;
1978 if (rootpart != null)
1979 {
1980 if (IsAttachment)
1981 {
1982 /*
1983 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
1984 if (avatar != null)
1985 {
1986 Rotate the Av?
1987 } */
1988 }
1989 else
1990 {
1991 if (rootpart.PhysActor != null)
1992 { // APID must be implemented in your physics system for this to function.
1993 rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W);
1994 rootpart.PhysActor.APIDStrength = strength;
1995 rootpart.PhysActor.APIDDamping = damping;
1996 rootpart.PhysActor.APIDActive = true;
1997 }
1998 }
1999 }
2000 }
2001
2002 public void stopLookAt()
2003 {
2004 SceneObjectPart rootpart = m_rootPart;
2005 if (rootpart != null)
2006 {
2007 if (rootpart.PhysActor != null)
2008 { // APID must be implemented in your physics system for this to function.
2009 rootpart.PhysActor.APIDActive = false;
2010 }
2011 }
2012
2013 }
2014
1622 /// <summary> 2015 /// <summary>
1623 /// Uses a PID to attempt to clamp the object on the Z axis at the given height over tau seconds. 2016 /// Uses a PID to attempt to clamp the object on the Z axis at the given height over tau seconds.
1624 /// </summary> 2017 /// </summary>
@@ -1674,6 +2067,8 @@ namespace OpenSim.Region.Framework.Scenes
1674 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) 2067 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
1675 { 2068 {
1676 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 2069 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
2070 newPart.SetParent(this);
2071
1677 AddPart(newPart); 2072 AddPart(newPart);
1678 2073
1679 SetPartAsNonRoot(newPart); 2074 SetPartAsNonRoot(newPart);
@@ -1802,11 +2197,11 @@ namespace OpenSim.Region.Framework.Scenes
1802 /// Immediately send a full update for this scene object. 2197 /// Immediately send a full update for this scene object.
1803 /// </summary> 2198 /// </summary>
1804 public void SendGroupFullUpdate() 2199 public void SendGroupFullUpdate()
1805 { 2200 {
1806 if (IsDeleted) 2201 if (IsDeleted)
1807 return; 2202 return;
1808 2203
1809// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); 2204// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID);
1810 2205
1811 RootPart.SendFullUpdateToAllClients(); 2206 RootPart.SendFullUpdateToAllClients();
1812 2207
@@ -2007,7 +2402,7 @@ namespace OpenSim.Region.Framework.Scenes
2007 objectGroup.IsDeleted = true; 2402 objectGroup.IsDeleted = true;
2008 2403
2009 objectGroup.m_parts.Clear(); 2404 objectGroup.m_parts.Clear();
2010 2405
2011 // Can't do this yet since backup still makes use of the root part without any synchronization 2406 // Can't do this yet since backup still makes use of the root part without any synchronization
2012// objectGroup.m_rootPart = null; 2407// objectGroup.m_rootPart = null;
2013 2408
@@ -2141,6 +2536,7 @@ namespace OpenSim.Region.Framework.Scenes
2141 /// <param name="objectGroup"></param> 2536 /// <param name="objectGroup"></param>
2142 public virtual void DetachFromBackup() 2537 public virtual void DetachFromBackup()
2143 { 2538 {
2539 m_scene.SceneGraph.FireDetachFromBackup(this);
2144 if (m_isBackedUp && Scene != null) 2540 if (m_isBackedUp && Scene != null)
2145 m_scene.EventManager.OnBackup -= ProcessBackup; 2541 m_scene.EventManager.OnBackup -= ProcessBackup;
2146 2542
@@ -2159,7 +2555,8 @@ namespace OpenSim.Region.Framework.Scenes
2159 2555
2160 axPos *= parentRot; 2556 axPos *= parentRot;
2161 part.OffsetPosition = axPos; 2557 part.OffsetPosition = axPos;
2162 part.GroupPosition = oldGroupPosition + part.OffsetPosition; 2558 Vector3 newPos = oldGroupPosition + part.OffsetPosition;
2559 part.GroupPosition = newPos;
2163 part.OffsetPosition = Vector3.Zero; 2560 part.OffsetPosition = Vector3.Zero;
2164 part.RotationOffset = worldRot; 2561 part.RotationOffset = worldRot;
2165 2562
@@ -2170,7 +2567,7 @@ namespace OpenSim.Region.Framework.Scenes
2170 2567
2171 part.LinkNum = linkNum; 2568 part.LinkNum = linkNum;
2172 2569
2173 part.OffsetPosition = part.GroupPosition - AbsolutePosition; 2570 part.OffsetPosition = newPos - AbsolutePosition;
2174 2571
2175 Quaternion rootRotation = m_rootPart.RotationOffset; 2572 Quaternion rootRotation = m_rootPart.RotationOffset;
2176 2573
@@ -2180,7 +2577,7 @@ namespace OpenSim.Region.Framework.Scenes
2180 2577
2181 parentRot = m_rootPart.RotationOffset; 2578 parentRot = m_rootPart.RotationOffset;
2182 oldRot = part.RotationOffset; 2579 oldRot = part.RotationOffset;
2183 Quaternion newRot = Quaternion.Inverse(parentRot) * oldRot; 2580 Quaternion newRot = Quaternion.Inverse(parentRot) * worldRot;
2184 part.RotationOffset = newRot; 2581 part.RotationOffset = newRot;
2185 } 2582 }
2186 2583
@@ -2427,8 +2824,12 @@ namespace OpenSim.Region.Framework.Scenes
2427 } 2824 }
2428 } 2825 }
2429 2826
2827 RootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect);
2430 for (int i = 0; i < parts.Length; i++) 2828 for (int i = 0; i < parts.Length; i++)
2431 parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect); 2829 {
2830 if (parts[i] != RootPart)
2831 parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect);
2832 }
2432 } 2833 }
2433 } 2834 }
2434 2835
@@ -2441,6 +2842,17 @@ namespace OpenSim.Region.Framework.Scenes
2441 } 2842 }
2442 } 2843 }
2443 2844
2845
2846
2847 /// <summary>
2848 /// Gets the number of parts
2849 /// </summary>
2850 /// <returns></returns>
2851 public int GetPartCount()
2852 {
2853 return Parts.Count();
2854 }
2855
2444 /// <summary> 2856 /// <summary>
2445 /// Update the texture entry for this part 2857 /// Update the texture entry for this part
2446 /// </summary> 2858 /// </summary>
@@ -2502,7 +2914,6 @@ namespace OpenSim.Region.Framework.Scenes
2502 { 2914 {
2503// m_log.DebugFormat( 2915// m_log.DebugFormat(
2504// "[SCENE OBJECT GROUP]: Group resizing {0} {1} from {2} to {3}", Name, LocalId, RootPart.Scale, scale); 2916// "[SCENE OBJECT GROUP]: Group resizing {0} {1} from {2} to {3}", Name, LocalId, RootPart.Scale, scale);
2505
2506 RootPart.StoreUndoState(true); 2917 RootPart.StoreUndoState(true);
2507 2918
2508 scale.X = Math.Min(scale.X, Scene.m_maxNonphys); 2919 scale.X = Math.Min(scale.X, Scene.m_maxNonphys);
@@ -2603,7 +3014,6 @@ namespace OpenSim.Region.Framework.Scenes
2603 prevScale.X *= x; 3014 prevScale.X *= x;
2604 prevScale.Y *= y; 3015 prevScale.Y *= y;
2605 prevScale.Z *= z; 3016 prevScale.Z *= z;
2606
2607// RootPart.IgnoreUndoUpdate = true; 3017// RootPart.IgnoreUndoUpdate = true;
2608 RootPart.Resize(prevScale); 3018 RootPart.Resize(prevScale);
2609// RootPart.IgnoreUndoUpdate = false; 3019// RootPart.IgnoreUndoUpdate = false;
@@ -2634,7 +3044,9 @@ namespace OpenSim.Region.Framework.Scenes
2634 } 3044 }
2635 3045
2636// obPart.IgnoreUndoUpdate = false; 3046// obPart.IgnoreUndoUpdate = false;
2637// obPart.StoreUndoState(); 3047 HasGroupChanged = true;
3048 m_rootPart.TriggerScriptChangedEvent(Changed.SCALE);
3049 ScheduleGroupForTerseUpdate();
2638 } 3050 }
2639 3051
2640// m_log.DebugFormat( 3052// m_log.DebugFormat(
@@ -2694,9 +3106,9 @@ namespace OpenSim.Region.Framework.Scenes
2694 { 3106 {
2695 SceneObjectPart part = GetChildPart(localID); 3107 SceneObjectPart part = GetChildPart(localID);
2696 3108
2697// SceneObjectPart[] parts = m_parts.GetArray(); 3109 SceneObjectPart[] parts = m_parts.GetArray();
2698// for (int i = 0; i < parts.Length; i++) 3110 for (int i = 0; i < parts.Length; i++)
2699// parts[i].StoreUndoState(); 3111 parts[i].StoreUndoState();
2700 3112
2701 if (part != null) 3113 if (part != null)
2702 { 3114 {
@@ -2752,10 +3164,27 @@ namespace OpenSim.Region.Framework.Scenes
2752 obPart.OffsetPosition = obPart.OffsetPosition + diff; 3164 obPart.OffsetPosition = obPart.OffsetPosition + diff;
2753 } 3165 }
2754 3166
2755 AbsolutePosition = newPos; 3167 //We have to set undoing here because otherwise an undo state will be saved
3168 if (!m_rootPart.Undoing)
3169 {
3170 m_rootPart.Undoing = true;
3171 AbsolutePosition = newPos;
3172 m_rootPart.Undoing = false;
3173 }
3174 else
3175 {
3176 AbsolutePosition = newPos;
3177 }
2756 3178
2757 HasGroupChanged = true; 3179 HasGroupChanged = true;
2758 ScheduleGroupForTerseUpdate(); 3180 if (m_rootPart.Undoing)
3181 {
3182 ScheduleGroupForFullUpdate();
3183 }
3184 else
3185 {
3186 ScheduleGroupForTerseUpdate();
3187 }
2759 } 3188 }
2760 3189
2761 #endregion 3190 #endregion
@@ -2832,10 +3261,7 @@ namespace OpenSim.Region.Framework.Scenes
2832 public void UpdateSingleRotation(Quaternion rot, uint localID) 3261 public void UpdateSingleRotation(Quaternion rot, uint localID)
2833 { 3262 {
2834 SceneObjectPart part = GetChildPart(localID); 3263 SceneObjectPart part = GetChildPart(localID);
2835
2836 SceneObjectPart[] parts = m_parts.GetArray(); 3264 SceneObjectPart[] parts = m_parts.GetArray();
2837 for (int i = 0; i < parts.Length; i++)
2838 parts[i].StoreUndoState();
2839 3265
2840 if (part != null) 3266 if (part != null)
2841 { 3267 {
@@ -2873,7 +3299,16 @@ namespace OpenSim.Region.Framework.Scenes
2873 if (part.UUID == m_rootPart.UUID) 3299 if (part.UUID == m_rootPart.UUID)
2874 { 3300 {
2875 UpdateRootRotation(rot); 3301 UpdateRootRotation(rot);
2876 AbsolutePosition = pos; 3302 if (!m_rootPart.Undoing)
3303 {
3304 m_rootPart.Undoing = true;
3305 AbsolutePosition = pos;
3306 m_rootPart.Undoing = false;
3307 }
3308 else
3309 {
3310 AbsolutePosition = pos;
3311 }
2877 } 3312 }
2878 else 3313 else
2879 { 3314 {
@@ -2897,9 +3332,10 @@ namespace OpenSim.Region.Framework.Scenes
2897 3332
2898 Quaternion axRot = rot; 3333 Quaternion axRot = rot;
2899 Quaternion oldParentRot = m_rootPart.RotationOffset; 3334 Quaternion oldParentRot = m_rootPart.RotationOffset;
2900
2901 m_rootPart.StoreUndoState(); 3335 m_rootPart.StoreUndoState();
2902 m_rootPart.UpdateRotation(rot); 3336
3337 //Don't use UpdateRotation because it schedules an update prematurely
3338 m_rootPart.RotationOffset = rot;
2903 if (m_rootPart.PhysActor != null) 3339 if (m_rootPart.PhysActor != null)
2904 { 3340 {
2905 m_rootPart.PhysActor.Orientation = m_rootPart.RotationOffset; 3341 m_rootPart.PhysActor.Orientation = m_rootPart.RotationOffset;
@@ -2913,15 +3349,17 @@ namespace OpenSim.Region.Framework.Scenes
2913 if (prim.UUID != m_rootPart.UUID) 3349 if (prim.UUID != m_rootPart.UUID)
2914 { 3350 {
2915 prim.IgnoreUndoUpdate = true; 3351 prim.IgnoreUndoUpdate = true;
3352
3353 Quaternion NewRot = oldParentRot * prim.RotationOffset;
3354 NewRot = Quaternion.Inverse(axRot) * NewRot;
3355 prim.RotationOffset = NewRot;
3356
2916 Vector3 axPos = prim.OffsetPosition; 3357 Vector3 axPos = prim.OffsetPosition;
3358
2917 axPos *= oldParentRot; 3359 axPos *= oldParentRot;
2918 axPos *= Quaternion.Inverse(axRot); 3360 axPos *= Quaternion.Inverse(axRot);
2919 prim.OffsetPosition = axPos; 3361 prim.OffsetPosition = axPos;
2920 Quaternion primsRot = prim.RotationOffset; 3362
2921 Quaternion newRot = oldParentRot * primsRot;
2922 newRot = Quaternion.Inverse(axRot) * newRot;
2923 prim.RotationOffset = newRot;
2924 prim.ScheduleTerseUpdate();
2925 prim.IgnoreUndoUpdate = false; 3363 prim.IgnoreUndoUpdate = false;
2926 } 3364 }
2927 } 3365 }
@@ -2935,8 +3373,8 @@ namespace OpenSim.Region.Framework.Scenes
2935//// childpart.StoreUndoState(); 3373//// childpart.StoreUndoState();
2936// } 3374// }
2937// } 3375// }
2938 3376 HasGroupChanged = true;
2939 m_rootPart.ScheduleTerseUpdate(); 3377 ScheduleGroupForFullUpdate();
2940 3378
2941// m_log.DebugFormat( 3379// m_log.DebugFormat(
2942// "[SCENE OBJECT GROUP]: Updated root rotation of {0} {1} to {2}", 3380// "[SCENE OBJECT GROUP]: Updated root rotation of {0} {1} to {2}",
@@ -3164,7 +3602,6 @@ namespace OpenSim.Region.Framework.Scenes
3164 public float GetMass() 3602 public float GetMass()
3165 { 3603 {
3166 float retmass = 0f; 3604 float retmass = 0f;
3167
3168 SceneObjectPart[] parts = m_parts.GetArray(); 3605 SceneObjectPart[] parts = m_parts.GetArray();
3169 for (int i = 0; i < parts.Length; i++) 3606 for (int i = 0; i < parts.Length; i++)
3170 retmass += parts[i].GetMass(); 3607 retmass += parts[i].GetMass();
@@ -3260,6 +3697,14 @@ namespace OpenSim.Region.Framework.Scenes
3260 SetFromItemID(uuid); 3697 SetFromItemID(uuid);
3261 } 3698 }
3262 3699
3700 public void ResetOwnerChangeFlag()
3701 {
3702 ForEachPart(delegate(SceneObjectPart part)
3703 {
3704 part.ResetOwnerChangeFlag();
3705 });
3706 }
3707
3263 #endregion 3708 #endregion
3264 } 3709 }
3265} 3710}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 36d3588..5576ec9 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -62,7 +62,8 @@ namespace OpenSim.Region.Framework.Scenes
62 TELEPORT = 512, 62 TELEPORT = 512,
63 REGION_RESTART = 1024, 63 REGION_RESTART = 1024,
64 MEDIA = 2048, 64 MEDIA = 2048,
65 ANIMATION = 16384 65 ANIMATION = 16384,
66 POSITION = 32768
66 } 67 }
67 68
68 // I don't really know where to put this except here. 69 // I don't really know where to put this except here.
@@ -184,6 +185,15 @@ namespace OpenSim.Region.Framework.Scenes
184 185
185 public UUID FromFolderID; 186 public UUID FromFolderID;
186 187
188 // The following two are to hold the attachment data
189 // while an object is inworld
190 [XmlIgnore]
191 public byte AttachPoint = 0;
192
193 [XmlIgnore]
194 public Vector3 AttachOffset = Vector3.Zero;
195
196 [XmlIgnore]
187 public int STATUS_ROTATE_X; 197 public int STATUS_ROTATE_X;
188 198
189 public int STATUS_ROTATE_Y; 199 public int STATUS_ROTATE_Y;
@@ -210,8 +220,7 @@ namespace OpenSim.Region.Framework.Scenes
210 220
211 public Vector3 RotationAxis = Vector3.One; 221 public Vector3 RotationAxis = Vector3.One;
212 222
213 public bool VolumeDetectActive; // XmlIgnore set to avoid problems with persistance until I come to care for this 223 public bool VolumeDetectActive;
214 // Certainly this must be a persistant setting finally
215 224
216 public bool IsWaitingForFirstSpinUpdatePacket; 225 public bool IsWaitingForFirstSpinUpdatePacket;
217 226
@@ -251,6 +260,7 @@ namespace OpenSim.Region.Framework.Scenes
251 private Quaternion m_sitTargetOrientation = Quaternion.Identity; 260 private Quaternion m_sitTargetOrientation = Quaternion.Identity;
252 private Vector3 m_sitTargetPosition; 261 private Vector3 m_sitTargetPosition;
253 private string m_sitAnimation = "SIT"; 262 private string m_sitAnimation = "SIT";
263 private bool m_occupied; // KF if any av is sitting on this prim
254 private string m_text = String.Empty; 264 private string m_text = String.Empty;
255 private string m_touchName = String.Empty; 265 private string m_touchName = String.Empty;
256 private readonly Stack<UndoState> m_undo = new Stack<UndoState>(5); 266 private readonly Stack<UndoState> m_undo = new Stack<UndoState>(5);
@@ -283,6 +293,7 @@ namespace OpenSim.Region.Framework.Scenes
283 protected Vector3 m_lastAcceleration; 293 protected Vector3 m_lastAcceleration;
284 protected Vector3 m_lastAngularVelocity; 294 protected Vector3 m_lastAngularVelocity;
285 protected int m_lastTerseSent; 295 protected int m_lastTerseSent;
296 protected float m_buoyancy = 0.0f;
286 297
287 /// <summary> 298 /// <summary>
288 /// Stores media texture data 299 /// Stores media texture data
@@ -338,7 +349,7 @@ namespace OpenSim.Region.Framework.Scenes
338 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition, 349 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition,
339 Quaternion rotationOffset, Vector3 offsetPosition) : this() 350 Quaternion rotationOffset, Vector3 offsetPosition) : this()
340 { 351 {
341 m_name = "Primitive"; 352 m_name = "Object";
342 353
343 CreationDate = (int)Utils.DateTimeToUnixTime(Rezzed); 354 CreationDate = (int)Utils.DateTimeToUnixTime(Rezzed);
344 LastOwnerID = CreatorID = OwnerID = ownerID; 355 LastOwnerID = CreatorID = OwnerID = ownerID;
@@ -378,7 +389,7 @@ namespace OpenSim.Region.Framework.Scenes
378 private uint _ownerMask = (uint)PermissionMask.All; 389 private uint _ownerMask = (uint)PermissionMask.All;
379 private uint _groupMask = (uint)PermissionMask.None; 390 private uint _groupMask = (uint)PermissionMask.None;
380 private uint _everyoneMask = (uint)PermissionMask.None; 391 private uint _everyoneMask = (uint)PermissionMask.None;
381 private uint _nextOwnerMask = (uint)PermissionMask.All; 392 private uint _nextOwnerMask = (uint)(PermissionMask.Move | PermissionMask.Modify | PermissionMask.Transfer);
382 private PrimFlags _flags = PrimFlags.None; 393 private PrimFlags _flags = PrimFlags.None;
383 private DateTime m_expires; 394 private DateTime m_expires;
384 private DateTime m_rezzed; 395 private DateTime m_rezzed;
@@ -472,12 +483,16 @@ namespace OpenSim.Region.Framework.Scenes
472 } 483 }
473 484
474 /// <value> 485 /// <value>
475 /// Access should be via Inventory directly - this property temporarily remains for xml serialization purposes 486 /// Get the inventory list
476 /// </value> 487 /// </value>
477 public TaskInventoryDictionary TaskInventory 488 public TaskInventoryDictionary TaskInventory
478 { 489 {
479 get { return m_inventory.Items; } 490 get {
480 set { m_inventory.Items = value; } 491 return m_inventory.Items;
492 }
493 set {
494 m_inventory.Items = value;
495 }
481 } 496 }
482 497
483 /// <summary> 498 /// <summary>
@@ -621,14 +636,12 @@ namespace OpenSim.Region.Framework.Scenes
621 set { m_LoopSoundSlavePrims = value; } 636 set { m_LoopSoundSlavePrims = value; }
622 } 637 }
623 638
624
625 public Byte[] TextureAnimation 639 public Byte[] TextureAnimation
626 { 640 {
627 get { return m_TextureAnimation; } 641 get { return m_TextureAnimation; }
628 set { m_TextureAnimation = value; } 642 set { m_TextureAnimation = value; }
629 } 643 }
630 644
631
632 public Byte[] ParticleSystem 645 public Byte[] ParticleSystem
633 { 646 {
634 get { return m_particleSystem; } 647 get { return m_particleSystem; }
@@ -665,9 +678,11 @@ namespace OpenSim.Region.Framework.Scenes
665 { 678 {
666 // If this is a linkset, we don't want the physics engine mucking up our group position here. 679 // If this is a linkset, we don't want the physics engine mucking up our group position here.
667 PhysicsActor actor = PhysActor; 680 PhysicsActor actor = PhysActor;
668 if (actor != null && ParentID == 0) 681 if (ParentID == 0)
669 { 682 {
670 m_groupPosition = actor.Position; 683 if (actor != null)
684 m_groupPosition = actor.Position;
685 return m_groupPosition;
671 } 686 }
672 687
673 if (ParentGroup.IsAttachment) 688 if (ParentGroup.IsAttachment)
@@ -677,12 +692,14 @@ namespace OpenSim.Region.Framework.Scenes
677 return sp.AbsolutePosition; 692 return sp.AbsolutePosition;
678 } 693 }
679 694
695 // use root prim's group position. Physics may have updated it
696 if (ParentGroup.RootPart != this)
697 m_groupPosition = ParentGroup.RootPart.GroupPosition;
680 return m_groupPosition; 698 return m_groupPosition;
681 } 699 }
682 set 700 set
683 { 701 {
684 m_groupPosition = value; 702 m_groupPosition = value;
685
686 PhysicsActor actor = PhysActor; 703 PhysicsActor actor = PhysActor;
687 if (actor != null) 704 if (actor != null)
688 { 705 {
@@ -708,16 +725,6 @@ namespace OpenSim.Region.Framework.Scenes
708 m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message); 725 m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message);
709 } 726 }
710 } 727 }
711
712 // TODO if we decide to do sitting in a more SL compatible way (multiple avatars per prim), this has to be fixed, too
713 if (SitTargetAvatar != UUID.Zero)
714 {
715 ScenePresence avatar;
716 if (ParentGroup.Scene.TryGetScenePresence(SitTargetAvatar, out avatar))
717 {
718 avatar.ParentPosition = GetWorldPosition();
719 }
720 }
721 } 728 }
722 } 729 }
723 730
@@ -726,7 +733,7 @@ namespace OpenSim.Region.Framework.Scenes
726 get { return m_offsetPosition; } 733 get { return m_offsetPosition; }
727 set 734 set
728 { 735 {
729// StoreUndoState(); 736 Vector3 oldpos = m_offsetPosition;
730 m_offsetPosition = value; 737 m_offsetPosition = value;
731 738
732 if (ParentGroup != null && !ParentGroup.IsDeleted) 739 if (ParentGroup != null && !ParentGroup.IsDeleted)
@@ -741,7 +748,22 @@ namespace OpenSim.Region.Framework.Scenes
741 if (ParentGroup.Scene != null) 748 if (ParentGroup.Scene != null)
742 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 749 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
743 } 750 }
751
752 if (!m_parentGroup.m_dupeInProgress)
753 {
754 List<ScenePresence> avs = ParentGroup.GetLinkedAvatars();
755 foreach (ScenePresence av in avs)
756 {
757 if (av.ParentID == m_localId)
758 {
759 Vector3 offset = (m_offsetPosition - oldpos);
760 av.AbsolutePosition += offset;
761 av.SendAvatarDataToAllAgents();
762 }
763 }
764 }
744 } 765 }
766 TriggerScriptChangedEvent(Changed.POSITION);
745 } 767 }
746 } 768 }
747 769
@@ -890,7 +912,16 @@ namespace OpenSim.Region.Framework.Scenes
890 /// <summary></summary> 912 /// <summary></summary>
891 public Vector3 Acceleration 913 public Vector3 Acceleration
892 { 914 {
893 get { return m_acceleration; } 915 get
916 {
917 PhysicsActor actor = PhysActor;
918 if (actor != null)
919 {
920 m_acceleration = actor.Acceleration;
921 }
922 return m_acceleration;
923 }
924
894 set { m_acceleration = value; } 925 set { m_acceleration = value; }
895 } 926 }
896 927
@@ -1041,10 +1072,7 @@ namespace OpenSim.Region.Framework.Scenes
1041 { 1072 {
1042 get 1073 get
1043 { 1074 {
1044 if (ParentGroup.IsAttachment) 1075 return GroupPosition + (m_offsetPosition * ParentGroup.RootPart.RotationOffset);
1045 return GroupPosition;
1046
1047 return m_offsetPosition + m_groupPosition;
1048 } 1076 }
1049 } 1077 }
1050 1078
@@ -1214,6 +1242,13 @@ namespace OpenSim.Region.Framework.Scenes
1214 _flags = value; 1242 _flags = value;
1215 } 1243 }
1216 } 1244 }
1245
1246 [XmlIgnore]
1247 public bool IsOccupied // KF If an av is sittingon this prim
1248 {
1249 get { return m_occupied; }
1250 set { m_occupied = value; }
1251 }
1217 1252
1218 /// <summary> 1253 /// <summary>
1219 /// ID of the avatar that is sat on us. If there is no such avatar then is UUID.Zero 1254 /// ID of the avatar that is sat on us. If there is no such avatar then is UUID.Zero
@@ -1273,6 +1308,19 @@ namespace OpenSim.Region.Framework.Scenes
1273 set { m_collisionSoundVolume = value; } 1308 set { m_collisionSoundVolume = value; }
1274 } 1309 }
1275 1310
1311 public float Buoyancy
1312 {
1313 get { return m_buoyancy; }
1314 set
1315 {
1316 m_buoyancy = value;
1317 if (PhysActor != null)
1318 {
1319 PhysActor.Buoyancy = value;
1320 }
1321 }
1322 }
1323
1276 #endregion Public Properties with only Get 1324 #endregion Public Properties with only Get
1277 1325
1278 private uint ApplyMask(uint val, bool set, uint mask) 1326 private uint ApplyMask(uint val, bool set, uint mask)
@@ -1597,6 +1645,9 @@ namespace OpenSim.Region.Framework.Scenes
1597 1645
1598 // Move afterwards ResetIDs as it clears the localID 1646 // Move afterwards ResetIDs as it clears the localID
1599 dupe.LocalId = localID; 1647 dupe.LocalId = localID;
1648 if(dupe.PhysActor != null)
1649 dupe.PhysActor.LocalID = localID;
1650
1600 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated. 1651 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated.
1601 dupe.LastOwnerID = OwnerID; 1652 dupe.LastOwnerID = OwnerID;
1602 1653
@@ -2602,17 +2653,18 @@ namespace OpenSim.Region.Framework.Scenes
2602 //Trys to fetch sound id from prim's inventory. 2653 //Trys to fetch sound id from prim's inventory.
2603 //Prim's inventory doesn't support non script items yet 2654 //Prim's inventory doesn't support non script items yet
2604 2655
2605 lock (TaskInventory) 2656 TaskInventory.LockItemsForRead(true);
2657
2658 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2606 { 2659 {
2607 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 2660 if (item.Value.Name == sound)
2608 { 2661 {
2609 if (item.Value.Name == sound) 2662 soundID = item.Value.ItemID;
2610 { 2663 break;
2611 soundID = item.Value.ItemID;
2612 break;
2613 }
2614 } 2664 }
2615 } 2665 }
2666
2667 TaskInventory.LockItemsForRead(false);
2616 } 2668 }
2617 2669
2618 ParentGroup.Scene.ForEachRootScenePresence(delegate(ScenePresence sp) 2670 ParentGroup.Scene.ForEachRootScenePresence(delegate(ScenePresence sp)
@@ -2925,8 +2977,8 @@ namespace OpenSim.Region.Framework.Scenes
2925 { 2977 {
2926 const float ROTATION_TOLERANCE = 0.01f; 2978 const float ROTATION_TOLERANCE = 0.01f;
2927 const float VELOCITY_TOLERANCE = 0.001f; 2979 const float VELOCITY_TOLERANCE = 0.001f;
2928 const float POSITION_TOLERANCE = 0.05f; 2980 const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary
2929 const int TIME_MS_TOLERANCE = 3000; 2981 const int TIME_MS_TOLERANCE = 200; //llSetPos has a 200ms delay. This should NOT be 3 seconds.
2930 2982
2931 switch (UpdateFlag) 2983 switch (UpdateFlag)
2932 { 2984 {
@@ -2988,17 +3040,16 @@ namespace OpenSim.Region.Framework.Scenes
2988 if (!UUID.TryParse(sound, out soundID)) 3040 if (!UUID.TryParse(sound, out soundID))
2989 { 3041 {
2990 // search sound file from inventory 3042 // search sound file from inventory
2991 lock (TaskInventory) 3043 TaskInventory.LockItemsForRead(true);
3044 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2992 { 3045 {
2993 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 3046 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound)
2994 { 3047 {
2995 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound) 3048 soundID = item.Value.ItemID;
2996 { 3049 break;
2997 soundID = item.Value.ItemID;
2998 break;
2999 }
3000 } 3050 }
3001 } 3051 }
3052 TaskInventory.LockItemsForRead(false);
3002 } 3053 }
3003 3054
3004 if (soundID == UUID.Zero) 3055 if (soundID == UUID.Zero)
@@ -3465,10 +3516,10 @@ namespace OpenSim.Region.Framework.Scenes
3465 // TODO: May need to fix for group comparison 3516 // TODO: May need to fix for group comparison
3466 if (last.Compare(this)) 3517 if (last.Compare(this))
3467 { 3518 {
3468 // m_log.DebugFormat( 3519 // m_log.DebugFormat(
3469 // "[SCENE OBJECT PART]: Not storing undo for {0} {1} since current state is same as last undo state, initial stack size {2}", 3520 // "[SCENE OBJECT PART]: Not storing undo for {0} {1} since current state is same as last undo state, initial stack size {2}",
3470 // Name, LocalId, m_undo.Count); 3521 // Name, LocalId, m_undo.Count);
3471 3522
3472 return; 3523 return;
3473 } 3524 }
3474 } 3525 }
@@ -3481,29 +3532,29 @@ namespace OpenSim.Region.Framework.Scenes
3481 if (ParentGroup.GetSceneMaxUndo() > 0) 3532 if (ParentGroup.GetSceneMaxUndo() > 0)
3482 { 3533 {
3483 UndoState nUndo = new UndoState(this, forGroup); 3534 UndoState nUndo = new UndoState(this, forGroup);
3484 3535
3485 m_undo.Push(nUndo); 3536 m_undo.Push(nUndo);
3486 3537
3487 if (m_redo.Count > 0) 3538 if (m_redo.Count > 0)
3488 m_redo.Clear(); 3539 m_redo.Clear();
3489 3540
3490 // m_log.DebugFormat( 3541 // m_log.DebugFormat(
3491 // "[SCENE OBJECT PART]: Stored undo state for {0} {1}, forGroup {2}, stack size now {3}", 3542 // "[SCENE OBJECT PART]: Stored undo state for {0} {1}, forGroup {2}, stack size now {3}",
3492 // Name, LocalId, forGroup, m_undo.Count); 3543 // Name, LocalId, forGroup, m_undo.Count);
3493 } 3544 }
3494 } 3545 }
3495 } 3546 }
3496 } 3547 }
3497// else 3548 // else
3498// { 3549 // {
3499// m_log.DebugFormat("[SCENE OBJECT PART]: Ignoring undo store for {0} {1}", Name, LocalId); 3550 // m_log.DebugFormat("[SCENE OBJECT PART]: Ignoring undo store for {0} {1}", Name, LocalId);
3500// } 3551 // }
3501 } 3552 }
3502// else 3553 // else
3503// { 3554 // {
3504// m_log.DebugFormat( 3555 // m_log.DebugFormat(
3505// "[SCENE OBJECT PART]: Ignoring undo store for {0} {1} since already undoing", Name, LocalId); 3556 // "[SCENE OBJECT PART]: Ignoring undo store for {0} {1} since already undoing", Name, LocalId);
3506// } 3557 // }
3507 } 3558 }
3508 3559
3509 /// <summary> 3560 /// <summary>
@@ -4234,6 +4285,9 @@ namespace OpenSim.Region.Framework.Scenes
4234 bool wasPhantom = ((Flags & PrimFlags.Phantom) != 0); 4285 bool wasPhantom = ((Flags & PrimFlags.Phantom) != 0);
4235 bool wasVD = VolumeDetectActive; 4286 bool wasVD = VolumeDetectActive;
4236 4287
4288// m_log.DebugFormat("[SOP]: Old states: phys: {0} temp: {1} phan: {2} vd: {3}", wasUsingPhysics, wasTemporary, wasPhantom, wasVD);
4289// m_log.DebugFormat("[SOP]: New states: phys: {0} temp: {1} phan: {2} vd: {3}", UsePhysics, SetTemporary, SetPhantom, SetVD);
4290
4237 if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD)) 4291 if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD))
4238 return; 4292 return;
4239 4293
@@ -4263,6 +4317,11 @@ namespace OpenSim.Region.Framework.Scenes
4263 SetPhantom = false; 4317 SetPhantom = false;
4264 } 4318 }
4265 } 4319 }
4320 else if (wasVD)
4321 {
4322 // Correspondingly, if VD is turned off, also turn off phantom
4323 SetPhantom = false;
4324 }
4266 4325
4267 if (UsePhysics && IsJoint()) 4326 if (UsePhysics && IsJoint())
4268 { 4327 {
@@ -4761,5 +4820,17 @@ namespace OpenSim.Region.Framework.Scenes
4761 Color color = Color; 4820 Color color = Color;
4762 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A)); 4821 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A));
4763 } 4822 }
4823
4824 public void ResetOwnerChangeFlag()
4825 {
4826 List<UUID> inv = Inventory.GetInventoryList();
4827
4828 foreach (UUID itemID in inv)
4829 {
4830 TaskInventoryItem item = Inventory.GetInventoryItem(itemID);
4831 item.OwnerChanged = false;
4832 Inventory.UpdateInventoryItem(item, false, false);
4833 }
4834 }
4764 } 4835 }
4765} 4836}
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 5c56150..c7c90da 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -168,6 +168,7 @@ namespace OpenSim.Region.Framework.Scenes
168// private int m_lastColCount = -1; //KF: Look for Collision chnages 168// private int m_lastColCount = -1; //KF: Look for Collision chnages
169// private int m_updateCount = 0; //KF: Update Anims for a while 169// private int m_updateCount = 0; //KF: Update Anims for a while
170// private static readonly int UPDATE_COUNT = 10; // how many frames to update for 170// private static readonly int UPDATE_COUNT = 10; // how many frames to update for
171 private List<uint> m_lastColliders = new List<uint>();
171 172
172 private TeleportFlags m_teleportFlags; 173 private TeleportFlags m_teleportFlags;
173 public TeleportFlags TeleportFlags 174 public TeleportFlags TeleportFlags
@@ -229,6 +230,9 @@ namespace OpenSim.Region.Framework.Scenes
229 //private int m_moveToPositionStateStatus; 230 //private int m_moveToPositionStateStatus;
230 //***************************************************** 231 //*****************************************************
231 232
233 private bool m_collisionEventFlag = false;
234 private object m_collisionEventLock = new Object();
235
232 protected AvatarAppearance m_appearance; 236 protected AvatarAppearance m_appearance;
233 237
234 public AvatarAppearance Appearance 238 public AvatarAppearance Appearance
@@ -1751,9 +1755,9 @@ namespace OpenSim.Region.Framework.Scenes
1751 if (pos.Z - terrainHeight < 0.2) 1755 if (pos.Z - terrainHeight < 0.2)
1752 pos.Z = terrainHeight; 1756 pos.Z = terrainHeight;
1753 1757
1754 m_log.DebugFormat( 1758// m_log.DebugFormat(
1755 "[SCENE PRESENCE]: Avatar {0} set move to target {1} (terrain height {2}) in {3}", 1759// "[SCENE PRESENCE]: Avatar {0} set move to target {1} (terrain height {2}) in {3}",
1756 Name, pos, terrainHeight, m_scene.RegionInfo.RegionName); 1760// Name, pos, terrainHeight, m_scene.RegionInfo.RegionName);
1757 1761
1758 if (noFly) 1762 if (noFly)
1759 Flying = false; 1763 Flying = false;
@@ -1837,6 +1841,7 @@ namespace OpenSim.Region.Framework.Scenes
1837 if (part.SitTargetAvatar == UUID) 1841 if (part.SitTargetAvatar == UUID)
1838 part.SitTargetAvatar = UUID.Zero; 1842 part.SitTargetAvatar = UUID.Zero;
1839 1843
1844 part.ParentGroup.DeleteAvatar(UUID);
1840 ParentPosition = part.GetWorldPosition(); 1845 ParentPosition = part.GetWorldPosition();
1841 ControllingClient.SendClearFollowCamProperties(part.ParentUUID); 1846 ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
1842 } 1847 }
@@ -1975,7 +1980,7 @@ namespace OpenSim.Region.Framework.Scenes
1975 forceMouselook = part.GetForceMouselook(); 1980 forceMouselook = part.GetForceMouselook();
1976 1981
1977 ControllingClient.SendSitResponse( 1982 ControllingClient.SendSitResponse(
1978 targetID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook); 1983 part.UUID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook);
1979 1984
1980 m_requestedSitTargetUUID = targetID; 1985 m_requestedSitTargetUUID = targetID;
1981 1986
@@ -2260,11 +2265,13 @@ namespace OpenSim.Region.Framework.Scenes
2260 m_pos = sitTargetPos + SIT_TARGET_ADJUSTMENT; 2265 m_pos = sitTargetPos + SIT_TARGET_ADJUSTMENT;
2261 Rotation = sitTargetOrient; 2266 Rotation = sitTargetOrient;
2262 ParentPosition = part.AbsolutePosition; 2267 ParentPosition = part.AbsolutePosition;
2268 part.ParentGroup.AddAvatar(UUID);
2263 } 2269 }
2264 else 2270 else
2265 { 2271 {
2266 m_pos -= part.AbsolutePosition; 2272 m_pos -= part.AbsolutePosition;
2267 ParentPosition = part.AbsolutePosition; 2273 ParentPosition = part.AbsolutePosition;
2274 part.ParentGroup.AddAvatar(UUID);
2268 2275
2269// m_log.DebugFormat( 2276// m_log.DebugFormat(
2270// "[SCENE PRESENCE]: Sitting {0} at position {1} ({2} + {3}) on part {4} {5} without sit target", 2277// "[SCENE PRESENCE]: Sitting {0} at position {1} ({2} + {3}) on part {4} {5} without sit target",
@@ -3370,6 +3377,8 @@ namespace OpenSim.Region.Framework.Scenes
3370 } 3377 }
3371 } 3378 }
3372 3379
3380 RaiseCollisionScriptEvents(coldata);
3381
3373 if (Invulnerable) 3382 if (Invulnerable)
3374 return; 3383 return;
3375 3384
@@ -3881,6 +3890,12 @@ namespace OpenSim.Region.Framework.Scenes
3881 3890
3882 private void CheckAndAdjustLandingPoint(ref Vector3 pos) 3891 private void CheckAndAdjustLandingPoint(ref Vector3 pos)
3883 { 3892 {
3893 string reason;
3894
3895 // Honor bans
3896 if (!m_scene.TestLandRestrictions(UUID, out reason, ref pos.X, ref pos.Y))
3897 return;
3898
3884 SceneObjectGroup telehub = null; 3899 SceneObjectGroup telehub = null;
3885 if (m_scene.RegionInfo.RegionSettings.TelehubObject != UUID.Zero && (telehub = m_scene.GetSceneObjectGroup(m_scene.RegionInfo.RegionSettings.TelehubObject)) != null) 3900 if (m_scene.RegionInfo.RegionSettings.TelehubObject != UUID.Zero && (telehub = m_scene.GetSceneObjectGroup(m_scene.RegionInfo.RegionSettings.TelehubObject)) != null)
3886 { 3901 {
@@ -3920,11 +3935,173 @@ namespace OpenSim.Region.Framework.Scenes
3920 pos = land.LandData.UserLocation; 3935 pos = land.LandData.UserLocation;
3921 } 3936 }
3922 } 3937 }
3923 3938
3924 land.SendLandUpdateToClient(ControllingClient); 3939 land.SendLandUpdateToClient(ControllingClient);
3925 } 3940 }
3926 } 3941 }
3927 3942
3943 private void RaiseCollisionScriptEvents(Dictionary<uint, ContactPoint> coldata)
3944 {
3945 lock(m_collisionEventLock)
3946 {
3947 if (m_collisionEventFlag)
3948 return;
3949 m_collisionEventFlag = true;
3950 }
3951
3952 Util.FireAndForget(delegate(object x)
3953 {
3954 try
3955 {
3956 List<uint> thisHitColliders = new List<uint>();
3957 List<uint> endedColliders = new List<uint>();
3958 List<uint> startedColliders = new List<uint>();
3959
3960 foreach (uint localid in coldata.Keys)
3961 {
3962 thisHitColliders.Add(localid);
3963 if (!m_lastColliders.Contains(localid))
3964 {
3965 startedColliders.Add(localid);
3966 }
3967 //m_log.Debug("[SCENE PRESENCE]: Collided with:" + localid.ToString() + " at depth of: " + collissionswith[localid].ToString());
3968 }
3969
3970 // calculate things that ended colliding
3971 foreach (uint localID in m_lastColliders)
3972 {
3973 if (!thisHitColliders.Contains(localID))
3974 {
3975 endedColliders.Add(localID);
3976 }
3977 }
3978 //add the items that started colliding this time to the last colliders list.
3979 foreach (uint localID in startedColliders)
3980 {
3981 m_lastColliders.Add(localID);
3982 }
3983 // remove things that ended colliding from the last colliders list
3984 foreach (uint localID in endedColliders)
3985 {
3986 m_lastColliders.Remove(localID);
3987 }
3988
3989 // do event notification
3990 if (startedColliders.Count > 0)
3991 {
3992 ColliderArgs StartCollidingMessage = new ColliderArgs();
3993 List<DetectedObject> colliding = new List<DetectedObject>();
3994 foreach (uint localId in startedColliders)
3995 {
3996 if (localId == 0)
3997 continue;
3998
3999 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
4000 string data = "";
4001 if (obj != null)
4002 {
4003 DetectedObject detobj = new DetectedObject();
4004 detobj.keyUUID = obj.UUID;
4005 detobj.nameStr = obj.Name;
4006 detobj.ownerUUID = obj.OwnerID;
4007 detobj.posVector = obj.AbsolutePosition;
4008 detobj.rotQuat = obj.GetWorldRotation();
4009 detobj.velVector = obj.Velocity;
4010 detobj.colliderType = 0;
4011 detobj.groupUUID = obj.GroupID;
4012 colliding.Add(detobj);
4013 }
4014 }
4015
4016 if (colliding.Count > 0)
4017 {
4018 StartCollidingMessage.Colliders = colliding;
4019
4020 foreach (SceneObjectGroup att in GetAttachments())
4021 Scene.EventManager.TriggerScriptCollidingStart(att.LocalId, StartCollidingMessage);
4022 }
4023 }
4024
4025 if (endedColliders.Count > 0)
4026 {
4027 ColliderArgs EndCollidingMessage = new ColliderArgs();
4028 List<DetectedObject> colliding = new List<DetectedObject>();
4029 foreach (uint localId in endedColliders)
4030 {
4031 if (localId == 0)
4032 continue;
4033
4034 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
4035 string data = "";
4036 if (obj != null)
4037 {
4038 DetectedObject detobj = new DetectedObject();
4039 detobj.keyUUID = obj.UUID;
4040 detobj.nameStr = obj.Name;
4041 detobj.ownerUUID = obj.OwnerID;
4042 detobj.posVector = obj.AbsolutePosition;
4043 detobj.rotQuat = obj.GetWorldRotation();
4044 detobj.velVector = obj.Velocity;
4045 detobj.colliderType = 0;
4046 detobj.groupUUID = obj.GroupID;
4047 colliding.Add(detobj);
4048 }
4049 }
4050
4051 if (colliding.Count > 0)
4052 {
4053 EndCollidingMessage.Colliders = colliding;
4054
4055 foreach (SceneObjectGroup att in GetAttachments())
4056 Scene.EventManager.TriggerScriptCollidingEnd(att.LocalId, EndCollidingMessage);
4057 }
4058 }
4059
4060 if (thisHitColliders.Count > 0)
4061 {
4062 ColliderArgs CollidingMessage = new ColliderArgs();
4063 List<DetectedObject> colliding = new List<DetectedObject>();
4064 foreach (uint localId in thisHitColliders)
4065 {
4066 if (localId == 0)
4067 continue;
4068
4069 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
4070 string data = "";
4071 if (obj != null)
4072 {
4073 DetectedObject detobj = new DetectedObject();
4074 detobj.keyUUID = obj.UUID;
4075 detobj.nameStr = obj.Name;
4076 detobj.ownerUUID = obj.OwnerID;
4077 detobj.posVector = obj.AbsolutePosition;
4078 detobj.rotQuat = obj.GetWorldRotation();
4079 detobj.velVector = obj.Velocity;
4080 detobj.colliderType = 0;
4081 detobj.groupUUID = obj.GroupID;
4082 colliding.Add(detobj);
4083 }
4084 }
4085
4086 if (colliding.Count > 0)
4087 {
4088 CollidingMessage.Colliders = colliding;
4089
4090 lock (m_attachments)
4091 {
4092 foreach (SceneObjectGroup att in m_attachments)
4093 Scene.EventManager.TriggerScriptColliding(att.LocalId, CollidingMessage);
4094 }
4095 }
4096 }
4097 }
4098 finally
4099 {
4100 m_collisionEventFlag = false;
4101 }
4102 });
4103 }
4104
3928 private void TeleportFlagsDebug() { 4105 private void TeleportFlagsDebug() {
3929 4106
3930 // Some temporary debugging help to show all the TeleportFlags we have... 4107 // Some temporary debugging help to show all the TeleportFlags we have...
@@ -3949,6 +4126,5 @@ namespace OpenSim.Region.Framework.Scenes
3949 m_log.InfoFormat("[SCENE PRESENCE]: TELEPORT ******************"); 4126 m_log.InfoFormat("[SCENE PRESENCE]: TELEPORT ******************");
3950 4127
3951 } 4128 }
3952
3953 } 4129 }
3954} 4130}
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
index 3a08271..2b0e115 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
@@ -1217,6 +1230,9 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1217 writer.WriteElementString("PayPrice3", sop.PayPrice[3].ToString()); 1230 writer.WriteElementString("PayPrice3", sop.PayPrice[3].ToString());
1218 writer.WriteElementString("PayPrice4", sop.PayPrice[4].ToString()); 1231 writer.WriteElementString("PayPrice4", sop.PayPrice[4].ToString());
1219 1232
1233 writer.WriteElementString("Buoyancy", sop.Buoyancy.ToString());
1234 writer.WriteElementString("VolumeDetectActive", sop.VolumeDetectActive.ToString().ToLower());
1235
1220 writer.WriteEndElement(); 1236 writer.WriteEndElement();
1221 } 1237 }
1222 1238
@@ -1506,12 +1522,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1506 { 1522 {
1507 TaskInventoryDictionary tinv = new TaskInventoryDictionary(); 1523 TaskInventoryDictionary tinv = new TaskInventoryDictionary();
1508 1524
1509 if (reader.IsEmptyElement)
1510 {
1511 reader.Read();
1512 return tinv;
1513 }
1514
1515 reader.ReadStartElement(name, String.Empty); 1525 reader.ReadStartElement(name, String.Empty);
1516 1526
1517 while (reader.Name == "TaskInventoryItem") 1527 while (reader.Name == "TaskInventoryItem")
@@ -1554,12 +1564,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1554 1564
1555 PrimitiveBaseShape shape = new PrimitiveBaseShape(); 1565 PrimitiveBaseShape shape = new PrimitiveBaseShape();
1556 1566
1557 if (reader.IsEmptyElement)
1558 {
1559 reader.Read();
1560 return shape;
1561 }
1562
1563 reader.ReadStartElement(name, String.Empty); // Shape 1567 reader.ReadStartElement(name, String.Empty); // Shape
1564 1568
1565 string nodeName = string.Empty; 1569 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;