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.cs355
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs3
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Permissions.cs17
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs476
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneBase.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs46
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs224
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs17
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs556
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs204
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs806
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs209
-rw-r--r--OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs23
-rw-r--r--OpenSim/Region/Framework/Scenes/UndoState.cs87
-rw-r--r--OpenSim/Region/Framework/Scenes/UuidGatherer.cs4
26 files changed, 2371 insertions, 754 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 950e4b0..9d68eb4 100644
--- a/OpenSim/Region/Framework/Interfaces/IScriptModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IScriptModule.cs
@@ -55,6 +55,8 @@ namespace OpenSim.Region.Framework.Interfaces
55 55
56 ArrayList GetScriptErrors(UUID itemID); 56 ArrayList GetScriptErrors(UUID itemID);
57 57
58 bool HasScript(UUID itemID, out bool running);
59
58 void SaveAllState(); 60 void SaveAllState();
59 61
60 /// <summary> 62 /// <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 96da2c3..65c6a29 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;
@@ -775,6 +779,26 @@ namespace OpenSim.Region.Framework.Scenes
775 } 779 }
776 } 780 }
777 } 781 }
782 public void TriggerTerrainUpdate()
783 {
784 OnTerrainUpdateDelegate handlerTerrainUpdate = OnTerrainUpdate;
785 if (handlerTerrainUpdate != null)
786 {
787 foreach (OnTerrainUpdateDelegate d in handlerTerrainUpdate.GetInvocationList())
788 {
789 try
790 {
791 d();
792 }
793 catch (Exception e)
794 {
795 m_log.ErrorFormat(
796 "[EVENT MANAGER]: Delegate for TriggerTerrainUpdate failed - continuing. {0} {1}",
797 e.Message, e.StackTrace);
798 }
799 }
800 }
801 }
778 802
779 public void TriggerTerrainTick() 803 public void TriggerTerrainTick()
780 { 804 {
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 663aa22..53f0f2e 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -124,34 +124,22 @@ namespace OpenSim.Region.Framework.Scenes
124 /// <param name="item"></param> 124 /// <param name="item"></param>
125 public bool AddInventoryItem(InventoryItemBase item) 125 public bool AddInventoryItem(InventoryItemBase item)
126 { 126 {
127 if (UUID.Zero == item.Folder) 127 InventoryFolderBase folder;
128
129 if (item.Folder == UUID.Zero)
128 { 130 {
129 InventoryFolderBase f = InventoryService.GetFolderForType(item.Owner, (AssetType)item.AssetType); 131 folder = InventoryService.GetFolderForType(item.Owner, (AssetType)item.AssetType);
130 if (f != null) 132 if (folder == null)
131 { 133 {
132// m_log.DebugFormat( 134 folder = InventoryService.GetRootFolder(item.Owner);
133// "[LOCAL INVENTORY SERVICES CONNECTOR]: Found folder {0} type {1} for item {2}", 135
134// f.Name, (AssetType)f.Type, item.Name); 136 if (folder == null)
135
136 item.Folder = f.ID;
137 }
138 else
139 {
140 f = InventoryService.GetRootFolder(item.Owner);
141 if (f != null)
142 {
143 item.Folder = f.ID;
144 }
145 else
146 {
147 m_log.WarnFormat(
148 "[AGENT INVENTORY]: Could not find root folder for {0} when trying to add item {1} with no parent folder specified",
149 item.Owner, item.Name);
150 return false; 137 return false;
151 }
152 } 138 }
139
140 item.Folder = folder.ID;
153 } 141 }
154 142
155 if (InventoryService.AddItem(item)) 143 if (InventoryService.AddItem(item))
156 { 144 {
157 int userlevel = 0; 145 int userlevel = 0;
@@ -271,8 +259,7 @@ namespace OpenSim.Region.Framework.Scenes
271 259
272 // Update item with new asset 260 // Update item with new asset
273 item.AssetID = asset.FullID; 261 item.AssetID = asset.FullID;
274 if (group.UpdateInventoryItem(item)) 262 group.UpdateInventoryItem(item);
275 remoteClient.SendAgentAlertMessage("Script saved", false);
276 263
277 part.SendPropertiesToClient(remoteClient); 264 part.SendPropertiesToClient(remoteClient);
278 265
@@ -283,12 +270,7 @@ namespace OpenSim.Region.Framework.Scenes
283 { 270 {
284 // Needs to determine which engine was running it and use that 271 // Needs to determine which engine was running it and use that
285 // 272 //
286 part.Inventory.CreateScriptInstance(item.ItemID, 0, false, DefaultScriptEngine, 0); 273 errors = part.Inventory.CreateScriptInstanceEr(item.ItemID, 0, false, DefaultScriptEngine, 0);
287 errors = part.Inventory.GetScriptErrors(item.ItemID);
288 }
289 else
290 {
291 remoteClient.SendAgentAlertMessage("Script saved", false);
292 } 274 }
293 part.ParentGroup.ResumeScripts(); 275 part.ParentGroup.ResumeScripts();
294 return errors; 276 return errors;
@@ -351,6 +333,7 @@ namespace OpenSim.Region.Framework.Scenes
351 { 333 {
352 if (UUID.Zero == transactionID) 334 if (UUID.Zero == transactionID)
353 { 335 {
336 item.Flags = (item.Flags & ~(uint)255) | (itemUpd.Flags & (uint)255);
354 item.Name = itemUpd.Name; 337 item.Name = itemUpd.Name;
355 item.Description = itemUpd.Description; 338 item.Description = itemUpd.Description;
356 if (item.NextPermissions != (itemUpd.NextPermissions & item.BasePermissions)) 339 if (item.NextPermissions != (itemUpd.NextPermissions & item.BasePermissions))
@@ -728,6 +711,8 @@ namespace OpenSim.Region.Framework.Scenes
728 return; 711 return;
729 } 712 }
730 713
714 if (newName == null) newName = item.Name;
715
731 AssetBase asset = AssetService.Get(item.AssetID.ToString()); 716 AssetBase asset = AssetService.Get(item.AssetID.ToString());
732 717
733 if (asset != null) 718 if (asset != null)
@@ -784,6 +769,24 @@ namespace OpenSim.Region.Framework.Scenes
784 } 769 }
785 770
786 /// <summary> 771 /// <summary>
772 /// Move an item within the agent's inventory, and leave a copy (used in making a new outfit)
773 /// </summary>
774 public void MoveInventoryItemsLeaveCopy(IClientAPI remoteClient, List<InventoryItemBase> items, UUID destfolder)
775 {
776 List<InventoryItemBase> moveitems = new List<InventoryItemBase>();
777 foreach (InventoryItemBase b in items)
778 {
779 CopyInventoryItem(remoteClient, 0, remoteClient.AgentId, b.ID, b.Folder, null);
780 InventoryItemBase n = InventoryService.GetItem(b);
781 n.Folder = destfolder;
782 moveitems.Add(n);
783 remoteClient.SendInventoryItemCreateUpdate(n, 0);
784 }
785
786 MoveInventoryItem(remoteClient, moveitems);
787 }
788
789 /// <summary>
787 /// Move an item within the agent's inventory. 790 /// Move an item within the agent's inventory.
788 /// </summary> 791 /// </summary>
789 /// <param name="remoteClient"></param> 792 /// <param name="remoteClient"></param>
@@ -984,25 +987,29 @@ namespace OpenSim.Region.Framework.Scenes
984 public void RemoveTaskInventory(IClientAPI remoteClient, UUID itemID, uint localID) 987 public void RemoveTaskInventory(IClientAPI remoteClient, UUID itemID, uint localID)
985 { 988 {
986 SceneObjectPart part = GetSceneObjectPart(localID); 989 SceneObjectPart part = GetSceneObjectPart(localID);
987 if (part == null) 990 SceneObjectGroup group = null;
988 return; 991 if (part != null)
992 {
993 group = part.ParentGroup;
994 }
995 if (part != null && group != null)
996 {
997 if (!Permissions.CanEditObjectInventory(part.UUID, remoteClient.AgentId))
998 return;
989 999
990 SceneObjectGroup group = part.ParentGroup; 1000 TaskInventoryItem item = group.GetInventoryItem(localID, itemID);
991 if (!Permissions.CanEditObjectInventory(part.UUID, remoteClient.AgentId)) 1001 if (item == null)
992 return; 1002 return;
993
994 TaskInventoryItem item = group.GetInventoryItem(localID, itemID);
995 if (item == null)
996 return;
997 1003
998 if (item.Type == 10) 1004 if (item.Type == 10)
999 { 1005 {
1000 part.RemoveScriptEvents(itemID); 1006 part.RemoveScriptEvents(itemID);
1001 EventManager.TriggerRemoveScript(localID, itemID); 1007 EventManager.TriggerRemoveScript(localID, itemID);
1008 }
1009
1010 group.RemoveInventoryItem(localID, itemID);
1011 part.SendPropertiesToClient(remoteClient);
1002 } 1012 }
1003
1004 group.RemoveInventoryItem(localID, itemID);
1005 part.SendPropertiesToClient(remoteClient);
1006 } 1013 }
1007 1014
1008 private InventoryItemBase CreateAgentInventoryItemFromTask(UUID destAgent, SceneObjectPart part, UUID itemId) 1015 private InventoryItemBase CreateAgentInventoryItemFromTask(UUID destAgent, SceneObjectPart part, UUID itemId)
@@ -1213,6 +1220,10 @@ namespace OpenSim.Region.Framework.Scenes
1213 if ((part.OwnerID != destPart.OwnerID) && ((srcTaskItem.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)) 1220 if ((part.OwnerID != destPart.OwnerID) && ((srcTaskItem.CurrentPermissions & (uint)PermissionMask.Transfer) == 0))
1214 return; 1221 return;
1215 1222
1223 bool overrideNoMod = false;
1224 if ((part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) != 0)
1225 overrideNoMod = true;
1226
1216 if (part.OwnerID != destPart.OwnerID && (part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) == 0) 1227 if (part.OwnerID != destPart.OwnerID && (part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) == 0)
1217 { 1228 {
1218 // object cannot copy items to an object owned by a different owner 1229 // object cannot copy items to an object owned by a different owner
@@ -1222,7 +1233,7 @@ namespace OpenSim.Region.Framework.Scenes
1222 } 1233 }
1223 1234
1224 // must have both move and modify permission to put an item in an object 1235 // must have both move and modify permission to put an item in an object
1225 if ((part.OwnerMask & ((uint)PermissionMask.Move | (uint)PermissionMask.Modify)) == 0) 1236 if (((part.OwnerMask & (uint)PermissionMask.Modify) == 0) && (!overrideNoMod))
1226 { 1237 {
1227 return; 1238 return;
1228 } 1239 }
@@ -1281,6 +1292,14 @@ namespace OpenSim.Region.Framework.Scenes
1281 1292
1282 public UUID MoveTaskInventoryItems(UUID destID, string category, SceneObjectPart host, List<UUID> items) 1293 public UUID MoveTaskInventoryItems(UUID destID, string category, SceneObjectPart host, List<UUID> items)
1283 { 1294 {
1295 SceneObjectPart destPart = GetSceneObjectPart(destID);
1296 if (destPart != null) // Move into a prim
1297 {
1298 foreach(UUID itemID in items)
1299 MoveTaskInventoryItem(destID, host, itemID);
1300 return destID; // Prim folder ID == prim ID
1301 }
1302
1284 InventoryFolderBase rootFolder = InventoryService.GetRootFolder(destID); 1303 InventoryFolderBase rootFolder = InventoryService.GetRootFolder(destID);
1285 1304
1286 UUID newFolderID = UUID.Random(); 1305 UUID newFolderID = UUID.Random();
@@ -1460,13 +1479,6 @@ namespace OpenSim.Region.Framework.Scenes
1460 { 1479 {
1461 agentTransactions.HandleTaskItemUpdateFromTransaction( 1480 agentTransactions.HandleTaskItemUpdateFromTransaction(
1462 remoteClient, part, transactionID, currentItem); 1481 remoteClient, part, transactionID, currentItem);
1463
1464 if ((InventoryType)itemInfo.InvType == InventoryType.Notecard)
1465 remoteClient.SendAgentAlertMessage("Notecard saved", false);
1466 else if ((InventoryType)itemInfo.InvType == InventoryType.LSL)
1467 remoteClient.SendAgentAlertMessage("Script saved", false);
1468 else
1469 remoteClient.SendAgentAlertMessage("Item saved", false);
1470 } 1482 }
1471 1483
1472 // Base ALWAYS has move 1484 // Base ALWAYS has move
@@ -1607,7 +1619,7 @@ namespace OpenSim.Region.Framework.Scenes
1607 return; 1619 return;
1608 1620
1609 AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType, 1621 AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType,
1610 Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n}"), 1622 Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n\n touch_start(integer num)\n {\n }\n}"),
1611 remoteClient.AgentId); 1623 remoteClient.AgentId);
1612 AssetService.Store(asset); 1624 AssetService.Store(asset);
1613 1625
@@ -1760,23 +1772,32 @@ namespace OpenSim.Region.Framework.Scenes
1760 // build a list of eligible objects 1772 // build a list of eligible objects
1761 List<uint> deleteIDs = new List<uint>(); 1773 List<uint> deleteIDs = new List<uint>();
1762 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>(); 1774 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>();
1763 1775 List<SceneObjectGroup> takeGroups = new List<SceneObjectGroup>();
1764 // Start with true for both, then remove the flags if objects
1765 // that we can't derez are part of the selection
1766 bool permissionToTake = true;
1767 bool permissionToTakeCopy = true;
1768 bool permissionToDelete = true;
1769 1776
1770 foreach (uint localID in localIDs) 1777 foreach (uint localID in localIDs)
1771 { 1778 {
1779 // Start with true for both, then remove the flags if objects
1780 // that we can't derez are part of the selection
1781 bool permissionToTake = true;
1782 bool permissionToTakeCopy = true;
1783 bool permissionToDelete = true;
1784
1772 // Invalid id 1785 // Invalid id
1773 SceneObjectPart part = GetSceneObjectPart(localID); 1786 SceneObjectPart part = GetSceneObjectPart(localID);
1774 if (part == null) 1787 if (part == null)
1788 {
1789 //Client still thinks the object exists, kill it
1790 deleteIDs.Add(localID);
1775 continue; 1791 continue;
1792 }
1776 1793
1777 // Already deleted by someone else 1794 // Already deleted by someone else
1778 if (part.ParentGroup.IsDeleted) 1795 if (part.ParentGroup.IsDeleted)
1796 {
1797 //Client still thinks the object exists, kill it
1798 deleteIDs.Add(localID);
1779 continue; 1799 continue;
1800 }
1780 1801
1781 // Can't delete child prims 1802 // Can't delete child prims
1782 if (part != part.ParentGroup.RootPart) 1803 if (part != part.ParentGroup.RootPart)
@@ -1784,9 +1805,6 @@ namespace OpenSim.Region.Framework.Scenes
1784 1805
1785 SceneObjectGroup grp = part.ParentGroup; 1806 SceneObjectGroup grp = part.ParentGroup;
1786 1807
1787 deleteIDs.Add(localID);
1788 deleteGroups.Add(grp);
1789
1790 if (remoteClient == null) 1808 if (remoteClient == null)
1791 { 1809 {
1792 // Autoreturn has a null client. Nothing else does. So 1810 // Autoreturn has a null client. Nothing else does. So
@@ -1803,81 +1821,193 @@ namespace OpenSim.Region.Framework.Scenes
1803 } 1821 }
1804 else 1822 else
1805 { 1823 {
1806 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId)) 1824 if (action == DeRezAction.TakeCopy)
1825 {
1826 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId))
1827 permissionToTakeCopy = false;
1828 }
1829 else
1830 {
1807 permissionToTakeCopy = false; 1831 permissionToTakeCopy = false;
1808 1832 }
1809 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId)) 1833 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId))
1810 permissionToTake = false; 1834 permissionToTake = false;
1811 1835
1812 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId)) 1836 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId))
1813 permissionToDelete = false; 1837 permissionToDelete = false;
1814 } 1838 }
1815 }
1816 1839
1817 // Handle god perms 1840 // Handle god perms
1818 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId)) 1841 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId))
1819 { 1842 {
1820 permissionToTake = true; 1843 permissionToTake = true;
1821 permissionToTakeCopy = true; 1844 permissionToTakeCopy = true;
1822 permissionToDelete = true; 1845 permissionToDelete = true;
1823 } 1846 }
1824 1847
1825 // If we're re-saving, we don't even want to delete 1848 // If we're re-saving, we don't even want to delete
1826 if (action == DeRezAction.SaveToExistingUserInventoryItem) 1849 if (action == DeRezAction.SaveToExistingUserInventoryItem)
1827 permissionToDelete = false; 1850 permissionToDelete = false;
1828 1851
1829 // if we want to take a copy, we also don't want to delete 1852 // if we want to take a copy, we also don't want to delete
1830 // Note: after this point, the permissionToTakeCopy flag 1853 // Note: after this point, the permissionToTakeCopy flag
1831 // becomes irrelevant. It already includes the permissionToTake 1854 // becomes irrelevant. It already includes the permissionToTake
1832 // permission and after excluding no copy items here, we can 1855 // permission and after excluding no copy items here, we can
1833 // just use that. 1856 // just use that.
1834 if (action == DeRezAction.TakeCopy) 1857 if (action == DeRezAction.TakeCopy)
1835 { 1858 {
1836 // If we don't have permission, stop right here 1859 // If we don't have permission, stop right here
1837 if (!permissionToTakeCopy) 1860 if (!permissionToTakeCopy)
1838 return; 1861 return;
1839 1862
1840 permissionToTake = true; 1863 permissionToTake = true;
1841 // Don't delete 1864 // Don't delete
1842 permissionToDelete = false; 1865 permissionToDelete = false;
1843 } 1866 }
1844 1867
1845 if (action == DeRezAction.Return) 1868 if (action == DeRezAction.Return)
1846 {
1847 if (remoteClient != null)
1848 { 1869 {
1849 if (Permissions.CanReturnObjects( 1870 if (remoteClient != null)
1850 null,
1851 remoteClient.AgentId,
1852 deleteGroups))
1853 { 1871 {
1854 permissionToTake = true; 1872 if (Permissions.CanReturnObjects(
1855 permissionToDelete = true; 1873 null,
1856 1874 remoteClient.AgentId,
1857 foreach (SceneObjectGroup g in deleteGroups) 1875 deleteGroups))
1858 { 1876 {
1859 AddReturn(g.OwnerID, g.Name, g.AbsolutePosition, "parcel owner return"); 1877 permissionToTake = true;
1878 permissionToDelete = true;
1879
1880 AddReturn(grp.OwnerID, grp.Name, grp.AbsolutePosition, "parcel owner return");
1860 } 1881 }
1861 } 1882 }
1883 else // Auto return passes through here with null agent
1884 {
1885 permissionToTake = true;
1886 permissionToDelete = true;
1887 }
1862 } 1888 }
1863 else // Auto return passes through here with null agent 1889
1890 if (permissionToTake && (!permissionToDelete))
1891 takeGroups.Add(grp);
1892
1893 if (permissionToDelete)
1864 { 1894 {
1865 permissionToTake = true; 1895 if (permissionToTake)
1866 permissionToDelete = true; 1896 deleteGroups.Add(grp);
1897 deleteIDs.Add(grp.LocalId);
1867 } 1898 }
1868 } 1899 }
1869 1900
1870 if (permissionToTake) 1901 SendKillObject(deleteIDs);
1902
1903 if (deleteGroups.Count > 0)
1871 { 1904 {
1905 foreach (SceneObjectGroup g in deleteGroups)
1906 deleteIDs.Remove(g.LocalId);
1907
1872 m_asyncSceneObjectDeleter.DeleteToInventory( 1908 m_asyncSceneObjectDeleter.DeleteToInventory(
1873 action, destinationID, deleteGroups, remoteClient, 1909 action, destinationID, deleteGroups, remoteClient,
1874 permissionToDelete); 1910 true);
1875 } 1911 }
1876 else if (permissionToDelete) 1912 if (takeGroups.Count > 0)
1913 {
1914 m_asyncSceneObjectDeleter.DeleteToInventory(
1915 action, destinationID, takeGroups, remoteClient,
1916 false);
1917 }
1918 if (deleteIDs.Count > 0)
1877 { 1919 {
1878 foreach (SceneObjectGroup g in deleteGroups) 1920 foreach (SceneObjectGroup g in deleteGroups)
1879 DeleteSceneObject(g, false); 1921 DeleteSceneObject(g, true);
1922 }
1923 }
1924
1925 public UUID attachObjectAssetStore(IClientAPI remoteClient, SceneObjectGroup grp, UUID AgentId, out UUID itemID)
1926 {
1927 itemID = UUID.Zero;
1928 if (grp != null)
1929 {
1930 Vector3 inventoryStoredPosition = new Vector3
1931 (((grp.AbsolutePosition.X > (int)Constants.RegionSize)
1932 ? 250
1933 : grp.AbsolutePosition.X)
1934 ,
1935 (grp.AbsolutePosition.X > (int)Constants.RegionSize)
1936 ? 250
1937 : grp.AbsolutePosition.X,
1938 grp.AbsolutePosition.Z);
1939
1940 Vector3 originalPosition = grp.AbsolutePosition;
1941
1942 grp.AbsolutePosition = inventoryStoredPosition;
1943
1944 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp);
1945
1946 grp.AbsolutePosition = originalPosition;
1947
1948 AssetBase asset = CreateAsset(
1949 grp.GetPartName(grp.LocalId),
1950 grp.GetPartDescription(grp.LocalId),
1951 (sbyte)AssetType.Object,
1952 Utils.StringToBytes(sceneObjectXml),
1953 remoteClient.AgentId);
1954 AssetService.Store(asset);
1955
1956 InventoryItemBase item = new InventoryItemBase();
1957 item.CreatorId = grp.RootPart.CreatorID.ToString();
1958 item.CreatorData = grp.RootPart.CreatorData;
1959 item.Owner = remoteClient.AgentId;
1960 item.ID = UUID.Random();
1961 item.AssetID = asset.FullID;
1962 item.Description = asset.Description;
1963 item.Name = asset.Name;
1964 item.AssetType = asset.Type;
1965 item.InvType = (int)InventoryType.Object;
1966
1967 InventoryFolderBase folder = InventoryService.GetFolderForType(remoteClient.AgentId, AssetType.Object);
1968 if (folder != null)
1969 item.Folder = folder.ID;
1970 else // oopsies
1971 item.Folder = UUID.Zero;
1972
1973 // Set up base perms properly
1974 uint permsBase = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify);
1975 permsBase &= grp.RootPart.BaseMask;
1976 permsBase |= (uint)PermissionMask.Move;
1977
1978 // Make sure we don't lock it
1979 grp.RootPart.NextOwnerMask |= (uint)PermissionMask.Move;
1980
1981 if ((remoteClient.AgentId != grp.RootPart.OwnerID) && Permissions.PropagatePermissions())
1982 {
1983 item.BasePermissions = permsBase & grp.RootPart.NextOwnerMask;
1984 item.CurrentPermissions = permsBase & grp.RootPart.NextOwnerMask;
1985 item.NextPermissions = permsBase & grp.RootPart.NextOwnerMask;
1986 item.EveryOnePermissions = permsBase & grp.RootPart.EveryoneMask & grp.RootPart.NextOwnerMask;
1987 item.GroupPermissions = permsBase & grp.RootPart.GroupMask & grp.RootPart.NextOwnerMask;
1988 }
1989 else
1990 {
1991 item.BasePermissions = permsBase;
1992 item.CurrentPermissions = permsBase & grp.RootPart.OwnerMask;
1993 item.NextPermissions = permsBase & grp.RootPart.NextOwnerMask;
1994 item.EveryOnePermissions = permsBase & grp.RootPart.EveryoneMask;
1995 item.GroupPermissions = permsBase & grp.RootPart.GroupMask;
1996 }
1997 item.CreationDate = Util.UnixTimeSinceEpoch();
1998
1999 // sets itemID so client can show item as 'attached' in inventory
2000 grp.SetFromItemID(item.ID);
2001
2002 if (AddInventoryItem(item))
2003 remoteClient.SendInventoryItemCreateUpdate(item, 0);
2004 else
2005 m_dialogModule.SendAlertToUser(remoteClient, "Operation failed");
2006
2007 itemID = item.ID;
2008 return item.AssetID;
1880 } 2009 }
2010 return UUID.Zero;
1881 } 2011 }
1882 2012
1883 /// <summary> 2013 /// <summary>
@@ -2006,6 +2136,9 @@ namespace OpenSim.Region.Framework.Scenes
2006 2136
2007 public void SetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID, bool running) 2137 public void SetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID, bool running)
2008 { 2138 {
2139 if (!Permissions.CanEditScript(itemID, objectID, controllingClient.AgentId))
2140 return;
2141
2009 SceneObjectPart part = GetSceneObjectPart(objectID); 2142 SceneObjectPart part = GetSceneObjectPart(objectID);
2010 if (part == null) 2143 if (part == null)
2011 return; 2144 return;
diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
index 270e582..575079f 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
@@ -374,7 +374,10 @@ namespace OpenSim.Region.Framework.Scenes
374 List<UserAccount> accounts = UserAccountService.GetUserAccounts(RegionInfo.ScopeID, query); 374 List<UserAccount> accounts = UserAccountService.GetUserAccounts(RegionInfo.ScopeID, query);
375 375
376 if (accounts == null) 376 if (accounts == null)
377 {
378 m_log.DebugFormat("[LLCIENT]: ProcessAvatarPickerRequest: returned null result");
377 return; 379 return;
380 }
378 381
379 AvatarPickerReplyPacket replyPacket = (AvatarPickerReplyPacket) PacketPool.Instance.GetPacket(PacketType.AvatarPickerReply); 382 AvatarPickerReplyPacket replyPacket = (AvatarPickerReplyPacket) PacketPool.Instance.GetPacket(PacketType.AvatarPickerReply);
380 // TODO: don't create new blocks if recycling an old packet 383 // TODO: don't create new blocks if recycling an old packet
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs b/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs
index e1fedf4..48beb9c 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs
@@ -49,6 +49,7 @@ namespace OpenSim.Region.Framework.Scenes
49 public delegate bool DuplicateObjectHandler(int objectCount, UUID objectID, UUID owner, Scene scene, Vector3 objectPosition); 49 public delegate bool DuplicateObjectHandler(int objectCount, UUID objectID, UUID owner, Scene scene, Vector3 objectPosition);
50 public delegate bool EditObjectHandler(UUID objectID, UUID editorID, Scene scene); 50 public delegate bool EditObjectHandler(UUID objectID, UUID editorID, Scene scene);
51 public delegate bool EditObjectInventoryHandler(UUID objectID, UUID editorID, Scene scene); 51 public delegate bool EditObjectInventoryHandler(UUID objectID, UUID editorID, Scene scene);
52 public delegate bool ViewObjectInventoryHandler(UUID objectID, UUID editorID, Scene scene);
52 public delegate bool MoveObjectHandler(UUID objectID, UUID moverID, Scene scene); 53 public delegate bool MoveObjectHandler(UUID objectID, UUID moverID, Scene scene);
53 public delegate bool ObjectEntryHandler(UUID objectID, bool enteringRegion, Vector3 newPoint, Scene scene); 54 public delegate bool ObjectEntryHandler(UUID objectID, bool enteringRegion, Vector3 newPoint, Scene scene);
54 public delegate bool ReturnObjectsHandler(ILandObject land, UUID user, List<SceneObjectGroup> objects, Scene scene); 55 public delegate bool ReturnObjectsHandler(ILandObject land, UUID user, List<SceneObjectGroup> objects, Scene scene);
@@ -116,6 +117,7 @@ namespace OpenSim.Region.Framework.Scenes
116 public event DuplicateObjectHandler OnDuplicateObject; 117 public event DuplicateObjectHandler OnDuplicateObject;
117 public event EditObjectHandler OnEditObject; 118 public event EditObjectHandler OnEditObject;
118 public event EditObjectInventoryHandler OnEditObjectInventory; 119 public event EditObjectInventoryHandler OnEditObjectInventory;
120 public event ViewObjectInventoryHandler OnViewObjectInventory;
119 public event MoveObjectHandler OnMoveObject; 121 public event MoveObjectHandler OnMoveObject;
120 public event ObjectEntryHandler OnObjectEntry; 122 public event ObjectEntryHandler OnObjectEntry;
121 public event ReturnObjectsHandler OnReturnObjects; 123 public event ReturnObjectsHandler OnReturnObjects;
@@ -401,6 +403,21 @@ namespace OpenSim.Region.Framework.Scenes
401 return true; 403 return true;
402 } 404 }
403 405
406 public bool CanViewObjectInventory(UUID objectID, UUID editorID)
407 {
408 ViewObjectInventoryHandler handler = OnViewObjectInventory;
409 if (handler != null)
410 {
411 Delegate[] list = handler.GetInvocationList();
412 foreach (ViewObjectInventoryHandler h in list)
413 {
414 if (h(objectID, editorID, m_scene) == false)
415 return false;
416 }
417 }
418 return true;
419 }
420
404 #endregion 421 #endregion
405 422
406 #region MOVE OBJECT 423 #region MOVE OBJECT
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index ce5b493..149d2d3 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -95,6 +95,7 @@ namespace OpenSim.Region.Framework.Scenes
95 // TODO: need to figure out how allow client agents but deny 95 // TODO: need to figure out how allow client agents but deny
96 // root agents when ACL denies access to root agent 96 // root agents when ACL denies access to root agent
97 public bool m_strictAccessControl = true; 97 public bool m_strictAccessControl = true;
98 public bool m_seeIntoBannedRegion = false;
98 public int MaxUndoCount = 5; 99 public int MaxUndoCount = 5;
99 // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet; 100 // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet;
100 public bool LoginLock = false; 101 public bool LoginLock = false;
@@ -110,12 +111,14 @@ namespace OpenSim.Region.Framework.Scenes
110 111
111 protected int m_splitRegionID; 112 protected int m_splitRegionID;
112 protected Timer m_restartWaitTimer = new Timer(); 113 protected Timer m_restartWaitTimer = new Timer();
114 protected Timer m_timerWatchdog = new Timer();
113 protected List<RegionInfo> m_regionRestartNotifyList = new List<RegionInfo>(); 115 protected List<RegionInfo> m_regionRestartNotifyList = new List<RegionInfo>();
114 protected List<RegionInfo> m_neighbours = new List<RegionInfo>(); 116 protected List<RegionInfo> m_neighbours = new List<RegionInfo>();
115 protected string m_simulatorVersion = "OpenSimulator Server"; 117 protected string m_simulatorVersion = "OpenSimulator Server";
116 protected ModuleLoader m_moduleLoader; 118 protected ModuleLoader m_moduleLoader;
117 protected AgentCircuitManager m_authenticateHandler; 119 protected AgentCircuitManager m_authenticateHandler;
118 protected SceneCommunicationService m_sceneGridService; 120 protected SceneCommunicationService m_sceneGridService;
121 protected ISnmpModule m_snmpService = null;
119 122
120 protected ISimulationDataService m_SimulationDataService; 123 protected ISimulationDataService m_SimulationDataService;
121 protected IEstateDataService m_EstateDataService; 124 protected IEstateDataService m_EstateDataService;
@@ -167,7 +170,7 @@ namespace OpenSim.Region.Framework.Scenes
167 private int m_update_events = 1; 170 private int m_update_events = 1;
168 private int m_update_backup = 200; 171 private int m_update_backup = 200;
169 private int m_update_terrain = 50; 172 private int m_update_terrain = 50;
170// private int m_update_land = 1; 173 private int m_update_land = 10;
171 private int m_update_coarse_locations = 50; 174 private int m_update_coarse_locations = 50;
172 175
173 private int agentMS; 176 private int agentMS;
@@ -182,6 +185,7 @@ namespace OpenSim.Region.Framework.Scenes
182 private int landMS; 185 private int landMS;
183 private int lastCompletedFrame; 186 private int lastCompletedFrame;
184 187
188 public bool CombineRegions = false;
185 /// <summary> 189 /// <summary>
186 /// Signals whether temporary objects are currently being cleaned up. Needed because this is launched 190 /// Signals whether temporary objects are currently being cleaned up. Needed because this is launched
187 /// asynchronously from the update loop. 191 /// asynchronously from the update loop.
@@ -204,10 +208,12 @@ namespace OpenSim.Region.Framework.Scenes
204 private bool m_scripts_enabled = true; 208 private bool m_scripts_enabled = true;
205 private string m_defaultScriptEngine; 209 private string m_defaultScriptEngine;
206 private int m_LastLogin; 210 private int m_LastLogin;
207 private Thread HeartbeatThread; 211 private Thread HeartbeatThread = null;
208 private volatile bool shuttingdown; 212 private volatile bool shuttingdown;
209 213
210 private int m_lastUpdate; 214 private int m_lastUpdate;
215 private int m_lastIncoming;
216 private int m_lastOutgoing;
211 private bool m_firstHeartbeat = true; 217 private bool m_firstHeartbeat = true;
212 218
213 private object m_deleting_scene_object = new object(); 219 private object m_deleting_scene_object = new object();
@@ -255,6 +261,19 @@ namespace OpenSim.Region.Framework.Scenes
255 get { return m_sceneGridService; } 261 get { return m_sceneGridService; }
256 } 262 }
257 263
264 public ISnmpModule SnmpService
265 {
266 get
267 {
268 if (m_snmpService == null)
269 {
270 m_snmpService = RequestModuleInterface<ISnmpModule>();
271 }
272
273 return m_snmpService;
274 }
275 }
276
258 public ISimulationDataService SimulationDataService 277 public ISimulationDataService SimulationDataService
259 { 278 {
260 get 279 get
@@ -536,6 +555,9 @@ namespace OpenSim.Region.Framework.Scenes
536 m_EstateDataService = estateDataService; 555 m_EstateDataService = estateDataService;
537 m_regionHandle = m_regInfo.RegionHandle; 556 m_regionHandle = m_regInfo.RegionHandle;
538 m_regionName = m_regInfo.RegionName; 557 m_regionName = m_regInfo.RegionName;
558 m_lastUpdate = Util.EnvironmentTickCount();
559 m_lastIncoming = 0;
560 m_lastOutgoing = 0;
539 561
540 m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this); 562 m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this);
541 m_asyncSceneObjectDeleter.Enabled = true; 563 m_asyncSceneObjectDeleter.Enabled = true;
@@ -652,6 +674,7 @@ namespace OpenSim.Region.Framework.Scenes
652 m_physicalPrim = startupConfig.GetBoolean("physical_prim", true); 674 m_physicalPrim = startupConfig.GetBoolean("physical_prim", true);
653 675
654 m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys); 676 m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys);
677
655 if (RegionInfo.NonphysPrimMax > 0) 678 if (RegionInfo.NonphysPrimMax > 0)
656 { 679 {
657 m_maxNonphys = RegionInfo.NonphysPrimMax; 680 m_maxNonphys = RegionInfo.NonphysPrimMax;
@@ -683,6 +706,7 @@ namespace OpenSim.Region.Framework.Scenes
683 m_persistAfter *= 10000000; 706 m_persistAfter *= 10000000;
684 707
685 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine"); 708 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine");
709 m_log.InfoFormat("[SCENE]: Default script engine {0}", m_defaultScriptEngine);
686 710
687 IConfig packetConfig = m_config.Configs["PacketPool"]; 711 IConfig packetConfig = m_config.Configs["PacketPool"];
688 if (packetConfig != null) 712 if (packetConfig != null)
@@ -692,6 +716,8 @@ namespace OpenSim.Region.Framework.Scenes
692 } 716 }
693 717
694 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl); 718 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl);
719 m_seeIntoBannedRegion = startupConfig.GetBoolean("SeeIntoBannedRegion", m_seeIntoBannedRegion);
720 CombineRegions = startupConfig.GetBoolean("CombineContiguousRegions", false);
695 721
696 m_generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", true); 722 m_generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", true);
697 if (m_generateMaptiles) 723 if (m_generateMaptiles)
@@ -727,9 +753,9 @@ namespace OpenSim.Region.Framework.Scenes
727 m_update_terrain = startupConfig.GetInt( "UpdateTerrainEveryNFrames", m_update_terrain); 753 m_update_terrain = startupConfig.GetInt( "UpdateTerrainEveryNFrames", m_update_terrain);
728 m_update_temp_cleaning = startupConfig.GetInt( "UpdateTempCleaningEveryNFrames", m_update_temp_cleaning); 754 m_update_temp_cleaning = startupConfig.GetInt( "UpdateTempCleaningEveryNFrames", m_update_temp_cleaning);
729 } 755 }
730 catch 756 catch (Exception e)
731 { 757 {
732 m_log.Warn("[SCENE]: Failed to load StartupConfig"); 758 m_log.Error("[SCENE]: Failed to load StartupConfig: " + e.ToString());
733 } 759 }
734 760
735 #endregion Region Config 761 #endregion Region Config
@@ -1140,7 +1166,9 @@ namespace OpenSim.Region.Framework.Scenes
1140 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat); 1166 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat);
1141 if (HeartbeatThread != null) 1167 if (HeartbeatThread != null)
1142 { 1168 {
1169 m_log.ErrorFormat("[SCENE]: Restarting heartbeat thread because it hasn't reported in in region {0}", RegionInfo.RegionName);
1143 HeartbeatThread.Abort(); 1170 HeartbeatThread.Abort();
1171 Watchdog.AbortThread(HeartbeatThread.ManagedThreadId);
1144 HeartbeatThread = null; 1172 HeartbeatThread = null;
1145 } 1173 }
1146 m_lastUpdate = Util.EnvironmentTickCount(); 1174 m_lastUpdate = Util.EnvironmentTickCount();
@@ -1183,9 +1211,6 @@ namespace OpenSim.Region.Framework.Scenes
1183 { 1211 {
1184 while (!shuttingdown) 1212 while (!shuttingdown)
1185 Update(); 1213 Update();
1186
1187 m_lastUpdate = Util.EnvironmentTickCount();
1188 m_firstHeartbeat = false;
1189 } 1214 }
1190 catch (ThreadAbortException) 1215 catch (ThreadAbortException)
1191 { 1216 {
@@ -1283,6 +1308,13 @@ namespace OpenSim.Region.Framework.Scenes
1283 eventMS = Util.EnvironmentTickCountSubtract(evMS); ; 1308 eventMS = Util.EnvironmentTickCountSubtract(evMS); ;
1284 } 1309 }
1285 1310
1311 // if (Frame % m_update_land == 0)
1312 // {
1313 // int ldMS = Util.EnvironmentTickCount();
1314 // UpdateLand();
1315 // landMS = Util.EnvironmentTickCountSubtract(ldMS);
1316 // }
1317
1286 if (Frame % m_update_backup == 0) 1318 if (Frame % m_update_backup == 0)
1287 { 1319 {
1288 int backMS = Util.EnvironmentTickCount(); 1320 int backMS = Util.EnvironmentTickCount();
@@ -1384,12 +1416,16 @@ namespace OpenSim.Region.Framework.Scenes
1384 maintc = Util.EnvironmentTickCountSubtract(maintc); 1416 maintc = Util.EnvironmentTickCountSubtract(maintc);
1385 maintc = (int)(MinFrameTime * 1000) - maintc; 1417 maintc = (int)(MinFrameTime * 1000) - maintc;
1386 1418
1419
1420 m_lastUpdate = Util.EnvironmentTickCount();
1421 m_firstHeartbeat = false;
1422
1387 if (maintc > 0) 1423 if (maintc > 0)
1388 Thread.Sleep(maintc); 1424 Thread.Sleep(maintc);
1389 1425
1390 // Tell the watchdog that this thread is still alive 1426 // Tell the watchdog that this thread is still alive
1391 Watchdog.UpdateThread(); 1427 Watchdog.UpdateThread();
1392 } 1428 }
1393 1429
1394 public void AddGroupTarget(SceneObjectGroup grp) 1430 public void AddGroupTarget(SceneObjectGroup grp)
1395 { 1431 {
@@ -1405,9 +1441,9 @@ namespace OpenSim.Region.Framework.Scenes
1405 1441
1406 private void CheckAtTargets() 1442 private void CheckAtTargets()
1407 { 1443 {
1408 Dictionary<UUID, SceneObjectGroup>.ValueCollection objs; 1444 List<SceneObjectGroup> objs = new List<SceneObjectGroup>();
1409 lock (m_groupsWithTargets) 1445 lock (m_groupsWithTargets)
1410 objs = m_groupsWithTargets.Values; 1446 objs = new List<SceneObjectGroup>(m_groupsWithTargets.Values);
1411 1447
1412 foreach (SceneObjectGroup entry in objs) 1448 foreach (SceneObjectGroup entry in objs)
1413 entry.checkAtTargets(); 1449 entry.checkAtTargets();
@@ -1489,7 +1525,7 @@ namespace OpenSim.Region.Framework.Scenes
1489 msg.fromAgentName = "Server"; 1525 msg.fromAgentName = "Server";
1490 msg.dialog = (byte)19; // Object msg 1526 msg.dialog = (byte)19; // Object msg
1491 msg.fromGroup = false; 1527 msg.fromGroup = false;
1492 msg.offline = (byte)0; 1528 msg.offline = (byte)1;
1493 msg.ParentEstateID = RegionInfo.EstateSettings.ParentEstateID; 1529 msg.ParentEstateID = RegionInfo.EstateSettings.ParentEstateID;
1494 msg.Position = Vector3.Zero; 1530 msg.Position = Vector3.Zero;
1495 msg.RegionID = RegionInfo.RegionID.Guid; 1531 msg.RegionID = RegionInfo.RegionID.Guid;
@@ -1724,14 +1760,24 @@ namespace OpenSim.Region.Framework.Scenes
1724 /// <returns></returns> 1760 /// <returns></returns>
1725 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter) 1761 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter)
1726 { 1762 {
1763
1764 float wheight = (float)RegionInfo.RegionSettings.WaterHeight;
1765 Vector3 wpos = Vector3.Zero;
1766 // Check for water surface intersection from above
1767 if ( (RayStart.Z > wheight) && (RayEnd.Z < wheight) )
1768 {
1769 float ratio = (RayStart.Z - wheight) / (RayStart.Z - RayEnd.Z);
1770 wpos.X = RayStart.X - (ratio * (RayStart.X - RayEnd.X));
1771 wpos.Y = RayStart.Y - (ratio * (RayStart.Y - RayEnd.Y));
1772 wpos.Z = wheight;
1773 }
1774
1727 Vector3 pos = Vector3.Zero; 1775 Vector3 pos = Vector3.Zero;
1728 if (RayEndIsIntersection == (byte)1) 1776 if (RayEndIsIntersection == (byte)1)
1729 { 1777 {
1730 pos = RayEnd; 1778 pos = RayEnd;
1731 return pos;
1732 } 1779 }
1733 1780 else if (RayTargetID != UUID.Zero)
1734 if (RayTargetID != UUID.Zero)
1735 { 1781 {
1736 SceneObjectPart target = GetSceneObjectPart(RayTargetID); 1782 SceneObjectPart target = GetSceneObjectPart(RayTargetID);
1737 1783
@@ -1753,7 +1799,7 @@ namespace OpenSim.Region.Framework.Scenes
1753 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter); 1799 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter);
1754 1800
1755 // Un-comment out the following line to Get Raytrace results printed to the console. 1801 // Un-comment out the following line to Get Raytrace results printed to the console.
1756 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString()); 1802 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
1757 float ScaleOffset = 0.5f; 1803 float ScaleOffset = 0.5f;
1758 1804
1759 // If we hit something 1805 // If we hit something
@@ -1776,13 +1822,10 @@ namespace OpenSim.Region.Framework.Scenes
1776 //pos.Z -= 0.25F; 1822 //pos.Z -= 0.25F;
1777 1823
1778 } 1824 }
1779
1780 return pos;
1781 } 1825 }
1782 else 1826 else
1783 { 1827 {
1784 // We don't have a target here, so we're going to raytrace all the objects in the scene. 1828 // We don't have a target here, so we're going to raytrace all the objects in the scene.
1785
1786 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false); 1829 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false);
1787 1830
1788 // Un-comment the following line to print the raytrace results to the console. 1831 // Un-comment the following line to print the raytrace results to the console.
@@ -1791,13 +1834,12 @@ namespace OpenSim.Region.Framework.Scenes
1791 if (ei.HitTF) 1834 if (ei.HitTF)
1792 { 1835 {
1793 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z); 1836 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z);
1794 } else 1837 }
1838 else
1795 { 1839 {
1796 // fall back to our stupid functionality 1840 // fall back to our stupid functionality
1797 pos = RayEnd; 1841 pos = RayEnd;
1798 } 1842 }
1799
1800 return pos;
1801 } 1843 }
1802 } 1844 }
1803 else 1845 else
@@ -1808,8 +1850,12 @@ namespace OpenSim.Region.Framework.Scenes
1808 //increase height so its above the ground. 1850 //increase height so its above the ground.
1809 //should be getting the normal of the ground at the rez point and using that? 1851 //should be getting the normal of the ground at the rez point and using that?
1810 pos.Z += scale.Z / 2f; 1852 pos.Z += scale.Z / 2f;
1811 return pos; 1853// return pos;
1812 } 1854 }
1855
1856 // check against posible water intercept
1857 if (wpos.Z > pos.Z) pos = wpos;
1858 return pos;
1813 } 1859 }
1814 1860
1815 1861
@@ -1893,7 +1939,10 @@ namespace OpenSim.Region.Framework.Scenes
1893 public bool AddRestoredSceneObject( 1939 public bool AddRestoredSceneObject(
1894 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 1940 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
1895 { 1941 {
1896 return m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates); 1942 bool result = m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates);
1943 if (result)
1944 sceneObject.IsDeleted = false;
1945 return result;
1897 } 1946 }
1898 1947
1899 /// <summary> 1948 /// <summary>
@@ -1983,6 +2032,15 @@ namespace OpenSim.Region.Framework.Scenes
1983 /// </summary> 2032 /// </summary>
1984 public void DeleteAllSceneObjects() 2033 public void DeleteAllSceneObjects()
1985 { 2034 {
2035 DeleteAllSceneObjects(false);
2036 }
2037
2038 /// <summary>
2039 /// Delete every object from the scene. This does not include attachments worn by avatars.
2040 /// </summary>
2041 public void DeleteAllSceneObjects(bool exceptNoCopy)
2042 {
2043 List<SceneObjectGroup> toReturn = new List<SceneObjectGroup>();
1986 lock (Entities) 2044 lock (Entities)
1987 { 2045 {
1988 EntityBase[] entities = Entities.GetEntities(); 2046 EntityBase[] entities = Entities.GetEntities();
@@ -1991,11 +2049,24 @@ namespace OpenSim.Region.Framework.Scenes
1991 if (e is SceneObjectGroup) 2049 if (e is SceneObjectGroup)
1992 { 2050 {
1993 SceneObjectGroup sog = (SceneObjectGroup)e; 2051 SceneObjectGroup sog = (SceneObjectGroup)e;
1994 if (!sog.IsAttachment) 2052 if (sog != null && !sog.IsAttachment)
1995 DeleteSceneObject((SceneObjectGroup)e, false); 2053 {
2054 if (!exceptNoCopy || ((sog.GetEffectivePermissions() & (uint)PermissionMask.Copy) != 0))
2055 {
2056 DeleteSceneObject((SceneObjectGroup)e, false);
2057 }
2058 else
2059 {
2060 toReturn.Add((SceneObjectGroup)e);
2061 }
2062 }
1996 } 2063 }
1997 } 2064 }
1998 } 2065 }
2066 if (toReturn.Count > 0)
2067 {
2068 returnObjects(toReturn.ToArray(), UUID.Zero);
2069 }
1999 } 2070 }
2000 2071
2001 /// <summary> 2072 /// <summary>
@@ -2043,6 +2114,8 @@ namespace OpenSim.Region.Framework.Scenes
2043 } 2114 }
2044 2115
2045 group.DeleteGroupFromScene(silent); 2116 group.DeleteGroupFromScene(silent);
2117 if (!silent)
2118 SendKillObject(new List<uint>() { group.LocalId });
2046 2119
2047// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID); 2120// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID);
2048 } 2121 }
@@ -2397,10 +2470,17 @@ namespace OpenSim.Region.Framework.Scenes
2397 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns> 2470 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns>
2398 public bool AddSceneObject(SceneObjectGroup sceneObject) 2471 public bool AddSceneObject(SceneObjectGroup sceneObject)
2399 { 2472 {
2473 if (sceneObject.OwnerID == UUID.Zero)
2474 {
2475 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero", sceneObject.UUID);
2476 return false;
2477 }
2478
2400 // If the user is banned, we won't let any of their objects 2479 // If the user is banned, we won't let any of their objects
2401 // enter. Period. 2480 // enter. Period.
2402 // 2481 //
2403 if (m_regInfo.EstateSettings.IsBanned(sceneObject.OwnerID)) 2482 int flags = GetUserFlags(sceneObject.OwnerID);
2483 if (m_regInfo.EstateSettings.IsBanned(sceneObject.OwnerID, flags))
2404 { 2484 {
2405 m_log.Info("[INTERREGION]: Denied prim crossing for " + 2485 m_log.Info("[INTERREGION]: Denied prim crossing for " +
2406 "banned avatar"); 2486 "banned avatar");
@@ -2447,12 +2527,23 @@ namespace OpenSim.Region.Framework.Scenes
2447 } 2527 }
2448 else 2528 else
2449 { 2529 {
2530 m_log.DebugFormat("[SCENE]: Attachment {0} arrived and scene presence was not found, setting to temp", sceneObject.UUID);
2450 RootPrim.RemFlag(PrimFlags.TemporaryOnRez); 2531 RootPrim.RemFlag(PrimFlags.TemporaryOnRez);
2451 RootPrim.AddFlag(PrimFlags.TemporaryOnRez); 2532 RootPrim.AddFlag(PrimFlags.TemporaryOnRez);
2452 } 2533 }
2534 if (sceneObject.OwnerID == UUID.Zero)
2535 {
2536 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero after attachment processing. BUG!", sceneObject.UUID);
2537 return false;
2538 }
2453 } 2539 }
2454 else 2540 else
2455 { 2541 {
2542 if (sceneObject.OwnerID == UUID.Zero)
2543 {
2544 m_log.ErrorFormat("[SCENE]: Owner ID for non-attachment {0} was zero", sceneObject.UUID);
2545 return false;
2546 }
2456 AddRestoredSceneObject(sceneObject, true, false); 2547 AddRestoredSceneObject(sceneObject, true, false);
2457 2548
2458 if (!Permissions.CanObjectEntry(sceneObject.UUID, 2549 if (!Permissions.CanObjectEntry(sceneObject.UUID,
@@ -2482,6 +2573,24 @@ namespace OpenSim.Region.Framework.Scenes
2482 return 2; // StateSource.PrimCrossing 2573 return 2; // StateSource.PrimCrossing
2483 } 2574 }
2484 2575
2576 public int GetUserFlags(UUID user)
2577 {
2578 //Unfortunately the SP approach means that the value is cached until region is restarted
2579 /*
2580 ScenePresence sp;
2581 if (TryGetScenePresence(user, out sp))
2582 {
2583 return sp.UserFlags;
2584 }
2585 else
2586 {
2587 */
2588 UserAccount uac = UserAccountService.GetUserAccount(RegionInfo.ScopeID, user);
2589 if (uac == null)
2590 return 0;
2591 return uac.UserFlags;
2592 //}
2593 }
2485 #endregion 2594 #endregion
2486 2595
2487 #region Add/Remove Avatar Methods 2596 #region Add/Remove Avatar Methods
@@ -2503,6 +2612,7 @@ namespace OpenSim.Region.Framework.Scenes
2503 (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; 2612 (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0;
2504 2613
2505 CheckHeartbeat(); 2614 CheckHeartbeat();
2615 ScenePresence presence;
2506 2616
2507 if (GetScenePresence(client.AgentId) == null) // ensure there is no SP here 2617 if (GetScenePresence(client.AgentId) == null) // ensure there is no SP here
2508 { 2618 {
@@ -2538,7 +2648,14 @@ namespace OpenSim.Region.Framework.Scenes
2538 2648
2539 EventManager.TriggerOnNewClient(client); 2649 EventManager.TriggerOnNewClient(client);
2540 if (vialogin) 2650 if (vialogin)
2651 {
2541 EventManager.TriggerOnClientLogin(client); 2652 EventManager.TriggerOnClientLogin(client);
2653
2654 // Send initial parcel data
2655 Vector3 pos = createdSp.AbsolutePosition;
2656 ILandObject land = LandChannel.GetLandObject(pos.X, pos.Y);
2657 land.SendLandUpdateToClient(client);
2658 }
2542 } 2659 }
2543 2660
2544 // Send all scene object to the new client 2661 // Send all scene object to the new client
@@ -2637,19 +2754,12 @@ namespace OpenSim.Region.Framework.Scenes
2637 // and the scene presence and the client, if they exist 2754 // and the scene presence and the client, if they exist
2638 try 2755 try
2639 { 2756 {
2640 // We need to wait for the client to make UDP contact first. 2757 ScenePresence sp = GetScenePresence(agentID);
2641 // It's the UDP contact that creates the scene presence 2758 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
2642 ScenePresence sp = WaitGetScenePresence(agentID); 2759
2643 if (sp != null) 2760 if (sp != null)
2644 {
2645 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
2646
2647 sp.ControllingClient.Close(); 2761 sp.ControllingClient.Close();
2648 } 2762
2649 else
2650 {
2651 m_log.WarnFormat("[SCENE]: Could not find scene presence for {0}", agentID);
2652 }
2653 // BANG! SLASH! 2763 // BANG! SLASH!
2654 m_authenticateHandler.RemoveCircuit(agentID); 2764 m_authenticateHandler.RemoveCircuit(agentID);
2655 2765
@@ -2749,6 +2859,7 @@ namespace OpenSim.Region.Framework.Scenes
2749 client.OnFetchInventory += m_asyncInventorySender.HandleFetchInventory; 2859 client.OnFetchInventory += m_asyncInventorySender.HandleFetchInventory;
2750 client.OnUpdateInventoryItem += UpdateInventoryItemAsset; 2860 client.OnUpdateInventoryItem += UpdateInventoryItemAsset;
2751 client.OnCopyInventoryItem += CopyInventoryItem; 2861 client.OnCopyInventoryItem += CopyInventoryItem;
2862 client.OnMoveItemsAndLeaveCopy += MoveInventoryItemsLeaveCopy;
2752 client.OnMoveInventoryItem += MoveInventoryItem; 2863 client.OnMoveInventoryItem += MoveInventoryItem;
2753 client.OnRemoveInventoryItem += RemoveInventoryItem; 2864 client.OnRemoveInventoryItem += RemoveInventoryItem;
2754 client.OnRemoveInventoryFolder += RemoveInventoryFolder; 2865 client.OnRemoveInventoryFolder += RemoveInventoryFolder;
@@ -2926,15 +3037,16 @@ namespace OpenSim.Region.Framework.Scenes
2926 /// </summary> 3037 /// </summary>
2927 /// <param name="agentId">The avatar's Unique ID</param> 3038 /// <param name="agentId">The avatar's Unique ID</param>
2928 /// <param name="client">The IClientAPI for the client</param> 3039 /// <param name="client">The IClientAPI for the client</param>
2929 public virtual void TeleportClientHome(UUID agentId, IClientAPI client) 3040 public virtual bool TeleportClientHome(UUID agentId, IClientAPI client)
2930 { 3041 {
2931 if (m_teleportModule != null) 3042 if (m_teleportModule != null)
2932 m_teleportModule.TeleportHome(agentId, client); 3043 return m_teleportModule.TeleportHome(agentId, client);
2933 else 3044 else
2934 { 3045 {
2935 m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active"); 3046 m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active");
2936 client.SendTeleportFailed("Unable to perform teleports on this simulator."); 3047 client.SendTeleportFailed("Unable to perform teleports on this simulator.");
2937 } 3048 }
3049 return false;
2938 } 3050 }
2939 3051
2940 /// <summary> 3052 /// <summary>
@@ -3026,6 +3138,16 @@ namespace OpenSim.Region.Framework.Scenes
3026 /// <param name="flags"></param> 3138 /// <param name="flags"></param>
3027 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags) 3139 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags)
3028 { 3140 {
3141 //Add half the avatar's height so that the user doesn't fall through prims
3142 ScenePresence presence;
3143 if (TryGetScenePresence(remoteClient.AgentId, out presence))
3144 {
3145 if (presence.Appearance != null)
3146 {
3147 position.Z = position.Z + (presence.Appearance.AvatarHeight / 2);
3148 }
3149 }
3150
3029 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt)) 3151 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt))
3030 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot. 3152 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot.
3031 m_dialogModule.SendAlertToUser(remoteClient, "Home position set."); 3153 m_dialogModule.SendAlertToUser(remoteClient, "Home position set.");
@@ -3094,8 +3216,9 @@ namespace OpenSim.Region.Framework.Scenes
3094 regions.Remove(RegionInfo.RegionHandle); 3216 regions.Remove(RegionInfo.RegionHandle);
3095 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); 3217 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions);
3096 } 3218 }
3097 3219 m_log.Debug("[Scene] Beginning ClientClosed");
3098 m_eventManager.TriggerClientClosed(agentID, this); 3220 m_eventManager.TriggerClientClosed(agentID, this);
3221 m_log.Debug("[Scene] Finished ClientClosed");
3099 } 3222 }
3100 catch (NullReferenceException) 3223 catch (NullReferenceException)
3101 { 3224 {
@@ -3103,7 +3226,12 @@ namespace OpenSim.Region.Framework.Scenes
3103 // Avatar is already disposed :/ 3226 // Avatar is already disposed :/
3104 } 3227 }
3105 3228
3229 m_log.Debug("[Scene] Beginning OnRemovePresence");
3106 m_eventManager.TriggerOnRemovePresence(agentID); 3230 m_eventManager.TriggerOnRemovePresence(agentID);
3231 m_log.Debug("[Scene] Finished OnRemovePresence");
3232
3233 if (AttachmentsModule != null && !avatar.IsChildAgent && avatar.PresenceType != PresenceType.Npc)
3234 AttachmentsModule.SaveChangedAttachments(avatar);
3107 3235
3108 if (AttachmentsModule != null && !avatar.IsChildAgent && avatar.PresenceType != PresenceType.Npc) 3236 if (AttachmentsModule != null && !avatar.IsChildAgent && avatar.PresenceType != PresenceType.Npc)
3109 AttachmentsModule.SaveChangedAttachments(avatar); 3237 AttachmentsModule.SaveChangedAttachments(avatar);
@@ -3123,8 +3251,11 @@ namespace OpenSim.Region.Framework.Scenes
3123 } 3251 }
3124 3252
3125 // Remove the avatar from the scene 3253 // Remove the avatar from the scene
3254 m_log.Debug("[Scene] Begin RemoveScenePresence");
3126 m_sceneGraph.RemoveScenePresence(agentID); 3255 m_sceneGraph.RemoveScenePresence(agentID);
3256 m_log.Debug("[Scene] Finished RemoveScenePresence. Removing the client manager");
3127 m_clientManager.Remove(agentID); 3257 m_clientManager.Remove(agentID);
3258 m_log.Debug("[Scene] Removed the client manager. Firing avatar.close");
3128 3259
3129 try 3260 try
3130 { 3261 {
@@ -3138,9 +3269,10 @@ namespace OpenSim.Region.Framework.Scenes
3138 { 3269 {
3139 m_log.Error("[SCENE] Scene.cs:RemoveClient exception: " + e.ToString()); 3270 m_log.Error("[SCENE] Scene.cs:RemoveClient exception: " + e.ToString());
3140 } 3271 }
3141 3272 m_log.Debug("[Scene] Done. Firing RemoveCircuit");
3142 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode); 3273 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode);
3143// CleanDroppedAttachments(); 3274// CleanDroppedAttachments();
3275 m_log.Debug("[Scene] The avatar has left the building");
3144 //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false)); 3276 //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false));
3145 //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true)); 3277 //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true));
3146 } 3278 }
@@ -3293,13 +3425,16 @@ namespace OpenSim.Region.Framework.Scenes
3293 sp = null; 3425 sp = null;
3294 } 3426 }
3295 3427
3296 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3297 3428
3298 //On login test land permisions 3429 //On login test land permisions
3299 if (vialogin) 3430 if (vialogin)
3300 { 3431 {
3301 if (land != null && !TestLandRestrictions(agent, land, out reason)) 3432 IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>();
3433 if (cache != null)
3434 cache.Remove(agent.firstname + " " + agent.lastname);
3435 if (!TestLandRestrictions(agent.AgentID, out reason, ref agent.startpos.X, ref agent.startpos.Y))
3302 { 3436 {
3437 m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString());
3303 return false; 3438 return false;
3304 } 3439 }
3305 } 3440 }
@@ -3322,8 +3457,13 @@ namespace OpenSim.Region.Framework.Scenes
3322 3457
3323 try 3458 try
3324 { 3459 {
3325 if (!AuthorizeUser(agent, out reason)) 3460 // Always check estate if this is a login. Always
3326 return false; 3461 // check if banned regions are to be blacked out.
3462 if (vialogin || (!m_seeIntoBannedRegion))
3463 {
3464 if (!AuthorizeUser(agent, out reason))
3465 return false;
3466 }
3327 } 3467 }
3328 catch (Exception e) 3468 catch (Exception e)
3329 { 3469 {
@@ -3425,6 +3565,8 @@ namespace OpenSim.Region.Framework.Scenes
3425 } 3565 }
3426 } 3566 }
3427 // Honor parcel landing type and position. 3567 // Honor parcel landing type and position.
3568 /*
3569 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3428 if (land != null) 3570 if (land != null)
3429 { 3571 {
3430 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) 3572 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero)
@@ -3432,26 +3574,34 @@ namespace OpenSim.Region.Framework.Scenes
3432 agent.startpos = land.LandData.UserLocation; 3574 agent.startpos = land.LandData.UserLocation;
3433 } 3575 }
3434 } 3576 }
3577 */// This is now handled properly in ScenePresence.MakeRootAgent
3435 } 3578 }
3436 3579
3437 return true; 3580 return true;
3438 } 3581 }
3439 3582
3440 private bool TestLandRestrictions(AgentCircuitData agent, ILandObject land, out string reason) 3583 private bool TestLandRestrictions(UUID agentID, out string reason, ref float posX, ref float posY)
3441 { 3584 {
3442 3585 reason = String.Empty;
3443 bool banned = land.IsBannedFromLand(agent.AgentID); 3586 if (Permissions.IsGod(agentID))
3444 bool restricted = land.IsRestrictedFromLand(agent.AgentID); 3587 return true;
3588
3589 ILandObject land = LandChannel.GetLandObject(posX, posY);
3590 if (land == null)
3591 return false;
3592
3593 bool banned = land.IsBannedFromLand(agentID);
3594 bool restricted = land.IsRestrictedFromLand(agentID);
3445 3595
3446 if (banned || restricted) 3596 if (banned || restricted)
3447 { 3597 {
3448 ILandObject nearestParcel = GetNearestAllowedParcel(agent.AgentID, agent.startpos.X, agent.startpos.Y); 3598 ILandObject nearestParcel = GetNearestAllowedParcel(agentID, posX, posY);
3449 if (nearestParcel != null) 3599 if (nearestParcel != null)
3450 { 3600 {
3451 //Move agent to nearest allowed 3601 //Move agent to nearest allowed
3452 Vector3 newPosition = GetParcelCenterAtGround(nearestParcel); 3602 Vector3 newPosition = GetParcelCenterAtGround(nearestParcel);
3453 agent.startpos.X = newPosition.X; 3603 posX = newPosition.X;
3454 agent.startpos.Y = newPosition.Y; 3604 posY = newPosition.Y;
3455 } 3605 }
3456 else 3606 else
3457 { 3607 {
@@ -3513,7 +3663,7 @@ namespace OpenSim.Region.Framework.Scenes
3513 3663
3514 if (!m_strictAccessControl) return true; 3664 if (!m_strictAccessControl) return true;
3515 if (Permissions.IsGod(agent.AgentID)) return true; 3665 if (Permissions.IsGod(agent.AgentID)) return true;
3516 3666
3517 if (AuthorizationService != null) 3667 if (AuthorizationService != null)
3518 { 3668 {
3519 if (!AuthorizationService.IsAuthorizedForRegion( 3669 if (!AuthorizationService.IsAuthorizedForRegion(
@@ -3521,14 +3671,14 @@ namespace OpenSim.Region.Framework.Scenes
3521 { 3671 {
3522 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the region", 3672 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the region",
3523 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 3673 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
3524 3674
3525 return false; 3675 return false;
3526 } 3676 }
3527 } 3677 }
3528 3678
3529 if (m_regInfo.EstateSettings != null) 3679 if (m_regInfo.EstateSettings != null)
3530 { 3680 {
3531 if (m_regInfo.EstateSettings.IsBanned(agent.AgentID)) 3681 if (m_regInfo.EstateSettings.IsBanned(agent.AgentID,0))
3532 { 3682 {
3533 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist", 3683 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist",
3534 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 3684 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
@@ -3718,6 +3868,13 @@ namespace OpenSim.Region.Framework.Scenes
3718 3868
3719 // We have to wait until the viewer contacts this region after receiving EAC. 3869 // We have to wait until the viewer contacts this region after receiving EAC.
3720 // That calls AddNewClient, which finally creates the ScenePresence 3870 // That calls AddNewClient, which finally creates the ScenePresence
3871 int flags = GetUserFlags(cAgentData.AgentID);
3872 if (m_regInfo.EstateSettings.IsBanned(cAgentData.AgentID, flags))
3873 {
3874 m_log.DebugFormat("[SCENE]: Denying root agent entry to {0}: banned", cAgentData.AgentID);
3875 return false;
3876 }
3877
3721 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2); 3878 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2);
3722 if (nearestParcel == null) 3879 if (nearestParcel == null)
3723 { 3880 {
@@ -3733,7 +3890,6 @@ namespace OpenSim.Region.Framework.Scenes
3733 return false; 3890 return false;
3734 } 3891 }
3735 3892
3736
3737 ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID); 3893 ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID);
3738 3894
3739 if (childAgentUpdate != null) 3895 if (childAgentUpdate != null)
@@ -3800,12 +3956,22 @@ namespace OpenSim.Region.Framework.Scenes
3800 return false; 3956 return false;
3801 } 3957 }
3802 3958
3959 public bool IncomingCloseAgent(UUID agentID)
3960 {
3961 return IncomingCloseAgent(agentID, false);
3962 }
3963
3964 public bool IncomingCloseChildAgent(UUID agentID)
3965 {
3966 return IncomingCloseAgent(agentID, true);
3967 }
3968
3803 /// <summary> 3969 /// <summary>
3804 /// Tell a single agent to disconnect from the region. 3970 /// Tell a single agent to disconnect from the region.
3805 /// </summary> 3971 /// </summary>
3806 /// <param name="regionHandle"></param>
3807 /// <param name="agentID"></param> 3972 /// <param name="agentID"></param>
3808 public bool IncomingCloseAgent(UUID agentID) 3973 /// <param name="childOnly"></param>
3974 public bool IncomingCloseAgent(UUID agentID, bool childOnly)
3809 { 3975 {
3810 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); 3976 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID);
3811 3977
@@ -3817,7 +3983,7 @@ namespace OpenSim.Region.Framework.Scenes
3817 { 3983 {
3818 m_sceneGraph.removeUserCount(false); 3984 m_sceneGraph.removeUserCount(false);
3819 } 3985 }
3820 else 3986 else if (!childOnly)
3821 { 3987 {
3822 m_sceneGraph.removeUserCount(true); 3988 m_sceneGraph.removeUserCount(true);
3823 } 3989 }
@@ -3833,9 +3999,12 @@ namespace OpenSim.Region.Framework.Scenes
3833 } 3999 }
3834 else 4000 else
3835 presence.ControllingClient.SendShutdownConnectionNotice(); 4001 presence.ControllingClient.SendShutdownConnectionNotice();
4002 presence.ControllingClient.Close(false);
4003 }
4004 else if (!childOnly)
4005 {
4006 presence.ControllingClient.Close(true);
3836 } 4007 }
3837
3838 presence.ControllingClient.Close();
3839 return true; 4008 return true;
3840 } 4009 }
3841 4010
@@ -4430,34 +4599,66 @@ namespace OpenSim.Region.Framework.Scenes
4430 SimulationDataService.RemoveObject(uuid, m_regInfo.RegionID); 4599 SimulationDataService.RemoveObject(uuid, m_regInfo.RegionID);
4431 } 4600 }
4432 4601
4433 public int GetHealth() 4602 public int GetHealth(out int flags, out string message)
4434 { 4603 {
4435 // Returns: 4604 // Returns:
4436 // 1 = sim is up and accepting http requests. The heartbeat has 4605 // 1 = sim is up and accepting http requests. The heartbeat has
4437 // stopped and the sim is probably locked up, but a remote 4606 // stopped and the sim is probably locked up, but a remote
4438 // admin restart may succeed 4607 // admin restart may succeed
4439 // 4608 //
4440 // 2 = Sim is up and the heartbeat is running. The sim is likely 4609 // 2 = Sim is up and the heartbeat is running. The sim is likely
4441 // usable for people within and logins _may_ work 4610 // usable for people within
4611 //
4612 // 3 = Sim is up and one packet thread is running. Sim is
4613 // unstable and will not accept new logins
4614 //
4615 // 4 = Sim is up and both packet threads are running. Sim is
4616 // likely usable
4442 // 4617 //
4443 // 3 = We have seen a new user enter within the past 4 minutes 4618 // 5 = We have seen a new user enter within the past 4 minutes
4444 // which can be seen as positive confirmation of sim health 4619 // which can be seen as positive confirmation of sim health
4445 // 4620 //
4621
4622 flags = 0;
4623 message = String.Empty;
4624
4625 CheckHeartbeat();
4626
4627 if (m_firstHeartbeat || (m_lastIncoming == 0 && m_lastOutgoing == 0))
4628 {
4629 // We're still starting
4630 // 0 means "in startup", it can't happen another way, since
4631 // to get here, we must be able to accept http connections
4632 return 0;
4633 }
4634
4446 int health=1; // Start at 1, means we're up 4635 int health=1; // Start at 1, means we're up
4447 4636
4448 if ((Util.EnvironmentTickCountSubtract(m_lastUpdate)) < 1000) 4637 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) < 1000)
4638 {
4449 health+=1; 4639 health+=1;
4450 else 4640 flags |= 1;
4641 }
4642
4643 if (Util.EnvironmentTickCountSubtract(m_lastIncoming) < 1000)
4644 {
4645 health+=1;
4646 flags |= 2;
4647 }
4648
4649 if (Util.EnvironmentTickCountSubtract(m_lastOutgoing) < 1000)
4650 {
4651 health+=1;
4652 flags |= 4;
4653 }
4654
4655 if (flags != 7)
4451 return health; 4656 return health;
4452 4657
4453 // A login in the last 4 mins? We can't be doing too badly 4658 // A login in the last 4 mins? We can't be doing too badly
4454 // 4659 //
4455 if ((Util.EnvironmentTickCountSubtract(m_LastLogin)) < 240000) 4660 if (Util.EnvironmentTickCountSubtract(m_LastLogin) < 240000)
4456 health++; 4661 health++;
4457 else
4458 return health;
4459
4460 CheckHeartbeat();
4461 4662
4462 return health; 4663 return health;
4463 } 4664 }
@@ -4650,7 +4851,7 @@ namespace OpenSim.Region.Framework.Scenes
4650 if (m_firstHeartbeat) 4851 if (m_firstHeartbeat)
4651 return; 4852 return;
4652 4853
4653 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) > 2000) 4854 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) > 5000)
4654 StartTimer(); 4855 StartTimer();
4655 } 4856 }
4656 4857
@@ -5064,6 +5265,54 @@ namespace OpenSim.Region.Framework.Scenes
5064 } 5265 }
5065 } 5266 }
5066 5267
5268// public void CleanDroppedAttachments()
5269// {
5270// List<SceneObjectGroup> objectsToDelete =
5271// new List<SceneObjectGroup>();
5272//
5273// lock (m_cleaningAttachments)
5274// {
5275// ForEachSOG(delegate (SceneObjectGroup grp)
5276// {
5277// if (grp.RootPart.Shape.PCode == 0 && grp.RootPart.Shape.State != 0 && (!objectsToDelete.Contains(grp)))
5278// {
5279// UUID agentID = grp.OwnerID;
5280// if (agentID == UUID.Zero)
5281// {
5282// objectsToDelete.Add(grp);
5283// return;
5284// }
5285//
5286// ScenePresence sp = GetScenePresence(agentID);
5287// if (sp == null)
5288// {
5289// objectsToDelete.Add(grp);
5290// return;
5291// }
5292// }
5293// });
5294// }
5295//
5296// foreach (SceneObjectGroup grp in objectsToDelete)
5297// {
5298// m_log.InfoFormat("[SCENE]: Deleting dropped attachment {0} of user {1}", grp.UUID, grp.OwnerID);
5299// DeleteSceneObject(grp, true);
5300// }
5301// }
5302
5303 public void ThreadAlive(int threadCode)
5304 {
5305 switch(threadCode)
5306 {
5307 case 1: // Incoming
5308 m_lastIncoming = Util.EnvironmentTickCount();
5309 break;
5310 case 2: // Incoming
5311 m_lastOutgoing = Util.EnvironmentTickCount();
5312 break;
5313 }
5314 }
5315
5067 // This method is called across the simulation connector to 5316 // This method is called across the simulation connector to
5068 // determine if a given agent is allowed in this region 5317 // determine if a given agent is allowed in this region
5069 // AS A ROOT AGENT. Returning false here will prevent them 5318 // AS A ROOT AGENT. Returning false here will prevent them
@@ -5072,6 +5321,14 @@ namespace OpenSim.Region.Framework.Scenes
5072 // child agent creation, thereby emulating the SL behavior. 5321 // child agent creation, thereby emulating the SL behavior.
5073 public bool QueryAccess(UUID agentID, Vector3 position, out string reason) 5322 public bool QueryAccess(UUID agentID, Vector3 position, out string reason)
5074 { 5323 {
5324 reason = "You are banned from the region";
5325
5326 if (Permissions.IsGod(agentID))
5327 {
5328 reason = String.Empty;
5329 return true;
5330 }
5331
5075 int num = m_sceneGraph.GetNumberOfScenePresences(); 5332 int num = m_sceneGraph.GetNumberOfScenePresences();
5076 5333
5077 if (num >= RegionInfo.RegionSettings.AgentLimit) 5334 if (num >= RegionInfo.RegionSettings.AgentLimit)
@@ -5083,11 +5340,82 @@ namespace OpenSim.Region.Framework.Scenes
5083 } 5340 }
5084 } 5341 }
5085 5342
5343 ScenePresence presence = GetScenePresence(agentID);
5344 IClientAPI client = null;
5345 AgentCircuitData aCircuit = null;
5346
5347 if (presence != null)
5348 {
5349 client = presence.ControllingClient;
5350 if (client != null)
5351 aCircuit = client.RequestClientInfo();
5352 }
5353
5354 // We may be called before there is a presence or a client.
5355 // Fake AgentCircuitData to keep IAuthorizationModule smiling
5356 if (client == null)
5357 {
5358 aCircuit = new AgentCircuitData();
5359 aCircuit.AgentID = agentID;
5360 aCircuit.firstname = String.Empty;
5361 aCircuit.lastname = String.Empty;
5362 }
5363
5364 try
5365 {
5366 if (!AuthorizeUser(aCircuit, out reason))
5367 {
5368 // m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID);
5369 return false;
5370 }
5371 }
5372 catch (Exception e)
5373 {
5374 m_log.DebugFormat("[SCENE]: Exception authorizing agent: {0} "+ e.StackTrace, e.Message);
5375 return false;
5376 }
5377
5378 if (position == Vector3.Zero) // Teleport
5379 {
5380 float posX = 128.0f;
5381 float posY = 128.0f;
5382
5383 if (!TestLandRestrictions(agentID, out reason, ref posX, ref posY))
5384 {
5385 // m_log.DebugFormat("[SCENE]: Denying {0} because they are banned on all parcels", agentID);
5386 return false;
5387 }
5388 }
5389 else // Walking
5390 {
5391 ILandObject land = LandChannel.GetLandObject(position.X, position.Y);
5392 if (land == null)
5393 return false;
5394
5395 bool banned = land.IsBannedFromLand(agentID);
5396 bool restricted = land.IsRestrictedFromLand(agentID);
5397
5398 if (banned || restricted)
5399 return false;
5400 }
5401
5086 reason = String.Empty; 5402 reason = String.Empty;
5087 return true; 5403 return true;
5088 } 5404 }
5089 5405
5090 /// <summary> 5406 public void StartTimerWatchdog()
5407 {
5408 m_timerWatchdog.Interval = 1000;
5409 m_timerWatchdog.Elapsed += TimerWatchdog;
5410 m_timerWatchdog.AutoReset = true;
5411 m_timerWatchdog.Start();
5412 }
5413
5414 public void TimerWatchdog(object sender, ElapsedEventArgs e)
5415 {
5416 CheckHeartbeat();
5417 }
5418
5091 /// This method deals with movement when an avatar is automatically moving (but this is distinct from the 5419 /// This method deals with movement when an avatar is automatically moving (but this is distinct from the
5092 /// autopilot that moves an avatar to a sit target!. 5420 /// autopilot that moves an avatar to a sit target!.
5093 /// </summary> 5421 /// </summary>
diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs
index dee2ecb..73e9392 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 eccce89..fe9fe31 100644
--- a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
@@ -164,7 +164,7 @@ namespace OpenSim.Region.Framework.Scenes
164 164
165 if (neighbour != null) 165 if (neighbour != null)
166 { 166 {
167 m_log.DebugFormat("[INTERGRID]: Successfully informed neighbour {0}-{1} that I'm here", x / Constants.RegionSize, y / Constants.RegionSize); 167 // m_log.DebugFormat("[INTERGRID]: Successfully informed neighbour {0}-{1} that I'm here", x / Constants.RegionSize, y / Constants.RegionSize);
168 m_scene.EventManager.TriggerOnRegionUp(neighbour); 168 m_scene.EventManager.TriggerOnRegionUp(neighbour);
169 } 169 }
170 else 170 else
@@ -179,7 +179,7 @@ namespace OpenSim.Region.Framework.Scenes
179 //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: Sending InterRegion Notification that region is up " + region.RegionName); 179 //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: Sending InterRegion Notification that region is up " + region.RegionName);
180 180
181 List<GridRegion> neighbours = m_scene.GridService.GetNeighbours(m_scene.RegionInfo.ScopeID, m_scene.RegionInfo.RegionID); 181 List<GridRegion> neighbours = m_scene.GridService.GetNeighbours(m_scene.RegionInfo.ScopeID, m_scene.RegionInfo.RegionID);
182 m_log.DebugFormat("[INTERGRID]: Informing {0} neighbours that this region is up", neighbours.Count); 182 //m_log.DebugFormat("[INTERGRID]: Informing {0} neighbours that this region is up", neighbours.Count);
183 foreach (GridRegion n in neighbours) 183 foreach (GridRegion n in neighbours)
184 { 184 {
185 InformNeighbourThatRegionUpDelegate d = InformNeighboursThatRegionIsUpAsync; 185 InformNeighbourThatRegionUpDelegate d = InformNeighboursThatRegionIsUpAsync;
@@ -255,46 +255,42 @@ namespace OpenSim.Region.Framework.Scenes
255 255
256 } 256 }
257 257
258 //public delegate void SendCloseChildAgentDelegate(UUID agentID, ulong regionHandle); 258 public delegate void SendCloseChildAgentDelegate(UUID agentID, ulong regionHandle);
259 //private void SendCloseChildAgentCompleted(IAsyncResult iar)
260 //{
261 // SendCloseChildAgentDelegate icon = (SendCloseChildAgentDelegate)iar.AsyncState;
262 // icon.EndInvoke(iar);
263 //}
264 259
265 /// <summary> 260 /// <summary>
266 /// Closes a child agent on a given region 261 /// This Closes child agents on neighboring regions
262 /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
267 /// </summary> 263 /// </summary>
268 protected void SendCloseChildAgent(UUID agentID, ulong regionHandle) 264 protected void SendCloseChildAgentAsync(UUID agentID, ulong regionHandle)
269 { 265 {
270 266
271 m_log.Debug("[INTERGRID]: Sending close agent to " + regionHandle); 267 //m_log.Debug("[INTERGRID]: Sending close agent to " + regionHandle);
272 // let's do our best, but there's not much we can do if the neighbour doesn't accept. 268 // let's do our best, but there's not much we can do if the neighbour doesn't accept.
273 269
274 //m_commsProvider.InterRegion.TellRegionToCloseChildConnection(regionHandle, agentID); 270 //m_commsProvider.InterRegion.TellRegionToCloseChildConnection(regionHandle, agentID);
275 uint x = 0, y = 0; 271 uint x = 0, y = 0;
276 Utils.LongToUInts(regionHandle, out x, out y); 272 Utils.LongToUInts(regionHandle, out x, out y);
277 GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y); 273 GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y);
278 m_scene.SimulationService.CloseAgent(destination, agentID); 274 m_scene.SimulationService.CloseChildAgent(destination, agentID);
275 }
276
277 private void SendCloseChildAgentCompleted(IAsyncResult iar)
278 {
279 SendCloseChildAgentDelegate icon = (SendCloseChildAgentDelegate)iar.AsyncState;
280 icon.EndInvoke(iar);
279 } 281 }
280 282
281 /// <summary>
282 /// Closes a child agents in a collection of regions. Does so asynchronously
283 /// so that the caller doesn't wait.
284 /// </summary>
285 /// <param name="agentID"></param>
286 /// <param name="regionslst"></param>
287 public void SendCloseChildAgentConnections(UUID agentID, List<ulong> regionslst) 283 public void SendCloseChildAgentConnections(UUID agentID, List<ulong> regionslst)
288 { 284 {
289 Util.FireAndForget(delegate 285 foreach (ulong handle in regionslst)
290 { 286 {
291 foreach (ulong handle in regionslst) 287 SendCloseChildAgentDelegate d = SendCloseChildAgentAsync;
292 { 288 d.BeginInvoke(agentID, handle,
293 SendCloseChildAgent(agentID, handle); 289 SendCloseChildAgentCompleted,
294 } 290 d);
295 }); 291 }
296 } 292 }
297 293
298 public List<GridRegion> RequestNamedRegions(string name, int maxNumber) 294 public List<GridRegion> RequestNamedRegions(string name, int maxNumber)
299 { 295 {
300 return m_scene.GridService.GetRegionsByName(UUID.Zero, name, maxNumber); 296 return m_scene.GridService.GetRegionsByName(UUID.Zero, name, maxNumber);
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index af95c28..c16038c 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -43,6 +43,12 @@ namespace OpenSim.Region.Framework.Scenes
43 43
44 public delegate void ObjectDuplicateDelegate(EntityBase original, EntityBase clone); 44 public delegate void ObjectDuplicateDelegate(EntityBase original, EntityBase clone);
45 45
46 public delegate void AttachToBackupDelegate(SceneObjectGroup sog);
47
48 public delegate void DetachFromBackupDelegate(SceneObjectGroup sog);
49
50 public delegate void ChangedBackupDelegate(SceneObjectGroup sog);
51
46 public delegate void ObjectCreateDelegate(EntityBase obj); 52 public delegate void ObjectCreateDelegate(EntityBase obj);
47 53
48 public delegate void ObjectDeleteDelegate(EntityBase obj); 54 public delegate void ObjectDeleteDelegate(EntityBase obj);
@@ -61,6 +67,9 @@ namespace OpenSim.Region.Framework.Scenes
61 private PhysicsCrash handlerPhysicsCrash = null; 67 private PhysicsCrash handlerPhysicsCrash = null;
62 68
63 public event ObjectDuplicateDelegate OnObjectDuplicate; 69 public event ObjectDuplicateDelegate OnObjectDuplicate;
70 public event AttachToBackupDelegate OnAttachToBackup;
71 public event DetachFromBackupDelegate OnDetachFromBackup;
72 public event ChangedBackupDelegate OnChangeBackup;
64 public event ObjectCreateDelegate OnObjectCreate; 73 public event ObjectCreateDelegate OnObjectCreate;
65 public event ObjectDeleteDelegate OnObjectRemove; 74 public event ObjectDeleteDelegate OnObjectRemove;
66 75
@@ -68,7 +77,7 @@ namespace OpenSim.Region.Framework.Scenes
68 77
69 #region Fields 78 #region Fields
70 79
71 protected object m_presenceLock = new object(); 80 protected OpenMetaverse.ReaderWriterLockSlim m_scenePresencesLock = new OpenMetaverse.ReaderWriterLockSlim();
72 protected Dictionary<UUID, ScenePresence> m_scenePresenceMap = new Dictionary<UUID, ScenePresence>(); 81 protected Dictionary<UUID, ScenePresence> m_scenePresenceMap = new Dictionary<UUID, ScenePresence>();
73 protected List<ScenePresence> m_scenePresenceArray = new List<ScenePresence>(); 82 protected List<ScenePresence> m_scenePresenceArray = new List<ScenePresence>();
74 83
@@ -130,13 +139,18 @@ namespace OpenSim.Region.Framework.Scenes
130 139
131 protected internal void Close() 140 protected internal void Close()
132 { 141 {
133 lock (m_presenceLock) 142 m_scenePresencesLock.EnterWriteLock();
143 try
134 { 144 {
135 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(); 145 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>();
136 List<ScenePresence> newlist = new List<ScenePresence>(); 146 List<ScenePresence> newlist = new List<ScenePresence>();
137 m_scenePresenceMap = newmap; 147 m_scenePresenceMap = newmap;
138 m_scenePresenceArray = newlist; 148 m_scenePresenceArray = newlist;
139 } 149 }
150 finally
151 {
152 m_scenePresencesLock.ExitWriteLock();
153 }
140 154
141 lock (SceneObjectGroupsByFullID) 155 lock (SceneObjectGroupsByFullID)
142 SceneObjectGroupsByFullID.Clear(); 156 SceneObjectGroupsByFullID.Clear();
@@ -275,6 +289,33 @@ namespace OpenSim.Region.Framework.Scenes
275 protected internal bool AddRestoredSceneObject( 289 protected internal bool AddRestoredSceneObject(
276 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 290 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
277 { 291 {
292 if (!m_parentScene.CombineRegions)
293 {
294 // KF: Check for out-of-region, move inside and make static.
295 Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X,
296 sceneObject.RootPart.GroupPosition.Y,
297 sceneObject.RootPart.GroupPosition.Z);
298 if (!(((sceneObject.RootPart.Shape.PCode == (byte)PCode.Prim) && (sceneObject.RootPart.Shape.State != 0))) && (npos.X < 0.0 || npos.Y < 0.0 || npos.Z < 0.0 ||
299 npos.X > Constants.RegionSize ||
300 npos.Y > Constants.RegionSize))
301 {
302 if (npos.X < 0.0) npos.X = 1.0f;
303 if (npos.Y < 0.0) npos.Y = 1.0f;
304 if (npos.Z < 0.0) npos.Z = 0.0f;
305 if (npos.X > Constants.RegionSize) npos.X = Constants.RegionSize - 1.0f;
306 if (npos.Y > Constants.RegionSize) npos.Y = Constants.RegionSize - 1.0f;
307
308 foreach (SceneObjectPart part in sceneObject.Parts)
309 {
310 part.GroupPosition = npos;
311 }
312 sceneObject.RootPart.Velocity = Vector3.Zero;
313 sceneObject.RootPart.AngularVelocity = Vector3.Zero;
314 sceneObject.RootPart.Acceleration = Vector3.Zero;
315 sceneObject.RootPart.Velocity = Vector3.Zero;
316 }
317 }
318
278 if (attachToBackup && (!alreadyPersisted)) 319 if (attachToBackup && (!alreadyPersisted))
279 { 320 {
280 sceneObject.ForceInventoryPersistence(); 321 sceneObject.ForceInventoryPersistence();
@@ -492,6 +533,30 @@ namespace OpenSim.Region.Framework.Scenes
492 m_updateList[obj.UUID] = obj; 533 m_updateList[obj.UUID] = obj;
493 } 534 }
494 535
536 public void FireAttachToBackup(SceneObjectGroup obj)
537 {
538 if (OnAttachToBackup != null)
539 {
540 OnAttachToBackup(obj);
541 }
542 }
543
544 public void FireDetachFromBackup(SceneObjectGroup obj)
545 {
546 if (OnDetachFromBackup != null)
547 {
548 OnDetachFromBackup(obj);
549 }
550 }
551
552 public void FireChangeBackup(SceneObjectGroup obj)
553 {
554 if (OnChangeBackup != null)
555 {
556 OnChangeBackup(obj);
557 }
558 }
559
495 /// <summary> 560 /// <summary>
496 /// Process all pending updates 561 /// Process all pending updates
497 /// </summary> 562 /// </summary>
@@ -623,7 +688,8 @@ namespace OpenSim.Region.Framework.Scenes
623 688
624 Entities[presence.UUID] = presence; 689 Entities[presence.UUID] = presence;
625 690
626 lock (m_presenceLock) 691 m_scenePresencesLock.EnterWriteLock();
692 try
627 { 693 {
628 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 694 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
629 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 695 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -647,6 +713,10 @@ namespace OpenSim.Region.Framework.Scenes
647 m_scenePresenceMap = newmap; 713 m_scenePresenceMap = newmap;
648 m_scenePresenceArray = newlist; 714 m_scenePresenceArray = newlist;
649 } 715 }
716 finally
717 {
718 m_scenePresencesLock.ExitWriteLock();
719 }
650 } 720 }
651 721
652 /// <summary> 722 /// <summary>
@@ -661,7 +731,8 @@ namespace OpenSim.Region.Framework.Scenes
661 agentID); 731 agentID);
662 } 732 }
663 733
664 lock (m_presenceLock) 734 m_scenePresencesLock.EnterWriteLock();
735 try
665 { 736 {
666 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 737 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
667 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 738 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -683,6 +754,10 @@ namespace OpenSim.Region.Framework.Scenes
683 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); 754 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID);
684 } 755 }
685 } 756 }
757 finally
758 {
759 m_scenePresencesLock.ExitWriteLock();
760 }
686 } 761 }
687 762
688 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) 763 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F)
@@ -1396,8 +1471,13 @@ namespace OpenSim.Region.Framework.Scenes
1396 { 1471 {
1397 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) 1472 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0))
1398 { 1473 {
1399 if (m_parentScene.AttachmentsModule != null) 1474 // Set the new attachment point data in the object
1400 m_parentScene.AttachmentsModule.UpdateAttachmentPosition(group, pos); 1475 byte attachmentPoint = group.GetAttachmentPoint();
1476 group.UpdateGroupPosition(pos);
1477 group.IsAttachment = false;
1478 group.AbsolutePosition = group.RootPart.AttachedPos;
1479 group.AttachmentPoint = attachmentPoint;
1480 group.HasGroupChanged = true;
1401 } 1481 }
1402 else 1482 else
1403 { 1483 {
@@ -1669,8 +1749,11 @@ namespace OpenSim.Region.Framework.Scenes
1669 return; 1749 return;
1670 1750
1671 Monitor.Enter(m_updateLock); 1751 Monitor.Enter(m_updateLock);
1752
1672 try 1753 try
1673 { 1754 {
1755 parentGroup.areUpdatesSuspended = true;
1756
1674 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); 1757 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
1675 1758
1676 // We do this in reverse to get the link order of the prims correct 1759 // We do this in reverse to get the link order of the prims correct
@@ -1681,9 +1764,13 @@ namespace OpenSim.Region.Framework.Scenes
1681 // Make sure no child prim is set for sale 1764 // Make sure no child prim is set for sale
1682 // So that, on delink, no prims are unwittingly 1765 // So that, on delink, no prims are unwittingly
1683 // left for sale and sold off 1766 // left for sale and sold off
1684 child.RootPart.ObjectSaleType = 0; 1767
1685 child.RootPart.SalePrice = 10; 1768 if (child != null)
1686 childGroups.Add(child); 1769 {
1770 child.RootPart.ObjectSaleType = 0;
1771 child.RootPart.SalePrice = 10;
1772 childGroups.Add(child);
1773 }
1687 } 1774 }
1688 1775
1689 foreach (SceneObjectGroup child in childGroups) 1776 foreach (SceneObjectGroup child in childGroups)
@@ -1702,12 +1789,19 @@ namespace OpenSim.Region.Framework.Scenes
1702 // occur on link to invoke this elsewhere (such as object selection) 1789 // occur on link to invoke this elsewhere (such as object selection)
1703 parentGroup.RootPart.CreateSelected = true; 1790 parentGroup.RootPart.CreateSelected = true;
1704 parentGroup.TriggerScriptChangedEvent(Changed.LINK); 1791 parentGroup.TriggerScriptChangedEvent(Changed.LINK);
1705 parentGroup.HasGroupChanged = true;
1706 parentGroup.ScheduleGroupForFullUpdate();
1707
1708 } 1792 }
1709 finally 1793 finally
1710 { 1794 {
1795 lock (SceneObjectGroupsByLocalPartID)
1796 {
1797 foreach (SceneObjectPart part in parentGroup.Parts)
1798 SceneObjectGroupsByLocalPartID[part.LocalId] = parentGroup;
1799 }
1800
1801 parentGroup.areUpdatesSuspended = false;
1802 parentGroup.HasGroupChanged = true;
1803 parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true);
1804 parentGroup.ScheduleGroupForFullUpdate();
1711 Monitor.Exit(m_updateLock); 1805 Monitor.Exit(m_updateLock);
1712 } 1806 }
1713 } 1807 }
@@ -1744,21 +1838,24 @@ namespace OpenSim.Region.Framework.Scenes
1744 1838
1745 SceneObjectGroup group = part.ParentGroup; 1839 SceneObjectGroup group = part.ParentGroup;
1746 if (!affectedGroups.Contains(group)) 1840 if (!affectedGroups.Contains(group))
1841 {
1842 group.areUpdatesSuspended = true;
1747 affectedGroups.Add(group); 1843 affectedGroups.Add(group);
1844 }
1748 } 1845 }
1749 } 1846 }
1750 } 1847 }
1751 1848
1752 foreach (SceneObjectPart child in childParts) 1849 if (childParts.Count > 0)
1753 { 1850 {
1754 // Unlink all child parts from their groups 1851 foreach (SceneObjectPart child in childParts)
1755 // 1852 {
1756 child.ParentGroup.DelinkFromGroup(child, true); 1853 // Unlink all child parts from their groups
1757 1854 //
1758 // These are not in affected groups and will not be 1855 child.ParentGroup.DelinkFromGroup(child, true);
1759 // handled further. Do the honors here. 1856 child.ParentGroup.HasGroupChanged = true;
1760 child.ParentGroup.HasGroupChanged = true; 1857 child.ParentGroup.ScheduleGroupForFullUpdate();
1761 child.ParentGroup.ScheduleGroupForFullUpdate(); 1858 }
1762 } 1859 }
1763 1860
1764 foreach (SceneObjectPart root in rootParts) 1861 foreach (SceneObjectPart root in rootParts)
@@ -1768,56 +1865,68 @@ namespace OpenSim.Region.Framework.Scenes
1768 // However, editing linked parts and unlinking may be different 1865 // However, editing linked parts and unlinking may be different
1769 // 1866 //
1770 SceneObjectGroup group = root.ParentGroup; 1867 SceneObjectGroup group = root.ParentGroup;
1868 group.areUpdatesSuspended = true;
1771 1869
1772 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); 1870 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts);
1773 int numChildren = newSet.Count; 1871 int numChildren = newSet.Count;
1774 1872
1873 if (numChildren == 1)
1874 break;
1875
1775 // If there are prims left in a link set, but the root is 1876 // If there are prims left in a link set, but the root is
1776 // slated for unlink, we need to do this 1877 // slated for unlink, we need to do this
1878 // Unlink the remaining set
1777 // 1879 //
1778 if (numChildren != 1) 1880 bool sendEventsToRemainder = true;
1779 { 1881 if (numChildren > 1)
1780 // Unlink the remaining set 1882 sendEventsToRemainder = false;
1781 //
1782 bool sendEventsToRemainder = true;
1783 if (numChildren > 1)
1784 sendEventsToRemainder = false;
1785 1883
1786 foreach (SceneObjectPart p in newSet) 1884 foreach (SceneObjectPart p in newSet)
1885 {
1886 if (p != group.RootPart)
1787 { 1887 {
1788 if (p != group.RootPart) 1888 group.DelinkFromGroup(p, sendEventsToRemainder);
1789 group.DelinkFromGroup(p, sendEventsToRemainder); 1889 if (numChildren > 2)
1890 {
1891 p.ParentGroup.areUpdatesSuspended = true;
1892 }
1893 else
1894 {
1895 p.ParentGroup.HasGroupChanged = true;
1896 p.ParentGroup.ScheduleGroupForFullUpdate();
1897 }
1790 } 1898 }
1899 }
1900
1901 // If there is more than one prim remaining, we
1902 // need to re-link
1903 //
1904 if (numChildren > 2)
1905 {
1906 // Remove old root
1907 //
1908 if (newSet.Contains(root))
1909 newSet.Remove(root);
1791 1910
1792 // If there is more than one prim remaining, we 1911 // Preserve link ordering
1793 // need to re-link
1794 // 1912 //
1795 if (numChildren > 2) 1913 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1796 { 1914 {
1797 // Remove old root 1915 return a.LinkNum.CompareTo(b.LinkNum);
1798 // 1916 });
1799 if (newSet.Contains(root))
1800 newSet.Remove(root);
1801
1802 // Preserve link ordering
1803 //
1804 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1805 {
1806 return a.LinkNum.CompareTo(b.LinkNum);
1807 });
1808 1917
1809 // Determine new root 1918 // Determine new root
1810 // 1919 //
1811 SceneObjectPart newRoot = newSet[0]; 1920 SceneObjectPart newRoot = newSet[0];
1812 newSet.RemoveAt(0); 1921 newSet.RemoveAt(0);
1813 1922
1814 foreach (SceneObjectPart newChild in newSet) 1923 foreach (SceneObjectPart newChild in newSet)
1815 newChild.ClearUpdateSchedule(); 1924 newChild.ClearUpdateSchedule();
1816 1925
1817 LinkObjects(newRoot, newSet); 1926 newRoot.ParentGroup.areUpdatesSuspended = true;
1818 if (!affectedGroups.Contains(newRoot.ParentGroup)) 1927 LinkObjects(newRoot, newSet);
1819 affectedGroups.Add(newRoot.ParentGroup); 1928 if (!affectedGroups.Contains(newRoot.ParentGroup))
1820 } 1929 affectedGroups.Add(newRoot.ParentGroup);
1821 } 1930 }
1822 } 1931 }
1823 1932
@@ -1825,8 +1934,14 @@ namespace OpenSim.Region.Framework.Scenes
1825 // 1934 //
1826 foreach (SceneObjectGroup g in affectedGroups) 1935 foreach (SceneObjectGroup g in affectedGroups)
1827 { 1936 {
1937 // Child prims that have been unlinked and deleted will
1938 // return unless the root is deleted. This will remove them
1939 // from the database. They will be rewritten immediately,
1940 // minus the rows for the unlinked child prims.
1941 m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID);
1828 g.TriggerScriptChangedEvent(Changed.LINK); 1942 g.TriggerScriptChangedEvent(Changed.LINK);
1829 g.HasGroupChanged = true; // Persist 1943 g.HasGroupChanged = true; // Persist
1944 g.areUpdatesSuspended = false;
1830 g.ScheduleGroupForFullUpdate(); 1945 g.ScheduleGroupForFullUpdate();
1831 } 1946 }
1832 } 1947 }
@@ -1944,9 +2059,6 @@ namespace OpenSim.Region.Framework.Scenes
1944 child.ApplyNextOwnerPermissions(); 2059 child.ApplyNextOwnerPermissions();
1945 } 2060 }
1946 } 2061 }
1947
1948 copy.RootPart.ObjectSaleType = 0;
1949 copy.RootPart.SalePrice = 10;
1950 } 2062 }
1951 2063
1952 // FIXME: This section needs to be refactored so that it just calls AddSceneObject() 2064 // FIXME: This section needs to be refactored so that it just calls AddSceneObject()
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
index 905ecc9..c7da4f4 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
@@ -69,10 +69,6 @@ namespace OpenSim.Region.Framework.Scenes
69 /// <summary> 69 /// <summary>
70 /// Stop the scripts contained in all the prims in this group 70 /// Stop the scripts contained in all the prims in this group
71 /// </summary> 71 /// </summary>
72 /// <param name="sceneObjectBeingDeleted">
73 /// Should be true if these scripts are being removed because the scene
74 /// object is being deleted. This will prevent spurious updates to the client.
75 /// </param>
76 public void RemoveScriptInstances(bool sceneObjectBeingDeleted) 72 public void RemoveScriptInstances(bool sceneObjectBeingDeleted)
77 { 73 {
78 SceneObjectPart[] parts = m_parts.GetArray(); 74 SceneObjectPart[] parts = m_parts.GetArray();
@@ -234,6 +230,11 @@ namespace OpenSim.Region.Framework.Scenes
234 230
235 public uint GetEffectivePermissions() 231 public uint GetEffectivePermissions()
236 { 232 {
233 return GetEffectivePermissions(false);
234 }
235
236 public uint GetEffectivePermissions(bool useBase)
237 {
237 uint perms=(uint)(PermissionMask.Modify | 238 uint perms=(uint)(PermissionMask.Modify |
238 PermissionMask.Copy | 239 PermissionMask.Copy |
239 PermissionMask.Move | 240 PermissionMask.Move |
@@ -245,7 +246,10 @@ namespace OpenSim.Region.Framework.Scenes
245 for (int i = 0; i < parts.Length; i++) 246 for (int i = 0; i < parts.Length; i++)
246 { 247 {
247 SceneObjectPart part = parts[i]; 248 SceneObjectPart part = parts[i];
248 ownerMask &= part.OwnerMask; 249 if (useBase)
250 ownerMask &= part.BaseMask;
251 else
252 ownerMask &= part.OwnerMask;
249 perms &= part.Inventory.MaskEffectivePermissions(); 253 perms &= part.Inventory.MaskEffectivePermissions();
250 } 254 }
251 255
@@ -385,6 +389,9 @@ namespace OpenSim.Region.Framework.Scenes
385 389
386 public void ResumeScripts() 390 public void ResumeScripts()
387 { 391 {
392 if (m_scene.RegionInfo.RegionSettings.DisableScripts)
393 return;
394
388 SceneObjectPart[] parts = m_parts.GetArray(); 395 SceneObjectPart[] parts = m_parts.GetArray();
389 for (int i = 0; i < parts.Length; i++) 396 for (int i = 0; i < parts.Length; i++)
390 parts[i].Inventory.ResumeScripts(); 397 parts[i].Inventory.ResumeScripts();
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 9587d5f..dd5e986 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,29 @@ 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 foreach (SceneObjectPart part in parts)
409 parts[i].GroupPosition = val; 485 {
486 part.GroupPosition = val;
487 if (!m_dupeInProgress)
488 {
489 part.TriggerScriptChangedEvent(Changed.POSITION);
490 }
491 }
492 if (!m_dupeInProgress)
493 {
494 foreach (ScenePresence av in m_linkedAvatars)
495 {
496 SceneObjectPart p = m_scene.GetSceneObjectPart(av.ParentID);
497 if (m_parts.TryGetValue(p.UUID, out p))
498 {
499 Vector3 offset = p.GetWorldPosition() - av.ParentPosition;
500 av.AbsolutePosition += offset;
501 av.ParentPosition = p.GetWorldPosition(); //ParentPosition gets cleared by AbsolutePosition
502 av.SendAvatarDataToAllAgents();
503 }
504 }
505 }
410 506
411 //if (m_rootPart.PhysActor != null) 507 //if (m_rootPart.PhysActor != null)
412 //{ 508 //{
@@ -565,6 +661,7 @@ namespace OpenSim.Region.Framework.Scenes
565 /// </summary> 661 /// </summary>
566 public SceneObjectGroup() 662 public SceneObjectGroup()
567 { 663 {
664
568 } 665 }
569 666
570 /// <summary> 667 /// <summary>
@@ -581,7 +678,7 @@ namespace OpenSim.Region.Framework.Scenes
581 /// Constructor. This object is added to the scene later via AttachToScene() 678 /// Constructor. This object is added to the scene later via AttachToScene()
582 /// </summary> 679 /// </summary>
583 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) 680 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape)
584 { 681 {
585 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero)); 682 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero));
586 } 683 }
587 684
@@ -629,6 +726,9 @@ namespace OpenSim.Region.Framework.Scenes
629 /// </summary> 726 /// </summary>
630 public virtual void AttachToBackup() 727 public virtual void AttachToBackup()
631 { 728 {
729 if (IsAttachment) return;
730 m_scene.SceneGraph.FireAttachToBackup(this);
731
632 if (InSceneBackup) 732 if (InSceneBackup)
633 { 733 {
634 //m_log.DebugFormat( 734 //m_log.DebugFormat(
@@ -671,6 +771,9 @@ namespace OpenSim.Region.Framework.Scenes
671 771
672 ApplyPhysics(m_scene.m_physicalPrim); 772 ApplyPhysics(m_scene.m_physicalPrim);
673 773
774 if (RootPart.PhysActor != null)
775 RootPart.Buoyancy = RootPart.Buoyancy;
776
674 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled 777 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled
675 // for the same object with very different properties. The caller must schedule the update. 778 // for the same object with very different properties. The caller must schedule the update.
676 //ScheduleGroupForFullUpdate(); 779 //ScheduleGroupForFullUpdate();
@@ -716,9 +819,9 @@ namespace OpenSim.Region.Framework.Scenes
716 result.normal = inter.normal; 819 result.normal = inter.normal;
717 result.distance = inter.distance; 820 result.distance = inter.distance;
718 } 821 }
822
719 } 823 }
720 } 824 }
721
722 return result; 825 return result;
723 } 826 }
724 827
@@ -738,17 +841,19 @@ namespace OpenSim.Region.Framework.Scenes
738 minZ = 8192f; 841 minZ = 8192f;
739 842
740 SceneObjectPart[] parts = m_parts.GetArray(); 843 SceneObjectPart[] parts = m_parts.GetArray();
741 for (int i = 0; i < parts.Length; i++) 844 foreach (SceneObjectPart part in parts)
742 { 845 {
743 SceneObjectPart part = parts[i];
744
745 Vector3 worldPos = part.GetWorldPosition(); 846 Vector3 worldPos = part.GetWorldPosition();
746 Vector3 offset = worldPos - AbsolutePosition; 847 Vector3 offset = worldPos - AbsolutePosition;
747 Quaternion worldRot; 848 Quaternion worldRot;
748 if (part.ParentID == 0) 849 if (part.ParentID == 0)
850 {
749 worldRot = part.RotationOffset; 851 worldRot = part.RotationOffset;
852 }
750 else 853 else
854 {
751 worldRot = part.GetWorldRotation(); 855 worldRot = part.GetWorldRotation();
856 }
752 857
753 Vector3 frontTopLeft; 858 Vector3 frontTopLeft;
754 Vector3 frontTopRight; 859 Vector3 frontTopRight;
@@ -760,6 +865,8 @@ namespace OpenSim.Region.Framework.Scenes
760 Vector3 backBottomLeft; 865 Vector3 backBottomLeft;
761 Vector3 backBottomRight; 866 Vector3 backBottomRight;
762 867
868 // Vector3[] corners = new Vector3[8];
869
763 Vector3 orig = Vector3.Zero; 870 Vector3 orig = Vector3.Zero;
764 871
765 frontTopLeft.X = orig.X - (part.Scale.X / 2); 872 frontTopLeft.X = orig.X - (part.Scale.X / 2);
@@ -794,6 +901,38 @@ namespace OpenSim.Region.Framework.Scenes
794 backBottomRight.Y = orig.Y + (part.Scale.Y / 2); 901 backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
795 backBottomRight.Z = orig.Z - (part.Scale.Z / 2); 902 backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
796 903
904
905
906 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
907 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
908 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
909 //m_log.InfoFormat("pre corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
910 //m_log.InfoFormat("pre corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
911 //m_log.InfoFormat("pre corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
912 //m_log.InfoFormat("pre corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
913 //m_log.InfoFormat("pre corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
914
915 //for (int i = 0; i < 8; i++)
916 //{
917 // corners[i] = corners[i] * worldRot;
918 // corners[i] += offset;
919
920 // if (corners[i].X > maxX)
921 // maxX = corners[i].X;
922 // if (corners[i].X < minX)
923 // minX = corners[i].X;
924
925 // if (corners[i].Y > maxY)
926 // maxY = corners[i].Y;
927 // if (corners[i].Y < minY)
928 // minY = corners[i].Y;
929
930 // if (corners[i].Z > maxZ)
931 // maxZ = corners[i].Y;
932 // if (corners[i].Z < minZ)
933 // minZ = corners[i].Z;
934 //}
935
797 frontTopLeft = frontTopLeft * worldRot; 936 frontTopLeft = frontTopLeft * worldRot;
798 frontTopRight = frontTopRight * worldRot; 937 frontTopRight = frontTopRight * worldRot;
799 frontBottomLeft = frontBottomLeft * worldRot; 938 frontBottomLeft = frontBottomLeft * worldRot;
@@ -815,6 +954,15 @@ namespace OpenSim.Region.Framework.Scenes
815 backTopLeft += offset; 954 backTopLeft += offset;
816 backTopRight += offset; 955 backTopRight += offset;
817 956
957 //m_log.InfoFormat("corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
958 //m_log.InfoFormat("corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
959 //m_log.InfoFormat("corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
960 //m_log.InfoFormat("corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
961 //m_log.InfoFormat("corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
962 //m_log.InfoFormat("corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
963 //m_log.InfoFormat("corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
964 //m_log.InfoFormat("corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
965
818 if (frontTopRight.X > maxX) 966 if (frontTopRight.X > maxX)
819 maxX = frontTopRight.X; 967 maxX = frontTopRight.X;
820 if (frontTopLeft.X > maxX) 968 if (frontTopLeft.X > maxX)
@@ -960,15 +1108,20 @@ namespace OpenSim.Region.Framework.Scenes
960 1108
961 public void SaveScriptedState(XmlTextWriter writer) 1109 public void SaveScriptedState(XmlTextWriter writer)
962 { 1110 {
1111 SaveScriptedState(writer, false);
1112 }
1113
1114 public void SaveScriptedState(XmlTextWriter writer, bool oldIDs)
1115 {
963 XmlDocument doc = new XmlDocument(); 1116 XmlDocument doc = new XmlDocument();
964 Dictionary<UUID,string> states = new Dictionary<UUID,string>(); 1117 Dictionary<UUID,string> states = new Dictionary<UUID,string>();
965 1118
966 SceneObjectPart[] parts = m_parts.GetArray(); 1119 SceneObjectPart[] parts = m_parts.GetArray();
967 for (int i = 0; i < parts.Length; i++) 1120 for (int i = 0; i < parts.Length; i++)
968 { 1121 {
969 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(); 1122 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(oldIDs);
970 foreach (KeyValuePair<UUID, string> kvp in pstates) 1123 foreach (KeyValuePair<UUID, string> kvp in pstates)
971 states.Add(kvp.Key, kvp.Value); 1124 states[kvp.Key] = kvp.Value;
972 } 1125 }
973 1126
974 if (states.Count > 0) 1127 if (states.Count > 0)
@@ -988,6 +1141,168 @@ namespace OpenSim.Region.Framework.Scenes
988 } 1141 }
989 1142
990 /// <summary> 1143 /// <summary>
1144 /// Add the avatar to this linkset (avatar is sat).
1145 /// </summary>
1146 /// <param name="agentID"></param>
1147 public void AddAvatar(UUID agentID)
1148 {
1149 ScenePresence presence;
1150 if (m_scene.TryGetScenePresence(agentID, out presence))
1151 {
1152 if (!m_linkedAvatars.Contains(presence))
1153 {
1154 m_linkedAvatars.Add(presence);
1155 }
1156 }
1157 }
1158
1159 /// <summary>
1160 /// Delete the avatar from this linkset (avatar is unsat).
1161 /// </summary>
1162 /// <param name="agentID"></param>
1163 public void DeleteAvatar(UUID agentID)
1164 {
1165 ScenePresence presence;
1166 if (m_scene.TryGetScenePresence(agentID, out presence))
1167 {
1168 if (m_linkedAvatars.Contains(presence))
1169 {
1170 m_linkedAvatars.Remove(presence);
1171 }
1172 }
1173 }
1174
1175 /// <summary>
1176 /// Returns the list of linked presences (avatars sat on this group)
1177 /// </summary>
1178 /// <param name="agentID"></param>
1179 public List<ScenePresence> GetLinkedAvatars()
1180 {
1181 return m_linkedAvatars;
1182 }
1183
1184 /// <summary>
1185 /// Attach this scene object to the given avatar.
1186 /// </summary>
1187 /// <param name="agentID"></param>
1188 /// <param name="attachmentpoint"></param>
1189 /// <param name="AttachOffset"></param>
1190 private void AttachToAgent(
1191 ScenePresence avatar, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent)
1192 {
1193 if (avatar != null)
1194 {
1195 // don't attach attachments to child agents
1196 if (avatar.IsChildAgent) return;
1197
1198 // Remove from database and parcel prim count
1199 m_scene.DeleteFromStorage(so.UUID);
1200 m_scene.EventManager.TriggerParcelPrimCountTainted();
1201
1202 so.AttachedAvatar = avatar.UUID;
1203
1204 if (so.RootPart.PhysActor != null)
1205 {
1206 m_scene.PhysicsScene.RemovePrim(so.RootPart.PhysActor);
1207 so.RootPart.PhysActor = null;
1208 }
1209
1210 so.AbsolutePosition = attachOffset;
1211 so.RootPart.AttachedPos = attachOffset;
1212 so.IsAttachment = true;
1213 so.RootPart.SetParentLocalId(avatar.LocalId);
1214 so.AttachmentPoint = attachmentpoint;
1215
1216 avatar.AddAttachment(this);
1217
1218 if (!silent)
1219 {
1220 // Killing it here will cause the client to deselect it
1221 // It then reappears on the avatar, deselected
1222 // through the full update below
1223 //
1224 if (IsSelected)
1225 {
1226 m_scene.SendKillObject(new List<uint> { m_rootPart.LocalId });
1227 }
1228
1229 IsSelected = false; // fudge....
1230 ScheduleGroupForFullUpdate();
1231 }
1232 }
1233 else
1234 {
1235 m_log.WarnFormat(
1236 "[SOG]: Tried to add attachment {0} to avatar with UUID {1} in region {2} but the avatar is not present",
1237 UUID, avatar.ControllingClient.AgentId, Scene.RegionInfo.RegionName);
1238 }
1239 }
1240
1241 public byte GetAttachmentPoint()
1242 {
1243 return m_rootPart.Shape.State;
1244 }
1245
1246 public void DetachToGround()
1247 {
1248 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
1249 if (avatar == null)
1250 return;
1251
1252 avatar.RemoveAttachment(this);
1253
1254 Vector3 detachedpos = new Vector3(127f,127f,127f);
1255 if (avatar == null)
1256 return;
1257
1258 detachedpos = avatar.AbsolutePosition;
1259 RootPart.FromItemID = UUID.Zero;
1260
1261 AbsolutePosition = detachedpos;
1262 AttachedAvatar = UUID.Zero;
1263
1264 //SceneObjectPart[] parts = m_parts.GetArray();
1265 //for (int i = 0; i < parts.Length; i++)
1266 // parts[i].AttachedAvatar = UUID.Zero;
1267
1268 m_rootPart.SetParentLocalId(0);
1269 AttachmentPoint = (byte)0;
1270 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive);
1271 HasGroupChanged = true;
1272 RootPart.Rezzed = DateTime.Now;
1273 RootPart.RemFlag(PrimFlags.TemporaryOnRez);
1274 AttachToBackup();
1275 m_scene.EventManager.TriggerParcelPrimCountTainted();
1276 m_rootPart.ScheduleFullUpdate();
1277 m_rootPart.ClearUndoState();
1278 }
1279
1280 public void DetachToInventoryPrep()
1281 {
1282 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
1283 //Vector3 detachedpos = new Vector3(127f, 127f, 127f);
1284 if (avatar != null)
1285 {
1286 //detachedpos = avatar.AbsolutePosition;
1287 avatar.RemoveAttachment(this);
1288 }
1289
1290 AttachedAvatar = UUID.Zero;
1291
1292 /*SceneObjectPart[] parts = m_parts.GetArray();
1293 for (int i = 0; i < parts.Length; i++)
1294 parts[i].AttachedAvatar = UUID.Zero;*/
1295
1296 m_rootPart.SetParentLocalId(0);
1297 //m_rootPart.SetAttachmentPoint((byte)0);
1298 IsAttachment = false;
1299 AbsolutePosition = m_rootPart.AttachedPos;
1300 //m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_scene.m_physicalPrim);
1301 //AttachToBackup();
1302 //m_rootPart.ScheduleFullUpdate();
1303 }
1304
1305 /// <summary>
991 /// 1306 ///
992 /// </summary> 1307 /// </summary>
993 /// <param name="part"></param> 1308 /// <param name="part"></param>
@@ -1037,7 +1352,10 @@ namespace OpenSim.Region.Framework.Scenes
1037 public void AddPart(SceneObjectPart part) 1352 public void AddPart(SceneObjectPart part)
1038 { 1353 {
1039 part.SetParent(this); 1354 part.SetParent(this);
1040 part.LinkNum = m_parts.Add(part.UUID, part); 1355 m_parts.Add(part.UUID, part);
1356
1357 part.LinkNum = m_parts.Count;
1358
1041 if (part.LinkNum == 2) 1359 if (part.LinkNum == 2)
1042 RootPart.LinkNum = 1; 1360 RootPart.LinkNum = 1;
1043 } 1361 }
@@ -1145,6 +1463,11 @@ namespace OpenSim.Region.Framework.Scenes
1145 /// <param name="silent">If true then deletion is not broadcast to clients</param> 1463 /// <param name="silent">If true then deletion is not broadcast to clients</param>
1146 public void DeleteGroupFromScene(bool silent) 1464 public void DeleteGroupFromScene(bool silent)
1147 { 1465 {
1466 // We need to keep track of this state in case this group is still queued for backup.
1467 IsDeleted = true;
1468
1469 DetachFromBackup();
1470
1148 SceneObjectPart[] parts = m_parts.GetArray(); 1471 SceneObjectPart[] parts = m_parts.GetArray();
1149 for (int i = 0; i < parts.Length; i++) 1472 for (int i = 0; i < parts.Length; i++)
1150 { 1473 {
@@ -1167,6 +1490,8 @@ namespace OpenSim.Region.Framework.Scenes
1167 } 1490 }
1168 }); 1491 });
1169 } 1492 }
1493
1494
1170 } 1495 }
1171 1496
1172 public void AddScriptLPS(int count) 1497 public void AddScriptLPS(int count)
@@ -1263,7 +1588,12 @@ namespace OpenSim.Region.Framework.Scenes
1263 1588
1264 public void SetOwnerId(UUID userId) 1589 public void SetOwnerId(UUID userId)
1265 { 1590 {
1266 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); 1591 ForEachPart(delegate(SceneObjectPart part)
1592 {
1593
1594 part.OwnerID = userId;
1595
1596 });
1267 } 1597 }
1268 1598
1269 public void ForEachPart(Action<SceneObjectPart> whatToDo) 1599 public void ForEachPart(Action<SceneObjectPart> whatToDo)
@@ -1295,11 +1625,17 @@ namespace OpenSim.Region.Framework.Scenes
1295 return; 1625 return;
1296 } 1626 }
1297 1627
1628 if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
1629 return;
1630
1298 // Since this is the top of the section of call stack for backing up a particular scene object, don't let 1631 // Since this is the top of the section of call stack for backing up a particular scene object, don't let
1299 // any exception propogate upwards. 1632 // any exception propogate upwards.
1300 try 1633 try
1301 { 1634 {
1302 if (!m_scene.ShuttingDown) // if shutting down then there will be nothing to handle the return so leave till next restart 1635 if (!m_scene.ShuttingDown || // if shutting down then there will be nothing to handle the return so leave till next restart
1636 m_scene.LoginsDisabled || // We're starting up or doing maintenance, don't mess with things
1637 m_scene.LoadingPrims) // Land may not be valid yet
1638
1303 { 1639 {
1304 ILandObject parcel = m_scene.LandChannel.GetLandObject( 1640 ILandObject parcel = m_scene.LandChannel.GetLandObject(
1305 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y); 1641 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y);
@@ -1326,6 +1662,7 @@ namespace OpenSim.Region.Framework.Scenes
1326 } 1662 }
1327 } 1663 }
1328 } 1664 }
1665
1329 } 1666 }
1330 1667
1331 if (m_scene.UseBackup && HasGroupChanged) 1668 if (m_scene.UseBackup && HasGroupChanged)
@@ -1333,6 +1670,20 @@ namespace OpenSim.Region.Framework.Scenes
1333 // don't backup while it's selected or you're asking for changes mid stream. 1670 // don't backup while it's selected or you're asking for changes mid stream.
1334 if (isTimeToPersist() || forcedBackup) 1671 if (isTimeToPersist() || forcedBackup)
1335 { 1672 {
1673 if (m_rootPart.PhysActor != null &&
1674 (!m_rootPart.PhysActor.IsPhysical))
1675 {
1676 // Possible ghost prim
1677 if (m_rootPart.PhysActor.Position != m_rootPart.GroupPosition)
1678 {
1679 foreach (SceneObjectPart part in m_parts.GetArray())
1680 {
1681 // Re-set physics actor positions and
1682 // orientations
1683 part.GroupPosition = m_rootPart.GroupPosition;
1684 }
1685 }
1686 }
1336// m_log.DebugFormat( 1687// m_log.DebugFormat(
1337// "[SCENE]: Storing {0}, {1} in {2}", 1688// "[SCENE]: Storing {0}, {1} in {2}",
1338// Name, UUID, m_scene.RegionInfo.RegionName); 1689// Name, UUID, m_scene.RegionInfo.RegionName);
@@ -1410,7 +1761,7 @@ namespace OpenSim.Region.Framework.Scenes
1410 // This is only necessary when userExposed is false! 1761 // This is only necessary when userExposed is false!
1411 1762
1412 bool previousAttachmentStatus = dupe.IsAttachment; 1763 bool previousAttachmentStatus = dupe.IsAttachment;
1413 1764
1414 if (!userExposed) 1765 if (!userExposed)
1415 dupe.IsAttachment = true; 1766 dupe.IsAttachment = true;
1416 1767
@@ -1428,11 +1779,11 @@ namespace OpenSim.Region.Framework.Scenes
1428 dupe.m_rootPart.TrimPermissions(); 1779 dupe.m_rootPart.TrimPermissions();
1429 1780
1430 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray()); 1781 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray());
1431 1782
1432 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) 1783 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1433 { 1784 {
1434 return p1.LinkNum.CompareTo(p2.LinkNum); 1785 return p1.LinkNum.CompareTo(p2.LinkNum);
1435 } 1786 }
1436 ); 1787 );
1437 1788
1438 foreach (SceneObjectPart part in partList) 1789 foreach (SceneObjectPart part in partList)
@@ -1452,7 +1803,7 @@ namespace OpenSim.Region.Framework.Scenes
1452 if (part.PhysActor != null && userExposed) 1803 if (part.PhysActor != null && userExposed)
1453 { 1804 {
1454 PrimitiveBaseShape pbs = newPart.Shape; 1805 PrimitiveBaseShape pbs = newPart.Shape;
1455 1806
1456 newPart.PhysActor 1807 newPart.PhysActor
1457 = m_scene.PhysicsScene.AddPrimShape( 1808 = m_scene.PhysicsScene.AddPrimShape(
1458 string.Format("{0}/{1}", newPart.Name, newPart.UUID), 1809 string.Format("{0}/{1}", newPart.Name, newPart.UUID),
@@ -1462,11 +1813,11 @@ namespace OpenSim.Region.Framework.Scenes
1462 newPart.RotationOffset, 1813 newPart.RotationOffset,
1463 part.PhysActor.IsPhysical, 1814 part.PhysActor.IsPhysical,
1464 newPart.LocalId); 1815 newPart.LocalId);
1465 1816
1466 newPart.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true); 1817 newPart.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true);
1467 } 1818 }
1468 } 1819 }
1469 1820
1470 if (userExposed) 1821 if (userExposed)
1471 { 1822 {
1472 dupe.UpdateParentIDs(); 1823 dupe.UpdateParentIDs();
@@ -1581,6 +1932,7 @@ namespace OpenSim.Region.Framework.Scenes
1581 return Vector3.Zero; 1932 return Vector3.Zero;
1582 } 1933 }
1583 1934
1935 // This is used by both Double-Click Auto-Pilot and llMoveToTarget() in an attached object
1584 public void moveToTarget(Vector3 target, float tau) 1936 public void moveToTarget(Vector3 target, float tau)
1585 { 1937 {
1586 if (IsAttachment) 1938 if (IsAttachment)
@@ -1608,10 +1960,44 @@ namespace OpenSim.Region.Framework.Scenes
1608 RootPart.PhysActor.PIDActive = false; 1960 RootPart.PhysActor.PIDActive = false;
1609 } 1961 }
1610 1962
1963 public void rotLookAt(Quaternion target, float strength, float damping)
1964 {
1965 SceneObjectPart rootpart = m_rootPart;
1966 if (rootpart != null)
1967 {
1968 if (IsAttachment)
1969 {
1970 /*
1971 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
1972 if (avatar != null)
1973 {
1974 Rotate the Av?
1975 } */
1976 }
1977 else
1978 {
1979 if (rootpart.PhysActor != null)
1980 { // APID must be implemented in your physics system for this to function.
1981 rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W);
1982 rootpart.PhysActor.APIDStrength = strength;
1983 rootpart.PhysActor.APIDDamping = damping;
1984 rootpart.PhysActor.APIDActive = true;
1985 }
1986 }
1987 }
1988 }
1989
1611 public void stopLookAt() 1990 public void stopLookAt()
1612 { 1991 {
1613 if (RootPart.PhysActor != null) 1992 SceneObjectPart rootpart = m_rootPart;
1614 RootPart.PhysActor.APIDActive = false; 1993 if (rootpart != null)
1994 {
1995 if (rootpart.PhysActor != null)
1996 { // APID must be implemented in your physics system for this to function.
1997 rootpart.PhysActor.APIDActive = false;
1998 }
1999 }
2000
1615 } 2001 }
1616 2002
1617 /// <summary> 2003 /// <summary>
@@ -1669,6 +2055,8 @@ namespace OpenSim.Region.Framework.Scenes
1669 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) 2055 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
1670 { 2056 {
1671 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 2057 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
2058 newPart.SetParent(this);
2059
1672 AddPart(newPart); 2060 AddPart(newPart);
1673 2061
1674 SetPartAsNonRoot(newPart); 2062 SetPartAsNonRoot(newPart);
@@ -1796,11 +2184,11 @@ namespace OpenSim.Region.Framework.Scenes
1796 /// Immediately send a full update for this scene object. 2184 /// Immediately send a full update for this scene object.
1797 /// </summary> 2185 /// </summary>
1798 public void SendGroupFullUpdate() 2186 public void SendGroupFullUpdate()
1799 { 2187 {
1800 if (IsDeleted) 2188 if (IsDeleted)
1801 return; 2189 return;
1802 2190
1803// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); 2191// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID);
1804 2192
1805 RootPart.SendFullUpdateToAllClients(); 2193 RootPart.SendFullUpdateToAllClients();
1806 2194
@@ -2001,7 +2389,7 @@ namespace OpenSim.Region.Framework.Scenes
2001 objectGroup.IsDeleted = true; 2389 objectGroup.IsDeleted = true;
2002 2390
2003 objectGroup.m_parts.Clear(); 2391 objectGroup.m_parts.Clear();
2004 2392
2005 // Can't do this yet since backup still makes use of the root part without any synchronization 2393 // Can't do this yet since backup still makes use of the root part without any synchronization
2006// objectGroup.m_rootPart = null; 2394// objectGroup.m_rootPart = null;
2007 2395
@@ -2135,6 +2523,7 @@ namespace OpenSim.Region.Framework.Scenes
2135 /// <param name="objectGroup"></param> 2523 /// <param name="objectGroup"></param>
2136 public virtual void DetachFromBackup() 2524 public virtual void DetachFromBackup()
2137 { 2525 {
2526 m_scene.SceneGraph.FireDetachFromBackup(this);
2138 if (m_isBackedUp && Scene != null) 2527 if (m_isBackedUp && Scene != null)
2139 m_scene.EventManager.OnBackup -= ProcessBackup; 2528 m_scene.EventManager.OnBackup -= ProcessBackup;
2140 2529
@@ -2153,7 +2542,8 @@ namespace OpenSim.Region.Framework.Scenes
2153 2542
2154 axPos *= parentRot; 2543 axPos *= parentRot;
2155 part.OffsetPosition = axPos; 2544 part.OffsetPosition = axPos;
2156 part.GroupPosition = oldGroupPosition + part.OffsetPosition; 2545 Vector3 newPos = oldGroupPosition + part.OffsetPosition;
2546 part.GroupPosition = newPos;
2157 part.OffsetPosition = Vector3.Zero; 2547 part.OffsetPosition = Vector3.Zero;
2158 part.RotationOffset = worldRot; 2548 part.RotationOffset = worldRot;
2159 2549
@@ -2164,7 +2554,7 @@ namespace OpenSim.Region.Framework.Scenes
2164 2554
2165 part.LinkNum = linkNum; 2555 part.LinkNum = linkNum;
2166 2556
2167 part.OffsetPosition = part.GroupPosition - AbsolutePosition; 2557 part.OffsetPosition = newPos - AbsolutePosition;
2168 2558
2169 Quaternion rootRotation = m_rootPart.RotationOffset; 2559 Quaternion rootRotation = m_rootPart.RotationOffset;
2170 2560
@@ -2174,7 +2564,7 @@ namespace OpenSim.Region.Framework.Scenes
2174 2564
2175 parentRot = m_rootPart.RotationOffset; 2565 parentRot = m_rootPart.RotationOffset;
2176 oldRot = part.RotationOffset; 2566 oldRot = part.RotationOffset;
2177 Quaternion newRot = Quaternion.Inverse(parentRot) * oldRot; 2567 Quaternion newRot = Quaternion.Inverse(parentRot) * worldRot;
2178 part.RotationOffset = newRot; 2568 part.RotationOffset = newRot;
2179 } 2569 }
2180 2570
@@ -2421,8 +2811,12 @@ namespace OpenSim.Region.Framework.Scenes
2421 } 2811 }
2422 } 2812 }
2423 2813
2814 RootPart.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, SetVolumeDetect);
2424 for (int i = 0; i < parts.Length; i++) 2815 for (int i = 0; i < parts.Length; i++)
2425 parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect); 2816 {
2817 if (parts[i] != RootPart)
2818 parts[i].UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, SetVolumeDetect);
2819 }
2426 } 2820 }
2427 } 2821 }
2428 2822
@@ -2435,6 +2829,17 @@ namespace OpenSim.Region.Framework.Scenes
2435 } 2829 }
2436 } 2830 }
2437 2831
2832
2833
2834 /// <summary>
2835 /// Gets the number of parts
2836 /// </summary>
2837 /// <returns></returns>
2838 public int GetPartCount()
2839 {
2840 return Parts.Count();
2841 }
2842
2438 /// <summary> 2843 /// <summary>
2439 /// Update the texture entry for this part 2844 /// Update the texture entry for this part
2440 /// </summary> 2845 /// </summary>
@@ -2496,7 +2901,6 @@ namespace OpenSim.Region.Framework.Scenes
2496 { 2901 {
2497// m_log.DebugFormat( 2902// m_log.DebugFormat(
2498// "[SCENE OBJECT GROUP]: Group resizing {0} {1} from {2} to {3}", Name, LocalId, RootPart.Scale, scale); 2903// "[SCENE OBJECT GROUP]: Group resizing {0} {1} from {2} to {3}", Name, LocalId, RootPart.Scale, scale);
2499
2500 RootPart.StoreUndoState(true); 2904 RootPart.StoreUndoState(true);
2501 2905
2502 scale.X = Math.Min(scale.X, Scene.m_maxNonphys); 2906 scale.X = Math.Min(scale.X, Scene.m_maxNonphys);
@@ -2597,7 +3001,6 @@ namespace OpenSim.Region.Framework.Scenes
2597 prevScale.X *= x; 3001 prevScale.X *= x;
2598 prevScale.Y *= y; 3002 prevScale.Y *= y;
2599 prevScale.Z *= z; 3003 prevScale.Z *= z;
2600
2601// RootPart.IgnoreUndoUpdate = true; 3004// RootPart.IgnoreUndoUpdate = true;
2602 RootPart.Resize(prevScale); 3005 RootPart.Resize(prevScale);
2603// RootPart.IgnoreUndoUpdate = false; 3006// RootPart.IgnoreUndoUpdate = false;
@@ -2628,7 +3031,9 @@ namespace OpenSim.Region.Framework.Scenes
2628 } 3031 }
2629 3032
2630// obPart.IgnoreUndoUpdate = false; 3033// obPart.IgnoreUndoUpdate = false;
2631// obPart.StoreUndoState(); 3034 HasGroupChanged = true;
3035 m_rootPart.TriggerScriptChangedEvent(Changed.SCALE);
3036 ScheduleGroupForTerseUpdate();
2632 } 3037 }
2633 3038
2634// m_log.DebugFormat( 3039// m_log.DebugFormat(
@@ -2688,9 +3093,9 @@ namespace OpenSim.Region.Framework.Scenes
2688 { 3093 {
2689 SceneObjectPart part = GetChildPart(localID); 3094 SceneObjectPart part = GetChildPart(localID);
2690 3095
2691// SceneObjectPart[] parts = m_parts.GetArray(); 3096 SceneObjectPart[] parts = m_parts.GetArray();
2692// for (int i = 0; i < parts.Length; i++) 3097 for (int i = 0; i < parts.Length; i++)
2693// parts[i].StoreUndoState(); 3098 parts[i].StoreUndoState();
2694 3099
2695 if (part != null) 3100 if (part != null)
2696 { 3101 {
@@ -2746,10 +3151,27 @@ namespace OpenSim.Region.Framework.Scenes
2746 obPart.OffsetPosition = obPart.OffsetPosition + diff; 3151 obPart.OffsetPosition = obPart.OffsetPosition + diff;
2747 } 3152 }
2748 3153
2749 AbsolutePosition = newPos; 3154 //We have to set undoing here because otherwise an undo state will be saved
3155 if (!m_rootPart.Undoing)
3156 {
3157 m_rootPart.Undoing = true;
3158 AbsolutePosition = newPos;
3159 m_rootPart.Undoing = false;
3160 }
3161 else
3162 {
3163 AbsolutePosition = newPos;
3164 }
2750 3165
2751 HasGroupChanged = true; 3166 HasGroupChanged = true;
2752 ScheduleGroupForTerseUpdate(); 3167 if (m_rootPart.Undoing)
3168 {
3169 ScheduleGroupForFullUpdate();
3170 }
3171 else
3172 {
3173 ScheduleGroupForTerseUpdate();
3174 }
2753 } 3175 }
2754 3176
2755 #endregion 3177 #endregion
@@ -2826,10 +3248,7 @@ namespace OpenSim.Region.Framework.Scenes
2826 public void UpdateSingleRotation(Quaternion rot, uint localID) 3248 public void UpdateSingleRotation(Quaternion rot, uint localID)
2827 { 3249 {
2828 SceneObjectPart part = GetChildPart(localID); 3250 SceneObjectPart part = GetChildPart(localID);
2829
2830 SceneObjectPart[] parts = m_parts.GetArray(); 3251 SceneObjectPart[] parts = m_parts.GetArray();
2831 for (int i = 0; i < parts.Length; i++)
2832 parts[i].StoreUndoState();
2833 3252
2834 if (part != null) 3253 if (part != null)
2835 { 3254 {
@@ -2867,7 +3286,16 @@ namespace OpenSim.Region.Framework.Scenes
2867 if (part.UUID == m_rootPart.UUID) 3286 if (part.UUID == m_rootPart.UUID)
2868 { 3287 {
2869 UpdateRootRotation(rot); 3288 UpdateRootRotation(rot);
2870 AbsolutePosition = pos; 3289 if (!m_rootPart.Undoing)
3290 {
3291 m_rootPart.Undoing = true;
3292 AbsolutePosition = pos;
3293 m_rootPart.Undoing = false;
3294 }
3295 else
3296 {
3297 AbsolutePosition = pos;
3298 }
2871 } 3299 }
2872 else 3300 else
2873 { 3301 {
@@ -2891,9 +3319,10 @@ namespace OpenSim.Region.Framework.Scenes
2891 3319
2892 Quaternion axRot = rot; 3320 Quaternion axRot = rot;
2893 Quaternion oldParentRot = m_rootPart.RotationOffset; 3321 Quaternion oldParentRot = m_rootPart.RotationOffset;
2894
2895 m_rootPart.StoreUndoState(); 3322 m_rootPart.StoreUndoState();
2896 m_rootPart.UpdateRotation(rot); 3323
3324 //Don't use UpdateRotation because it schedules an update prematurely
3325 m_rootPart.RotationOffset = rot;
2897 if (m_rootPart.PhysActor != null) 3326 if (m_rootPart.PhysActor != null)
2898 { 3327 {
2899 m_rootPart.PhysActor.Orientation = m_rootPart.RotationOffset; 3328 m_rootPart.PhysActor.Orientation = m_rootPart.RotationOffset;
@@ -2907,15 +3336,17 @@ namespace OpenSim.Region.Framework.Scenes
2907 if (prim.UUID != m_rootPart.UUID) 3336 if (prim.UUID != m_rootPart.UUID)
2908 { 3337 {
2909 prim.IgnoreUndoUpdate = true; 3338 prim.IgnoreUndoUpdate = true;
3339
3340 Quaternion NewRot = oldParentRot * prim.RotationOffset;
3341 NewRot = Quaternion.Inverse(axRot) * NewRot;
3342 prim.RotationOffset = NewRot;
3343
2910 Vector3 axPos = prim.OffsetPosition; 3344 Vector3 axPos = prim.OffsetPosition;
3345
2911 axPos *= oldParentRot; 3346 axPos *= oldParentRot;
2912 axPos *= Quaternion.Inverse(axRot); 3347 axPos *= Quaternion.Inverse(axRot);
2913 prim.OffsetPosition = axPos; 3348 prim.OffsetPosition = axPos;
2914 Quaternion primsRot = prim.RotationOffset; 3349
2915 Quaternion newRot = oldParentRot * primsRot;
2916 newRot = Quaternion.Inverse(axRot) * newRot;
2917 prim.RotationOffset = newRot;
2918 prim.ScheduleTerseUpdate();
2919 prim.IgnoreUndoUpdate = false; 3350 prim.IgnoreUndoUpdate = false;
2920 } 3351 }
2921 } 3352 }
@@ -2929,8 +3360,8 @@ namespace OpenSim.Region.Framework.Scenes
2929//// childpart.StoreUndoState(); 3360//// childpart.StoreUndoState();
2930// } 3361// }
2931// } 3362// }
2932 3363 HasGroupChanged = true;
2933 m_rootPart.ScheduleTerseUpdate(); 3364 ScheduleGroupForFullUpdate();
2934 3365
2935// m_log.DebugFormat( 3366// m_log.DebugFormat(
2936// "[SCENE OBJECT GROUP]: Updated root rotation of {0} {1} to {2}", 3367// "[SCENE OBJECT GROUP]: Updated root rotation of {0} {1} to {2}",
@@ -3158,7 +3589,6 @@ namespace OpenSim.Region.Framework.Scenes
3158 public float GetMass() 3589 public float GetMass()
3159 { 3590 {
3160 float retmass = 0f; 3591 float retmass = 0f;
3161
3162 SceneObjectPart[] parts = m_parts.GetArray(); 3592 SceneObjectPart[] parts = m_parts.GetArray();
3163 for (int i = 0; i < parts.Length; i++) 3593 for (int i = 0; i < parts.Length; i++)
3164 retmass += parts[i].GetMass(); 3594 retmass += parts[i].GetMass();
@@ -3252,6 +3682,14 @@ namespace OpenSim.Region.Framework.Scenes
3252 SetFromItemID(uuid); 3682 SetFromItemID(uuid);
3253 } 3683 }
3254 3684
3685 public void ResetOwnerChangeFlag()
3686 {
3687 ForEachPart(delegate(SceneObjectPart part)
3688 {
3689 part.ResetOwnerChangeFlag();
3690 });
3691 }
3692
3255 #endregion 3693 #endregion
3256 } 3694 }
3257} 3695}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index f693b36..45ca0b7 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;
@@ -253,6 +263,7 @@ namespace OpenSim.Region.Framework.Scenes
253 private Quaternion m_sitTargetOrientation = Quaternion.Identity; 263 private Quaternion m_sitTargetOrientation = Quaternion.Identity;
254 private Vector3 m_sitTargetPosition; 264 private Vector3 m_sitTargetPosition;
255 private string m_sitAnimation = "SIT"; 265 private string m_sitAnimation = "SIT";
266 private bool m_occupied; // KF if any av is sitting on this prim
256 private string m_text = String.Empty; 267 private string m_text = String.Empty;
257 private string m_touchName = String.Empty; 268 private string m_touchName = String.Empty;
258 private readonly Stack<UndoState> m_undo = new Stack<UndoState>(5); 269 private readonly Stack<UndoState> m_undo = new Stack<UndoState>(5);
@@ -287,6 +298,7 @@ namespace OpenSim.Region.Framework.Scenes
287 protected Vector3 m_lastAcceleration; 298 protected Vector3 m_lastAcceleration;
288 protected Vector3 m_lastAngularVelocity; 299 protected Vector3 m_lastAngularVelocity;
289 protected int m_lastTerseSent; 300 protected int m_lastTerseSent;
301 protected float m_buoyancy = 0.0f;
290 302
291 /// <summary> 303 /// <summary>
292 /// Stores media texture data 304 /// Stores media texture data
@@ -339,7 +351,7 @@ namespace OpenSim.Region.Framework.Scenes
339 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition, 351 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition,
340 Quaternion rotationOffset, Vector3 offsetPosition) 352 Quaternion rotationOffset, Vector3 offsetPosition)
341 { 353 {
342 m_name = "Primitive"; 354 m_name = "Object";
343 355
344 Rezzed = DateTime.UtcNow; 356 Rezzed = DateTime.UtcNow;
345 CreationDate = (int)Utils.DateTimeToUnixTime(Rezzed); 357 CreationDate = (int)Utils.DateTimeToUnixTime(Rezzed);
@@ -389,7 +401,7 @@ namespace OpenSim.Region.Framework.Scenes
389 private uint _ownerMask = (uint)PermissionMask.All; 401 private uint _ownerMask = (uint)PermissionMask.All;
390 private uint _groupMask = (uint)PermissionMask.None; 402 private uint _groupMask = (uint)PermissionMask.None;
391 private uint _everyoneMask = (uint)PermissionMask.None; 403 private uint _everyoneMask = (uint)PermissionMask.None;
392 private uint _nextOwnerMask = (uint)PermissionMask.All; 404 private uint _nextOwnerMask = (uint)(PermissionMask.Move | PermissionMask.Modify | PermissionMask.Transfer);
393 private PrimFlags _flags = PrimFlags.None; 405 private PrimFlags _flags = PrimFlags.None;
394 private DateTime m_expires; 406 private DateTime m_expires;
395 private DateTime m_rezzed; 407 private DateTime m_rezzed;
@@ -483,12 +495,16 @@ namespace OpenSim.Region.Framework.Scenes
483 } 495 }
484 496
485 /// <value> 497 /// <value>
486 /// Access should be via Inventory directly - this property temporarily remains for xml serialization purposes 498 /// Get the inventory list
487 /// </value> 499 /// </value>
488 public TaskInventoryDictionary TaskInventory 500 public TaskInventoryDictionary TaskInventory
489 { 501 {
490 get { return m_inventory.Items; } 502 get {
491 set { m_inventory.Items = value; } 503 return m_inventory.Items;
504 }
505 set {
506 m_inventory.Items = value;
507 }
492 } 508 }
493 509
494 /// <summary> 510 /// <summary>
@@ -629,14 +645,12 @@ namespace OpenSim.Region.Framework.Scenes
629 set { m_LoopSoundSlavePrims = value; } 645 set { m_LoopSoundSlavePrims = value; }
630 } 646 }
631 647
632
633 public Byte[] TextureAnimation 648 public Byte[] TextureAnimation
634 { 649 {
635 get { return m_TextureAnimation; } 650 get { return m_TextureAnimation; }
636 set { m_TextureAnimation = value; } 651 set { m_TextureAnimation = value; }
637 } 652 }
638 653
639
640 public Byte[] ParticleSystem 654 public Byte[] ParticleSystem
641 { 655 {
642 get { return m_particleSystem; } 656 get { return m_particleSystem; }
@@ -675,7 +689,9 @@ namespace OpenSim.Region.Framework.Scenes
675 PhysicsActor actor = PhysActor; 689 PhysicsActor actor = PhysActor;
676 if (actor != null && ParentID == 0) 690 if (actor != null && ParentID == 0)
677 { 691 {
678 m_groupPosition = actor.Position; 692 if (actor != null)
693 m_groupPosition = actor.Position;
694 return m_groupPosition;
679 } 695 }
680 696
681 if (ParentGroup.IsAttachment) 697 if (ParentGroup.IsAttachment)
@@ -685,12 +701,14 @@ namespace OpenSim.Region.Framework.Scenes
685 return sp.AbsolutePosition; 701 return sp.AbsolutePosition;
686 } 702 }
687 703
704 // use root prim's group position. Physics may have updated it
705 if (ParentGroup.RootPart != this)
706 m_groupPosition = ParentGroup.RootPart.GroupPosition;
688 return m_groupPosition; 707 return m_groupPosition;
689 } 708 }
690 set 709 set
691 { 710 {
692 m_groupPosition = value; 711 m_groupPosition = value;
693
694 PhysicsActor actor = PhysActor; 712 PhysicsActor actor = PhysActor;
695 if (actor != null) 713 if (actor != null)
696 { 714 {
@@ -716,16 +734,6 @@ namespace OpenSim.Region.Framework.Scenes
716 m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message); 734 m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message);
717 } 735 }
718 } 736 }
719
720 // TODO if we decide to do sitting in a more SL compatible way (multiple avatars per prim), this has to be fixed, too
721 if (SitTargetAvatar != UUID.Zero)
722 {
723 ScenePresence avatar;
724 if (ParentGroup.Scene.TryGetScenePresence(SitTargetAvatar, out avatar))
725 {
726 avatar.ParentPosition = GetWorldPosition();
727 }
728 }
729 } 737 }
730 } 738 }
731 739
@@ -734,7 +742,7 @@ namespace OpenSim.Region.Framework.Scenes
734 get { return m_offsetPosition; } 742 get { return m_offsetPosition; }
735 set 743 set
736 { 744 {
737// StoreUndoState(); 745 Vector3 oldpos = m_offsetPosition;
738 m_offsetPosition = value; 746 m_offsetPosition = value;
739 747
740 if (ParentGroup != null && !ParentGroup.IsDeleted) 748 if (ParentGroup != null && !ParentGroup.IsDeleted)
@@ -749,7 +757,22 @@ namespace OpenSim.Region.Framework.Scenes
749 if (ParentGroup.Scene != null) 757 if (ParentGroup.Scene != null)
750 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 758 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
751 } 759 }
760
761 if (!m_parentGroup.m_dupeInProgress)
762 {
763 List<ScenePresence> avs = ParentGroup.GetLinkedAvatars();
764 foreach (ScenePresence av in avs)
765 {
766 if (av.ParentID == m_localId)
767 {
768 Vector3 offset = (m_offsetPosition - oldpos);
769 av.AbsolutePosition += offset;
770 av.SendAvatarDataToAllAgents();
771 }
772 }
773 }
752 } 774 }
775 TriggerScriptChangedEvent(Changed.POSITION);
753 } 776 }
754 } 777 }
755 778
@@ -898,7 +921,16 @@ namespace OpenSim.Region.Framework.Scenes
898 /// <summary></summary> 921 /// <summary></summary>
899 public Vector3 Acceleration 922 public Vector3 Acceleration
900 { 923 {
901 get { return m_acceleration; } 924 get
925 {
926 PhysicsActor actor = PhysActor;
927 if (actor != null)
928 {
929 m_acceleration = actor.Acceleration;
930 }
931 return m_acceleration;
932 }
933
902 set { m_acceleration = value; } 934 set { m_acceleration = value; }
903 } 935 }
904 936
@@ -1238,6 +1270,13 @@ namespace OpenSim.Region.Framework.Scenes
1238 _flags = value; 1270 _flags = value;
1239 } 1271 }
1240 } 1272 }
1273
1274 [XmlIgnore]
1275 public bool IsOccupied // KF If an av is sittingon this prim
1276 {
1277 get { return m_occupied; }
1278 set { m_occupied = value; }
1279 }
1241 1280
1242 /// <summary> 1281 /// <summary>
1243 /// ID of the avatar that is sat on us. If there is no such avatar then is UUID.Zero 1282 /// ID of the avatar that is sat on us. If there is no such avatar then is UUID.Zero
@@ -1297,6 +1336,19 @@ namespace OpenSim.Region.Framework.Scenes
1297 set { m_collisionSoundVolume = value; } 1336 set { m_collisionSoundVolume = value; }
1298 } 1337 }
1299 1338
1339 public float Buoyancy
1340 {
1341 get { return m_buoyancy; }
1342 set
1343 {
1344 m_buoyancy = value;
1345 if (PhysActor != null)
1346 {
1347 PhysActor.Buoyancy = value;
1348 }
1349 }
1350 }
1351
1300 #endregion Public Properties with only Get 1352 #endregion Public Properties with only Get
1301 1353
1302 private uint ApplyMask(uint val, bool set, uint mask) 1354 private uint ApplyMask(uint val, bool set, uint mask)
@@ -1619,6 +1671,9 @@ namespace OpenSim.Region.Framework.Scenes
1619 1671
1620 // Move afterwards ResetIDs as it clears the localID 1672 // Move afterwards ResetIDs as it clears the localID
1621 dupe.LocalId = localID; 1673 dupe.LocalId = localID;
1674 if(dupe.PhysActor != null)
1675 dupe.PhysActor.LocalID = localID;
1676
1622 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated. 1677 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated.
1623 dupe.LastOwnerID = OwnerID; 1678 dupe.LastOwnerID = OwnerID;
1624 1679
@@ -1980,19 +2035,17 @@ namespace OpenSim.Region.Framework.Scenes
1980 public Vector3 GetWorldPosition() 2035 public Vector3 GetWorldPosition()
1981 { 2036 {
1982 Quaternion parentRot = ParentGroup.RootPart.RotationOffset; 2037 Quaternion parentRot = ParentGroup.RootPart.RotationOffset;
1983
1984 Vector3 axPos = OffsetPosition; 2038 Vector3 axPos = OffsetPosition;
1985
1986 axPos *= parentRot; 2039 axPos *= parentRot;
1987 Vector3 translationOffsetPosition = axPos; 2040 Vector3 translationOffsetPosition = axPos;
1988 2041 if(_parentID == 0)
1989// m_log.DebugFormat("[SCENE OBJECT PART]: Found group pos {0} for part {1}", GroupPosition, Name); 2042 {
1990 2043 return GroupPosition;
1991 Vector3 worldPos = GroupPosition + translationOffsetPosition; 2044 }
1992 2045 else
1993// m_log.DebugFormat("[SCENE OBJECT PART]: Found world pos {0} for part {1}", worldPos, Name); 2046 {
1994 2047 return ParentGroup.AbsolutePosition + translationOffsetPosition; //KF: Fix child prim position
1995 return worldPos; 2048 }
1996 } 2049 }
1997 2050
1998 /// <summary> 2051 /// <summary>
@@ -2630,17 +2683,18 @@ namespace OpenSim.Region.Framework.Scenes
2630 //Trys to fetch sound id from prim's inventory. 2683 //Trys to fetch sound id from prim's inventory.
2631 //Prim's inventory doesn't support non script items yet 2684 //Prim's inventory doesn't support non script items yet
2632 2685
2633 lock (TaskInventory) 2686 TaskInventory.LockItemsForRead(true);
2687
2688 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2634 { 2689 {
2635 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 2690 if (item.Value.Name == sound)
2636 { 2691 {
2637 if (item.Value.Name == sound) 2692 soundID = item.Value.ItemID;
2638 { 2693 break;
2639 soundID = item.Value.ItemID;
2640 break;
2641 }
2642 } 2694 }
2643 } 2695 }
2696
2697 TaskInventory.LockItemsForRead(false);
2644 } 2698 }
2645 2699
2646 ParentGroup.Scene.ForEachRootScenePresence(delegate(ScenePresence sp) 2700 ParentGroup.Scene.ForEachRootScenePresence(delegate(ScenePresence sp)
@@ -2723,7 +2777,7 @@ namespace OpenSim.Region.Framework.Scenes
2723 2777
2724 public void RotLookAt(Quaternion target, float strength, float damping) 2778 public void RotLookAt(Quaternion target, float strength, float damping)
2725 { 2779 {
2726 rotLookAt(target, strength, damping); 2780 m_parentGroup.rotLookAt(target, strength, damping); // This calls method in SceneObjectGroup.
2727 } 2781 }
2728 2782
2729 public void rotLookAt(Quaternion target, float strength, float damping) 2783 public void rotLookAt(Quaternion target, float strength, float damping)
@@ -2959,8 +3013,8 @@ namespace OpenSim.Region.Framework.Scenes
2959 { 3013 {
2960 const float ROTATION_TOLERANCE = 0.01f; 3014 const float ROTATION_TOLERANCE = 0.01f;
2961 const float VELOCITY_TOLERANCE = 0.001f; 3015 const float VELOCITY_TOLERANCE = 0.001f;
2962 const float POSITION_TOLERANCE = 0.05f; 3016 const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary
2963 const int TIME_MS_TOLERANCE = 3000; 3017 const int TIME_MS_TOLERANCE = 200; //llSetPos has a 200ms delay. This should NOT be 3 seconds.
2964 3018
2965 switch (UpdateFlag) 3019 switch (UpdateFlag)
2966 { 3020 {
@@ -3024,17 +3078,16 @@ namespace OpenSim.Region.Framework.Scenes
3024 if (!UUID.TryParse(sound, out soundID)) 3078 if (!UUID.TryParse(sound, out soundID))
3025 { 3079 {
3026 // search sound file from inventory 3080 // search sound file from inventory
3027 lock (TaskInventory) 3081 TaskInventory.LockItemsForRead(true);
3082 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
3028 { 3083 {
3029 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 3084 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound)
3030 { 3085 {
3031 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound) 3086 soundID = item.Value.ItemID;
3032 { 3087 break;
3033 soundID = item.Value.ItemID;
3034 break;
3035 }
3036 } 3088 }
3037 } 3089 }
3090 TaskInventory.LockItemsForRead(false);
3038 } 3091 }
3039 3092
3040 if (soundID == UUID.Zero) 3093 if (soundID == UUID.Zero)
@@ -3496,10 +3549,10 @@ namespace OpenSim.Region.Framework.Scenes
3496 // TODO: May need to fix for group comparison 3549 // TODO: May need to fix for group comparison
3497 if (last.Compare(this)) 3550 if (last.Compare(this))
3498 { 3551 {
3499 // m_log.DebugFormat( 3552 // m_log.DebugFormat(
3500 // "[SCENE OBJECT PART]: Not storing undo for {0} {1} since current state is same as last undo state, initial stack size {2}", 3553 // "[SCENE OBJECT PART]: Not storing undo for {0} {1} since current state is same as last undo state, initial stack size {2}",
3501 // Name, LocalId, m_undo.Count); 3554 // Name, LocalId, m_undo.Count);
3502 3555
3503 return; 3556 return;
3504 } 3557 }
3505 } 3558 }
@@ -3512,29 +3565,29 @@ namespace OpenSim.Region.Framework.Scenes
3512 if (ParentGroup.GetSceneMaxUndo() > 0) 3565 if (ParentGroup.GetSceneMaxUndo() > 0)
3513 { 3566 {
3514 UndoState nUndo = new UndoState(this, forGroup); 3567 UndoState nUndo = new UndoState(this, forGroup);
3515 3568
3516 m_undo.Push(nUndo); 3569 m_undo.Push(nUndo);
3517 3570
3518 if (m_redo.Count > 0) 3571 if (m_redo.Count > 0)
3519 m_redo.Clear(); 3572 m_redo.Clear();
3520 3573
3521 // m_log.DebugFormat( 3574 // m_log.DebugFormat(
3522 // "[SCENE OBJECT PART]: Stored undo state for {0} {1}, forGroup {2}, stack size now {3}", 3575 // "[SCENE OBJECT PART]: Stored undo state for {0} {1}, forGroup {2}, stack size now {3}",
3523 // Name, LocalId, forGroup, m_undo.Count); 3576 // Name, LocalId, forGroup, m_undo.Count);
3524 } 3577 }
3525 } 3578 }
3526 } 3579 }
3527 } 3580 }
3528// else 3581 // else
3529// { 3582 // {
3530// m_log.DebugFormat("[SCENE OBJECT PART]: Ignoring undo store for {0} {1}", Name, LocalId); 3583 // m_log.DebugFormat("[SCENE OBJECT PART]: Ignoring undo store for {0} {1}", Name, LocalId);
3531// } 3584 // }
3532 } 3585 }
3533// else 3586 // else
3534// { 3587 // {
3535// m_log.DebugFormat( 3588 // m_log.DebugFormat(
3536// "[SCENE OBJECT PART]: Ignoring undo store for {0} {1} since already undoing", Name, LocalId); 3589 // "[SCENE OBJECT PART]: Ignoring undo store for {0} {1} since already undoing", Name, LocalId);
3537// } 3590 // }
3538 } 3591 }
3539 3592
3540 /// <summary> 3593 /// <summary>
@@ -4589,8 +4642,9 @@ namespace OpenSim.Region.Framework.Scenes
4589 { 4642 {
4590 m_shape.TextureEntry = textureEntry; 4643 m_shape.TextureEntry = textureEntry;
4591 TriggerScriptChangedEvent(Changed.TEXTURE); 4644 TriggerScriptChangedEvent(Changed.TEXTURE);
4592 4645 UpdateFlag = UpdateRequired.FULL;
4593 ParentGroup.HasGroupChanged = true; 4646 ParentGroup.HasGroupChanged = true;
4647
4594 //This is madness.. 4648 //This is madness..
4595 //ParentGroup.ScheduleGroupForFullUpdate(); 4649 //ParentGroup.ScheduleGroupForFullUpdate();
4596 //This is sparta 4650 //This is sparta
@@ -4787,5 +4841,17 @@ namespace OpenSim.Region.Framework.Scenes
4787 Color color = Color; 4841 Color color = Color;
4788 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A)); 4842 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A));
4789 } 4843 }
4844
4845 public void ResetOwnerChangeFlag()
4846 {
4847 List<UUID> inv = Inventory.GetInventoryList();
4848
4849 foreach (UUID itemID in inv)
4850 {
4851 TaskInventoryItem item = Inventory.GetInventoryItem(itemID);
4852 item.OwnerChanged = false;
4853 Inventory.UpdateInventoryItem(item, false, false);
4854 }
4855 }
4790 } 4856 }
4791} 4857}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index 9446741..309f543 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)
@@ -257,9 +307,18 @@ namespace OpenSim.Region.Framework.Scenes
257 /// </param> 307 /// </param>
258 public void RemoveScriptInstances(bool sceneObjectBeingDeleted) 308 public void RemoveScriptInstances(bool sceneObjectBeingDeleted)
259 { 309 {
260 List<TaskInventoryItem> scripts = GetInventoryScripts(); 310 Items.LockItemsForRead(true);
261 foreach (TaskInventoryItem item in scripts) 311 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
262 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted); 312 Items.LockItemsForRead(false);
313
314 foreach (TaskInventoryItem item in items)
315 {
316 if ((int)InventoryType.LSL == item.InvType)
317 {
318 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted);
319 m_part.RemoveScriptEvents(item.ItemID);
320 }
321 }
263 } 322 }
264 323
265 /// <summary> 324 /// <summary>
@@ -275,7 +334,10 @@ namespace OpenSim.Region.Framework.Scenes
275 // item.Name, item.ItemID, Name, UUID); 334 // item.Name, item.ItemID, Name, UUID);
276 335
277 if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID)) 336 if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID))
337 {
338 StoreScriptError(item.ItemID, "no permission");
278 return; 339 return;
340 }
279 341
280 m_part.AddFlag(PrimFlags.Scripted); 342 m_part.AddFlag(PrimFlags.Scripted);
281 343
@@ -284,14 +346,13 @@ namespace OpenSim.Region.Framework.Scenes
284 if (stateSource == 2 && // Prim crossing 346 if (stateSource == 2 && // Prim crossing
285 m_part.ParentGroup.Scene.m_trustBinaries) 347 m_part.ParentGroup.Scene.m_trustBinaries)
286 { 348 {
287 lock (m_items) 349 m_items.LockItemsForWrite(true);
288 { 350 m_items[item.ItemID].PermsMask = 0;
289 m_items[item.ItemID].PermsMask = 0; 351 m_items[item.ItemID].PermsGranter = UUID.Zero;
290 m_items[item.ItemID].PermsGranter = UUID.Zero; 352 m_items.LockItemsForWrite(false);
291 }
292
293 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 353 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
294 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource); 354 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource);
355 StoreScriptErrors(item.ItemID, null);
295 m_part.ParentGroup.AddActiveScriptCount(1); 356 m_part.ParentGroup.AddActiveScriptCount(1);
296 m_part.ScheduleFullUpdate(); 357 m_part.ScheduleFullUpdate();
297 return; 358 return;
@@ -300,6 +361,8 @@ namespace OpenSim.Region.Framework.Scenes
300 AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString()); 361 AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString());
301 if (null == asset) 362 if (null == asset)
302 { 363 {
364 string msg = String.Format("asset ID {0} could not be found", item.AssetID);
365 StoreScriptError(item.ItemID, msg);
303 m_log.ErrorFormat( 366 m_log.ErrorFormat(
304 "[PRIM INVENTORY]: " + 367 "[PRIM INVENTORY]: " +
305 "Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found", 368 "Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found",
@@ -311,15 +374,20 @@ namespace OpenSim.Region.Framework.Scenes
311 if (m_part.ParentGroup.m_savedScriptState != null) 374 if (m_part.ParentGroup.m_savedScriptState != null)
312 RestoreSavedScriptState(item.OldItemID, item.ItemID); 375 RestoreSavedScriptState(item.OldItemID, item.ItemID);
313 376
314 lock (m_items) 377 m_items.LockItemsForWrite(true);
315 { 378
316 m_items[item.ItemID].PermsMask = 0; 379 m_items[item.ItemID].PermsMask = 0;
317 m_items[item.ItemID].PermsGranter = UUID.Zero; 380 m_items[item.ItemID].PermsGranter = UUID.Zero;
318 } 381
382 m_items.LockItemsForWrite(false);
319 383
320 string script = Utils.BytesToString(asset.Data); 384 string script = Utils.BytesToString(asset.Data);
321 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 385 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
322 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource); 386 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource);
387 StoreScriptErrors(item.ItemID, null);
388 if (!item.ScriptRunning)
389 m_part.ParentGroup.Scene.EventManager.TriggerStopScript(
390 m_part.LocalId, item.ItemID);
323 m_part.ParentGroup.AddActiveScriptCount(1); 391 m_part.ParentGroup.AddActiveScriptCount(1);
324 m_part.ScheduleFullUpdate(); 392 m_part.ScheduleFullUpdate();
325 } 393 }
@@ -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 }
799 1003
800 lock (m_items) 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 }
1032
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", TaskInventoryItem.Types[item.Type]);
836 invString.AddNameValueLine("inv_type", TaskInventoryItem.InvTypes[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", TaskInventoryItem.Types[item.Type]);
1089 invString.AddNameValueLine("inv_type", TaskInventoryItem.InvTypes[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 == null) // No engine at all 1330 if (engines == null) // 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 == null) 1368 if (engines == null)
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 098437a..839259f 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -152,6 +152,7 @@ namespace OpenSim.Region.Framework.Scenes
152 private int m_lastColCount = -1; //KF: Look for Collision chnages 152 private int m_lastColCount = -1; //KF: Look for Collision chnages
153 private int m_updateCount = 0; //KF: Update Anims for a while 153 private int m_updateCount = 0; //KF: Update Anims for a while
154 private static readonly int UPDATE_COUNT = 10; // how many frames to update for 154 private static readonly int UPDATE_COUNT = 10; // how many frames to update for
155 private List<uint> m_lastColliders = new List<uint>();
155 156
156 private TeleportFlags m_teleportFlags; 157 private TeleportFlags m_teleportFlags;
157 public TeleportFlags TeleportFlags 158 public TeleportFlags TeleportFlags
@@ -898,6 +899,8 @@ namespace OpenSim.Region.Framework.Scenes
898 pos.Y = crossedBorder.BorderLine.Z - 1; 899 pos.Y = crossedBorder.BorderLine.Z - 1;
899 } 900 }
900 901
902 CheckAndAdjustLandingPoint(ref pos);
903
901 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f) 904 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f)
902 { 905 {
903 m_log.WarnFormat( 906 m_log.WarnFormat(
@@ -1060,6 +1063,7 @@ namespace OpenSim.Region.Framework.Scenes
1060 1063
1061 RemoveFromPhysicalScene(); 1064 RemoveFromPhysicalScene();
1062 Velocity = Vector3.Zero; 1065 Velocity = Vector3.Zero;
1066 CheckLandingPoint(ref pos);
1063 AbsolutePosition = pos; 1067 AbsolutePosition = pos;
1064 AddToPhysicalScene(isFlying); 1068 AddToPhysicalScene(isFlying);
1065 1069
@@ -1073,6 +1077,7 @@ namespace OpenSim.Region.Framework.Scenes
1073 isFlying = PhysicsActor.Flying; 1077 isFlying = PhysicsActor.Flying;
1074 1078
1075 RemoveFromPhysicalScene(); 1079 RemoveFromPhysicalScene();
1080 CheckLandingPoint(ref pos);
1076 AbsolutePosition = pos; 1081 AbsolutePosition = pos;
1077 AddToPhysicalScene(isFlying); 1082 AddToPhysicalScene(isFlying);
1078 1083
@@ -1840,6 +1845,7 @@ namespace OpenSim.Region.Framework.Scenes
1840 if (part.SitTargetAvatar == UUID) 1845 if (part.SitTargetAvatar == UUID)
1841 part.SitTargetAvatar = UUID.Zero; 1846 part.SitTargetAvatar = UUID.Zero;
1842 1847
1848 part.ParentGroup.DeleteAvatar(UUID);
1843 ParentPosition = part.GetWorldPosition(); 1849 ParentPosition = part.GetWorldPosition();
1844 ControllingClient.SendClearFollowCamProperties(part.ParentUUID); 1850 ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
1845 } 1851 }
@@ -2263,11 +2269,13 @@ namespace OpenSim.Region.Framework.Scenes
2263 m_pos = sitTargetPos + SIT_TARGET_ADJUSTMENT; 2269 m_pos = sitTargetPos + SIT_TARGET_ADJUSTMENT;
2264 Rotation = sitTargetOrient; 2270 Rotation = sitTargetOrient;
2265 ParentPosition = part.AbsolutePosition; 2271 ParentPosition = part.AbsolutePosition;
2272 part.ParentGroup.AddAvatar(UUID);
2266 } 2273 }
2267 else 2274 else
2268 { 2275 {
2269 m_pos -= part.AbsolutePosition; 2276 m_pos -= part.AbsolutePosition;
2270 ParentPosition = part.AbsolutePosition; 2277 ParentPosition = part.AbsolutePosition;
2278 part.ParentGroup.AddAvatar(UUID);
2271 2279
2272// m_log.DebugFormat( 2280// m_log.DebugFormat(
2273// "[SCENE PRESENCE]: Sitting {0} at position {1} ({2} + {3}) on part {4} {5} without sit target", 2281// "[SCENE PRESENCE]: Sitting {0} at position {1} ({2} + {3}) on part {4} {5} without sit target",
@@ -3334,6 +3342,8 @@ namespace OpenSim.Region.Framework.Scenes
3334 } 3342 }
3335 } 3343 }
3336 3344
3345 RaiseCollisionScriptEvents(coldata);
3346
3337 if (Invulnerable) 3347 if (Invulnerable)
3338 return; 3348 return;
3339 3349
@@ -3770,5 +3780,204 @@ namespace OpenSim.Region.Framework.Scenes
3770 m_reprioritization_called = false; 3780 m_reprioritization_called = false;
3771 } 3781 }
3772 } 3782 }
3783
3784 private void CheckLandingPoint(ref Vector3 pos)
3785 {
3786 // Never constrain lures
3787 if ((TeleportFlags & TeleportFlags.ViaLure) != 0)
3788 return;
3789
3790 if (m_scene.RegionInfo.EstateSettings.AllowDirectTeleport)
3791 return;
3792
3793 ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y);
3794
3795 if (land.LandData.LandingType == (byte)LandingType.LandingPoint &&
3796 land.LandData.UserLocation != Vector3.Zero &&
3797 land.LandData.OwnerID != m_uuid &&
3798 (!m_scene.Permissions.IsGod(m_uuid)) &&
3799 (!m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid)))
3800 {
3801 float curr = Vector3.Distance(AbsolutePosition, pos);
3802 if (Vector3.Distance(land.LandData.UserLocation, pos) < curr)
3803 pos = land.LandData.UserLocation;
3804 else
3805 ControllingClient.SendAlertMessage("Can't teleport closer to destination");
3806 }
3807 }
3808
3809 private void CheckAndAdjustLandingPoint(ref Vector3 pos)
3810 {
3811 ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y);
3812 if (land != null)
3813 {
3814 // If we come in via login, landmark or map, we want to
3815 // honor landing points. If we come in via Lure, we want
3816 // to ignore them.
3817 if ((m_teleportFlags & (TeleportFlags.ViaLogin | TeleportFlags.ViaRegionID)) == (TeleportFlags.ViaLogin | TeleportFlags.ViaRegionID) ||
3818 (m_teleportFlags & TeleportFlags.ViaLandmark) != 0 ||
3819 (m_teleportFlags & TeleportFlags.ViaLocation) != 0)
3820 {
3821 // Don't restrict gods, estate managers, or land owners to
3822 // the TP point. This behaviour mimics agni.
3823 if (land.LandData.LandingType == (byte)LandingType.LandingPoint &&
3824 land.LandData.UserLocation != Vector3.Zero &&
3825 GodLevel < 200 &&
3826 ((land.LandData.OwnerID != m_uuid &&
3827 (!m_scene.Permissions.IsGod(m_uuid)) &&
3828 (!m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid))) || (m_teleportFlags & TeleportFlags.ViaLocation) != 0))
3829 {
3830 pos = land.LandData.UserLocation;
3831 }
3832 }
3833
3834 land.SendLandUpdateToClient(ControllingClient);
3835 }
3836 }
3837
3838 private void RaiseCollisionScriptEvents(Dictionary<uint, ContactPoint> coldata)
3839 {
3840 List<uint> thisHitColliders = new List<uint>();
3841 List<uint> endedColliders = new List<uint>();
3842 List<uint> startedColliders = new List<uint>();
3843
3844 foreach (uint localid in coldata.Keys)
3845 {
3846 thisHitColliders.Add(localid);
3847 if (!m_lastColliders.Contains(localid))
3848 {
3849 startedColliders.Add(localid);
3850 }
3851 //m_log.Debug("[SCENE PRESENCE]: Collided with:" + localid.ToString() + " at depth of: " + collissionswith[localid].ToString());
3852 }
3853
3854 // calculate things that ended colliding
3855 foreach (uint localID in m_lastColliders)
3856 {
3857 if (!thisHitColliders.Contains(localID))
3858 {
3859 endedColliders.Add(localID);
3860 }
3861 }
3862 //add the items that started colliding this time to the last colliders list.
3863 foreach (uint localID in startedColliders)
3864 {
3865 m_lastColliders.Add(localID);
3866 }
3867 // remove things that ended colliding from the last colliders list
3868 foreach (uint localID in endedColliders)
3869 {
3870 m_lastColliders.Remove(localID);
3871 }
3872
3873 // do event notification
3874 if (startedColliders.Count > 0)
3875 {
3876 ColliderArgs StartCollidingMessage = new ColliderArgs();
3877 List<DetectedObject> colliding = new List<DetectedObject>();
3878 foreach (uint localId in startedColliders)
3879 {
3880 if (localId == 0)
3881 continue;
3882
3883 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
3884 string data = "";
3885 if (obj != null)
3886 {
3887 DetectedObject detobj = new DetectedObject();
3888 detobj.keyUUID = obj.UUID;
3889 detobj.nameStr = obj.Name;
3890 detobj.ownerUUID = obj.OwnerID;
3891 detobj.posVector = obj.AbsolutePosition;
3892 detobj.rotQuat = obj.GetWorldRotation();
3893 detobj.velVector = obj.Velocity;
3894 detobj.colliderType = 0;
3895 detobj.groupUUID = obj.GroupID;
3896 colliding.Add(detobj);
3897 }
3898 }
3899
3900 if (colliding.Count > 0)
3901 {
3902 StartCollidingMessage.Colliders = colliding;
3903
3904 foreach (SceneObjectGroup att in GetAttachments())
3905 Scene.EventManager.TriggerScriptCollidingStart(att.LocalId, StartCollidingMessage);
3906 }
3907 }
3908
3909 if (endedColliders.Count > 0)
3910 {
3911 ColliderArgs EndCollidingMessage = new ColliderArgs();
3912 List<DetectedObject> colliding = new List<DetectedObject>();
3913 foreach (uint localId in endedColliders)
3914 {
3915 if (localId == 0)
3916 continue;
3917
3918 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
3919 string data = "";
3920 if (obj != null)
3921 {
3922 DetectedObject detobj = new DetectedObject();
3923 detobj.keyUUID = obj.UUID;
3924 detobj.nameStr = obj.Name;
3925 detobj.ownerUUID = obj.OwnerID;
3926 detobj.posVector = obj.AbsolutePosition;
3927 detobj.rotQuat = obj.GetWorldRotation();
3928 detobj.velVector = obj.Velocity;
3929 detobj.colliderType = 0;
3930 detobj.groupUUID = obj.GroupID;
3931 colliding.Add(detobj);
3932 }
3933 }
3934
3935 if (colliding.Count > 0)
3936 {
3937 EndCollidingMessage.Colliders = colliding;
3938
3939 foreach (SceneObjectGroup att in GetAttachments())
3940 Scene.EventManager.TriggerScriptCollidingEnd(att.LocalId, EndCollidingMessage);
3941 }
3942 }
3943
3944 if (thisHitColliders.Count > 0)
3945 {
3946 ColliderArgs CollidingMessage = new ColliderArgs();
3947 List<DetectedObject> colliding = new List<DetectedObject>();
3948 foreach (uint localId in thisHitColliders)
3949 {
3950 if (localId == 0)
3951 continue;
3952
3953 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
3954 string data = "";
3955 if (obj != null)
3956 {
3957 DetectedObject detobj = new DetectedObject();
3958 detobj.keyUUID = obj.UUID;
3959 detobj.nameStr = obj.Name;
3960 detobj.ownerUUID = obj.OwnerID;
3961 detobj.posVector = obj.AbsolutePosition;
3962 detobj.rotQuat = obj.GetWorldRotation();
3963 detobj.velVector = obj.Velocity;
3964 detobj.colliderType = 0;
3965 detobj.groupUUID = obj.GroupID;
3966 colliding.Add(detobj);
3967 }
3968 }
3969
3970 if (colliding.Count > 0)
3971 {
3972 CollidingMessage.Colliders = colliding;
3973
3974 lock (m_attachments)
3975 {
3976 foreach (SceneObjectGroup att in m_attachments)
3977 Scene.EventManager.TriggerScriptColliding(att.LocalId, CollidingMessage);
3978 }
3979 }
3980 }
3981 }
3773 } 3982 }
3774} 3983}
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
index 60cc788..680a6fa 100644
--- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
+++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
@@ -345,6 +345,8 @@ 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);
348 #endregion 350 #endregion
349 351
350 #region TaskInventoryXmlProcessors initialization 352 #region TaskInventoryXmlProcessors initialization
@@ -729,6 +731,11 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
729 obj.PayPrice[4] = (int)reader.ReadElementContentAsInt("PayPrice4", String.Empty); 731 obj.PayPrice[4] = (int)reader.ReadElementContentAsInt("PayPrice4", String.Empty);
730 } 732 }
731 733
734 private static void ProcessBuoyancy(SceneObjectPart obj, XmlTextReader reader)
735 {
736 obj.Buoyancy = (int)reader.ReadElementContentAsFloat("Buoyancy", String.Empty);
737 }
738
732 #endregion 739 #endregion
733 740
734 #region TaskInventoryXmlProcessors 741 #region TaskInventoryXmlProcessors
@@ -1212,6 +1219,8 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1212 writer.WriteElementString("PayPrice3", sop.PayPrice[3].ToString()); 1219 writer.WriteElementString("PayPrice3", sop.PayPrice[3].ToString());
1213 writer.WriteElementString("PayPrice4", sop.PayPrice[4].ToString()); 1220 writer.WriteElementString("PayPrice4", sop.PayPrice[4].ToString());
1214 1221
1222 writer.WriteElementString("Buoyancy", sop.Buoyancy.ToString());
1223
1215 writer.WriteEndElement(); 1224 writer.WriteEndElement();
1216 } 1225 }
1217 1226
@@ -1496,12 +1505,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1496 { 1505 {
1497 TaskInventoryDictionary tinv = new TaskInventoryDictionary(); 1506 TaskInventoryDictionary tinv = new TaskInventoryDictionary();
1498 1507
1499 if (reader.IsEmptyElement)
1500 {
1501 reader.Read();
1502 return tinv;
1503 }
1504
1505 reader.ReadStartElement(name, String.Empty); 1508 reader.ReadStartElement(name, String.Empty);
1506 1509
1507 while (reader.Name == "TaskInventoryItem") 1510 while (reader.Name == "TaskInventoryItem")
@@ -1544,12 +1547,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1544 1547
1545 PrimitiveBaseShape shape = new PrimitiveBaseShape(); 1548 PrimitiveBaseShape shape = new PrimitiveBaseShape();
1546 1549
1547 if (reader.IsEmptyElement)
1548 {
1549 reader.Read();
1550 return shape;
1551 }
1552
1553 reader.ReadStartElement(name, String.Empty); // Shape 1550 reader.ReadStartElement(name, String.Empty); // Shape
1554 1551
1555 string nodeName = string.Empty; 1552 string nodeName = string.Empty;
@@ -1589,4 +1586,4 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1589 1586
1590 #endregion 1587 #endregion
1591 } 1588 }
1592} 1589} \ No newline at end of file
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;