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.cs359
-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.cs490
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneBase.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs44
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs224
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneManager.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs17
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs566
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs219
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs806
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs322
-rw-r--r--OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs28
-rw-r--r--OpenSim/Region/Framework/Scenes/UndoState.cs87
-rw-r--r--OpenSim/Region/Framework/Scenes/UuidGatherer.cs4
27 files changed, 2486 insertions, 800 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 4f71915..209a0a6 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;
@@ -788,6 +792,26 @@ namespace OpenSim.Region.Framework.Scenes
788 } 792 }
789 } 793 }
790 } 794 }
795 public void TriggerTerrainUpdate()
796 {
797 OnTerrainUpdateDelegate handlerTerrainUpdate = OnTerrainUpdate;
798 if (handlerTerrainUpdate != null)
799 {
800 foreach (OnTerrainUpdateDelegate d in handlerTerrainUpdate.GetInvocationList())
801 {
802 try
803 {
804 d();
805 }
806 catch (Exception e)
807 {
808 m_log.ErrorFormat(
809 "[EVENT MANAGER]: Delegate for TriggerTerrainUpdate failed - continuing. {0} {1}",
810 e.Message, e.StackTrace);
811 }
812 }
813 }
814 }
791 815
792 public void TriggerTerrainTick() 816 public void TriggerTerrainTick()
793 { 817 {
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 b62023b..1746cfe 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -117,34 +117,22 @@ namespace OpenSim.Region.Framework.Scenes
117 /// <param name="item"></param> 117 /// <param name="item"></param>
118 public bool AddInventoryItem(InventoryItemBase item) 118 public bool AddInventoryItem(InventoryItemBase item)
119 { 119 {
120 if (UUID.Zero == item.Folder) 120 InventoryFolderBase folder;
121
122 if (item.Folder == UUID.Zero)
121 { 123 {
122 InventoryFolderBase f = InventoryService.GetFolderForType(item.Owner, (AssetType)item.AssetType); 124 folder = InventoryService.GetFolderForType(item.Owner, (AssetType)item.AssetType);
123 if (f != null) 125 if (folder == null)
124 { 126 {
125// m_log.DebugFormat( 127 folder = InventoryService.GetRootFolder(item.Owner);
126// "[LOCAL INVENTORY SERVICES CONNECTOR]: Found folder {0} type {1} for item {2}", 128
127// f.Name, (AssetType)f.Type, item.Name); 129 if (folder == null)
128
129 item.Folder = f.ID;
130 }
131 else
132 {
133 f = InventoryService.GetRootFolder(item.Owner);
134 if (f != null)
135 {
136 item.Folder = f.ID;
137 }
138 else
139 {
140 m_log.WarnFormat(
141 "[AGENT INVENTORY]: Could not find root folder for {0} when trying to add item {1} with no parent folder specified",
142 item.Owner, item.Name);
143 return false; 130 return false;
144 }
145 } 131 }
132
133 item.Folder = folder.ID;
146 } 134 }
147 135
148 if (InventoryService.AddItem(item)) 136 if (InventoryService.AddItem(item))
149 { 137 {
150 int userlevel = 0; 138 int userlevel = 0;
@@ -264,8 +252,7 @@ namespace OpenSim.Region.Framework.Scenes
264 252
265 // Update item with new asset 253 // Update item with new asset
266 item.AssetID = asset.FullID; 254 item.AssetID = asset.FullID;
267 if (group.UpdateInventoryItem(item)) 255 group.UpdateInventoryItem(item);
268 remoteClient.SendAgentAlertMessage("Script saved", false);
269 256
270 part.SendPropertiesToClient(remoteClient); 257 part.SendPropertiesToClient(remoteClient);
271 258
@@ -276,12 +263,7 @@ namespace OpenSim.Region.Framework.Scenes
276 { 263 {
277 // Needs to determine which engine was running it and use that 264 // Needs to determine which engine was running it and use that
278 // 265 //
279 part.Inventory.CreateScriptInstance(item.ItemID, 0, false, DefaultScriptEngine, 0); 266 errors = part.Inventory.CreateScriptInstanceEr(item.ItemID, 0, false, DefaultScriptEngine, 0);
280 errors = part.Inventory.GetScriptErrors(item.ItemID);
281 }
282 else
283 {
284 remoteClient.SendAgentAlertMessage("Script saved", false);
285 } 267 }
286 part.ParentGroup.ResumeScripts(); 268 part.ParentGroup.ResumeScripts();
287 return errors; 269 return errors;
@@ -345,6 +327,7 @@ namespace OpenSim.Region.Framework.Scenes
345 327
346 if (UUID.Zero == transactionID) 328 if (UUID.Zero == transactionID)
347 { 329 {
330 item.Flags = (item.Flags & ~(uint)255) | (itemUpd.Flags & (uint)255);
348 item.Name = itemUpd.Name; 331 item.Name = itemUpd.Name;
349 item.Description = itemUpd.Description; 332 item.Description = itemUpd.Description;
350 if (item.NextPermissions != (itemUpd.NextPermissions & item.BasePermissions)) 333 if (item.NextPermissions != (itemUpd.NextPermissions & item.BasePermissions))
@@ -723,6 +706,8 @@ namespace OpenSim.Region.Framework.Scenes
723 return; 706 return;
724 } 707 }
725 708
709 if (newName == null) newName = item.Name;
710
726 AssetBase asset = AssetService.Get(item.AssetID.ToString()); 711 AssetBase asset = AssetService.Get(item.AssetID.ToString());
727 712
728 if (asset != null) 713 if (asset != null)
@@ -779,6 +764,24 @@ namespace OpenSim.Region.Framework.Scenes
779 } 764 }
780 765
781 /// <summary> 766 /// <summary>
767 /// Move an item within the agent's inventory, and leave a copy (used in making a new outfit)
768 /// </summary>
769 public void MoveInventoryItemsLeaveCopy(IClientAPI remoteClient, List<InventoryItemBase> items, UUID destfolder)
770 {
771 List<InventoryItemBase> moveitems = new List<InventoryItemBase>();
772 foreach (InventoryItemBase b in items)
773 {
774 CopyInventoryItem(remoteClient, 0, remoteClient.AgentId, b.ID, b.Folder, null);
775 InventoryItemBase n = InventoryService.GetItem(b);
776 n.Folder = destfolder;
777 moveitems.Add(n);
778 remoteClient.SendInventoryItemCreateUpdate(n, 0);
779 }
780
781 MoveInventoryItem(remoteClient, moveitems);
782 }
783
784 /// <summary>
782 /// Move an item within the agent's inventory. 785 /// Move an item within the agent's inventory.
783 /// </summary> 786 /// </summary>
784 /// <param name="remoteClient"></param> 787 /// <param name="remoteClient"></param>
@@ -979,25 +982,29 @@ namespace OpenSim.Region.Framework.Scenes
979 public void RemoveTaskInventory(IClientAPI remoteClient, UUID itemID, uint localID) 982 public void RemoveTaskInventory(IClientAPI remoteClient, UUID itemID, uint localID)
980 { 983 {
981 SceneObjectPart part = GetSceneObjectPart(localID); 984 SceneObjectPart part = GetSceneObjectPart(localID);
982 if (part == null) 985 SceneObjectGroup group = null;
983 return; 986 if (part != null)
987 {
988 group = part.ParentGroup;
989 }
990 if (part != null && group != null)
991 {
992 if (!Permissions.CanEditObjectInventory(part.UUID, remoteClient.AgentId))
993 return;
984 994
985 SceneObjectGroup group = part.ParentGroup; 995 TaskInventoryItem item = group.GetInventoryItem(localID, itemID);
986 if (!Permissions.CanEditObjectInventory(part.UUID, remoteClient.AgentId)) 996 if (item == null)
987 return; 997 return;
988
989 TaskInventoryItem item = group.GetInventoryItem(localID, itemID);
990 if (item == null)
991 return;
992 998
993 if (item.Type == 10) 999 if (item.Type == 10)
994 { 1000 {
995 part.RemoveScriptEvents(itemID); 1001 part.RemoveScriptEvents(itemID);
996 EventManager.TriggerRemoveScript(localID, itemID); 1002 EventManager.TriggerRemoveScript(localID, itemID);
1003 }
1004
1005 group.RemoveInventoryItem(localID, itemID);
1006 part.SendPropertiesToClient(remoteClient);
997 } 1007 }
998
999 group.RemoveInventoryItem(localID, itemID);
1000 part.SendPropertiesToClient(remoteClient);
1001 } 1008 }
1002 1009
1003 private InventoryItemBase CreateAgentInventoryItemFromTask(UUID destAgent, SceneObjectPart part, UUID itemId) 1010 private InventoryItemBase CreateAgentInventoryItemFromTask(UUID destAgent, SceneObjectPart part, UUID itemId)
@@ -1098,6 +1105,10 @@ namespace OpenSim.Region.Framework.Scenes
1098 { 1105 {
1099 SceneObjectPart part = GetSceneObjectPart(primLocalId); 1106 SceneObjectPart part = GetSceneObjectPart(primLocalId);
1100 1107
1108 // Can't move a null item
1109 if (itemId == UUID.Zero)
1110 return;
1111
1101 if (null == part) 1112 if (null == part)
1102 { 1113 {
1103 m_log.WarnFormat( 1114 m_log.WarnFormat(
@@ -1208,6 +1219,10 @@ namespace OpenSim.Region.Framework.Scenes
1208 if ((part.OwnerID != destPart.OwnerID) && ((srcTaskItem.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)) 1219 if ((part.OwnerID != destPart.OwnerID) && ((srcTaskItem.CurrentPermissions & (uint)PermissionMask.Transfer) == 0))
1209 return; 1220 return;
1210 1221
1222 bool overrideNoMod = false;
1223 if ((part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) != 0)
1224 overrideNoMod = true;
1225
1211 if (part.OwnerID != destPart.OwnerID && (part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) == 0) 1226 if (part.OwnerID != destPart.OwnerID && (part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) == 0)
1212 { 1227 {
1213 // object cannot copy items to an object owned by a different owner 1228 // object cannot copy items to an object owned by a different owner
@@ -1217,7 +1232,7 @@ namespace OpenSim.Region.Framework.Scenes
1217 } 1232 }
1218 1233
1219 // must have both move and modify permission to put an item in an object 1234 // must have both move and modify permission to put an item in an object
1220 if ((part.OwnerMask & ((uint)PermissionMask.Move | (uint)PermissionMask.Modify)) == 0) 1235 if (((part.OwnerMask & (uint)PermissionMask.Modify) == 0) && (!overrideNoMod))
1221 { 1236 {
1222 return; 1237 return;
1223 } 1238 }
@@ -1276,6 +1291,14 @@ namespace OpenSim.Region.Framework.Scenes
1276 1291
1277 public UUID MoveTaskInventoryItems(UUID destID, string category, SceneObjectPart host, List<UUID> items) 1292 public UUID MoveTaskInventoryItems(UUID destID, string category, SceneObjectPart host, List<UUID> items)
1278 { 1293 {
1294 SceneObjectPart destPart = GetSceneObjectPart(destID);
1295 if (destPart != null) // Move into a prim
1296 {
1297 foreach(UUID itemID in items)
1298 MoveTaskInventoryItem(destID, host, itemID);
1299 return destID; // Prim folder ID == prim ID
1300 }
1301
1279 InventoryFolderBase rootFolder = InventoryService.GetRootFolder(destID); 1302 InventoryFolderBase rootFolder = InventoryService.GetRootFolder(destID);
1280 1303
1281 UUID newFolderID = UUID.Random(); 1304 UUID newFolderID = UUID.Random();
@@ -1455,13 +1478,6 @@ namespace OpenSim.Region.Framework.Scenes
1455 { 1478 {
1456 agentTransactions.HandleTaskItemUpdateFromTransaction( 1479 agentTransactions.HandleTaskItemUpdateFromTransaction(
1457 remoteClient, part, transactionID, currentItem); 1480 remoteClient, part, transactionID, currentItem);
1458
1459 if ((InventoryType)itemInfo.InvType == InventoryType.Notecard)
1460 remoteClient.SendAgentAlertMessage("Notecard saved", false);
1461 else if ((InventoryType)itemInfo.InvType == InventoryType.LSL)
1462 remoteClient.SendAgentAlertMessage("Script saved", false);
1463 else
1464 remoteClient.SendAgentAlertMessage("Item saved", false);
1465 } 1481 }
1466 1482
1467 // Base ALWAYS has move 1483 // Base ALWAYS has move
@@ -1602,7 +1618,7 @@ namespace OpenSim.Region.Framework.Scenes
1602 return; 1618 return;
1603 1619
1604 AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType, 1620 AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType,
1605 Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n}"), 1621 Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n\n touch_start(integer num)\n {\n }\n}"),
1606 remoteClient.AgentId); 1622 remoteClient.AgentId);
1607 AssetService.Store(asset); 1623 AssetService.Store(asset);
1608 1624
@@ -1755,23 +1771,32 @@ namespace OpenSim.Region.Framework.Scenes
1755 // build a list of eligible objects 1771 // build a list of eligible objects
1756 List<uint> deleteIDs = new List<uint>(); 1772 List<uint> deleteIDs = new List<uint>();
1757 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>(); 1773 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>();
1758 1774 List<SceneObjectGroup> takeGroups = new List<SceneObjectGroup>();
1759 // Start with true for both, then remove the flags if objects
1760 // that we can't derez are part of the selection
1761 bool permissionToTake = true;
1762 bool permissionToTakeCopy = true;
1763 bool permissionToDelete = true;
1764 1775
1765 foreach (uint localID in localIDs) 1776 foreach (uint localID in localIDs)
1766 { 1777 {
1778 // Start with true for both, then remove the flags if objects
1779 // that we can't derez are part of the selection
1780 bool permissionToTake = true;
1781 bool permissionToTakeCopy = true;
1782 bool permissionToDelete = true;
1783
1767 // Invalid id 1784 // Invalid id
1768 SceneObjectPart part = GetSceneObjectPart(localID); 1785 SceneObjectPart part = GetSceneObjectPart(localID);
1769 if (part == null) 1786 if (part == null)
1787 {
1788 //Client still thinks the object exists, kill it
1789 deleteIDs.Add(localID);
1770 continue; 1790 continue;
1791 }
1771 1792
1772 // Already deleted by someone else 1793 // Already deleted by someone else
1773 if (part.ParentGroup.IsDeleted) 1794 if (part.ParentGroup.IsDeleted)
1795 {
1796 //Client still thinks the object exists, kill it
1797 deleteIDs.Add(localID);
1774 continue; 1798 continue;
1799 }
1775 1800
1776 // Can't delete child prims 1801 // Can't delete child prims
1777 if (part != part.ParentGroup.RootPart) 1802 if (part != part.ParentGroup.RootPart)
@@ -1779,9 +1804,6 @@ namespace OpenSim.Region.Framework.Scenes
1779 1804
1780 SceneObjectGroup grp = part.ParentGroup; 1805 SceneObjectGroup grp = part.ParentGroup;
1781 1806
1782 deleteIDs.Add(localID);
1783 deleteGroups.Add(grp);
1784
1785 if (remoteClient == null) 1807 if (remoteClient == null)
1786 { 1808 {
1787 // Autoreturn has a null client. Nothing else does. So 1809 // Autoreturn has a null client. Nothing else does. So
@@ -1798,83 +1820,195 @@ namespace OpenSim.Region.Framework.Scenes
1798 } 1820 }
1799 else 1821 else
1800 { 1822 {
1801 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId)) 1823 if (action == DeRezAction.TakeCopy)
1824 {
1825 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId))
1826 permissionToTakeCopy = false;
1827 }
1828 else
1829 {
1802 permissionToTakeCopy = false; 1830 permissionToTakeCopy = false;
1803 1831 }
1804 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId)) 1832 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId))
1805 permissionToTake = false; 1833 permissionToTake = false;
1806 1834
1807 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId)) 1835 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId))
1808 permissionToDelete = false; 1836 permissionToDelete = false;
1809 } 1837 }
1810 }
1811 1838
1812 // Handle god perms 1839 // Handle god perms
1813 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId)) 1840 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId))
1814 { 1841 {
1815 permissionToTake = true; 1842 permissionToTake = true;
1816 permissionToTakeCopy = true; 1843 permissionToTakeCopy = true;
1817 permissionToDelete = true; 1844 permissionToDelete = true;
1818 } 1845 }
1819 1846
1820 // If we're re-saving, we don't even want to delete 1847 // If we're re-saving, we don't even want to delete
1821 if (action == DeRezAction.SaveToExistingUserInventoryItem) 1848 if (action == DeRezAction.SaveToExistingUserInventoryItem)
1822 permissionToDelete = false; 1849 permissionToDelete = false;
1823 1850
1824 // if we want to take a copy, we also don't want to delete 1851 // if we want to take a copy, we also don't want to delete
1825 // Note: after this point, the permissionToTakeCopy flag 1852 // Note: after this point, the permissionToTakeCopy flag
1826 // becomes irrelevant. It already includes the permissionToTake 1853 // becomes irrelevant. It already includes the permissionToTake
1827 // permission and after excluding no copy items here, we can 1854 // permission and after excluding no copy items here, we can
1828 // just use that. 1855 // just use that.
1829 if (action == DeRezAction.TakeCopy) 1856 if (action == DeRezAction.TakeCopy)
1830 { 1857 {
1831 // If we don't have permission, stop right here 1858 // If we don't have permission, stop right here
1832 if (!permissionToTakeCopy) 1859 if (!permissionToTakeCopy)
1833 return; 1860 return;
1834 1861
1835 permissionToTake = true; 1862 permissionToTake = true;
1836 // Don't delete 1863 // Don't delete
1837 permissionToDelete = false; 1864 permissionToDelete = false;
1838 } 1865 }
1839 1866
1840 if (action == DeRezAction.Return) 1867 if (action == DeRezAction.Return)
1841 {
1842 if (remoteClient != null)
1843 { 1868 {
1844 if (Permissions.CanReturnObjects( 1869 if (remoteClient != null)
1845 null,
1846 remoteClient.AgentId,
1847 deleteGroups))
1848 { 1870 {
1849 permissionToTake = true; 1871 if (Permissions.CanReturnObjects(
1850 permissionToDelete = true; 1872 null,
1851 1873 remoteClient.AgentId,
1852 foreach (SceneObjectGroup g in deleteGroups) 1874 deleteGroups))
1853 { 1875 {
1854 AddReturn(g.OwnerID, g.Name, g.AbsolutePosition, "parcel owner return"); 1876 permissionToTake = true;
1877 permissionToDelete = true;
1878
1879 AddReturn(grp.OwnerID, grp.Name, grp.AbsolutePosition, "parcel owner return");
1855 } 1880 }
1856 } 1881 }
1882 else // Auto return passes through here with null agent
1883 {
1884 permissionToTake = true;
1885 permissionToDelete = true;
1886 }
1857 } 1887 }
1858 else // Auto return passes through here with null agent 1888
1889 if (permissionToTake && (!permissionToDelete))
1890 takeGroups.Add(grp);
1891
1892 if (permissionToDelete)
1859 { 1893 {
1860 permissionToTake = true; 1894 if (permissionToTake)
1861 permissionToDelete = true; 1895 deleteGroups.Add(grp);
1896 deleteIDs.Add(grp.LocalId);
1862 } 1897 }
1863 } 1898 }
1864 1899
1865 if (permissionToTake) 1900 SendKillObject(deleteIDs);
1901
1902 if (deleteGroups.Count > 0)
1866 { 1903 {
1904 foreach (SceneObjectGroup g in deleteGroups)
1905 deleteIDs.Remove(g.LocalId);
1906
1867 m_asyncSceneObjectDeleter.DeleteToInventory( 1907 m_asyncSceneObjectDeleter.DeleteToInventory(
1868 action, destinationID, deleteGroups, remoteClient, 1908 action, destinationID, deleteGroups, remoteClient,
1869 permissionToDelete); 1909 true);
1870 } 1910 }
1871 else if (permissionToDelete) 1911 if (takeGroups.Count > 0)
1912 {
1913 m_asyncSceneObjectDeleter.DeleteToInventory(
1914 action, destinationID, takeGroups, remoteClient,
1915 false);
1916 }
1917 if (deleteIDs.Count > 0)
1872 { 1918 {
1873 foreach (SceneObjectGroup g in deleteGroups) 1919 foreach (SceneObjectGroup g in deleteGroups)
1874 DeleteSceneObject(g, false); 1920 DeleteSceneObject(g, true);
1875 } 1921 }
1876 } 1922 }
1877 1923
1924 public UUID attachObjectAssetStore(IClientAPI remoteClient, SceneObjectGroup grp, UUID AgentId, out UUID itemID)
1925 {
1926 itemID = UUID.Zero;
1927 if (grp != null)
1928 {
1929 Vector3 inventoryStoredPosition = new Vector3
1930 (((grp.AbsolutePosition.X > (int)Constants.RegionSize)
1931 ? 250
1932 : grp.AbsolutePosition.X)
1933 ,
1934 (grp.AbsolutePosition.X > (int)Constants.RegionSize)
1935 ? 250
1936 : grp.AbsolutePosition.X,
1937 grp.AbsolutePosition.Z);
1938
1939 Vector3 originalPosition = grp.AbsolutePosition;
1940
1941 grp.AbsolutePosition = inventoryStoredPosition;
1942
1943 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp);
1944
1945 grp.AbsolutePosition = originalPosition;
1946
1947 AssetBase asset = CreateAsset(
1948 grp.GetPartName(grp.LocalId),
1949 grp.GetPartDescription(grp.LocalId),
1950 (sbyte)AssetType.Object,
1951 Utils.StringToBytes(sceneObjectXml),
1952 remoteClient.AgentId);
1953 AssetService.Store(asset);
1954
1955 InventoryItemBase item = new InventoryItemBase();
1956 item.CreatorId = grp.RootPart.CreatorID.ToString();
1957 item.CreatorData = grp.RootPart.CreatorData;
1958 item.Owner = remoteClient.AgentId;
1959 item.ID = UUID.Random();
1960 item.AssetID = asset.FullID;
1961 item.Description = asset.Description;
1962 item.Name = asset.Name;
1963 item.AssetType = asset.Type;
1964 item.InvType = (int)InventoryType.Object;
1965
1966 InventoryFolderBase folder = InventoryService.GetFolderForType(remoteClient.AgentId, AssetType.Object);
1967 if (folder != null)
1968 item.Folder = folder.ID;
1969 else // oopsies
1970 item.Folder = UUID.Zero;
1971
1972 // Set up base perms properly
1973 uint permsBase = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify);
1974 permsBase &= grp.RootPart.BaseMask;
1975 permsBase |= (uint)PermissionMask.Move;
1976
1977 // Make sure we don't lock it
1978 grp.RootPart.NextOwnerMask |= (uint)PermissionMask.Move;
1979
1980 if ((remoteClient.AgentId != grp.RootPart.OwnerID) && Permissions.PropagatePermissions())
1981 {
1982 item.BasePermissions = permsBase & grp.RootPart.NextOwnerMask;
1983 item.CurrentPermissions = permsBase & grp.RootPart.NextOwnerMask;
1984 item.NextPermissions = permsBase & grp.RootPart.NextOwnerMask;
1985 item.EveryOnePermissions = permsBase & grp.RootPart.EveryoneMask & grp.RootPart.NextOwnerMask;
1986 item.GroupPermissions = permsBase & grp.RootPart.GroupMask & grp.RootPart.NextOwnerMask;
1987 }
1988 else
1989 {
1990 item.BasePermissions = permsBase;
1991 item.CurrentPermissions = permsBase & grp.RootPart.OwnerMask;
1992 item.NextPermissions = permsBase & grp.RootPart.NextOwnerMask;
1993 item.EveryOnePermissions = permsBase & grp.RootPart.EveryoneMask;
1994 item.GroupPermissions = permsBase & grp.RootPart.GroupMask;
1995 }
1996 item.CreationDate = Util.UnixTimeSinceEpoch();
1997
1998 // sets itemID so client can show item as 'attached' in inventory
1999 grp.SetFromItemID(item.ID);
2000
2001 if (AddInventoryItem(item))
2002 remoteClient.SendInventoryItemCreateUpdate(item, 0);
2003 else
2004 m_dialogModule.SendAlertToUser(remoteClient, "Operation failed");
2005
2006 itemID = item.ID;
2007 return item.AssetID;
2008 }
2009 return UUID.Zero;
2010 }
2011
1878 /// <summary> 2012 /// <summary>
1879 /// Event Handler Rez an object into a scene 2013 /// Event Handler Rez an object into a scene
1880 /// Calls the non-void event handler 2014 /// Calls the non-void event handler
@@ -2001,6 +2135,9 @@ namespace OpenSim.Region.Framework.Scenes
2001 2135
2002 public void SetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID, bool running) 2136 public void SetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID, bool running)
2003 { 2137 {
2138 if (!Permissions.CanEditScript(itemID, objectID, controllingClient.AgentId))
2139 return;
2140
2004 SceneObjectPart part = GetSceneObjectPart(objectID); 2141 SceneObjectPart part = GetSceneObjectPart(objectID);
2005 if (part == null) 2142 if (part == null)
2006 return; 2143 return;
diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
index f9d0e0a..fd179ba 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
@@ -307,7 +307,10 @@ namespace OpenSim.Region.Framework.Scenes
307 List<UserAccount> accounts = UserAccountService.GetUserAccounts(RegionInfo.ScopeID, query); 307 List<UserAccount> accounts = UserAccountService.GetUserAccounts(RegionInfo.ScopeID, query);
308 308
309 if (accounts == null) 309 if (accounts == null)
310 {
311 m_log.DebugFormat("[LLCIENT]: ProcessAvatarPickerRequest: returned null result");
310 return; 312 return;
313 }
311 314
312 AvatarPickerReplyPacket replyPacket = (AvatarPickerReplyPacket) PacketPool.Instance.GetPacket(PacketType.AvatarPickerReply); 315 AvatarPickerReplyPacket replyPacket = (AvatarPickerReplyPacket) PacketPool.Instance.GetPacket(PacketType.AvatarPickerReply);
313 // TODO: don't create new blocks if recycling an old packet 316 // 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 4914d65..f8487e7 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,11 +208,14 @@ 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;
218 private int m_hbRestarts = 0;
212 219
213 private object m_deleting_scene_object = new object(); 220 private object m_deleting_scene_object = new object();
214 221
@@ -255,6 +262,19 @@ namespace OpenSim.Region.Framework.Scenes
255 get { return m_sceneGridService; } 262 get { return m_sceneGridService; }
256 } 263 }
257 264
265 public ISnmpModule SnmpService
266 {
267 get
268 {
269 if (m_snmpService == null)
270 {
271 m_snmpService = RequestModuleInterface<ISnmpModule>();
272 }
273
274 return m_snmpService;
275 }
276 }
277
258 public ISimulationDataService SimulationDataService 278 public ISimulationDataService SimulationDataService
259 { 279 {
260 get 280 get
@@ -536,6 +556,9 @@ namespace OpenSim.Region.Framework.Scenes
536 m_EstateDataService = estateDataService; 556 m_EstateDataService = estateDataService;
537 m_regionHandle = m_regInfo.RegionHandle; 557 m_regionHandle = m_regInfo.RegionHandle;
538 m_regionName = m_regInfo.RegionName; 558 m_regionName = m_regInfo.RegionName;
559 m_lastUpdate = Util.EnvironmentTickCount();
560 m_lastIncoming = 0;
561 m_lastOutgoing = 0;
539 562
540 m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this); 563 m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this);
541 m_asyncSceneObjectDeleter.Enabled = true; 564 m_asyncSceneObjectDeleter.Enabled = true;
@@ -652,6 +675,7 @@ namespace OpenSim.Region.Framework.Scenes
652 m_physicalPrim = startupConfig.GetBoolean("physical_prim", true); 675 m_physicalPrim = startupConfig.GetBoolean("physical_prim", true);
653 676
654 m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys); 677 m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys);
678
655 if (RegionInfo.NonphysPrimMax > 0) 679 if (RegionInfo.NonphysPrimMax > 0)
656 { 680 {
657 m_maxNonphys = RegionInfo.NonphysPrimMax; 681 m_maxNonphys = RegionInfo.NonphysPrimMax;
@@ -683,6 +707,7 @@ namespace OpenSim.Region.Framework.Scenes
683 m_persistAfter *= 10000000; 707 m_persistAfter *= 10000000;
684 708
685 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine"); 709 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine");
710 m_log.InfoFormat("[SCENE]: Default script engine {0}", m_defaultScriptEngine);
686 711
687 IConfig packetConfig = m_config.Configs["PacketPool"]; 712 IConfig packetConfig = m_config.Configs["PacketPool"];
688 if (packetConfig != null) 713 if (packetConfig != null)
@@ -692,6 +717,8 @@ namespace OpenSim.Region.Framework.Scenes
692 } 717 }
693 718
694 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl); 719 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl);
720 m_seeIntoBannedRegion = startupConfig.GetBoolean("SeeIntoBannedRegion", m_seeIntoBannedRegion);
721 CombineRegions = startupConfig.GetBoolean("CombineContiguousRegions", false);
695 722
696 m_generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", true); 723 m_generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", true);
697 if (m_generateMaptiles) 724 if (m_generateMaptiles)
@@ -727,9 +754,9 @@ namespace OpenSim.Region.Framework.Scenes
727 m_update_terrain = startupConfig.GetInt( "UpdateTerrainEveryNFrames", m_update_terrain); 754 m_update_terrain = startupConfig.GetInt( "UpdateTerrainEveryNFrames", m_update_terrain);
728 m_update_temp_cleaning = startupConfig.GetInt( "UpdateTempCleaningEveryNFrames", m_update_temp_cleaning); 755 m_update_temp_cleaning = startupConfig.GetInt( "UpdateTempCleaningEveryNFrames", m_update_temp_cleaning);
729 } 756 }
730 catch 757 catch (Exception e)
731 { 758 {
732 m_log.Warn("[SCENE]: Failed to load StartupConfig"); 759 m_log.Error("[SCENE]: Failed to load StartupConfig: " + e.ToString());
733 } 760 }
734 761
735 #endregion Region Config 762 #endregion Region Config
@@ -1140,7 +1167,22 @@ namespace OpenSim.Region.Framework.Scenes
1140 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat); 1167 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat);
1141 if (HeartbeatThread != null) 1168 if (HeartbeatThread != null)
1142 { 1169 {
1170 m_hbRestarts++;
1171 if(m_hbRestarts > 10)
1172 Environment.Exit(1);
1173 m_log.ErrorFormat("[SCENE]: Restarting heartbeat thread because it hasn't reported in in region {0}", RegionInfo.RegionName);
1174
1175//int pid = System.Diagnostics.Process.GetCurrentProcess().Id;
1176//System.Diagnostics.Process proc = new System.Diagnostics.Process();
1177//proc.EnableRaisingEvents=false;
1178//proc.StartInfo.FileName = "/bin/kill";
1179//proc.StartInfo.Arguments = "-QUIT " + pid.ToString();
1180//proc.Start();
1181//proc.WaitForExit();
1182//Thread.Sleep(1000);
1183//Environment.Exit(1);
1143 HeartbeatThread.Abort(); 1184 HeartbeatThread.Abort();
1185 Watchdog.AbortThread(HeartbeatThread.ManagedThreadId);
1144 HeartbeatThread = null; 1186 HeartbeatThread = null;
1145 } 1187 }
1146 m_lastUpdate = Util.EnvironmentTickCount(); 1188 m_lastUpdate = Util.EnvironmentTickCount();
@@ -1185,9 +1227,6 @@ namespace OpenSim.Region.Framework.Scenes
1185 { 1227 {
1186 while (!shuttingdown) 1228 while (!shuttingdown)
1187 Update(); 1229 Update();
1188
1189 m_lastUpdate = Util.EnvironmentTickCount();
1190 m_firstHeartbeat = false;
1191 } 1230 }
1192 catch (ThreadAbortException) 1231 catch (ThreadAbortException)
1193 { 1232 {
@@ -1285,6 +1324,13 @@ namespace OpenSim.Region.Framework.Scenes
1285 eventMS = Util.EnvironmentTickCountSubtract(evMS); ; 1324 eventMS = Util.EnvironmentTickCountSubtract(evMS); ;
1286 } 1325 }
1287 1326
1327 // if (Frame % m_update_land == 0)
1328 // {
1329 // int ldMS = Util.EnvironmentTickCount();
1330 // UpdateLand();
1331 // landMS = Util.EnvironmentTickCountSubtract(ldMS);
1332 // }
1333
1288 if (Frame % m_update_backup == 0) 1334 if (Frame % m_update_backup == 0)
1289 { 1335 {
1290 int backMS = Util.EnvironmentTickCount(); 1336 int backMS = Util.EnvironmentTickCount();
@@ -1392,12 +1438,16 @@ namespace OpenSim.Region.Framework.Scenes
1392 maintc = Util.EnvironmentTickCountSubtract(maintc); 1438 maintc = Util.EnvironmentTickCountSubtract(maintc);
1393 maintc = (int)(MinFrameTime * 1000) - maintc; 1439 maintc = (int)(MinFrameTime * 1000) - maintc;
1394 1440
1441
1442 m_lastUpdate = Util.EnvironmentTickCount();
1443 m_firstHeartbeat = false;
1444
1395 if (maintc > 0) 1445 if (maintc > 0)
1396 Thread.Sleep(maintc); 1446 Thread.Sleep(maintc);
1397 1447
1398 // Tell the watchdog that this thread is still alive 1448 // Tell the watchdog that this thread is still alive
1399 Watchdog.UpdateThread(); 1449 Watchdog.UpdateThread();
1400 } 1450 }
1401 1451
1402 public void AddGroupTarget(SceneObjectGroup grp) 1452 public void AddGroupTarget(SceneObjectGroup grp)
1403 { 1453 {
@@ -1413,9 +1463,9 @@ namespace OpenSim.Region.Framework.Scenes
1413 1463
1414 private void CheckAtTargets() 1464 private void CheckAtTargets()
1415 { 1465 {
1416 Dictionary<UUID, SceneObjectGroup>.ValueCollection objs; 1466 List<SceneObjectGroup> objs = new List<SceneObjectGroup>();
1417 lock (m_groupsWithTargets) 1467 lock (m_groupsWithTargets)
1418 objs = m_groupsWithTargets.Values; 1468 objs = new List<SceneObjectGroup>(m_groupsWithTargets.Values);
1419 1469
1420 foreach (SceneObjectGroup entry in objs) 1470 foreach (SceneObjectGroup entry in objs)
1421 entry.checkAtTargets(); 1471 entry.checkAtTargets();
@@ -1497,7 +1547,7 @@ namespace OpenSim.Region.Framework.Scenes
1497 msg.fromAgentName = "Server"; 1547 msg.fromAgentName = "Server";
1498 msg.dialog = (byte)19; // Object msg 1548 msg.dialog = (byte)19; // Object msg
1499 msg.fromGroup = false; 1549 msg.fromGroup = false;
1500 msg.offline = (byte)0; 1550 msg.offline = (byte)1;
1501 msg.ParentEstateID = RegionInfo.EstateSettings.ParentEstateID; 1551 msg.ParentEstateID = RegionInfo.EstateSettings.ParentEstateID;
1502 msg.Position = Vector3.Zero; 1552 msg.Position = Vector3.Zero;
1503 msg.RegionID = RegionInfo.RegionID.Guid; 1553 msg.RegionID = RegionInfo.RegionID.Guid;
@@ -1732,14 +1782,24 @@ namespace OpenSim.Region.Framework.Scenes
1732 /// <returns></returns> 1782 /// <returns></returns>
1733 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter) 1783 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter)
1734 { 1784 {
1785
1786 float wheight = (float)RegionInfo.RegionSettings.WaterHeight;
1787 Vector3 wpos = Vector3.Zero;
1788 // Check for water surface intersection from above
1789 if ( (RayStart.Z > wheight) && (RayEnd.Z < wheight) )
1790 {
1791 float ratio = (RayStart.Z - wheight) / (RayStart.Z - RayEnd.Z);
1792 wpos.X = RayStart.X - (ratio * (RayStart.X - RayEnd.X));
1793 wpos.Y = RayStart.Y - (ratio * (RayStart.Y - RayEnd.Y));
1794 wpos.Z = wheight;
1795 }
1796
1735 Vector3 pos = Vector3.Zero; 1797 Vector3 pos = Vector3.Zero;
1736 if (RayEndIsIntersection == (byte)1) 1798 if (RayEndIsIntersection == (byte)1)
1737 { 1799 {
1738 pos = RayEnd; 1800 pos = RayEnd;
1739 return pos;
1740 } 1801 }
1741 1802 else if (RayTargetID != UUID.Zero)
1742 if (RayTargetID != UUID.Zero)
1743 { 1803 {
1744 SceneObjectPart target = GetSceneObjectPart(RayTargetID); 1804 SceneObjectPart target = GetSceneObjectPart(RayTargetID);
1745 1805
@@ -1761,7 +1821,7 @@ namespace OpenSim.Region.Framework.Scenes
1761 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter); 1821 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter);
1762 1822
1763 // Un-comment out the following line to Get Raytrace results printed to the console. 1823 // Un-comment out the following line to Get Raytrace results printed to the console.
1764 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString()); 1824 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
1765 float ScaleOffset = 0.5f; 1825 float ScaleOffset = 0.5f;
1766 1826
1767 // If we hit something 1827 // If we hit something
@@ -1784,13 +1844,10 @@ namespace OpenSim.Region.Framework.Scenes
1784 //pos.Z -= 0.25F; 1844 //pos.Z -= 0.25F;
1785 1845
1786 } 1846 }
1787
1788 return pos;
1789 } 1847 }
1790 else 1848 else
1791 { 1849 {
1792 // We don't have a target here, so we're going to raytrace all the objects in the scene. 1850 // We don't have a target here, so we're going to raytrace all the objects in the scene.
1793
1794 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false); 1851 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false);
1795 1852
1796 // Un-comment the following line to print the raytrace results to the console. 1853 // Un-comment the following line to print the raytrace results to the console.
@@ -1799,13 +1856,12 @@ namespace OpenSim.Region.Framework.Scenes
1799 if (ei.HitTF) 1856 if (ei.HitTF)
1800 { 1857 {
1801 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z); 1858 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z);
1802 } else 1859 }
1860 else
1803 { 1861 {
1804 // fall back to our stupid functionality 1862 // fall back to our stupid functionality
1805 pos = RayEnd; 1863 pos = RayEnd;
1806 } 1864 }
1807
1808 return pos;
1809 } 1865 }
1810 } 1866 }
1811 else 1867 else
@@ -1816,8 +1872,12 @@ namespace OpenSim.Region.Framework.Scenes
1816 //increase height so its above the ground. 1872 //increase height so its above the ground.
1817 //should be getting the normal of the ground at the rez point and using that? 1873 //should be getting the normal of the ground at the rez point and using that?
1818 pos.Z += scale.Z / 2f; 1874 pos.Z += scale.Z / 2f;
1819 return pos; 1875// return pos;
1820 } 1876 }
1877
1878 // check against posible water intercept
1879 if (wpos.Z > pos.Z) pos = wpos;
1880 return pos;
1821 } 1881 }
1822 1882
1823 1883
@@ -1901,7 +1961,10 @@ namespace OpenSim.Region.Framework.Scenes
1901 public bool AddRestoredSceneObject( 1961 public bool AddRestoredSceneObject(
1902 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 1962 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
1903 { 1963 {
1904 return m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates); 1964 bool result = m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates);
1965 if (result)
1966 sceneObject.IsDeleted = false;
1967 return result;
1905 } 1968 }
1906 1969
1907 /// <summary> 1970 /// <summary>
@@ -1991,6 +2054,15 @@ namespace OpenSim.Region.Framework.Scenes
1991 /// </summary> 2054 /// </summary>
1992 public void DeleteAllSceneObjects() 2055 public void DeleteAllSceneObjects()
1993 { 2056 {
2057 DeleteAllSceneObjects(false);
2058 }
2059
2060 /// <summary>
2061 /// Delete every object from the scene. This does not include attachments worn by avatars.
2062 /// </summary>
2063 public void DeleteAllSceneObjects(bool exceptNoCopy)
2064 {
2065 List<SceneObjectGroup> toReturn = new List<SceneObjectGroup>();
1994 lock (Entities) 2066 lock (Entities)
1995 { 2067 {
1996 EntityBase[] entities = Entities.GetEntities(); 2068 EntityBase[] entities = Entities.GetEntities();
@@ -1999,11 +2071,24 @@ namespace OpenSim.Region.Framework.Scenes
1999 if (e is SceneObjectGroup) 2071 if (e is SceneObjectGroup)
2000 { 2072 {
2001 SceneObjectGroup sog = (SceneObjectGroup)e; 2073 SceneObjectGroup sog = (SceneObjectGroup)e;
2002 if (!sog.IsAttachment) 2074 if (sog != null && !sog.IsAttachment)
2003 DeleteSceneObject((SceneObjectGroup)e, false); 2075 {
2076 if (!exceptNoCopy || ((sog.GetEffectivePermissions() & (uint)PermissionMask.Copy) != 0))
2077 {
2078 DeleteSceneObject((SceneObjectGroup)e, false);
2079 }
2080 else
2081 {
2082 toReturn.Add((SceneObjectGroup)e);
2083 }
2084 }
2004 } 2085 }
2005 } 2086 }
2006 } 2087 }
2088 if (toReturn.Count > 0)
2089 {
2090 returnObjects(toReturn.ToArray(), UUID.Zero);
2091 }
2007 } 2092 }
2008 2093
2009 /// <summary> 2094 /// <summary>
@@ -2051,6 +2136,8 @@ namespace OpenSim.Region.Framework.Scenes
2051 } 2136 }
2052 2137
2053 group.DeleteGroupFromScene(silent); 2138 group.DeleteGroupFromScene(silent);
2139 if (!silent)
2140 SendKillObject(new List<uint>() { group.LocalId });
2054 2141
2055// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID); 2142// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID);
2056 } 2143 }
@@ -2405,10 +2492,17 @@ namespace OpenSim.Region.Framework.Scenes
2405 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns> 2492 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns>
2406 public bool AddSceneObject(SceneObjectGroup sceneObject) 2493 public bool AddSceneObject(SceneObjectGroup sceneObject)
2407 { 2494 {
2495 if (sceneObject.OwnerID == UUID.Zero)
2496 {
2497 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero", sceneObject.UUID);
2498 return false;
2499 }
2500
2408 // If the user is banned, we won't let any of their objects 2501 // If the user is banned, we won't let any of their objects
2409 // enter. Period. 2502 // enter. Period.
2410 // 2503 //
2411 if (m_regInfo.EstateSettings.IsBanned(sceneObject.OwnerID)) 2504 int flags = GetUserFlags(sceneObject.OwnerID);
2505 if (m_regInfo.EstateSettings.IsBanned(sceneObject.OwnerID, flags))
2412 { 2506 {
2413 m_log.InfoFormat("[INTERREGION]: Denied prim crossing for banned avatar {0}", sceneObject.OwnerID); 2507 m_log.InfoFormat("[INTERREGION]: Denied prim crossing for banned avatar {0}", sceneObject.OwnerID);
2414 2508
@@ -2454,12 +2548,23 @@ namespace OpenSim.Region.Framework.Scenes
2454 } 2548 }
2455 else 2549 else
2456 { 2550 {
2551 m_log.DebugFormat("[SCENE]: Attachment {0} arrived and scene presence was not found, setting to temp", sceneObject.UUID);
2457 RootPrim.RemFlag(PrimFlags.TemporaryOnRez); 2552 RootPrim.RemFlag(PrimFlags.TemporaryOnRez);
2458 RootPrim.AddFlag(PrimFlags.TemporaryOnRez); 2553 RootPrim.AddFlag(PrimFlags.TemporaryOnRez);
2459 } 2554 }
2555 if (sceneObject.OwnerID == UUID.Zero)
2556 {
2557 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero after attachment processing. BUG!", sceneObject.UUID);
2558 return false;
2559 }
2460 } 2560 }
2461 else 2561 else
2462 { 2562 {
2563 if (sceneObject.OwnerID == UUID.Zero)
2564 {
2565 m_log.ErrorFormat("[SCENE]: Owner ID for non-attachment {0} was zero", sceneObject.UUID);
2566 return false;
2567 }
2463 AddRestoredSceneObject(sceneObject, true, false); 2568 AddRestoredSceneObject(sceneObject, true, false);
2464 2569
2465 if (!Permissions.CanObjectEntry(sceneObject.UUID, 2570 if (!Permissions.CanObjectEntry(sceneObject.UUID,
@@ -2488,6 +2593,24 @@ namespace OpenSim.Region.Framework.Scenes
2488 return 2; // StateSource.PrimCrossing 2593 return 2; // StateSource.PrimCrossing
2489 } 2594 }
2490 2595
2596 public int GetUserFlags(UUID user)
2597 {
2598 //Unfortunately the SP approach means that the value is cached until region is restarted
2599 /*
2600 ScenePresence sp;
2601 if (TryGetScenePresence(user, out sp))
2602 {
2603 return sp.UserFlags;
2604 }
2605 else
2606 {
2607 */
2608 UserAccount uac = UserAccountService.GetUserAccount(RegionInfo.ScopeID, user);
2609 if (uac == null)
2610 return 0;
2611 return uac.UserFlags;
2612 //}
2613 }
2491 #endregion 2614 #endregion
2492 2615
2493 #region Add/Remove Avatar Methods 2616 #region Add/Remove Avatar Methods
@@ -2502,6 +2625,7 @@ namespace OpenSim.Region.Framework.Scenes
2502 || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; 2625 || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0;
2503 2626
2504 CheckHeartbeat(); 2627 CheckHeartbeat();
2628 ScenePresence presence;
2505 2629
2506 ScenePresence sp = GetScenePresence(client.AgentId); 2630 ScenePresence sp = GetScenePresence(client.AgentId);
2507 2631
@@ -2550,7 +2674,13 @@ namespace OpenSim.Region.Framework.Scenes
2550 2674
2551 EventManager.TriggerOnNewClient(client); 2675 EventManager.TriggerOnNewClient(client);
2552 if (vialogin) 2676 if (vialogin)
2677 {
2553 EventManager.TriggerOnClientLogin(client); 2678 EventManager.TriggerOnClientLogin(client);
2679 // Send initial parcel data
2680 Vector3 pos = sp.AbsolutePosition;
2681 ILandObject land = LandChannel.GetLandObject(pos.X, pos.Y);
2682 land.SendLandUpdateToClient(client);
2683 }
2554 2684
2555 return sp; 2685 return sp;
2556 } 2686 }
@@ -2640,19 +2770,12 @@ namespace OpenSim.Region.Framework.Scenes
2640 // and the scene presence and the client, if they exist 2770 // and the scene presence and the client, if they exist
2641 try 2771 try
2642 { 2772 {
2643 // We need to wait for the client to make UDP contact first. 2773 ScenePresence sp = GetScenePresence(agentID);
2644 // It's the UDP contact that creates the scene presence 2774 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
2645 ScenePresence sp = WaitGetScenePresence(agentID); 2775
2646 if (sp != null) 2776 if (sp != null)
2647 {
2648 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
2649
2650 sp.ControllingClient.Close(); 2777 sp.ControllingClient.Close();
2651 } 2778
2652 else
2653 {
2654 m_log.WarnFormat("[SCENE]: Could not find scene presence for {0}", agentID);
2655 }
2656 // BANG! SLASH! 2779 // BANG! SLASH!
2657 m_authenticateHandler.RemoveCircuit(agentID); 2780 m_authenticateHandler.RemoveCircuit(agentID);
2658 2781
@@ -2752,6 +2875,7 @@ namespace OpenSim.Region.Framework.Scenes
2752 client.OnFetchInventory += m_asyncInventorySender.HandleFetchInventory; 2875 client.OnFetchInventory += m_asyncInventorySender.HandleFetchInventory;
2753 client.OnUpdateInventoryItem += UpdateInventoryItemAsset; 2876 client.OnUpdateInventoryItem += UpdateInventoryItemAsset;
2754 client.OnCopyInventoryItem += CopyInventoryItem; 2877 client.OnCopyInventoryItem += CopyInventoryItem;
2878 client.OnMoveItemsAndLeaveCopy += MoveInventoryItemsLeaveCopy;
2755 client.OnMoveInventoryItem += MoveInventoryItem; 2879 client.OnMoveInventoryItem += MoveInventoryItem;
2756 client.OnRemoveInventoryItem += RemoveInventoryItem; 2880 client.OnRemoveInventoryItem += RemoveInventoryItem;
2757 client.OnRemoveInventoryFolder += RemoveInventoryFolder; 2881 client.OnRemoveInventoryFolder += RemoveInventoryFolder;
@@ -2927,15 +3051,16 @@ namespace OpenSim.Region.Framework.Scenes
2927 /// </summary> 3051 /// </summary>
2928 /// <param name="agentId">The avatar's Unique ID</param> 3052 /// <param name="agentId">The avatar's Unique ID</param>
2929 /// <param name="client">The IClientAPI for the client</param> 3053 /// <param name="client">The IClientAPI for the client</param>
2930 public virtual void TeleportClientHome(UUID agentId, IClientAPI client) 3054 public virtual bool TeleportClientHome(UUID agentId, IClientAPI client)
2931 { 3055 {
2932 if (m_teleportModule != null) 3056 if (m_teleportModule != null)
2933 m_teleportModule.TeleportHome(agentId, client); 3057 return m_teleportModule.TeleportHome(agentId, client);
2934 else 3058 else
2935 { 3059 {
2936 m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active"); 3060 m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active");
2937 client.SendTeleportFailed("Unable to perform teleports on this simulator."); 3061 client.SendTeleportFailed("Unable to perform teleports on this simulator.");
2938 } 3062 }
3063 return false;
2939 } 3064 }
2940 3065
2941 /// <summary> 3066 /// <summary>
@@ -3027,6 +3152,16 @@ namespace OpenSim.Region.Framework.Scenes
3027 /// <param name="flags"></param> 3152 /// <param name="flags"></param>
3028 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags) 3153 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags)
3029 { 3154 {
3155 //Add half the avatar's height so that the user doesn't fall through prims
3156 ScenePresence presence;
3157 if (TryGetScenePresence(remoteClient.AgentId, out presence))
3158 {
3159 if (presence.Appearance != null)
3160 {
3161 position.Z = position.Z + (presence.Appearance.AvatarHeight / 2);
3162 }
3163 }
3164
3030 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt)) 3165 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt))
3031 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot. 3166 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot.
3032 m_dialogModule.SendAlertToUser(remoteClient, "Home position set."); 3167 m_dialogModule.SendAlertToUser(remoteClient, "Home position set.");
@@ -3095,8 +3230,9 @@ namespace OpenSim.Region.Framework.Scenes
3095 regions.Remove(RegionInfo.RegionHandle); 3230 regions.Remove(RegionInfo.RegionHandle);
3096 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); 3231 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions);
3097 } 3232 }
3098 3233 m_log.Debug("[Scene] Beginning ClientClosed");
3099 m_eventManager.TriggerClientClosed(agentID, this); 3234 m_eventManager.TriggerClientClosed(agentID, this);
3235 m_log.Debug("[Scene] Finished ClientClosed");
3100 } 3236 }
3101 catch (NullReferenceException) 3237 catch (NullReferenceException)
3102 { 3238 {
@@ -3148,9 +3284,10 @@ namespace OpenSim.Region.Framework.Scenes
3148 { 3284 {
3149 m_log.ErrorFormat("[SCENE] Scene.cs:RemoveClient exception {0}{1}", e.Message, e.StackTrace); 3285 m_log.ErrorFormat("[SCENE] Scene.cs:RemoveClient exception {0}{1}", e.Message, e.StackTrace);
3150 } 3286 }
3151 3287 m_log.Debug("[Scene] Done. Firing RemoveCircuit");
3152 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode); 3288 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode);
3153// CleanDroppedAttachments(); 3289// CleanDroppedAttachments();
3290 m_log.Debug("[Scene] The avatar has left the building");
3154 //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false)); 3291 //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false));
3155 //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true)); 3292 //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true));
3156 } 3293 }
@@ -3269,13 +3406,16 @@ namespace OpenSim.Region.Framework.Scenes
3269 sp = null; 3406 sp = null;
3270 } 3407 }
3271 3408
3272 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3273 3409
3274 //On login test land permisions 3410 //On login test land permisions
3275 if (vialogin) 3411 if (vialogin)
3276 { 3412 {
3277 if (land != null && !TestLandRestrictions(agent, land, out reason)) 3413 IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>();
3414 if (cache != null)
3415 cache.Remove(agent.firstname + " " + agent.lastname);
3416 if (!TestLandRestrictions(agent.AgentID, out reason, ref agent.startpos.X, ref agent.startpos.Y))
3278 { 3417 {
3418 m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString());
3279 return false; 3419 return false;
3280 } 3420 }
3281 } 3421 }
@@ -3299,8 +3439,13 @@ namespace OpenSim.Region.Framework.Scenes
3299 3439
3300 try 3440 try
3301 { 3441 {
3302 if (!AuthorizeUser(agent, out reason)) 3442 // Always check estate if this is a login. Always
3303 return false; 3443 // check if banned regions are to be blacked out.
3444 if (vialogin || (!m_seeIntoBannedRegion))
3445 {
3446 if (!AuthorizeUser(agent, out reason))
3447 return false;
3448 }
3304 } 3449 }
3305 catch (Exception e) 3450 catch (Exception e)
3306 { 3451 {
@@ -3403,6 +3548,8 @@ namespace OpenSim.Region.Framework.Scenes
3403 } 3548 }
3404 } 3549 }
3405 // Honor parcel landing type and position. 3550 // Honor parcel landing type and position.
3551 /*
3552 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3406 if (land != null) 3553 if (land != null)
3407 { 3554 {
3408 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) 3555 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero)
@@ -3410,26 +3557,34 @@ namespace OpenSim.Region.Framework.Scenes
3410 agent.startpos = land.LandData.UserLocation; 3557 agent.startpos = land.LandData.UserLocation;
3411 } 3558 }
3412 } 3559 }
3560 */// This is now handled properly in ScenePresence.MakeRootAgent
3413 } 3561 }
3414 3562
3415 return true; 3563 return true;
3416 } 3564 }
3417 3565
3418 private bool TestLandRestrictions(AgentCircuitData agent, ILandObject land, out string reason) 3566 private bool TestLandRestrictions(UUID agentID, out string reason, ref float posX, ref float posY)
3419 { 3567 {
3420 3568 reason = String.Empty;
3421 bool banned = land.IsBannedFromLand(agent.AgentID); 3569 if (Permissions.IsGod(agentID))
3422 bool restricted = land.IsRestrictedFromLand(agent.AgentID); 3570 return true;
3571
3572 ILandObject land = LandChannel.GetLandObject(posX, posY);
3573 if (land == null)
3574 return false;
3575
3576 bool banned = land.IsBannedFromLand(agentID);
3577 bool restricted = land.IsRestrictedFromLand(agentID);
3423 3578
3424 if (banned || restricted) 3579 if (banned || restricted)
3425 { 3580 {
3426 ILandObject nearestParcel = GetNearestAllowedParcel(agent.AgentID, agent.startpos.X, agent.startpos.Y); 3581 ILandObject nearestParcel = GetNearestAllowedParcel(agentID, posX, posY);
3427 if (nearestParcel != null) 3582 if (nearestParcel != null)
3428 { 3583 {
3429 //Move agent to nearest allowed 3584 //Move agent to nearest allowed
3430 Vector3 newPosition = GetParcelCenterAtGround(nearestParcel); 3585 Vector3 newPosition = GetParcelCenterAtGround(nearestParcel);
3431 agent.startpos.X = newPosition.X; 3586 posX = newPosition.X;
3432 agent.startpos.Y = newPosition.Y; 3587 posY = newPosition.Y;
3433 } 3588 }
3434 else 3589 else
3435 { 3590 {
@@ -3491,7 +3646,7 @@ namespace OpenSim.Region.Framework.Scenes
3491 3646
3492 if (!m_strictAccessControl) return true; 3647 if (!m_strictAccessControl) return true;
3493 if (Permissions.IsGod(agent.AgentID)) return true; 3648 if (Permissions.IsGod(agent.AgentID)) return true;
3494 3649
3495 if (AuthorizationService != null) 3650 if (AuthorizationService != null)
3496 { 3651 {
3497 if (!AuthorizationService.IsAuthorizedForRegion( 3652 if (!AuthorizationService.IsAuthorizedForRegion(
@@ -3499,14 +3654,14 @@ namespace OpenSim.Region.Framework.Scenes
3499 { 3654 {
3500 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the region", 3655 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the region",
3501 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 3656 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
3502 3657
3503 return false; 3658 return false;
3504 } 3659 }
3505 } 3660 }
3506 3661
3507 if (m_regInfo.EstateSettings != null) 3662 if (m_regInfo.EstateSettings != null)
3508 { 3663 {
3509 if (m_regInfo.EstateSettings.IsBanned(agent.AgentID)) 3664 if (m_regInfo.EstateSettings.IsBanned(agent.AgentID,0))
3510 { 3665 {
3511 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist", 3666 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist",
3512 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 3667 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
@@ -3702,6 +3857,13 @@ namespace OpenSim.Region.Framework.Scenes
3702 3857
3703 // We have to wait until the viewer contacts this region after receiving EAC. 3858 // We have to wait until the viewer contacts this region after receiving EAC.
3704 // That calls AddNewClient, which finally creates the ScenePresence 3859 // That calls AddNewClient, which finally creates the ScenePresence
3860 int flags = GetUserFlags(cAgentData.AgentID);
3861 if (m_regInfo.EstateSettings.IsBanned(cAgentData.AgentID, flags))
3862 {
3863 m_log.DebugFormat("[SCENE]: Denying root agent entry to {0}: banned", cAgentData.AgentID);
3864 return false;
3865 }
3866
3705 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2); 3867 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2);
3706 if (nearestParcel == null) 3868 if (nearestParcel == null)
3707 { 3869 {
@@ -3783,12 +3945,22 @@ namespace OpenSim.Region.Framework.Scenes
3783 return false; 3945 return false;
3784 } 3946 }
3785 3947
3948 public bool IncomingCloseAgent(UUID agentID)
3949 {
3950 return IncomingCloseAgent(agentID, false);
3951 }
3952
3953 public bool IncomingCloseChildAgent(UUID agentID)
3954 {
3955 return IncomingCloseAgent(agentID, true);
3956 }
3957
3786 /// <summary> 3958 /// <summary>
3787 /// Tell a single agent to disconnect from the region. 3959 /// Tell a single agent to disconnect from the region.
3788 /// </summary> 3960 /// </summary>
3789 /// <param name="regionHandle"></param>
3790 /// <param name="agentID"></param> 3961 /// <param name="agentID"></param>
3791 public bool IncomingCloseAgent(UUID agentID) 3962 /// <param name="childOnly"></param>
3963 public bool IncomingCloseAgent(UUID agentID, bool childOnly)
3792 { 3964 {
3793 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); 3965 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID);
3794 3966
@@ -3800,7 +3972,7 @@ namespace OpenSim.Region.Framework.Scenes
3800 { 3972 {
3801 m_sceneGraph.removeUserCount(false); 3973 m_sceneGraph.removeUserCount(false);
3802 } 3974 }
3803 else 3975 else if (!childOnly)
3804 { 3976 {
3805 m_sceneGraph.removeUserCount(true); 3977 m_sceneGraph.removeUserCount(true);
3806 } 3978 }
@@ -3816,9 +3988,12 @@ namespace OpenSim.Region.Framework.Scenes
3816 } 3988 }
3817 else 3989 else
3818 presence.ControllingClient.SendShutdownConnectionNotice(); 3990 presence.ControllingClient.SendShutdownConnectionNotice();
3991 presence.ControllingClient.Close(false);
3992 }
3993 else if (!childOnly)
3994 {
3995 presence.ControllingClient.Close(true);
3819 } 3996 }
3820
3821 presence.ControllingClient.Close();
3822 return true; 3997 return true;
3823 } 3998 }
3824 3999
@@ -4401,34 +4576,78 @@ namespace OpenSim.Region.Framework.Scenes
4401 SimulationDataService.RemoveObject(uuid, m_regInfo.RegionID); 4576 SimulationDataService.RemoveObject(uuid, m_regInfo.RegionID);
4402 } 4577 }
4403 4578
4404 public int GetHealth() 4579 public int GetHealth(out int flags, out string message)
4405 { 4580 {
4406 // Returns: 4581 // Returns:
4407 // 1 = sim is up and accepting http requests. The heartbeat has 4582 // 1 = sim is up and accepting http requests. The heartbeat has
4408 // stopped and the sim is probably locked up, but a remote 4583 // stopped and the sim is probably locked up, but a remote
4409 // admin restart may succeed 4584 // admin restart may succeed
4410 // 4585 //
4411 // 2 = Sim is up and the heartbeat is running. The sim is likely 4586 // 2 = Sim is up and the heartbeat is running. The sim is likely
4412 // usable for people within and logins _may_ work 4587 // usable for people within
4588 //
4589 // 3 = Sim is up and one packet thread is running. Sim is
4590 // unstable and will not accept new logins
4591 //
4592 // 4 = Sim is up and both packet threads are running. Sim is
4593 // likely usable
4413 // 4594 //
4414 // 3 = We have seen a new user enter within the past 4 minutes 4595 // 5 = We have seen a new user enter within the past 4 minutes
4415 // which can be seen as positive confirmation of sim health 4596 // which can be seen as positive confirmation of sim health
4416 // 4597 //
4598
4599 flags = 0;
4600 message = String.Empty;
4601
4602 CheckHeartbeat();
4603
4604 if (m_firstHeartbeat || (m_lastIncoming == 0 && m_lastOutgoing == 0))
4605 {
4606 // We're still starting
4607 // 0 means "in startup", it can't happen another way, since
4608 // to get here, we must be able to accept http connections
4609 return 0;
4610 }
4611
4417 int health=1; // Start at 1, means we're up 4612 int health=1; // Start at 1, means we're up
4418 4613
4419 if ((Util.EnvironmentTickCountSubtract(m_lastUpdate)) < 1000) 4614 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) < 1000)
4615 {
4616 health+=1;
4617 flags |= 1;
4618 }
4619
4620 if (Util.EnvironmentTickCountSubtract(m_lastIncoming) < 1000)
4621 {
4622 health+=1;
4623 flags |= 2;
4624 }
4625
4626 if (Util.EnvironmentTickCountSubtract(m_lastOutgoing) < 1000)
4627 {
4420 health+=1; 4628 health+=1;
4629 flags |= 4;
4630 }
4421 else 4631 else
4632 {
4633int pid = System.Diagnostics.Process.GetCurrentProcess().Id;
4634System.Diagnostics.Process proc = new System.Diagnostics.Process();
4635proc.EnableRaisingEvents=false;
4636proc.StartInfo.FileName = "/bin/kill";
4637proc.StartInfo.Arguments = "-QUIT " + pid.ToString();
4638proc.Start();
4639proc.WaitForExit();
4640Thread.Sleep(1000);
4641Environment.Exit(1);
4642 }
4643
4644 if (flags != 7)
4422 return health; 4645 return health;
4423 4646
4424 // A login in the last 4 mins? We can't be doing too badly 4647 // A login in the last 4 mins? We can't be doing too badly
4425 // 4648 //
4426 if ((Util.EnvironmentTickCountSubtract(m_LastLogin)) < 240000) 4649 if (Util.EnvironmentTickCountSubtract(m_LastLogin) < 240000)
4427 health++; 4650 health++;
4428 else
4429 return health;
4430
4431 CheckHeartbeat();
4432 4651
4433 return health; 4652 return health;
4434 } 4653 }
@@ -4621,7 +4840,7 @@ namespace OpenSim.Region.Framework.Scenes
4621 if (m_firstHeartbeat) 4840 if (m_firstHeartbeat)
4622 return; 4841 return;
4623 4842
4624 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) > 2000) 4843 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) > 5000)
4625 StartTimer(); 4844 StartTimer();
4626 } 4845 }
4627 4846
@@ -5031,6 +5250,54 @@ namespace OpenSim.Region.Framework.Scenes
5031 mapModule.GenerateMaptile(); 5250 mapModule.GenerateMaptile();
5032 } 5251 }
5033 5252
5253// public void CleanDroppedAttachments()
5254// {
5255// List<SceneObjectGroup> objectsToDelete =
5256// new List<SceneObjectGroup>();
5257//
5258// lock (m_cleaningAttachments)
5259// {
5260// ForEachSOG(delegate (SceneObjectGroup grp)
5261// {
5262// if (grp.RootPart.Shape.PCode == 0 && grp.RootPart.Shape.State != 0 && (!objectsToDelete.Contains(grp)))
5263// {
5264// UUID agentID = grp.OwnerID;
5265// if (agentID == UUID.Zero)
5266// {
5267// objectsToDelete.Add(grp);
5268// return;
5269// }
5270//
5271// ScenePresence sp = GetScenePresence(agentID);
5272// if (sp == null)
5273// {
5274// objectsToDelete.Add(grp);
5275// return;
5276// }
5277// }
5278// });
5279// }
5280//
5281// foreach (SceneObjectGroup grp in objectsToDelete)
5282// {
5283// m_log.InfoFormat("[SCENE]: Deleting dropped attachment {0} of user {1}", grp.UUID, grp.OwnerID);
5284// DeleteSceneObject(grp, true);
5285// }
5286// }
5287
5288 public void ThreadAlive(int threadCode)
5289 {
5290 switch(threadCode)
5291 {
5292 case 1: // Incoming
5293 m_lastIncoming = Util.EnvironmentTickCount();
5294 break;
5295 case 2: // Incoming
5296 m_lastOutgoing = Util.EnvironmentTickCount();
5297 break;
5298 }
5299 }
5300
5034 // This method is called across the simulation connector to 5301 // This method is called across the simulation connector to
5035 // determine if a given agent is allowed in this region 5302 // determine if a given agent is allowed in this region
5036 // AS A ROOT AGENT. Returning false here will prevent them 5303 // AS A ROOT AGENT. Returning false here will prevent them
@@ -5039,6 +5306,14 @@ namespace OpenSim.Region.Framework.Scenes
5039 // child agent creation, thereby emulating the SL behavior. 5306 // child agent creation, thereby emulating the SL behavior.
5040 public bool QueryAccess(UUID agentID, Vector3 position, out string reason) 5307 public bool QueryAccess(UUID agentID, Vector3 position, out string reason)
5041 { 5308 {
5309 reason = "You are banned from the region";
5310
5311 if (Permissions.IsGod(agentID))
5312 {
5313 reason = String.Empty;
5314 return true;
5315 }
5316
5042 int num = m_sceneGraph.GetNumberOfScenePresences(); 5317 int num = m_sceneGraph.GetNumberOfScenePresences();
5043 5318
5044 if (num >= RegionInfo.RegionSettings.AgentLimit) 5319 if (num >= RegionInfo.RegionSettings.AgentLimit)
@@ -5050,11 +5325,82 @@ namespace OpenSim.Region.Framework.Scenes
5050 } 5325 }
5051 } 5326 }
5052 5327
5328 ScenePresence presence = GetScenePresence(agentID);
5329 IClientAPI client = null;
5330 AgentCircuitData aCircuit = null;
5331
5332 if (presence != null)
5333 {
5334 client = presence.ControllingClient;
5335 if (client != null)
5336 aCircuit = client.RequestClientInfo();
5337 }
5338
5339 // We may be called before there is a presence or a client.
5340 // Fake AgentCircuitData to keep IAuthorizationModule smiling
5341 if (client == null)
5342 {
5343 aCircuit = new AgentCircuitData();
5344 aCircuit.AgentID = agentID;
5345 aCircuit.firstname = String.Empty;
5346 aCircuit.lastname = String.Empty;
5347 }
5348
5349 try
5350 {
5351 if (!AuthorizeUser(aCircuit, out reason))
5352 {
5353 // m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID);
5354 return false;
5355 }
5356 }
5357 catch (Exception e)
5358 {
5359 m_log.DebugFormat("[SCENE]: Exception authorizing agent: {0} "+ e.StackTrace, e.Message);
5360 return false;
5361 }
5362
5363 if (position == Vector3.Zero) // Teleport
5364 {
5365 float posX = 128.0f;
5366 float posY = 128.0f;
5367
5368 if (!TestLandRestrictions(agentID, out reason, ref posX, ref posY))
5369 {
5370 // m_log.DebugFormat("[SCENE]: Denying {0} because they are banned on all parcels", agentID);
5371 return false;
5372 }
5373 }
5374 else // Walking
5375 {
5376 ILandObject land = LandChannel.GetLandObject(position.X, position.Y);
5377 if (land == null)
5378 return false;
5379
5380 bool banned = land.IsBannedFromLand(agentID);
5381 bool restricted = land.IsRestrictedFromLand(agentID);
5382
5383 if (banned || restricted)
5384 return false;
5385 }
5386
5053 reason = String.Empty; 5387 reason = String.Empty;
5054 return true; 5388 return true;
5055 } 5389 }
5056 5390
5057 /// <summary> 5391 public void StartTimerWatchdog()
5392 {
5393 m_timerWatchdog.Interval = 1000;
5394 m_timerWatchdog.Elapsed += TimerWatchdog;
5395 m_timerWatchdog.AutoReset = true;
5396 m_timerWatchdog.Start();
5397 }
5398
5399 public void TimerWatchdog(object sender, ElapsedEventArgs e)
5400 {
5401 CheckHeartbeat();
5402 }
5403
5058 /// This method deals with movement when an avatar is automatically moving (but this is distinct from the 5404 /// This method deals with movement when an avatar is automatically moving (but this is distinct from the
5059 /// autopilot that moves an avatar to a sit target!. 5405 /// autopilot that moves an avatar to a sit target!.
5060 /// </summary> 5406 /// </summary>
diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs
index 712e094..da3b4dd 100644
--- a/OpenSim/Region/Framework/Scenes/SceneBase.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneBase.cs
@@ -136,6 +136,8 @@ namespace OpenSim.Region.Framework.Scenes
136 get { return m_permissions; } 136 get { return m_permissions; }
137 } 137 }
138 138
139 protected string m_datastore;
140
139 /* Used by the loadbalancer plugin on GForge */ 141 /* Used by the loadbalancer plugin on GForge */
140 protected RegionStatus m_regStatus; 142 protected RegionStatus m_regStatus;
141 public RegionStatus RegionStatus 143 public RegionStatus RegionStatus
diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
index d76ed3e..27833e8 100644
--- a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
@@ -88,7 +88,7 @@ namespace OpenSim.Region.Framework.Scenes
88 88
89 if (neighbour != null) 89 if (neighbour != null)
90 { 90 {
91 m_log.DebugFormat("[INTERGRID]: Successfully informed neighbour {0}-{1} that I'm here", x / Constants.RegionSize, y / Constants.RegionSize); 91 // m_log.DebugFormat("[INTERGRID]: Successfully informed neighbour {0}-{1} that I'm here", x / Constants.RegionSize, y / Constants.RegionSize);
92 m_scene.EventManager.TriggerOnRegionUp(neighbour); 92 m_scene.EventManager.TriggerOnRegionUp(neighbour);
93 } 93 }
94 else 94 else
@@ -102,7 +102,7 @@ namespace OpenSim.Region.Framework.Scenes
102 //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: Sending InterRegion Notification that region is up " + region.RegionName); 102 //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: Sending InterRegion Notification that region is up " + region.RegionName);
103 103
104 List<GridRegion> neighbours = m_scene.GridService.GetNeighbours(m_scene.RegionInfo.ScopeID, m_scene.RegionInfo.RegionID); 104 List<GridRegion> neighbours = m_scene.GridService.GetNeighbours(m_scene.RegionInfo.ScopeID, m_scene.RegionInfo.RegionID);
105 m_log.DebugFormat("[INTERGRID]: Informing {0} neighbours that this region is up", neighbours.Count); 105 //m_log.DebugFormat("[INTERGRID]: Informing {0} neighbours that this region is up", neighbours.Count);
106 foreach (GridRegion n in neighbours) 106 foreach (GridRegion n in neighbours)
107 { 107 {
108 InformNeighbourThatRegionUpDelegate d = InformNeighboursThatRegionIsUpAsync; 108 InformNeighbourThatRegionUpDelegate d = InformNeighboursThatRegionIsUpAsync;
@@ -176,10 +176,13 @@ namespace OpenSim.Region.Framework.Scenes
176 } 176 }
177 } 177 }
178 178
179 public delegate void SendCloseChildAgentDelegate(UUID agentID, ulong regionHandle);
180
179 /// <summary> 181 /// <summary>
180 /// Closes a child agent on a given region 182 /// This Closes child agents on neighboring regions
183 /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
181 /// </summary> 184 /// </summary>
182 protected void SendCloseChildAgent(UUID agentID, ulong regionHandle) 185 protected void SendCloseChildAgentAsync(UUID agentID, ulong regionHandle)
183 { 186 {
184 // let's do our best, but there's not much we can do if the neighbour doesn't accept. 187 // let's do our best, but there's not much we can do if the neighbour doesn't accept.
185 188
@@ -188,34 +191,29 @@ namespace OpenSim.Region.Framework.Scenes
188 Utils.LongToUInts(regionHandle, out x, out y); 191 Utils.LongToUInts(regionHandle, out x, out y);
189 192
190 GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y); 193 GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y);
194 m_scene.SimulationService.CloseChildAgent(destination, agentID);
195 }
191 196
192 m_log.DebugFormat( 197 private void SendCloseChildAgentCompleted(IAsyncResult iar)
193 "[INTERGRID]: Sending close agent {0} to region at {1}-{2}", 198 {
194 agentID, destination.RegionCoordX, destination.RegionCoordY); 199 SendCloseChildAgentDelegate icon = (SendCloseChildAgentDelegate)iar.AsyncState;
195 200 icon.EndInvoke(iar);
196 m_scene.SimulationService.CloseAgent(destination, agentID);
197 } 201 }
198 202
199 /// <summary>
200 /// Closes a child agents in a collection of regions. Does so asynchronously
201 /// so that the caller doesn't wait.
202 /// </summary>
203 /// <param name="agentID"></param>
204 /// <param name="regionslst"></param>
205 public void SendCloseChildAgentConnections(UUID agentID, List<ulong> regionslst) 203 public void SendCloseChildAgentConnections(UUID agentID, List<ulong> regionslst)
206 { 204 {
207 Util.FireAndForget(delegate 205 foreach (ulong handle in regionslst)
208 { 206 {
209 foreach (ulong handle in regionslst) 207 SendCloseChildAgentDelegate d = SendCloseChildAgentAsync;
210 { 208 d.BeginInvoke(agentID, handle,
211 SendCloseChildAgent(agentID, handle); 209 SendCloseChildAgentCompleted,
212 } 210 d);
213 }); 211 }
214 } 212 }
215 213
216 public List<GridRegion> RequestNamedRegions(string name, int maxNumber) 214 public List<GridRegion> RequestNamedRegions(string name, int maxNumber)
217 { 215 {
218 return m_scene.GridService.GetRegionsByName(UUID.Zero, name, maxNumber); 216 return m_scene.GridService.GetRegionsByName(UUID.Zero, name, maxNumber);
219 } 217 }
220 } 218 }
221} \ No newline at end of file 219}
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index a3e4b46..cd825eb 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>
@@ -609,7 +674,8 @@ namespace OpenSim.Region.Framework.Scenes
609 674
610 Entities[presence.UUID] = presence; 675 Entities[presence.UUID] = presence;
611 676
612 lock (m_presenceLock) 677 m_scenePresencesLock.EnterWriteLock();
678 try
613 { 679 {
614 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 680 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
615 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 681 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -633,6 +699,10 @@ namespace OpenSim.Region.Framework.Scenes
633 m_scenePresenceMap = newmap; 699 m_scenePresenceMap = newmap;
634 m_scenePresenceArray = newlist; 700 m_scenePresenceArray = newlist;
635 } 701 }
702 finally
703 {
704 m_scenePresencesLock.ExitWriteLock();
705 }
636 } 706 }
637 707
638 /// <summary> 708 /// <summary>
@@ -647,7 +717,8 @@ namespace OpenSim.Region.Framework.Scenes
647 agentID); 717 agentID);
648 } 718 }
649 719
650 lock (m_presenceLock) 720 m_scenePresencesLock.EnterWriteLock();
721 try
651 { 722 {
652 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 723 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
653 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 724 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -669,6 +740,10 @@ namespace OpenSim.Region.Framework.Scenes
669 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); 740 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID);
670 } 741 }
671 } 742 }
743 finally
744 {
745 m_scenePresencesLock.ExitWriteLock();
746 }
672 } 747 }
673 748
674 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) 749 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F)
@@ -1382,8 +1457,13 @@ namespace OpenSim.Region.Framework.Scenes
1382 { 1457 {
1383 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) 1458 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0))
1384 { 1459 {
1385 if (m_parentScene.AttachmentsModule != null) 1460 // Set the new attachment point data in the object
1386 m_parentScene.AttachmentsModule.UpdateAttachmentPosition(group, pos); 1461 byte attachmentPoint = group.GetAttachmentPoint();
1462 group.UpdateGroupPosition(pos);
1463 group.IsAttachment = false;
1464 group.AbsolutePosition = group.RootPart.AttachedPos;
1465 group.AttachmentPoint = attachmentPoint;
1466 group.HasGroupChanged = true;
1387 } 1467 }
1388 else 1468 else
1389 { 1469 {
@@ -1655,8 +1735,11 @@ namespace OpenSim.Region.Framework.Scenes
1655 return; 1735 return;
1656 1736
1657 Monitor.Enter(m_updateLock); 1737 Monitor.Enter(m_updateLock);
1738
1658 try 1739 try
1659 { 1740 {
1741 parentGroup.areUpdatesSuspended = true;
1742
1660 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); 1743 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
1661 1744
1662 // We do this in reverse to get the link order of the prims correct 1745 // We do this in reverse to get the link order of the prims correct
@@ -1667,9 +1750,13 @@ namespace OpenSim.Region.Framework.Scenes
1667 // Make sure no child prim is set for sale 1750 // Make sure no child prim is set for sale
1668 // So that, on delink, no prims are unwittingly 1751 // So that, on delink, no prims are unwittingly
1669 // left for sale and sold off 1752 // left for sale and sold off
1670 child.RootPart.ObjectSaleType = 0; 1753
1671 child.RootPart.SalePrice = 10; 1754 if (child != null)
1672 childGroups.Add(child); 1755 {
1756 child.RootPart.ObjectSaleType = 0;
1757 child.RootPart.SalePrice = 10;
1758 childGroups.Add(child);
1759 }
1673 } 1760 }
1674 1761
1675 foreach (SceneObjectGroup child in childGroups) 1762 foreach (SceneObjectGroup child in childGroups)
@@ -1688,12 +1775,19 @@ namespace OpenSim.Region.Framework.Scenes
1688 // occur on link to invoke this elsewhere (such as object selection) 1775 // occur on link to invoke this elsewhere (such as object selection)
1689 parentGroup.RootPart.CreateSelected = true; 1776 parentGroup.RootPart.CreateSelected = true;
1690 parentGroup.TriggerScriptChangedEvent(Changed.LINK); 1777 parentGroup.TriggerScriptChangedEvent(Changed.LINK);
1691 parentGroup.HasGroupChanged = true;
1692 parentGroup.ScheduleGroupForFullUpdate();
1693
1694 } 1778 }
1695 finally 1779 finally
1696 { 1780 {
1781 lock (SceneObjectGroupsByLocalPartID)
1782 {
1783 foreach (SceneObjectPart part in parentGroup.Parts)
1784 SceneObjectGroupsByLocalPartID[part.LocalId] = parentGroup;
1785 }
1786
1787 parentGroup.areUpdatesSuspended = false;
1788 parentGroup.HasGroupChanged = true;
1789 parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true);
1790 parentGroup.ScheduleGroupForFullUpdate();
1697 Monitor.Exit(m_updateLock); 1791 Monitor.Exit(m_updateLock);
1698 } 1792 }
1699 } 1793 }
@@ -1730,21 +1824,24 @@ namespace OpenSim.Region.Framework.Scenes
1730 1824
1731 SceneObjectGroup group = part.ParentGroup; 1825 SceneObjectGroup group = part.ParentGroup;
1732 if (!affectedGroups.Contains(group)) 1826 if (!affectedGroups.Contains(group))
1827 {
1828 group.areUpdatesSuspended = true;
1733 affectedGroups.Add(group); 1829 affectedGroups.Add(group);
1830 }
1734 } 1831 }
1735 } 1832 }
1736 } 1833 }
1737 1834
1738 foreach (SceneObjectPart child in childParts) 1835 if (childParts.Count > 0)
1739 { 1836 {
1740 // Unlink all child parts from their groups 1837 foreach (SceneObjectPart child in childParts)
1741 // 1838 {
1742 child.ParentGroup.DelinkFromGroup(child, true); 1839 // Unlink all child parts from their groups
1743 1840 //
1744 // These are not in affected groups and will not be 1841 child.ParentGroup.DelinkFromGroup(child, true);
1745 // handled further. Do the honors here. 1842 child.ParentGroup.HasGroupChanged = true;
1746 child.ParentGroup.HasGroupChanged = true; 1843 child.ParentGroup.ScheduleGroupForFullUpdate();
1747 child.ParentGroup.ScheduleGroupForFullUpdate(); 1844 }
1748 } 1845 }
1749 1846
1750 foreach (SceneObjectPart root in rootParts) 1847 foreach (SceneObjectPart root in rootParts)
@@ -1754,56 +1851,68 @@ namespace OpenSim.Region.Framework.Scenes
1754 // However, editing linked parts and unlinking may be different 1851 // However, editing linked parts and unlinking may be different
1755 // 1852 //
1756 SceneObjectGroup group = root.ParentGroup; 1853 SceneObjectGroup group = root.ParentGroup;
1854 group.areUpdatesSuspended = true;
1757 1855
1758 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); 1856 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts);
1759 int numChildren = newSet.Count; 1857 int numChildren = newSet.Count;
1760 1858
1859 if (numChildren == 1)
1860 break;
1861
1761 // If there are prims left in a link set, but the root is 1862 // If there are prims left in a link set, but the root is
1762 // slated for unlink, we need to do this 1863 // slated for unlink, we need to do this
1864 // Unlink the remaining set
1763 // 1865 //
1764 if (numChildren != 1) 1866 bool sendEventsToRemainder = true;
1765 { 1867 if (numChildren > 1)
1766 // Unlink the remaining set 1868 sendEventsToRemainder = false;
1767 //
1768 bool sendEventsToRemainder = true;
1769 if (numChildren > 1)
1770 sendEventsToRemainder = false;
1771 1869
1772 foreach (SceneObjectPart p in newSet) 1870 foreach (SceneObjectPart p in newSet)
1871 {
1872 if (p != group.RootPart)
1773 { 1873 {
1774 if (p != group.RootPart) 1874 group.DelinkFromGroup(p, sendEventsToRemainder);
1775 group.DelinkFromGroup(p, sendEventsToRemainder); 1875 if (numChildren > 2)
1876 {
1877 p.ParentGroup.areUpdatesSuspended = true;
1878 }
1879 else
1880 {
1881 p.ParentGroup.HasGroupChanged = true;
1882 p.ParentGroup.ScheduleGroupForFullUpdate();
1883 }
1776 } 1884 }
1885 }
1886
1887 // If there is more than one prim remaining, we
1888 // need to re-link
1889 //
1890 if (numChildren > 2)
1891 {
1892 // Remove old root
1893 //
1894 if (newSet.Contains(root))
1895 newSet.Remove(root);
1777 1896
1778 // If there is more than one prim remaining, we 1897 // Preserve link ordering
1779 // need to re-link
1780 // 1898 //
1781 if (numChildren > 2) 1899 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1782 { 1900 {
1783 // Remove old root 1901 return a.LinkNum.CompareTo(b.LinkNum);
1784 // 1902 });
1785 if (newSet.Contains(root))
1786 newSet.Remove(root);
1787
1788 // Preserve link ordering
1789 //
1790 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1791 {
1792 return a.LinkNum.CompareTo(b.LinkNum);
1793 });
1794 1903
1795 // Determine new root 1904 // Determine new root
1796 // 1905 //
1797 SceneObjectPart newRoot = newSet[0]; 1906 SceneObjectPart newRoot = newSet[0];
1798 newSet.RemoveAt(0); 1907 newSet.RemoveAt(0);
1799 1908
1800 foreach (SceneObjectPart newChild in newSet) 1909 foreach (SceneObjectPart newChild in newSet)
1801 newChild.ClearUpdateSchedule(); 1910 newChild.ClearUpdateSchedule();
1802 1911
1803 LinkObjects(newRoot, newSet); 1912 newRoot.ParentGroup.areUpdatesSuspended = true;
1804 if (!affectedGroups.Contains(newRoot.ParentGroup)) 1913 LinkObjects(newRoot, newSet);
1805 affectedGroups.Add(newRoot.ParentGroup); 1914 if (!affectedGroups.Contains(newRoot.ParentGroup))
1806 } 1915 affectedGroups.Add(newRoot.ParentGroup);
1807 } 1916 }
1808 } 1917 }
1809 1918
@@ -1811,8 +1920,14 @@ namespace OpenSim.Region.Framework.Scenes
1811 // 1920 //
1812 foreach (SceneObjectGroup g in affectedGroups) 1921 foreach (SceneObjectGroup g in affectedGroups)
1813 { 1922 {
1923 // Child prims that have been unlinked and deleted will
1924 // return unless the root is deleted. This will remove them
1925 // from the database. They will be rewritten immediately,
1926 // minus the rows for the unlinked child prims.
1927 m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID);
1814 g.TriggerScriptChangedEvent(Changed.LINK); 1928 g.TriggerScriptChangedEvent(Changed.LINK);
1815 g.HasGroupChanged = true; // Persist 1929 g.HasGroupChanged = true; // Persist
1930 g.areUpdatesSuspended = false;
1816 g.ScheduleGroupForFullUpdate(); 1931 g.ScheduleGroupForFullUpdate();
1817 } 1932 }
1818 } 1933 }
@@ -1930,9 +2045,6 @@ namespace OpenSim.Region.Framework.Scenes
1930 child.ApplyNextOwnerPermissions(); 2045 child.ApplyNextOwnerPermissions();
1931 } 2046 }
1932 } 2047 }
1933
1934 copy.RootPart.ObjectSaleType = 0;
1935 copy.RootPart.SalePrice = 10;
1936 } 2048 }
1937 2049
1938 // FIXME: This section needs to be refactored so that it just calls AddSceneObject() 2050 // FIXME: This section needs to be refactored so that it just calls AddSceneObject()
diff --git a/OpenSim/Region/Framework/Scenes/SceneManager.cs b/OpenSim/Region/Framework/Scenes/SceneManager.cs
index d73a959..e4eaf3a 100644
--- a/OpenSim/Region/Framework/Scenes/SceneManager.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneManager.cs
@@ -356,7 +356,7 @@ namespace OpenSim.Region.Framework.Scenes
356 356
357 public bool TrySetCurrentScene(UUID regionID) 357 public bool TrySetCurrentScene(UUID regionID)
358 { 358 {
359 m_log.Debug("Searching for Region: '" + regionID + "'"); 359// m_log.Debug("Searching for Region: '" + regionID + "'");
360 360
361 lock (m_localScenes) 361 lock (m_localScenes)
362 { 362 {
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
index 905ecc9..c7da4f4 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
@@ -69,10 +69,6 @@ namespace OpenSim.Region.Framework.Scenes
69 /// <summary> 69 /// <summary>
70 /// Stop the scripts contained in all the prims in this group 70 /// Stop the scripts contained in all the prims in this group
71 /// </summary> 71 /// </summary>
72 /// <param name="sceneObjectBeingDeleted">
73 /// Should be true if these scripts are being removed because the scene
74 /// object is being deleted. This will prevent spurious updates to the client.
75 /// </param>
76 public void RemoveScriptInstances(bool sceneObjectBeingDeleted) 72 public void RemoveScriptInstances(bool sceneObjectBeingDeleted)
77 { 73 {
78 SceneObjectPart[] parts = m_parts.GetArray(); 74 SceneObjectPart[] parts = m_parts.GetArray();
@@ -234,6 +230,11 @@ namespace OpenSim.Region.Framework.Scenes
234 230
235 public uint GetEffectivePermissions() 231 public uint GetEffectivePermissions()
236 { 232 {
233 return GetEffectivePermissions(false);
234 }
235
236 public uint GetEffectivePermissions(bool useBase)
237 {
237 uint perms=(uint)(PermissionMask.Modify | 238 uint perms=(uint)(PermissionMask.Modify |
238 PermissionMask.Copy | 239 PermissionMask.Copy |
239 PermissionMask.Move | 240 PermissionMask.Move |
@@ -245,7 +246,10 @@ namespace OpenSim.Region.Framework.Scenes
245 for (int i = 0; i < parts.Length; i++) 246 for (int i = 0; i < parts.Length; i++)
246 { 247 {
247 SceneObjectPart part = parts[i]; 248 SceneObjectPart part = parts[i];
248 ownerMask &= part.OwnerMask; 249 if (useBase)
250 ownerMask &= part.BaseMask;
251 else
252 ownerMask &= part.OwnerMask;
249 perms &= part.Inventory.MaskEffectivePermissions(); 253 perms &= part.Inventory.MaskEffectivePermissions();
250 } 254 }
251 255
@@ -385,6 +389,9 @@ namespace OpenSim.Region.Framework.Scenes
385 389
386 public void ResumeScripts() 390 public void ResumeScripts()
387 { 391 {
392 if (m_scene.RegionInfo.RegionSettings.DisableScripts)
393 return;
394
388 SceneObjectPart[] parts = m_parts.GetArray(); 395 SceneObjectPart[] parts = m_parts.GetArray();
389 for (int i = 0; i < parts.Length; i++) 396 for (int i = 0; i < parts.Length; i++)
390 parts[i].Inventory.ResumeScripts(); 397 parts[i].Inventory.ResumeScripts();
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index abea788..948dca2 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();
@@ -686,6 +789,10 @@ namespace OpenSim.Region.Framework.Scenes
686 EntityIntersection result = new EntityIntersection(); 789 EntityIntersection result = new EntityIntersection();
687 790
688 SceneObjectPart[] parts = m_parts.GetArray(); 791 SceneObjectPart[] parts = m_parts.GetArray();
792
793 // Find closest hit here
794 float idist = float.MaxValue;
795
689 for (int i = 0; i < parts.Length; i++) 796 for (int i = 0; i < parts.Length; i++)
690 { 797 {
691 SceneObjectPart part = parts[i]; 798 SceneObjectPart part = parts[i];
@@ -700,11 +807,6 @@ namespace OpenSim.Region.Framework.Scenes
700 807
701 EntityIntersection inter = part.TestIntersectionOBB(hRay, parentrotation, frontFacesOnly, faceCenters); 808 EntityIntersection inter = part.TestIntersectionOBB(hRay, parentrotation, frontFacesOnly, faceCenters);
702 809
703 // This may need to be updated to the maximum draw distance possible..
704 // We might (and probably will) be checking for prim creation from other sims
705 // when the camera crosses the border.
706 float idist = Constants.RegionSize;
707
708 if (inter.HitTF) 810 if (inter.HitTF)
709 { 811 {
710 // We need to find the closest prim to return to the testcaller along the ray 812 // We need to find the closest prim to return to the testcaller along the ray
@@ -715,10 +817,11 @@ namespace OpenSim.Region.Framework.Scenes
715 result.obj = part; 817 result.obj = part;
716 result.normal = inter.normal; 818 result.normal = inter.normal;
717 result.distance = inter.distance; 819 result.distance = inter.distance;
820
821 idist = inter.distance;
718 } 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);
@@ -1416,7 +1767,7 @@ namespace OpenSim.Region.Framework.Scenes
1416 // This is only necessary when userExposed is false! 1767 // This is only necessary when userExposed is false!
1417 1768
1418 bool previousAttachmentStatus = dupe.IsAttachment; 1769 bool previousAttachmentStatus = dupe.IsAttachment;
1419 1770
1420 if (!userExposed) 1771 if (!userExposed)
1421 dupe.IsAttachment = true; 1772 dupe.IsAttachment = true;
1422 1773
@@ -1434,11 +1785,11 @@ namespace OpenSim.Region.Framework.Scenes
1434 dupe.m_rootPart.TrimPermissions(); 1785 dupe.m_rootPart.TrimPermissions();
1435 1786
1436 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray()); 1787 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray());
1437 1788
1438 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) 1789 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1439 { 1790 {
1440 return p1.LinkNum.CompareTo(p2.LinkNum); 1791 return p1.LinkNum.CompareTo(p2.LinkNum);
1441 } 1792 }
1442 ); 1793 );
1443 1794
1444 foreach (SceneObjectPart part in partList) 1795 foreach (SceneObjectPart part in partList)
@@ -1458,7 +1809,7 @@ namespace OpenSim.Region.Framework.Scenes
1458 if (part.PhysActor != null && userExposed) 1809 if (part.PhysActor != null && userExposed)
1459 { 1810 {
1460 PrimitiveBaseShape pbs = newPart.Shape; 1811 PrimitiveBaseShape pbs = newPart.Shape;
1461 1812
1462 newPart.PhysActor 1813 newPart.PhysActor
1463 = m_scene.PhysicsScene.AddPrimShape( 1814 = m_scene.PhysicsScene.AddPrimShape(
1464 string.Format("{0}/{1}", newPart.Name, newPart.UUID), 1815 string.Format("{0}/{1}", newPart.Name, newPart.UUID),
@@ -1468,11 +1819,11 @@ namespace OpenSim.Region.Framework.Scenes
1468 newPart.RotationOffset, 1819 newPart.RotationOffset,
1469 part.PhysActor.IsPhysical, 1820 part.PhysActor.IsPhysical,
1470 newPart.LocalId); 1821 newPart.LocalId);
1471 1822
1472 newPart.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true); 1823 newPart.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true);
1473 } 1824 }
1474 } 1825 }
1475 1826
1476 if (userExposed) 1827 if (userExposed)
1477 { 1828 {
1478 dupe.UpdateParentIDs(); 1829 dupe.UpdateParentIDs();
@@ -1587,6 +1938,7 @@ namespace OpenSim.Region.Framework.Scenes
1587 return Vector3.Zero; 1938 return Vector3.Zero;
1588 } 1939 }
1589 1940
1941 // This is used by both Double-Click Auto-Pilot and llMoveToTarget() in an attached object
1590 public void moveToTarget(Vector3 target, float tau) 1942 public void moveToTarget(Vector3 target, float tau)
1591 { 1943 {
1592 if (IsAttachment) 1944 if (IsAttachment)
@@ -1614,10 +1966,44 @@ namespace OpenSim.Region.Framework.Scenes
1614 RootPart.PhysActor.PIDActive = false; 1966 RootPart.PhysActor.PIDActive = false;
1615 } 1967 }
1616 1968
1969 public void rotLookAt(Quaternion target, float strength, float damping)
1970 {
1971 SceneObjectPart rootpart = m_rootPart;
1972 if (rootpart != null)
1973 {
1974 if (IsAttachment)
1975 {
1976 /*
1977 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
1978 if (avatar != null)
1979 {
1980 Rotate the Av?
1981 } */
1982 }
1983 else
1984 {
1985 if (rootpart.PhysActor != null)
1986 { // APID must be implemented in your physics system for this to function.
1987 rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W);
1988 rootpart.PhysActor.APIDStrength = strength;
1989 rootpart.PhysActor.APIDDamping = damping;
1990 rootpart.PhysActor.APIDActive = true;
1991 }
1992 }
1993 }
1994 }
1995
1617 public void stopLookAt() 1996 public void stopLookAt()
1618 { 1997 {
1619 if (RootPart.PhysActor != null) 1998 SceneObjectPart rootpart = m_rootPart;
1620 RootPart.PhysActor.APIDActive = false; 1999 if (rootpart != null)
2000 {
2001 if (rootpart.PhysActor != null)
2002 { // APID must be implemented in your physics system for this to function.
2003 rootpart.PhysActor.APIDActive = false;
2004 }
2005 }
2006
1621 } 2007 }
1622 2008
1623 /// <summary> 2009 /// <summary>
@@ -1675,6 +2061,8 @@ namespace OpenSim.Region.Framework.Scenes
1675 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) 2061 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
1676 { 2062 {
1677 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 2063 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
2064 newPart.SetParent(this);
2065
1678 AddPart(newPart); 2066 AddPart(newPart);
1679 2067
1680 SetPartAsNonRoot(newPart); 2068 SetPartAsNonRoot(newPart);
@@ -1803,11 +2191,11 @@ namespace OpenSim.Region.Framework.Scenes
1803 /// Immediately send a full update for this scene object. 2191 /// Immediately send a full update for this scene object.
1804 /// </summary> 2192 /// </summary>
1805 public void SendGroupFullUpdate() 2193 public void SendGroupFullUpdate()
1806 { 2194 {
1807 if (IsDeleted) 2195 if (IsDeleted)
1808 return; 2196 return;
1809 2197
1810// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); 2198// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID);
1811 2199
1812 RootPart.SendFullUpdateToAllClients(); 2200 RootPart.SendFullUpdateToAllClients();
1813 2201
@@ -2008,7 +2396,7 @@ namespace OpenSim.Region.Framework.Scenes
2008 objectGroup.IsDeleted = true; 2396 objectGroup.IsDeleted = true;
2009 2397
2010 objectGroup.m_parts.Clear(); 2398 objectGroup.m_parts.Clear();
2011 2399
2012 // Can't do this yet since backup still makes use of the root part without any synchronization 2400 // Can't do this yet since backup still makes use of the root part without any synchronization
2013// objectGroup.m_rootPart = null; 2401// objectGroup.m_rootPart = null;
2014 2402
@@ -2142,6 +2530,7 @@ namespace OpenSim.Region.Framework.Scenes
2142 /// <param name="objectGroup"></param> 2530 /// <param name="objectGroup"></param>
2143 public virtual void DetachFromBackup() 2531 public virtual void DetachFromBackup()
2144 { 2532 {
2533 m_scene.SceneGraph.FireDetachFromBackup(this);
2145 if (m_isBackedUp && Scene != null) 2534 if (m_isBackedUp && Scene != null)
2146 m_scene.EventManager.OnBackup -= ProcessBackup; 2535 m_scene.EventManager.OnBackup -= ProcessBackup;
2147 2536
@@ -2160,7 +2549,8 @@ namespace OpenSim.Region.Framework.Scenes
2160 2549
2161 axPos *= parentRot; 2550 axPos *= parentRot;
2162 part.OffsetPosition = axPos; 2551 part.OffsetPosition = axPos;
2163 part.GroupPosition = oldGroupPosition + part.OffsetPosition; 2552 Vector3 newPos = oldGroupPosition + part.OffsetPosition;
2553 part.GroupPosition = newPos;
2164 part.OffsetPosition = Vector3.Zero; 2554 part.OffsetPosition = Vector3.Zero;
2165 part.RotationOffset = worldRot; 2555 part.RotationOffset = worldRot;
2166 2556
@@ -2171,7 +2561,7 @@ namespace OpenSim.Region.Framework.Scenes
2171 2561
2172 part.LinkNum = linkNum; 2562 part.LinkNum = linkNum;
2173 2563
2174 part.OffsetPosition = part.GroupPosition - AbsolutePosition; 2564 part.OffsetPosition = newPos - AbsolutePosition;
2175 2565
2176 Quaternion rootRotation = m_rootPart.RotationOffset; 2566 Quaternion rootRotation = m_rootPart.RotationOffset;
2177 2567
@@ -2181,7 +2571,7 @@ namespace OpenSim.Region.Framework.Scenes
2181 2571
2182 parentRot = m_rootPart.RotationOffset; 2572 parentRot = m_rootPart.RotationOffset;
2183 oldRot = part.RotationOffset; 2573 oldRot = part.RotationOffset;
2184 Quaternion newRot = Quaternion.Inverse(parentRot) * oldRot; 2574 Quaternion newRot = Quaternion.Inverse(parentRot) * worldRot;
2185 part.RotationOffset = newRot; 2575 part.RotationOffset = newRot;
2186 } 2576 }
2187 2577
@@ -2428,8 +2818,12 @@ namespace OpenSim.Region.Framework.Scenes
2428 } 2818 }
2429 } 2819 }
2430 2820
2821 RootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect);
2431 for (int i = 0; i < parts.Length; i++) 2822 for (int i = 0; i < parts.Length; i++)
2432 parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect); 2823 {
2824 if (parts[i] != RootPart)
2825 parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect);
2826 }
2433 } 2827 }
2434 } 2828 }
2435 2829
@@ -2442,6 +2836,17 @@ namespace OpenSim.Region.Framework.Scenes
2442 } 2836 }
2443 } 2837 }
2444 2838
2839
2840
2841 /// <summary>
2842 /// Gets the number of parts
2843 /// </summary>
2844 /// <returns></returns>
2845 public int GetPartCount()
2846 {
2847 return Parts.Count();
2848 }
2849
2445 /// <summary> 2850 /// <summary>
2446 /// Update the texture entry for this part 2851 /// Update the texture entry for this part
2447 /// </summary> 2852 /// </summary>
@@ -2503,7 +2908,6 @@ namespace OpenSim.Region.Framework.Scenes
2503 { 2908 {
2504// m_log.DebugFormat( 2909// m_log.DebugFormat(
2505// "[SCENE OBJECT GROUP]: Group resizing {0} {1} from {2} to {3}", Name, LocalId, RootPart.Scale, scale); 2910// "[SCENE OBJECT GROUP]: Group resizing {0} {1} from {2} to {3}", Name, LocalId, RootPart.Scale, scale);
2506
2507 RootPart.StoreUndoState(true); 2911 RootPart.StoreUndoState(true);
2508 2912
2509 scale.X = Math.Min(scale.X, Scene.m_maxNonphys); 2913 scale.X = Math.Min(scale.X, Scene.m_maxNonphys);
@@ -2604,7 +3008,6 @@ namespace OpenSim.Region.Framework.Scenes
2604 prevScale.X *= x; 3008 prevScale.X *= x;
2605 prevScale.Y *= y; 3009 prevScale.Y *= y;
2606 prevScale.Z *= z; 3010 prevScale.Z *= z;
2607
2608// RootPart.IgnoreUndoUpdate = true; 3011// RootPart.IgnoreUndoUpdate = true;
2609 RootPart.Resize(prevScale); 3012 RootPart.Resize(prevScale);
2610// RootPart.IgnoreUndoUpdate = false; 3013// RootPart.IgnoreUndoUpdate = false;
@@ -2635,7 +3038,9 @@ namespace OpenSim.Region.Framework.Scenes
2635 } 3038 }
2636 3039
2637// obPart.IgnoreUndoUpdate = false; 3040// obPart.IgnoreUndoUpdate = false;
2638// obPart.StoreUndoState(); 3041 HasGroupChanged = true;
3042 m_rootPart.TriggerScriptChangedEvent(Changed.SCALE);
3043 ScheduleGroupForTerseUpdate();
2639 } 3044 }
2640 3045
2641// m_log.DebugFormat( 3046// m_log.DebugFormat(
@@ -2695,9 +3100,9 @@ namespace OpenSim.Region.Framework.Scenes
2695 { 3100 {
2696 SceneObjectPart part = GetChildPart(localID); 3101 SceneObjectPart part = GetChildPart(localID);
2697 3102
2698// SceneObjectPart[] parts = m_parts.GetArray(); 3103 SceneObjectPart[] parts = m_parts.GetArray();
2699// for (int i = 0; i < parts.Length; i++) 3104 for (int i = 0; i < parts.Length; i++)
2700// parts[i].StoreUndoState(); 3105 parts[i].StoreUndoState();
2701 3106
2702 if (part != null) 3107 if (part != null)
2703 { 3108 {
@@ -2753,10 +3158,27 @@ namespace OpenSim.Region.Framework.Scenes
2753 obPart.OffsetPosition = obPart.OffsetPosition + diff; 3158 obPart.OffsetPosition = obPart.OffsetPosition + diff;
2754 } 3159 }
2755 3160
2756 AbsolutePosition = newPos; 3161 //We have to set undoing here because otherwise an undo state will be saved
3162 if (!m_rootPart.Undoing)
3163 {
3164 m_rootPart.Undoing = true;
3165 AbsolutePosition = newPos;
3166 m_rootPart.Undoing = false;
3167 }
3168 else
3169 {
3170 AbsolutePosition = newPos;
3171 }
2757 3172
2758 HasGroupChanged = true; 3173 HasGroupChanged = true;
2759 ScheduleGroupForTerseUpdate(); 3174 if (m_rootPart.Undoing)
3175 {
3176 ScheduleGroupForFullUpdate();
3177 }
3178 else
3179 {
3180 ScheduleGroupForTerseUpdate();
3181 }
2760 } 3182 }
2761 3183
2762 #endregion 3184 #endregion
@@ -2833,10 +3255,7 @@ namespace OpenSim.Region.Framework.Scenes
2833 public void UpdateSingleRotation(Quaternion rot, uint localID) 3255 public void UpdateSingleRotation(Quaternion rot, uint localID)
2834 { 3256 {
2835 SceneObjectPart part = GetChildPart(localID); 3257 SceneObjectPart part = GetChildPart(localID);
2836
2837 SceneObjectPart[] parts = m_parts.GetArray(); 3258 SceneObjectPart[] parts = m_parts.GetArray();
2838 for (int i = 0; i < parts.Length; i++)
2839 parts[i].StoreUndoState();
2840 3259
2841 if (part != null) 3260 if (part != null)
2842 { 3261 {
@@ -2874,7 +3293,16 @@ namespace OpenSim.Region.Framework.Scenes
2874 if (part.UUID == m_rootPart.UUID) 3293 if (part.UUID == m_rootPart.UUID)
2875 { 3294 {
2876 UpdateRootRotation(rot); 3295 UpdateRootRotation(rot);
2877 AbsolutePosition = pos; 3296 if (!m_rootPart.Undoing)
3297 {
3298 m_rootPart.Undoing = true;
3299 AbsolutePosition = pos;
3300 m_rootPart.Undoing = false;
3301 }
3302 else
3303 {
3304 AbsolutePosition = pos;
3305 }
2878 } 3306 }
2879 else 3307 else
2880 { 3308 {
@@ -2898,9 +3326,10 @@ namespace OpenSim.Region.Framework.Scenes
2898 3326
2899 Quaternion axRot = rot; 3327 Quaternion axRot = rot;
2900 Quaternion oldParentRot = m_rootPart.RotationOffset; 3328 Quaternion oldParentRot = m_rootPart.RotationOffset;
2901
2902 m_rootPart.StoreUndoState(); 3329 m_rootPart.StoreUndoState();
2903 m_rootPart.UpdateRotation(rot); 3330
3331 //Don't use UpdateRotation because it schedules an update prematurely
3332 m_rootPart.RotationOffset = rot;
2904 if (m_rootPart.PhysActor != null) 3333 if (m_rootPart.PhysActor != null)
2905 { 3334 {
2906 m_rootPart.PhysActor.Orientation = m_rootPart.RotationOffset; 3335 m_rootPart.PhysActor.Orientation = m_rootPart.RotationOffset;
@@ -2914,15 +3343,17 @@ namespace OpenSim.Region.Framework.Scenes
2914 if (prim.UUID != m_rootPart.UUID) 3343 if (prim.UUID != m_rootPart.UUID)
2915 { 3344 {
2916 prim.IgnoreUndoUpdate = true; 3345 prim.IgnoreUndoUpdate = true;
3346
3347 Quaternion NewRot = oldParentRot * prim.RotationOffset;
3348 NewRot = Quaternion.Inverse(axRot) * NewRot;
3349 prim.RotationOffset = NewRot;
3350
2917 Vector3 axPos = prim.OffsetPosition; 3351 Vector3 axPos = prim.OffsetPosition;
3352
2918 axPos *= oldParentRot; 3353 axPos *= oldParentRot;
2919 axPos *= Quaternion.Inverse(axRot); 3354 axPos *= Quaternion.Inverse(axRot);
2920 prim.OffsetPosition = axPos; 3355 prim.OffsetPosition = axPos;
2921 Quaternion primsRot = prim.RotationOffset; 3356
2922 Quaternion newRot = oldParentRot * primsRot;
2923 newRot = Quaternion.Inverse(axRot) * newRot;
2924 prim.RotationOffset = newRot;
2925 prim.ScheduleTerseUpdate();
2926 prim.IgnoreUndoUpdate = false; 3357 prim.IgnoreUndoUpdate = false;
2927 } 3358 }
2928 } 3359 }
@@ -2936,8 +3367,8 @@ namespace OpenSim.Region.Framework.Scenes
2936//// childpart.StoreUndoState(); 3367//// childpart.StoreUndoState();
2937// } 3368// }
2938// } 3369// }
2939 3370 HasGroupChanged = true;
2940 m_rootPart.ScheduleTerseUpdate(); 3371 ScheduleGroupForFullUpdate();
2941 3372
2942// m_log.DebugFormat( 3373// m_log.DebugFormat(
2943// "[SCENE OBJECT GROUP]: Updated root rotation of {0} {1} to {2}", 3374// "[SCENE OBJECT GROUP]: Updated root rotation of {0} {1} to {2}",
@@ -3165,7 +3596,6 @@ namespace OpenSim.Region.Framework.Scenes
3165 public float GetMass() 3596 public float GetMass()
3166 { 3597 {
3167 float retmass = 0f; 3598 float retmass = 0f;
3168
3169 SceneObjectPart[] parts = m_parts.GetArray(); 3599 SceneObjectPart[] parts = m_parts.GetArray();
3170 for (int i = 0; i < parts.Length; i++) 3600 for (int i = 0; i < parts.Length; i++)
3171 retmass += parts[i].GetMass(); 3601 retmass += parts[i].GetMass();
@@ -3261,6 +3691,14 @@ namespace OpenSim.Region.Framework.Scenes
3261 SetFromItemID(uuid); 3691 SetFromItemID(uuid);
3262 } 3692 }
3263 3693
3694 public void ResetOwnerChangeFlag()
3695 {
3696 ForEachPart(delegate(SceneObjectPart part)
3697 {
3698 part.ResetOwnerChangeFlag();
3699 });
3700 }
3701
3264 #endregion 3702 #endregion
3265 } 3703 }
3266} 3704}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index b29ecc6..fd70bfd 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -62,7 +62,8 @@ namespace OpenSim.Region.Framework.Scenes
62 TELEPORT = 512, 62 TELEPORT = 512,
63 REGION_RESTART = 1024, 63 REGION_RESTART = 1024,
64 MEDIA = 2048, 64 MEDIA = 2048,
65 ANIMATION = 16384 65 ANIMATION = 16384,
66 POSITION = 32768
66 } 67 }
67 68
68 // I don't really know where to put this except here. 69 // I don't really know where to put this except here.
@@ -184,6 +185,15 @@ namespace OpenSim.Region.Framework.Scenes
184 185
185 public UUID FromFolderID; 186 public UUID FromFolderID;
186 187
188 // The following two are to hold the attachment data
189 // while an object is inworld
190 [XmlIgnore]
191 public byte AttachPoint = 0;
192
193 [XmlIgnore]
194 public Vector3 AttachOffset = Vector3.Zero;
195
196 [XmlIgnore]
187 public int STATUS_ROTATE_X; 197 public int STATUS_ROTATE_X;
188 198
189 public int STATUS_ROTATE_Y; 199 public int STATUS_ROTATE_Y;
@@ -210,8 +220,7 @@ namespace OpenSim.Region.Framework.Scenes
210 220
211 public Vector3 RotationAxis = Vector3.One; 221 public Vector3 RotationAxis = Vector3.One;
212 222
213 public bool VolumeDetectActive; // XmlIgnore set to avoid problems with persistance until I come to care for this 223 public bool VolumeDetectActive;
214 // Certainly this must be a persistant setting finally
215 224
216 public bool IsWaitingForFirstSpinUpdatePacket; 225 public bool IsWaitingForFirstSpinUpdatePacket;
217 226
@@ -252,6 +261,7 @@ namespace OpenSim.Region.Framework.Scenes
252 private Quaternion m_sitTargetOrientation = Quaternion.Identity; 261 private Quaternion m_sitTargetOrientation = Quaternion.Identity;
253 private Vector3 m_sitTargetPosition; 262 private Vector3 m_sitTargetPosition;
254 private string m_sitAnimation = "SIT"; 263 private string m_sitAnimation = "SIT";
264 private bool m_occupied; // KF if any av is sitting on this prim
255 private string m_text = String.Empty; 265 private string m_text = String.Empty;
256 private string m_touchName = String.Empty; 266 private string m_touchName = String.Empty;
257 private readonly Stack<UndoState> m_undo = new Stack<UndoState>(5); 267 private readonly Stack<UndoState> m_undo = new Stack<UndoState>(5);
@@ -284,6 +294,7 @@ namespace OpenSim.Region.Framework.Scenes
284 protected Vector3 m_lastAcceleration; 294 protected Vector3 m_lastAcceleration;
285 protected Vector3 m_lastAngularVelocity; 295 protected Vector3 m_lastAngularVelocity;
286 protected int m_lastTerseSent; 296 protected int m_lastTerseSent;
297 protected float m_buoyancy = 0.0f;
287 298
288 /// <summary> 299 /// <summary>
289 /// Stores media texture data 300 /// Stores media texture data
@@ -339,7 +350,7 @@ namespace OpenSim.Region.Framework.Scenes
339 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition, 350 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition,
340 Quaternion rotationOffset, Vector3 offsetPosition) : this() 351 Quaternion rotationOffset, Vector3 offsetPosition) : this()
341 { 352 {
342 m_name = "Primitive"; 353 m_name = "Object";
343 354
344 CreationDate = (int)Utils.DateTimeToUnixTime(Rezzed); 355 CreationDate = (int)Utils.DateTimeToUnixTime(Rezzed);
345 LastOwnerID = CreatorID = OwnerID = ownerID; 356 LastOwnerID = CreatorID = OwnerID = ownerID;
@@ -379,7 +390,7 @@ namespace OpenSim.Region.Framework.Scenes
379 private uint _ownerMask = (uint)PermissionMask.All; 390 private uint _ownerMask = (uint)PermissionMask.All;
380 private uint _groupMask = (uint)PermissionMask.None; 391 private uint _groupMask = (uint)PermissionMask.None;
381 private uint _everyoneMask = (uint)PermissionMask.None; 392 private uint _everyoneMask = (uint)PermissionMask.None;
382 private uint _nextOwnerMask = (uint)PermissionMask.All; 393 private uint _nextOwnerMask = (uint)(PermissionMask.Move | PermissionMask.Modify | PermissionMask.Transfer);
383 private PrimFlags _flags = PrimFlags.None; 394 private PrimFlags _flags = PrimFlags.None;
384 private DateTime m_expires; 395 private DateTime m_expires;
385 private DateTime m_rezzed; 396 private DateTime m_rezzed;
@@ -473,12 +484,16 @@ namespace OpenSim.Region.Framework.Scenes
473 } 484 }
474 485
475 /// <value> 486 /// <value>
476 /// Access should be via Inventory directly - this property temporarily remains for xml serialization purposes 487 /// Get the inventory list
477 /// </value> 488 /// </value>
478 public TaskInventoryDictionary TaskInventory 489 public TaskInventoryDictionary TaskInventory
479 { 490 {
480 get { return m_inventory.Items; } 491 get {
481 set { m_inventory.Items = value; } 492 return m_inventory.Items;
493 }
494 set {
495 m_inventory.Items = value;
496 }
482 } 497 }
483 498
484 /// <summary> 499 /// <summary>
@@ -623,14 +638,12 @@ namespace OpenSim.Region.Framework.Scenes
623 set { m_LoopSoundSlavePrims = value; } 638 set { m_LoopSoundSlavePrims = value; }
624 } 639 }
625 640
626
627 public Byte[] TextureAnimation 641 public Byte[] TextureAnimation
628 { 642 {
629 get { return m_TextureAnimation; } 643 get { return m_TextureAnimation; }
630 set { m_TextureAnimation = value; } 644 set { m_TextureAnimation = value; }
631 } 645 }
632 646
633
634 public Byte[] ParticleSystem 647 public Byte[] ParticleSystem
635 { 648 {
636 get { return m_particleSystem; } 649 get { return m_particleSystem; }
@@ -667,9 +680,11 @@ namespace OpenSim.Region.Framework.Scenes
667 { 680 {
668 // If this is a linkset, we don't want the physics engine mucking up our group position here. 681 // If this is a linkset, we don't want the physics engine mucking up our group position here.
669 PhysicsActor actor = PhysActor; 682 PhysicsActor actor = PhysActor;
670 if (actor != null && ParentID == 0) 683 if (ParentID == 0)
671 { 684 {
672 m_groupPosition = actor.Position; 685 if (actor != null)
686 m_groupPosition = actor.Position;
687 return m_groupPosition;
673 } 688 }
674 689
675 if (ParentGroup.IsAttachment) 690 if (ParentGroup.IsAttachment)
@@ -679,12 +694,14 @@ namespace OpenSim.Region.Framework.Scenes
679 return sp.AbsolutePosition; 694 return sp.AbsolutePosition;
680 } 695 }
681 696
697 // use root prim's group position. Physics may have updated it
698 if (ParentGroup.RootPart != this)
699 m_groupPosition = ParentGroup.RootPart.GroupPosition;
682 return m_groupPosition; 700 return m_groupPosition;
683 } 701 }
684 set 702 set
685 { 703 {
686 m_groupPosition = value; 704 m_groupPosition = value;
687
688 PhysicsActor actor = PhysActor; 705 PhysicsActor actor = PhysActor;
689 if (actor != null) 706 if (actor != null)
690 { 707 {
@@ -710,16 +727,6 @@ namespace OpenSim.Region.Framework.Scenes
710 m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message); 727 m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message);
711 } 728 }
712 } 729 }
713
714 // TODO if we decide to do sitting in a more SL compatible way (multiple avatars per prim), this has to be fixed, too
715 if (SitTargetAvatar != UUID.Zero)
716 {
717 ScenePresence avatar;
718 if (ParentGroup.Scene.TryGetScenePresence(SitTargetAvatar, out avatar))
719 {
720 avatar.ParentPosition = GetWorldPosition();
721 }
722 }
723 } 730 }
724 } 731 }
725 732
@@ -728,7 +735,7 @@ namespace OpenSim.Region.Framework.Scenes
728 get { return m_offsetPosition; } 735 get { return m_offsetPosition; }
729 set 736 set
730 { 737 {
731// StoreUndoState(); 738 Vector3 oldpos = m_offsetPosition;
732 m_offsetPosition = value; 739 m_offsetPosition = value;
733 740
734 if (ParentGroup != null && !ParentGroup.IsDeleted) 741 if (ParentGroup != null && !ParentGroup.IsDeleted)
@@ -743,7 +750,22 @@ namespace OpenSim.Region.Framework.Scenes
743 if (ParentGroup.Scene != null) 750 if (ParentGroup.Scene != null)
744 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 751 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
745 } 752 }
753
754 if (!m_parentGroup.m_dupeInProgress)
755 {
756 List<ScenePresence> avs = ParentGroup.GetLinkedAvatars();
757 foreach (ScenePresence av in avs)
758 {
759 if (av.ParentID == m_localId)
760 {
761 Vector3 offset = (m_offsetPosition - oldpos);
762 av.AbsolutePosition += offset;
763 av.SendAvatarDataToAllAgents();
764 }
765 }
766 }
746 } 767 }
768 TriggerScriptChangedEvent(Changed.POSITION);
747 } 769 }
748 } 770 }
749 771
@@ -892,7 +914,16 @@ namespace OpenSim.Region.Framework.Scenes
892 /// <summary></summary> 914 /// <summary></summary>
893 public Vector3 Acceleration 915 public Vector3 Acceleration
894 { 916 {
895 get { return m_acceleration; } 917 get
918 {
919 PhysicsActor actor = PhysActor;
920 if (actor != null)
921 {
922 m_acceleration = actor.Acceleration;
923 }
924 return m_acceleration;
925 }
926
896 set { m_acceleration = value; } 927 set { m_acceleration = value; }
897 } 928 }
898 929
@@ -1043,10 +1074,7 @@ namespace OpenSim.Region.Framework.Scenes
1043 { 1074 {
1044 get 1075 get
1045 { 1076 {
1046 if (ParentGroup.IsAttachment) 1077 return GroupPosition + (m_offsetPosition * ParentGroup.RootPart.RotationOffset);
1047 return GroupPosition;
1048
1049 return m_offsetPosition + m_groupPosition;
1050 } 1078 }
1051 } 1079 }
1052 1080
@@ -1216,6 +1244,13 @@ namespace OpenSim.Region.Framework.Scenes
1216 _flags = value; 1244 _flags = value;
1217 } 1245 }
1218 } 1246 }
1247
1248 [XmlIgnore]
1249 public bool IsOccupied // KF If an av is sittingon this prim
1250 {
1251 get { return m_occupied; }
1252 set { m_occupied = value; }
1253 }
1219 1254
1220 /// <summary> 1255 /// <summary>
1221 /// ID of the avatar that is sat on us. If there is no such avatar then is UUID.Zero 1256 /// ID of the avatar that is sat on us. If there is no such avatar then is UUID.Zero
@@ -1275,6 +1310,19 @@ namespace OpenSim.Region.Framework.Scenes
1275 set { m_collisionSoundVolume = value; } 1310 set { m_collisionSoundVolume = value; }
1276 } 1311 }
1277 1312
1313 public float Buoyancy
1314 {
1315 get { return m_buoyancy; }
1316 set
1317 {
1318 m_buoyancy = value;
1319 if (PhysActor != null)
1320 {
1321 PhysActor.Buoyancy = value;
1322 }
1323 }
1324 }
1325
1278 #endregion Public Properties with only Get 1326 #endregion Public Properties with only Get
1279 1327
1280 private uint ApplyMask(uint val, bool set, uint mask) 1328 private uint ApplyMask(uint val, bool set, uint mask)
@@ -1596,6 +1644,9 @@ namespace OpenSim.Region.Framework.Scenes
1596 1644
1597 // Move afterwards ResetIDs as it clears the localID 1645 // Move afterwards ResetIDs as it clears the localID
1598 dupe.LocalId = localID; 1646 dupe.LocalId = localID;
1647 if(dupe.PhysActor != null)
1648 dupe.PhysActor.LocalID = localID;
1649
1599 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated. 1650 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated.
1600 dupe.LastOwnerID = OwnerID; 1651 dupe.LastOwnerID = OwnerID;
1601 1652
@@ -1957,19 +2008,17 @@ namespace OpenSim.Region.Framework.Scenes
1957 public Vector3 GetWorldPosition() 2008 public Vector3 GetWorldPosition()
1958 { 2009 {
1959 Quaternion parentRot = ParentGroup.RootPart.RotationOffset; 2010 Quaternion parentRot = ParentGroup.RootPart.RotationOffset;
1960
1961 Vector3 axPos = OffsetPosition; 2011 Vector3 axPos = OffsetPosition;
1962
1963 axPos *= parentRot; 2012 axPos *= parentRot;
1964 Vector3 translationOffsetPosition = axPos; 2013 Vector3 translationOffsetPosition = axPos;
1965 2014 if(_parentID == 0)
1966// m_log.DebugFormat("[SCENE OBJECT PART]: Found group pos {0} for part {1}", GroupPosition, Name); 2015 {
1967 2016 return GroupPosition;
1968 Vector3 worldPos = GroupPosition + translationOffsetPosition; 2017 }
1969 2018 else
1970// m_log.DebugFormat("[SCENE OBJECT PART]: Found world pos {0} for part {1}", worldPos, Name); 2019 {
1971 2020 return ParentGroup.AbsolutePosition + translationOffsetPosition; //KF: Fix child prim position
1972 return worldPos; 2021 }
1973 } 2022 }
1974 2023
1975 /// <summary> 2024 /// <summary>
@@ -2607,17 +2656,18 @@ namespace OpenSim.Region.Framework.Scenes
2607 //Trys to fetch sound id from prim's inventory. 2656 //Trys to fetch sound id from prim's inventory.
2608 //Prim's inventory doesn't support non script items yet 2657 //Prim's inventory doesn't support non script items yet
2609 2658
2610 lock (TaskInventory) 2659 TaskInventory.LockItemsForRead(true);
2660
2661 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2611 { 2662 {
2612 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 2663 if (item.Value.Name == sound)
2613 { 2664 {
2614 if (item.Value.Name == sound) 2665 soundID = item.Value.ItemID;
2615 { 2666 break;
2616 soundID = item.Value.ItemID;
2617 break;
2618 }
2619 } 2667 }
2620 } 2668 }
2669
2670 TaskInventory.LockItemsForRead(false);
2621 } 2671 }
2622 2672
2623 ParentGroup.Scene.ForEachRootScenePresence(delegate(ScenePresence sp) 2673 ParentGroup.Scene.ForEachRootScenePresence(delegate(ScenePresence sp)
@@ -2700,7 +2750,7 @@ namespace OpenSim.Region.Framework.Scenes
2700 2750
2701 public void RotLookAt(Quaternion target, float strength, float damping) 2751 public void RotLookAt(Quaternion target, float strength, float damping)
2702 { 2752 {
2703 rotLookAt(target, strength, damping); 2753 m_parentGroup.rotLookAt(target, strength, damping); // This calls method in SceneObjectGroup.
2704 } 2754 }
2705 2755
2706 public void rotLookAt(Quaternion target, float strength, float damping) 2756 public void rotLookAt(Quaternion target, float strength, float damping)
@@ -2926,8 +2976,8 @@ namespace OpenSim.Region.Framework.Scenes
2926 { 2976 {
2927 const float ROTATION_TOLERANCE = 0.01f; 2977 const float ROTATION_TOLERANCE = 0.01f;
2928 const float VELOCITY_TOLERANCE = 0.001f; 2978 const float VELOCITY_TOLERANCE = 0.001f;
2929 const float POSITION_TOLERANCE = 0.05f; 2979 const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary
2930 const int TIME_MS_TOLERANCE = 3000; 2980 const int TIME_MS_TOLERANCE = 200; //llSetPos has a 200ms delay. This should NOT be 3 seconds.
2931 2981
2932 switch (UpdateFlag) 2982 switch (UpdateFlag)
2933 { 2983 {
@@ -2989,17 +3039,16 @@ namespace OpenSim.Region.Framework.Scenes
2989 if (!UUID.TryParse(sound, out soundID)) 3039 if (!UUID.TryParse(sound, out soundID))
2990 { 3040 {
2991 // search sound file from inventory 3041 // search sound file from inventory
2992 lock (TaskInventory) 3042 TaskInventory.LockItemsForRead(true);
3043 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2993 { 3044 {
2994 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 3045 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound)
2995 { 3046 {
2996 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound) 3047 soundID = item.Value.ItemID;
2997 { 3048 break;
2998 soundID = item.Value.ItemID;
2999 break;
3000 }
3001 } 3049 }
3002 } 3050 }
3051 TaskInventory.LockItemsForRead(false);
3003 } 3052 }
3004 3053
3005 if (soundID == UUID.Zero) 3054 if (soundID == UUID.Zero)
@@ -3473,10 +3522,10 @@ namespace OpenSim.Region.Framework.Scenes
3473 // TODO: May need to fix for group comparison 3522 // TODO: May need to fix for group comparison
3474 if (last.Compare(this)) 3523 if (last.Compare(this))
3475 { 3524 {
3476 // m_log.DebugFormat( 3525 // m_log.DebugFormat(
3477 // "[SCENE OBJECT PART]: Not storing undo for {0} {1} since current state is same as last undo state, initial stack size {2}", 3526 // "[SCENE OBJECT PART]: Not storing undo for {0} {1} since current state is same as last undo state, initial stack size {2}",
3478 // Name, LocalId, m_undo.Count); 3527 // Name, LocalId, m_undo.Count);
3479 3528
3480 return; 3529 return;
3481 } 3530 }
3482 } 3531 }
@@ -3489,29 +3538,29 @@ namespace OpenSim.Region.Framework.Scenes
3489 if (ParentGroup.GetSceneMaxUndo() > 0) 3538 if (ParentGroup.GetSceneMaxUndo() > 0)
3490 { 3539 {
3491 UndoState nUndo = new UndoState(this, forGroup); 3540 UndoState nUndo = new UndoState(this, forGroup);
3492 3541
3493 m_undo.Push(nUndo); 3542 m_undo.Push(nUndo);
3494 3543
3495 if (m_redo.Count > 0) 3544 if (m_redo.Count > 0)
3496 m_redo.Clear(); 3545 m_redo.Clear();
3497 3546
3498 // m_log.DebugFormat( 3547 // m_log.DebugFormat(
3499 // "[SCENE OBJECT PART]: Stored undo state for {0} {1}, forGroup {2}, stack size now {3}", 3548 // "[SCENE OBJECT PART]: Stored undo state for {0} {1}, forGroup {2}, stack size now {3}",
3500 // Name, LocalId, forGroup, m_undo.Count); 3549 // Name, LocalId, forGroup, m_undo.Count);
3501 } 3550 }
3502 } 3551 }
3503 } 3552 }
3504 } 3553 }
3505// else 3554 // else
3506// { 3555 // {
3507// m_log.DebugFormat("[SCENE OBJECT PART]: Ignoring undo store for {0} {1}", Name, LocalId); 3556 // m_log.DebugFormat("[SCENE OBJECT PART]: Ignoring undo store for {0} {1}", Name, LocalId);
3508// } 3557 // }
3509 } 3558 }
3510// else 3559 // else
3511// { 3560 // {
3512// m_log.DebugFormat( 3561 // m_log.DebugFormat(
3513// "[SCENE OBJECT PART]: Ignoring undo store for {0} {1} since already undoing", Name, LocalId); 3562 // "[SCENE OBJECT PART]: Ignoring undo store for {0} {1} since already undoing", Name, LocalId);
3514// } 3563 // }
3515 } 3564 }
3516 3565
3517 /// <summary> 3566 /// <summary>
@@ -4242,6 +4291,9 @@ namespace OpenSim.Region.Framework.Scenes
4242 bool wasPhantom = ((Flags & PrimFlags.Phantom) != 0); 4291 bool wasPhantom = ((Flags & PrimFlags.Phantom) != 0);
4243 bool wasVD = VolumeDetectActive; 4292 bool wasVD = VolumeDetectActive;
4244 4293
4294// m_log.DebugFormat("[SOP]: Old states: phys: {0} temp: {1} phan: {2} vd: {3}", wasUsingPhysics, wasTemporary, wasPhantom, wasVD);
4295// m_log.DebugFormat("[SOP]: New states: phys: {0} temp: {1} phan: {2} vd: {3}", UsePhysics, SetTemporary, SetPhantom, SetVD);
4296
4245 if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD)) 4297 if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD))
4246 return; 4298 return;
4247 4299
@@ -4271,6 +4323,11 @@ namespace OpenSim.Region.Framework.Scenes
4271 SetPhantom = false; 4323 SetPhantom = false;
4272 } 4324 }
4273 } 4325 }
4326 else if (wasVD)
4327 {
4328 // Correspondingly, if VD is turned off, also turn off phantom
4329 SetPhantom = false;
4330 }
4274 4331
4275 if (UsePhysics && IsJoint()) 4332 if (UsePhysics && IsJoint())
4276 { 4333 {
@@ -4765,5 +4822,17 @@ namespace OpenSim.Region.Framework.Scenes
4765 Color color = Color; 4822 Color color = Color;
4766 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A)); 4823 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A));
4767 } 4824 }
4825
4826 public void ResetOwnerChangeFlag()
4827 {
4828 List<UUID> inv = Inventory.GetInventoryList();
4829
4830 foreach (UUID itemID in inv)
4831 {
4832 TaskInventoryItem item = Inventory.GetInventoryItem(itemID);
4833 item.OwnerChanged = false;
4834 Inventory.UpdateInventoryItem(item, false, false);
4835 }
4836 }
4768 } 4837 }
4769} 4838}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index daddb90..2335ad5 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
@@ -48,6 +48,9 @@ namespace OpenSim.Region.Framework.Scenes
48 private string m_inventoryFileName = String.Empty; 48 private string m_inventoryFileName = String.Empty;
49 private byte[] m_inventoryFileData = new byte[0]; 49 private byte[] m_inventoryFileData = new byte[0];
50 private uint m_inventoryFileNameSerial = 0; 50 private uint m_inventoryFileNameSerial = 0;
51 private bool m_inventoryPrivileged = false;
52
53 private Dictionary<UUID, ArrayList> m_scriptErrors = new Dictionary<UUID, ArrayList>();
51 54
52 /// <value> 55 /// <value>
53 /// The part to which the inventory belongs. 56 /// The part to which the inventory belongs.
@@ -84,11 +87,14 @@ namespace OpenSim.Region.Framework.Scenes
84 /// </value> 87 /// </value>
85 protected internal TaskInventoryDictionary Items 88 protected internal TaskInventoryDictionary Items
86 { 89 {
87 get { return m_items; } 90 get {
91 return m_items;
92 }
88 set 93 set
89 { 94 {
90 m_items = value; 95 m_items = value;
91 m_inventorySerial++; 96 m_inventorySerial++;
97 QueryScriptStates();
92 } 98 }
93 } 99 }
94 100
@@ -123,38 +129,45 @@ namespace OpenSim.Region.Framework.Scenes
123 public void ResetInventoryIDs() 129 public void ResetInventoryIDs()
124 { 130 {
125 if (null == m_part) 131 if (null == m_part)
126 return; 132 m_items.LockItemsForWrite(true);
127 133
128 lock (m_items) 134 if (Items.Count == 0)
129 { 135 {
130 if (0 == m_items.Count) 136 m_items.LockItemsForWrite(false);
131 return; 137 return;
138 }
132 139
133 IList<TaskInventoryItem> items = GetInventoryItems(); 140 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
134 m_items.Clear(); 141 Items.Clear();
135 142
136 foreach (TaskInventoryItem item in items) 143 foreach (TaskInventoryItem item in items)
137 { 144 {
138 item.ResetIDs(m_part.UUID); 145 item.ResetIDs(m_part.UUID);
139 m_items.Add(item.ItemID, item); 146 Items.Add(item.ItemID, item);
140 }
141 } 147 }
148 m_items.LockItemsForWrite(false);
142 } 149 }
143 150
144 public void ResetObjectID() 151 public void ResetObjectID()
145 { 152 {
146 lock (Items) 153 m_items.LockItemsForWrite(true);
154
155 if (Items.Count == 0)
147 { 156 {
148 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values); 157 m_items.LockItemsForWrite(false);
149 Items.Clear(); 158 return;
150
151 foreach (TaskInventoryItem item in items)
152 {
153 item.ParentPartID = m_part.UUID;
154 item.ParentID = m_part.UUID;
155 Items.Add(item.ItemID, item);
156 }
157 } 159 }
160
161 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
162 Items.Clear();
163
164 foreach (TaskInventoryItem item in items)
165 {
166 item.ParentPartID = m_part.UUID;
167 item.ParentID = m_part.UUID;
168 Items.Add(item.ItemID, item);
169 }
170 m_items.LockItemsForWrite(false);
158 } 171 }
159 172
160 /// <summary> 173 /// <summary>
@@ -163,12 +176,11 @@ namespace OpenSim.Region.Framework.Scenes
163 /// <param name="ownerId"></param> 176 /// <param name="ownerId"></param>
164 public void ChangeInventoryOwner(UUID ownerId) 177 public void ChangeInventoryOwner(UUID ownerId)
165 { 178 {
166 lock (Items) 179 m_items.LockItemsForWrite(true);
180 if (0 == Items.Count)
167 { 181 {
168 if (0 == Items.Count) 182 m_items.LockItemsForWrite(false);
169 { 183 return;
170 return;
171 }
172 } 184 }
173 185
174 HasInventoryChanged = true; 186 HasInventoryChanged = true;
@@ -184,6 +196,7 @@ namespace OpenSim.Region.Framework.Scenes
184 item.PermsGranter = UUID.Zero; 196 item.PermsGranter = UUID.Zero;
185 item.OwnerChanged = true; 197 item.OwnerChanged = true;
186 } 198 }
199 m_items.LockItemsForWrite(false);
187 } 200 }
188 201
189 /// <summary> 202 /// <summary>
@@ -192,12 +205,11 @@ namespace OpenSim.Region.Framework.Scenes
192 /// <param name="groupID"></param> 205 /// <param name="groupID"></param>
193 public void ChangeInventoryGroup(UUID groupID) 206 public void ChangeInventoryGroup(UUID groupID)
194 { 207 {
195 lock (Items) 208 m_items.LockItemsForWrite(true);
209 if (0 == Items.Count)
196 { 210 {
197 if (0 == Items.Count) 211 m_items.LockItemsForWrite(false);
198 { 212 return;
199 return;
200 }
201 } 213 }
202 214
203 // Don't let this set the HasGroupChanged flag for attachments 215 // Don't let this set the HasGroupChanged flag for attachments
@@ -209,12 +221,45 @@ namespace OpenSim.Region.Framework.Scenes
209 m_part.ParentGroup.HasGroupChanged = true; 221 m_part.ParentGroup.HasGroupChanged = true;
210 } 222 }
211 223
212 List<TaskInventoryItem> items = GetInventoryItems(); 224 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
213 foreach (TaskInventoryItem item in items) 225 foreach (TaskInventoryItem item in items)
214 { 226 {
215 if (groupID != item.GroupID) 227 if (groupID != item.GroupID)
228 {
216 item.GroupID = groupID; 229 item.GroupID = groupID;
230 }
231 }
232 m_items.LockItemsForWrite(false);
233 }
234
235 private void QueryScriptStates()
236 {
237 if (m_part == null || m_part.ParentGroup == null)
238 return;
239
240 IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>();
241 if (engines == null) // No engine at all
242 return;
243
244 Items.LockItemsForRead(true);
245 foreach (TaskInventoryItem item in Items.Values)
246 {
247 if (item.InvType == (int)InventoryType.LSL)
248 {
249 foreach (IScriptModule e in engines)
250 {
251 bool running;
252
253 if (e.HasScript(item.ItemID, out running))
254 {
255 item.ScriptRunning = running;
256 break;
257 }
258 }
259 }
217 } 260 }
261
262 Items.LockItemsForRead(false);
218 } 263 }
219 264
220 /// <summary> 265 /// <summary>
@@ -222,9 +267,14 @@ namespace OpenSim.Region.Framework.Scenes
222 /// </summary> 267 /// </summary>
223 public void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource) 268 public void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource)
224 { 269 {
225 List<TaskInventoryItem> scripts = GetInventoryScripts(); 270 Items.LockItemsForRead(true);
226 foreach (TaskInventoryItem item in scripts) 271 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
227 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource); 272 Items.LockItemsForRead(false);
273 foreach (TaskInventoryItem item in items)
274 {
275 if ((int)InventoryType.LSL == item.InvType)
276 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource);
277 }
228 } 278 }
229 279
230 public ArrayList GetScriptErrors(UUID itemID) 280 public ArrayList GetScriptErrors(UUID itemID)
@@ -255,9 +305,18 @@ namespace OpenSim.Region.Framework.Scenes
255 /// </param> 305 /// </param>
256 public void RemoveScriptInstances(bool sceneObjectBeingDeleted) 306 public void RemoveScriptInstances(bool sceneObjectBeingDeleted)
257 { 307 {
258 List<TaskInventoryItem> scripts = GetInventoryScripts(); 308 Items.LockItemsForRead(true);
259 foreach (TaskInventoryItem item in scripts) 309 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
260 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted); 310 Items.LockItemsForRead(false);
311
312 foreach (TaskInventoryItem item in items)
313 {
314 if ((int)InventoryType.LSL == item.InvType)
315 {
316 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted);
317 m_part.RemoveScriptEvents(item.ItemID);
318 }
319 }
261 } 320 }
262 321
263 /// <summary> 322 /// <summary>
@@ -273,7 +332,10 @@ namespace OpenSim.Region.Framework.Scenes
273 // item.Name, item.ItemID, Name, UUID); 332 // item.Name, item.ItemID, Name, UUID);
274 333
275 if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID)) 334 if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID))
335 {
336 StoreScriptError(item.ItemID, "no permission");
276 return; 337 return;
338 }
277 339
278 m_part.AddFlag(PrimFlags.Scripted); 340 m_part.AddFlag(PrimFlags.Scripted);
279 341
@@ -282,14 +344,13 @@ namespace OpenSim.Region.Framework.Scenes
282 if (stateSource == 2 && // Prim crossing 344 if (stateSource == 2 && // Prim crossing
283 m_part.ParentGroup.Scene.m_trustBinaries) 345 m_part.ParentGroup.Scene.m_trustBinaries)
284 { 346 {
285 lock (m_items) 347 m_items.LockItemsForWrite(true);
286 { 348 m_items[item.ItemID].PermsMask = 0;
287 m_items[item.ItemID].PermsMask = 0; 349 m_items[item.ItemID].PermsGranter = UUID.Zero;
288 m_items[item.ItemID].PermsGranter = UUID.Zero; 350 m_items.LockItemsForWrite(false);
289 }
290
291 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 351 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
292 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource); 352 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource);
353 StoreScriptErrors(item.ItemID, null);
293 m_part.ParentGroup.AddActiveScriptCount(1); 354 m_part.ParentGroup.AddActiveScriptCount(1);
294 m_part.ScheduleFullUpdate(); 355 m_part.ScheduleFullUpdate();
295 return; 356 return;
@@ -298,6 +359,8 @@ namespace OpenSim.Region.Framework.Scenes
298 AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString()); 359 AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString());
299 if (null == asset) 360 if (null == asset)
300 { 361 {
362 string msg = String.Format("asset ID {0} could not be found", item.AssetID);
363 StoreScriptError(item.ItemID, msg);
301 m_log.ErrorFormat( 364 m_log.ErrorFormat(
302 "[PRIM INVENTORY]: " + 365 "[PRIM INVENTORY]: " +
303 "Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found", 366 "Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found",
@@ -309,15 +372,20 @@ namespace OpenSim.Region.Framework.Scenes
309 if (m_part.ParentGroup.m_savedScriptState != null) 372 if (m_part.ParentGroup.m_savedScriptState != null)
310 RestoreSavedScriptState(item.OldItemID, item.ItemID); 373 RestoreSavedScriptState(item.OldItemID, item.ItemID);
311 374
312 lock (m_items) 375 m_items.LockItemsForWrite(true);
313 { 376
314 m_items[item.ItemID].PermsMask = 0; 377 m_items[item.ItemID].PermsMask = 0;
315 m_items[item.ItemID].PermsGranter = UUID.Zero; 378 m_items[item.ItemID].PermsGranter = UUID.Zero;
316 } 379
380 m_items.LockItemsForWrite(false);
317 381
318 string script = Utils.BytesToString(asset.Data); 382 string script = Utils.BytesToString(asset.Data);
319 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 383 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
320 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource); 384 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource);
385 StoreScriptErrors(item.ItemID, null);
386 if (!item.ScriptRunning)
387 m_part.ParentGroup.Scene.EventManager.TriggerStopScript(
388 m_part.LocalId, item.ItemID);
321 m_part.ParentGroup.AddActiveScriptCount(1); 389 m_part.ParentGroup.AddActiveScriptCount(1);
322 m_part.ScheduleFullUpdate(); 390 m_part.ScheduleFullUpdate();
323 } 391 }
@@ -383,21 +451,145 @@ namespace OpenSim.Region.Framework.Scenes
383 451
384 /// <summary> 452 /// <summary>
385 /// Start a script which is in this prim's inventory. 453 /// Start a script which is in this prim's inventory.
454 /// Some processing may occur in the background, but this routine returns asap.
386 /// </summary> 455 /// </summary>
387 /// <param name="itemId"> 456 /// <param name="itemId">
388 /// A <see cref="UUID"/> 457 /// A <see cref="UUID"/>
389 /// </param> 458 /// </param>
390 public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource) 459 public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
391 { 460 {
392 TaskInventoryItem item = GetInventoryItem(itemId); 461 lock (m_scriptErrors)
393 if (item != null) 462 {
394 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource); 463 // Indicate to CreateScriptInstanceInternal() we don't want it to wait for completion
464 m_scriptErrors.Remove(itemId);
465 }
466 CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
467 }
468
469 private void CreateScriptInstanceInternal(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
470 {
471 m_items.LockItemsForRead(true);
472 if (m_items.ContainsKey(itemId))
473 {
474 if (m_items.ContainsKey(itemId))
475 {
476 m_items.LockItemsForRead(false);
477 CreateScriptInstance(m_items[itemId], startParam, postOnRez, engine, stateSource);
478 }
479 else
480 {
481 m_items.LockItemsForRead(false);
482 string msg = String.Format("couldn't be found for prim {0}, {1} at {2} in {3}", m_part.Name, m_part.UUID,
483 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
484 StoreScriptError(itemId, msg);
485 m_log.ErrorFormat(
486 "[PRIM INVENTORY]: " +
487 "Couldn't start script with ID {0} since it {1}", itemId, msg);
488 }
489 }
395 else 490 else
491 {
492 m_items.LockItemsForRead(false);
493 string msg = String.Format("couldn't be found for prim {0}, {1}", m_part.Name, m_part.UUID);
494 StoreScriptError(itemId, msg);
396 m_log.ErrorFormat( 495 m_log.ErrorFormat(
397 "[PRIM INVENTORY]: " + 496 "[PRIM INVENTORY]: " +
398 "Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}", 497 "Couldn't start script with ID {0} since it {1}", itemId, msg);
399 itemId, m_part.Name, m_part.UUID, 498 }
400 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 499
500 }
501
502 /// <summary>
503 /// Start a script which is in this prim's inventory and return any compilation error messages.
504 /// </summary>
505 /// <param name="itemId">
506 /// A <see cref="UUID"/>
507 /// </param>
508 public ArrayList CreateScriptInstanceEr(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
509 {
510 ArrayList errors;
511
512 // Indicate to CreateScriptInstanceInternal() we want it to
513 // post any compilation/loading error messages
514 lock (m_scriptErrors)
515 {
516 m_scriptErrors[itemId] = null;
517 }
518
519 // Perform compilation/loading
520 CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
521
522 // Wait for and retrieve any errors
523 lock (m_scriptErrors)
524 {
525 while ((errors = m_scriptErrors[itemId]) == null)
526 {
527 if (!System.Threading.Monitor.Wait(m_scriptErrors, 15000))
528 {
529 m_log.ErrorFormat(
530 "[PRIM INVENTORY]: " +
531 "timedout waiting for script {0} errors", itemId);
532 errors = m_scriptErrors[itemId];
533 if (errors == null)
534 {
535 errors = new ArrayList(1);
536 errors.Add("timedout waiting for errors");
537 }
538 break;
539 }
540 }
541 m_scriptErrors.Remove(itemId);
542 }
543 return errors;
544 }
545
546 // Signal to CreateScriptInstanceEr() that compilation/loading is complete
547 private void StoreScriptErrors(UUID itemId, ArrayList errors)
548 {
549 lock (m_scriptErrors)
550 {
551 // If compilation/loading initiated via CreateScriptInstance(),
552 // it does not want the errors, so just get out
553 if (!m_scriptErrors.ContainsKey(itemId))
554 {
555 return;
556 }
557
558 // Initiated via CreateScriptInstanceEr(), if we know what the
559 // errors are, save them and wake CreateScriptInstanceEr().
560 if (errors != null)
561 {
562 m_scriptErrors[itemId] = errors;
563 System.Threading.Monitor.PulseAll(m_scriptErrors);
564 return;
565 }
566 }
567
568 // Initiated via CreateScriptInstanceEr() but we don't know what
569 // the errors are yet, so retrieve them from the script engine.
570 // This may involve some waiting internal to GetScriptErrors().
571 errors = GetScriptErrors(itemId);
572
573 // Get a default non-null value to indicate success.
574 if (errors == null)
575 {
576 errors = new ArrayList();
577 }
578
579 // Post to CreateScriptInstanceEr() and wake it up
580 lock (m_scriptErrors)
581 {
582 m_scriptErrors[itemId] = errors;
583 System.Threading.Monitor.PulseAll(m_scriptErrors);
584 }
585 }
586
587 // Like StoreScriptErrors(), but just posts a single string message
588 private void StoreScriptError(UUID itemId, string message)
589 {
590 ArrayList errors = new ArrayList(1);
591 errors.Add(message);
592 StoreScriptErrors(itemId, errors);
401 } 593 }
402 594
403 /// <summary> 595 /// <summary>
@@ -410,15 +602,7 @@ namespace OpenSim.Region.Framework.Scenes
410 /// </param> 602 /// </param>
411 public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted) 603 public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted)
412 { 604 {
413 bool scriptPresent = false; 605 if (m_items.ContainsKey(itemId))
414
415 lock (m_items)
416 {
417 if (m_items.ContainsKey(itemId))
418 scriptPresent = true;
419 }
420
421 if (scriptPresent)
422 { 606 {
423 if (!sceneObjectBeingDeleted) 607 if (!sceneObjectBeingDeleted)
424 m_part.RemoveScriptEvents(itemId); 608 m_part.RemoveScriptEvents(itemId);
@@ -443,14 +627,16 @@ namespace OpenSim.Region.Framework.Scenes
443 /// <returns></returns> 627 /// <returns></returns>
444 private bool InventoryContainsName(string name) 628 private bool InventoryContainsName(string name)
445 { 629 {
446 lock (m_items) 630 m_items.LockItemsForRead(true);
631 foreach (TaskInventoryItem item in m_items.Values)
447 { 632 {
448 foreach (TaskInventoryItem item in m_items.Values) 633 if (item.Name == name)
449 { 634 {
450 if (item.Name == name) 635 m_items.LockItemsForRead(false);
451 return true; 636 return true;
452 } 637 }
453 } 638 }
639 m_items.LockItemsForRead(false);
454 return false; 640 return false;
455 } 641 }
456 642
@@ -492,8 +678,9 @@ namespace OpenSim.Region.Framework.Scenes
492 /// <param name="item"></param> 678 /// <param name="item"></param>
493 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop) 679 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop)
494 { 680 {
495 List<TaskInventoryItem> il = GetInventoryItems(); 681 m_items.LockItemsForRead(true);
496 682 List<TaskInventoryItem> il = new List<TaskInventoryItem>(m_items.Values);
683 m_items.LockItemsForRead(false);
497 foreach (TaskInventoryItem i in il) 684 foreach (TaskInventoryItem i in il)
498 { 685 {
499 if (i.Name == item.Name) 686 if (i.Name == item.Name)
@@ -531,14 +718,14 @@ namespace OpenSim.Region.Framework.Scenes
531 item.Name = name; 718 item.Name = name;
532 item.GroupID = m_part.GroupID; 719 item.GroupID = m_part.GroupID;
533 720
534 lock (m_items) 721 m_items.LockItemsForWrite(true);
535 m_items.Add(item.ItemID, item); 722 m_items.Add(item.ItemID, item);
536 723 m_items.LockItemsForWrite(false);
537 if (allowedDrop) 724 if (allowedDrop)
538 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP); 725 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP);
539 else 726 else
540 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 727 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
541 728
542 m_inventorySerial++; 729 m_inventorySerial++;
543 //m_inventorySerial += 2; 730 //m_inventorySerial += 2;
544 HasInventoryChanged = true; 731 HasInventoryChanged = true;
@@ -554,15 +741,15 @@ namespace OpenSim.Region.Framework.Scenes
554 /// <param name="items"></param> 741 /// <param name="items"></param>
555 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items) 742 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items)
556 { 743 {
557 lock (m_items) 744 m_items.LockItemsForWrite(true);
745 foreach (TaskInventoryItem item in items)
558 { 746 {
559 foreach (TaskInventoryItem item in items) 747 m_items.Add(item.ItemID, item);
560 { 748// m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
561 m_items.Add(item.ItemID, item);
562// m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
563 }
564 m_inventorySerial++;
565 } 749 }
750 m_items.LockItemsForWrite(false);
751
752 m_inventorySerial++;
566 } 753 }
567 754
568 /// <summary> 755 /// <summary>
@@ -573,10 +760,9 @@ namespace OpenSim.Region.Framework.Scenes
573 public TaskInventoryItem GetInventoryItem(UUID itemId) 760 public TaskInventoryItem GetInventoryItem(UUID itemId)
574 { 761 {
575 TaskInventoryItem item; 762 TaskInventoryItem item;
576 763 m_items.LockItemsForRead(true);
577 lock (m_items) 764 m_items.TryGetValue(itemId, out item);
578 m_items.TryGetValue(itemId, out item); 765 m_items.LockItemsForRead(false);
579
580 return item; 766 return item;
581 } 767 }
582 768
@@ -592,15 +778,16 @@ namespace OpenSim.Region.Framework.Scenes
592 { 778 {
593 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(); 779 IList<TaskInventoryItem> items = new List<TaskInventoryItem>();
594 780
595 lock (m_items) 781 m_items.LockItemsForRead(true);
782
783 foreach (TaskInventoryItem item in m_items.Values)
596 { 784 {
597 foreach (TaskInventoryItem item in m_items.Values) 785 if (item.Name == name)
598 { 786 items.Add(item);
599 if (item.Name == name)
600 items.Add(item);
601 }
602 } 787 }
603 788
789 m_items.LockItemsForRead(false);
790
604 return items; 791 return items;
605 } 792 }
606 793
@@ -619,6 +806,9 @@ namespace OpenSim.Region.Framework.Scenes
619 string xmlData = Utils.BytesToString(rezAsset.Data); 806 string xmlData = Utils.BytesToString(rezAsset.Data);
620 SceneObjectGroup group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); 807 SceneObjectGroup group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
621 808
809 group.RootPart.AttachPoint = group.RootPart.Shape.State;
810 group.RootPart.AttachOffset = group.AbsolutePosition;
811
622 group.ResetIDs(); 812 group.ResetIDs();
623 813
624 SceneObjectPart rootPart = group.GetChildPart(group.UUID); 814 SceneObjectPart rootPart = group.GetChildPart(group.UUID);
@@ -693,8 +883,9 @@ namespace OpenSim.Region.Framework.Scenes
693 883
694 public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged) 884 public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged)
695 { 885 {
696 TaskInventoryItem it = GetInventoryItem(item.ItemID); 886 m_items.LockItemsForWrite(true);
697 if (it != null) 887
888 if (m_items.ContainsKey(item.ItemID))
698 { 889 {
699// m_log.DebugFormat("[PRIM INVENTORY]: Updating item {0} in {1}", item.Name, m_part.Name); 890// m_log.DebugFormat("[PRIM INVENTORY]: Updating item {0} in {1}", item.Name, m_part.Name);
700 891
@@ -707,14 +898,10 @@ namespace OpenSim.Region.Framework.Scenes
707 item.GroupID = m_part.GroupID; 898 item.GroupID = m_part.GroupID;
708 899
709 if (item.AssetID == UUID.Zero) 900 if (item.AssetID == UUID.Zero)
710 item.AssetID = it.AssetID; 901 item.AssetID = m_items[item.ItemID].AssetID;
711 902
712 lock (m_items) 903 m_items[item.ItemID] = item;
713 { 904 m_inventorySerial++;
714 m_items[item.ItemID] = item;
715 m_inventorySerial++;
716 }
717
718 if (fireScriptEvents) 905 if (fireScriptEvents)
719 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 906 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
720 907
@@ -723,7 +910,7 @@ namespace OpenSim.Region.Framework.Scenes
723 HasInventoryChanged = true; 910 HasInventoryChanged = true;
724 m_part.ParentGroup.HasGroupChanged = true; 911 m_part.ParentGroup.HasGroupChanged = true;
725 } 912 }
726 913 m_items.LockItemsForWrite(false);
727 return true; 914 return true;
728 } 915 }
729 else 916 else
@@ -734,8 +921,9 @@ namespace OpenSim.Region.Framework.Scenes
734 item.ItemID, m_part.Name, m_part.UUID, 921 item.ItemID, m_part.Name, m_part.UUID,
735 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 922 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
736 } 923 }
737 return false; 924 m_items.LockItemsForWrite(false);
738 925
926 return false;
739 } 927 }
740 928
741 /// <summary> 929 /// <summary>
@@ -746,43 +934,59 @@ namespace OpenSim.Region.Framework.Scenes
746 /// in this prim's inventory.</returns> 934 /// in this prim's inventory.</returns>
747 public int RemoveInventoryItem(UUID itemID) 935 public int RemoveInventoryItem(UUID itemID)
748 { 936 {
749 TaskInventoryItem item = GetInventoryItem(itemID); 937 m_items.LockItemsForRead(true);
750 if (item != null) 938
939 if (m_items.ContainsKey(itemID))
751 { 940 {
752 int type = m_items[itemID].InvType; 941 int type = m_items[itemID].InvType;
942 m_items.LockItemsForRead(false);
753 if (type == 10) // Script 943 if (type == 10) // Script
754 { 944 {
755 m_part.RemoveScriptEvents(itemID);
756 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID); 945 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID);
757 } 946 }
947 m_items.LockItemsForWrite(true);
758 m_items.Remove(itemID); 948 m_items.Remove(itemID);
949 m_items.LockItemsForWrite(false);
759 m_inventorySerial++; 950 m_inventorySerial++;
760 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 951 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
761 952
762 HasInventoryChanged = true; 953 HasInventoryChanged = true;
763 m_part.ParentGroup.HasGroupChanged = true; 954 m_part.ParentGroup.HasGroupChanged = true;
764 955
765 if (!ContainsScripts()) 956 int scriptcount = 0;
957 m_items.LockItemsForRead(true);
958 foreach (TaskInventoryItem item in m_items.Values)
959 {
960 if (item.Type == 10)
961 {
962 scriptcount++;
963 }
964 }
965 m_items.LockItemsForRead(false);
966
967
968 if (scriptcount <= 0)
969 {
766 m_part.RemFlag(PrimFlags.Scripted); 970 m_part.RemFlag(PrimFlags.Scripted);
971 }
767 972
768 m_part.ScheduleFullUpdate(); 973 m_part.ScheduleFullUpdate();
769 974
770 return type; 975 return type;
771
772 } 976 }
773 else 977 else
774 { 978 {
979 m_items.LockItemsForRead(false);
775 m_log.ErrorFormat( 980 m_log.ErrorFormat(
776 "[PRIM INVENTORY]: " + 981 "[PRIM INVENTORY]: " +
777 "Tried to remove item ID {0} from prim {1}, {2} at {3} in {4} but the item does not exist in this inventory", 982 "Tried to remove item ID {0} from prim {1}, {2} but the item does not exist in this inventory",
778 itemID, m_part.Name, m_part.UUID, 983 itemID, m_part.Name, m_part.UUID);
779 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
780 } 984 }
781 985
782 return -1; 986 return -1;
783 } 987 }
784 988
785 private bool CreateInventoryFile() 989 private bool CreateInventoryFileName()
786 { 990 {
787// m_log.DebugFormat( 991// m_log.DebugFormat(
788// "[PRIM INVENTORY]: Creating inventory file for {0} {1} {2}, serial {3}", 992// "[PRIM INVENTORY]: Creating inventory file for {0} {1} {2}, serial {3}",
@@ -791,116 +995,125 @@ namespace OpenSim.Region.Framework.Scenes
791 if (m_inventoryFileName == String.Empty || 995 if (m_inventoryFileName == String.Empty ||
792 m_inventoryFileNameSerial < m_inventorySerial) 996 m_inventoryFileNameSerial < m_inventorySerial)
793 { 997 {
794 // Something changed, we need to create a new file
795 m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp"; 998 m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp";
796 m_inventoryFileNameSerial = m_inventorySerial; 999 m_inventoryFileNameSerial = m_inventorySerial;
797 1000
798 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero); 1001 return true;
1002 }
1003
1004 return false;
1005 }
1006
1007 /// <summary>
1008 /// Serialize all the metadata for the items in this prim's inventory ready for sending to the client
1009 /// </summary>
1010 /// <param name="xferManager"></param>
1011 public void RequestInventoryFile(IClientAPI client, IXfer xferManager)
1012 {
1013 bool changed = CreateInventoryFileName();
1014
1015 bool includeAssets = false;
1016 if (m_part.ParentGroup.Scene.Permissions.CanEditObjectInventory(m_part.UUID, client.AgentId))
1017 includeAssets = true;
1018
1019 if (m_inventoryPrivileged != includeAssets)
1020 changed = true;
1021
1022 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero);
1023
1024 Items.LockItemsForRead(true);
1025
1026 if (m_inventorySerial == 0) // No inventory
1027 {
1028 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
1029 Items.LockItemsForRead(false);
1030 return;
1031 }
799 1032
800 lock (m_items) 1033 if (m_items.Count == 0) // No inventory
1034 {
1035 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
1036 Items.LockItemsForRead(false);
1037 return;
1038 }
1039
1040 if (!changed)
1041 {
1042 if (m_inventoryFileData.Length > 2)
801 { 1043 {
802 foreach (TaskInventoryItem item in m_items.Values) 1044 xferManager.AddNewFile(m_inventoryFileName,
803 { 1045 m_inventoryFileData);
804// m_log.DebugFormat( 1046 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
805// "[PRIM INVENTORY]: Adding item {0} {1} for serial {2} on prim {3} {4} {5}", 1047 Util.StringToBytes256(m_inventoryFileName));
806// item.Name, item.ItemID, m_inventorySerial, m_part.Name, m_part.UUID, m_part.LocalId);
807 1048
808 UUID ownerID = item.OwnerID; 1049 Items.LockItemsForRead(false);
809 uint everyoneMask = 0; 1050 return;
810 uint baseMask = item.BasePermissions; 1051 }
811 uint ownerMask = item.CurrentPermissions; 1052 }
812 uint groupMask = item.GroupPermissions;
813 1053
814 invString.AddItemStart(); 1054 m_inventoryPrivileged = includeAssets;
815 invString.AddNameValueLine("item_id", item.ItemID.ToString());
816 invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
817 1055
818 invString.AddPermissionsStart(); 1056 foreach (TaskInventoryItem item in m_items.Values)
1057 {
1058 UUID ownerID = item.OwnerID;
1059 uint everyoneMask = 0;
1060 uint baseMask = item.BasePermissions;
1061 uint ownerMask = item.CurrentPermissions;
1062 uint groupMask = item.GroupPermissions;
819 1063
820 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask)); 1064 invString.AddItemStart();
821 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask)); 1065 invString.AddNameValueLine("item_id", item.ItemID.ToString());
822 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask)); 1066 invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
823 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask));
824 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
825 1067
826 invString.AddNameValueLine("creator_id", item.CreatorID.ToString()); 1068 invString.AddPermissionsStart();
827 invString.AddNameValueLine("owner_id", ownerID.ToString());
828 1069
829 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString()); 1070 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask));
1071 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask));
1072 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask));
1073 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask));
1074 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
830 1075
831 invString.AddNameValueLine("group_id", item.GroupID.ToString()); 1076 invString.AddNameValueLine("creator_id", item.CreatorID.ToString());
832 invString.AddSectionEnd(); 1077 invString.AddNameValueLine("owner_id", ownerID.ToString());
833 1078
834 invString.AddNameValueLine("asset_id", item.AssetID.ToString()); 1079 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString());
835 invString.AddNameValueLine("type", Utils.AssetTypeToString((AssetType)item.Type));
836 invString.AddNameValueLine("inv_type", Utils.InventoryTypeToString((InventoryType)item.InvType));
837 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags));
838 1080
839 invString.AddSaleStart(); 1081 invString.AddNameValueLine("group_id", item.GroupID.ToString());
840 invString.AddNameValueLine("sale_type", "not"); 1082 invString.AddSectionEnd();
841 invString.AddNameValueLine("sale_price", "0");
842 invString.AddSectionEnd();
843 1083
844 invString.AddNameValueLine("name", item.Name + "|"); 1084 if (includeAssets)
845 invString.AddNameValueLine("desc", item.Description + "|"); 1085 invString.AddNameValueLine("asset_id", item.AssetID.ToString());
1086 else
1087 invString.AddNameValueLine("asset_id", UUID.Zero.ToString());
1088 invString.AddNameValueLine("type", Utils.AssetTypeToString((AssetType)item.Type));
1089 invString.AddNameValueLine("inv_type", Utils.InventoryTypeToString((InventoryType)item.InvType));
1090 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags));
846 1091
847 invString.AddNameValueLine("creation_date", item.CreationDate.ToString()); 1092 invString.AddSaleStart();
848 invString.AddSectionEnd(); 1093 invString.AddNameValueLine("sale_type", "not");
849 } 1094 invString.AddNameValueLine("sale_price", "0");
850 } 1095 invString.AddSectionEnd();
851 1096
852 m_inventoryFileData = Utils.StringToBytes(invString.BuildString); 1097 invString.AddNameValueLine("name", item.Name + "|");
1098 invString.AddNameValueLine("desc", item.Description + "|");
853 1099
854 return true; 1100 invString.AddNameValueLine("creation_date", item.CreationDate.ToString());
1101 invString.AddSectionEnd();
855 } 1102 }
856 1103
857 // No need to recreate, the existing file is fine 1104 Items.LockItemsForRead(false);
858 return false;
859 }
860 1105
861 /// <summary> 1106 m_inventoryFileData = Utils.StringToBytes(invString.BuildString);
862 /// Serialize all the metadata for the items in this prim's inventory ready for sending to the client
863 /// </summary>
864 /// <param name="xferManager"></param>
865 public void RequestInventoryFile(IClientAPI client, IXfer xferManager)
866 {
867 lock (m_items)
868 {
869 // Don't send a inventory xfer name if there are no items. Doing so causes viewer 3 to crash when rezzing
870 // a new script if any previous deletion has left the prim inventory empty.
871 if (m_items.Count == 0) // No inventory
872 {
873// m_log.DebugFormat(
874// "[PRIM INVENTORY]: Not sending inventory data for part {0} {1} {2} for {3} since no items",
875// m_part.Name, m_part.LocalId, m_part.UUID, client.Name);
876 1107
877 client.SendTaskInventory(m_part.UUID, 0, new byte[0]); 1108 if (m_inventoryFileData.Length > 2)
878 return; 1109 {
879 } 1110 xferManager.AddNewFile(m_inventoryFileName, m_inventoryFileData);
880 1111 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
881 CreateInventoryFile(); 1112 Util.StringToBytes256(m_inventoryFileName));
882 1113 return;
883 // In principle, we should only do the rest if the inventory changed;
884 // by sending m_inventorySerial to the client, it ought to know
885 // that nothing changed and that it doesn't need to request the file.
886 // Unfortunately, it doesn't look like the client optimizes this;
887 // the client seems to always come back and request the Xfer,
888 // no matter what value m_inventorySerial has.
889 // FIXME: Could probably be > 0 here rather than > 2
890 if (m_inventoryFileData.Length > 2)
891 {
892 // Add the file for Xfer
893 // m_log.DebugFormat(
894 // "[PRIM INVENTORY]: Adding inventory file {0} (length {1}) for transfer on {2} {3} {4}",
895 // m_inventoryFileName, m_inventoryFileData.Length, m_part.Name, m_part.UUID, m_part.LocalId);
896
897 xferManager.AddNewFile(m_inventoryFileName, m_inventoryFileData);
898 }
899
900 // Tell the client we're ready to Xfer the file
901 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
902 Util.StringToBytes256(m_inventoryFileName));
903 } 1114 }
1115
1116 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
904 } 1117 }
905 1118
906 /// <summary> 1119 /// <summary>
@@ -909,13 +1122,19 @@ namespace OpenSim.Region.Framework.Scenes
909 /// <param name="datastore"></param> 1122 /// <param name="datastore"></param>
910 public void ProcessInventoryBackup(ISimulationDataService datastore) 1123 public void ProcessInventoryBackup(ISimulationDataService datastore)
911 { 1124 {
912 if (HasInventoryChanged) 1125// Removed this because linking will cause an immediate delete of the new
913 { 1126// child prim from the database and the subsequent storing of the prim sees
914 HasInventoryChanged = false; 1127// the inventory of it as unchanged and doesn't store it at all. The overhead
915 List<TaskInventoryItem> items = GetInventoryItems(); 1128// of storing prim inventory needlessly is much less than the aggravation
916 datastore.StorePrimInventory(m_part.UUID, items); 1129// of prim inventory loss.
1130// if (HasInventoryChanged)
1131// {
1132 Items.LockItemsForRead(true);
1133 datastore.StorePrimInventory(m_part.UUID, Items.Values);
1134 Items.LockItemsForRead(false);
917 1135
918 } 1136 HasInventoryChanged = false;
1137// }
919 } 1138 }
920 1139
921 public class InventoryStringBuilder 1140 public class InventoryStringBuilder
@@ -981,82 +1200,63 @@ namespace OpenSim.Region.Framework.Scenes
981 { 1200 {
982 uint mask=0x7fffffff; 1201 uint mask=0x7fffffff;
983 1202
984 lock (m_items) 1203 foreach (TaskInventoryItem item in m_items.Values)
985 { 1204 {
986 foreach (TaskInventoryItem item in m_items.Values) 1205 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0)
1206 mask &= ~((uint)PermissionMask.Copy >> 13);
1207 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0)
1208 mask &= ~((uint)PermissionMask.Transfer >> 13);
1209 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0)
1210 mask &= ~((uint)PermissionMask.Modify >> 13);
1211
1212 if (item.InvType == (int)InventoryType.Object)
987 { 1213 {
988 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0) 1214 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
989 mask &= ~((uint)PermissionMask.Copy >> 13); 1215 mask &= ~((uint)PermissionMask.Copy >> 13);
990 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0) 1216 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
991 mask &= ~((uint)PermissionMask.Transfer >> 13); 1217 mask &= ~((uint)PermissionMask.Transfer >> 13);
992 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0) 1218 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
993 mask &= ~((uint)PermissionMask.Modify >> 13); 1219 mask &= ~((uint)PermissionMask.Modify >> 13);
994
995 if (item.InvType != (int)InventoryType.Object)
996 {
997 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0)
998 mask &= ~((uint)PermissionMask.Copy >> 13);
999 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0)
1000 mask &= ~((uint)PermissionMask.Transfer >> 13);
1001 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0)
1002 mask &= ~((uint)PermissionMask.Modify >> 13);
1003 }
1004 else
1005 {
1006 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
1007 mask &= ~((uint)PermissionMask.Copy >> 13);
1008 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
1009 mask &= ~((uint)PermissionMask.Transfer >> 13);
1010 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1011 mask &= ~((uint)PermissionMask.Modify >> 13);
1012 }
1013
1014 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
1015 mask &= ~(uint)PermissionMask.Copy;
1016 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
1017 mask &= ~(uint)PermissionMask.Transfer;
1018 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
1019 mask &= ~(uint)PermissionMask.Modify;
1020 } 1220 }
1221
1222 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
1223 mask &= ~(uint)PermissionMask.Copy;
1224 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
1225 mask &= ~(uint)PermissionMask.Transfer;
1226 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
1227 mask &= ~(uint)PermissionMask.Modify;
1021 } 1228 }
1022
1023 return mask; 1229 return mask;
1024 } 1230 }
1025 1231
1026 public void ApplyNextOwnerPermissions() 1232 public void ApplyNextOwnerPermissions()
1027 { 1233 {
1028 lock (m_items) 1234 foreach (TaskInventoryItem item in m_items.Values)
1029 { 1235 {
1030 foreach (TaskInventoryItem item in m_items.Values) 1236 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0)
1031 { 1237 {
1032 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0) 1238 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
1033 { 1239 item.CurrentPermissions &= ~(uint)PermissionMask.Copy;
1034 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0) 1240 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
1035 item.CurrentPermissions &= ~(uint)PermissionMask.Copy; 1241 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer;
1036 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0) 1242 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1037 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer; 1243 item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
1038 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1039 item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
1040 }
1041 item.CurrentPermissions &= item.NextPermissions;
1042 item.BasePermissions &= item.NextPermissions;
1043 item.EveryonePermissions &= item.NextPermissions;
1044 item.OwnerChanged = true;
1045 item.PermsMask = 0;
1046 item.PermsGranter = UUID.Zero;
1047 } 1244 }
1245 item.OwnerChanged = true;
1246 item.CurrentPermissions &= item.NextPermissions;
1247 item.BasePermissions &= item.NextPermissions;
1248 item.EveryonePermissions &= item.NextPermissions;
1249 item.PermsMask = 0;
1250 item.PermsGranter = UUID.Zero;
1048 } 1251 }
1049 } 1252 }
1050 1253
1051 public void ApplyGodPermissions(uint perms) 1254 public void ApplyGodPermissions(uint perms)
1052 { 1255 {
1053 lock (m_items) 1256 foreach (TaskInventoryItem item in m_items.Values)
1054 { 1257 {
1055 foreach (TaskInventoryItem item in m_items.Values) 1258 item.CurrentPermissions = perms;
1056 { 1259 item.BasePermissions = perms;
1057 item.CurrentPermissions = perms;
1058 item.BasePermissions = perms;
1059 }
1060 } 1260 }
1061 1261
1062 m_inventorySerial++; 1262 m_inventorySerial++;
@@ -1069,17 +1269,13 @@ namespace OpenSim.Region.Framework.Scenes
1069 /// <returns></returns> 1269 /// <returns></returns>
1070 public bool ContainsScripts() 1270 public bool ContainsScripts()
1071 { 1271 {
1072 lock (m_items) 1272 foreach (TaskInventoryItem item in m_items.Values)
1073 { 1273 {
1074 foreach (TaskInventoryItem item in m_items.Values) 1274 if (item.InvType == (int)InventoryType.LSL)
1075 { 1275 {
1076 if (item.InvType == (int)InventoryType.LSL) 1276 return true;
1077 {
1078 return true;
1079 }
1080 } 1277 }
1081 } 1278 }
1082
1083 return false; 1279 return false;
1084 } 1280 }
1085 1281
@@ -1087,11 +1283,8 @@ namespace OpenSim.Region.Framework.Scenes
1087 { 1283 {
1088 List<UUID> ret = new List<UUID>(); 1284 List<UUID> ret = new List<UUID>();
1089 1285
1090 lock (m_items) 1286 foreach (TaskInventoryItem item in m_items.Values)
1091 { 1287 ret.Add(item.ItemID);
1092 foreach (TaskInventoryItem item in m_items.Values)
1093 ret.Add(item.ItemID);
1094 }
1095 1288
1096 return ret; 1289 return ret;
1097 } 1290 }
@@ -1122,6 +1315,11 @@ namespace OpenSim.Region.Framework.Scenes
1122 1315
1123 public Dictionary<UUID, string> GetScriptStates() 1316 public Dictionary<UUID, string> GetScriptStates()
1124 { 1317 {
1318 return GetScriptStates(false);
1319 }
1320
1321 public Dictionary<UUID, string> GetScriptStates(bool oldIDs)
1322 {
1125 Dictionary<UUID, string> ret = new Dictionary<UUID, string>(); 1323 Dictionary<UUID, string> ret = new Dictionary<UUID, string>();
1126 1324
1127 if (m_part.ParentGroup.Scene == null) // Group not in a scene 1325 if (m_part.ParentGroup.Scene == null) // Group not in a scene
@@ -1132,25 +1330,35 @@ namespace OpenSim.Region.Framework.Scenes
1132 if (engines.Length == 0) // No engine at all 1330 if (engines.Length == 0) // No engine at all
1133 return ret; 1331 return ret;
1134 1332
1135 List<TaskInventoryItem> scripts = GetInventoryScripts(); 1333 Items.LockItemsForRead(true);
1136 1334 foreach (TaskInventoryItem item in m_items.Values)
1137 foreach (TaskInventoryItem item in scripts)
1138 { 1335 {
1139 foreach (IScriptModule e in engines) 1336 if (item.InvType == (int)InventoryType.LSL)
1140 { 1337 {
1141 if (e != null) 1338 foreach (IScriptModule e in engines)
1142 { 1339 {
1143 string n = e.GetXMLState(item.ItemID); 1340 if (e != null)
1144 if (n != String.Empty)
1145 { 1341 {
1146 if (!ret.ContainsKey(item.ItemID)) 1342 string n = e.GetXMLState(item.ItemID);
1147 ret[item.ItemID] = n; 1343 if (n != String.Empty)
1148 break; 1344 {
1345 if (oldIDs)
1346 {
1347 if (!ret.ContainsKey(item.OldItemID))
1348 ret[item.OldItemID] = n;
1349 }
1350 else
1351 {
1352 if (!ret.ContainsKey(item.ItemID))
1353 ret[item.ItemID] = n;
1354 }
1355 break;
1356 }
1149 } 1357 }
1150 } 1358 }
1151 } 1359 }
1152 } 1360 }
1153 1361 Items.LockItemsForRead(false);
1154 return ret; 1362 return ret;
1155 } 1363 }
1156 1364
@@ -1160,21 +1368,27 @@ namespace OpenSim.Region.Framework.Scenes
1160 if (engines.Length == 0) 1368 if (engines.Length == 0)
1161 return; 1369 return;
1162 1370
1163 List<TaskInventoryItem> scripts = GetInventoryScripts();
1164 1371
1165 foreach (TaskInventoryItem item in scripts) 1372 Items.LockItemsForRead(true);
1373
1374 foreach (TaskInventoryItem item in m_items.Values)
1166 { 1375 {
1167 foreach (IScriptModule engine in engines) 1376 if (item.InvType == (int)InventoryType.LSL)
1168 { 1377 {
1169 if (engine != null) 1378 foreach (IScriptModule engine in engines)
1170 { 1379 {
1171 if (item.OwnerChanged) 1380 if (engine != null)
1172 engine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.OWNER }); 1381 {
1173 item.OwnerChanged = false; 1382 if (item.OwnerChanged)
1174 engine.ResumeScript(item.ItemID); 1383 engine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.OWNER });
1384 item.OwnerChanged = false;
1385 engine.ResumeScript(item.ItemID);
1386 }
1175 } 1387 }
1176 } 1388 }
1177 } 1389 }
1390
1391 Items.LockItemsForRead(false);
1178 } 1392 }
1179 } 1393 }
1180} 1394}
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 7be95cd..0eecf77 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -118,7 +118,7 @@ namespace OpenSim.Region.Framework.Scenes
118 /// TODO: For some reason, we effectively have a list both here and in Appearance. Need to work out if this is 118 /// TODO: For some reason, we effectively have a list both here and in Appearance. Need to work out if this is
119 /// necessary. 119 /// necessary.
120 /// </remarks> 120 /// </remarks>
121 protected List<SceneObjectGroup> m_attachments = new List<SceneObjectGroup>(); 121 private List<SceneObjectGroup> m_attachments = new List<SceneObjectGroup>();
122 122
123 public Object AttachmentsSyncLock { get; private set; } 123 public Object AttachmentsSyncLock { get; private set; }
124 124
@@ -167,6 +167,7 @@ namespace OpenSim.Region.Framework.Scenes
167// private int m_lastColCount = -1; //KF: Look for Collision chnages 167// private int m_lastColCount = -1; //KF: Look for Collision chnages
168// private int m_updateCount = 0; //KF: Update Anims for a while 168// private int m_updateCount = 0; //KF: Update Anims for a while
169// private static readonly int UPDATE_COUNT = 10; // how many frames to update for 169// private static readonly int UPDATE_COUNT = 10; // how many frames to update for
170 private List<uint> m_lastColliders = new List<uint>();
170 171
171 private TeleportFlags m_teleportFlags; 172 private TeleportFlags m_teleportFlags;
172 public TeleportFlags TeleportFlags 173 public TeleportFlags TeleportFlags
@@ -228,6 +229,9 @@ namespace OpenSim.Region.Framework.Scenes
228 //private int m_moveToPositionStateStatus; 229 //private int m_moveToPositionStateStatus;
229 //***************************************************** 230 //*****************************************************
230 231
232 private bool m_collisionEventFlag = false;
233 private object m_collisionEventLock = new Object();
234
231 protected AvatarAppearance m_appearance; 235 protected AvatarAppearance m_appearance;
232 236
233 public AvatarAppearance Appearance 237 public AvatarAppearance Appearance
@@ -550,8 +554,12 @@ namespace OpenSim.Region.Framework.Scenes
550 } 554 }
551 } 555 }
552 556
553 m_pos = value; 557 // Don't update while sitting
554 ParentPosition = Vector3.Zero; 558 if (ParentID == 0)
559 {
560 m_pos = value;
561 ParentPosition = Vector3.Zero;
562 }
555 563
556 //m_log.DebugFormat( 564 //m_log.DebugFormat(
557 // "[ENTITY BASE]: In {0} set AbsolutePosition of {1} to {2}", 565 // "[ENTITY BASE]: In {0} set AbsolutePosition of {1} to {2}",
@@ -566,6 +574,13 @@ namespace OpenSim.Region.Framework.Scenes
566 public Vector3 OffsetPosition 574 public Vector3 OffsetPosition
567 { 575 {
568 get { return m_pos; } 576 get { return m_pos; }
577 set
578 {
579 // There is no offset position when not seated
580 if (ParentID == 0)
581 return;
582 m_pos = value;
583 }
569 } 584 }
570 585
571 /// <summary> 586 /// <summary>
@@ -879,6 +894,8 @@ namespace OpenSim.Region.Framework.Scenes
879 pos.Y = crossedBorder.BorderLine.Z - 1; 894 pos.Y = crossedBorder.BorderLine.Z - 1;
880 } 895 }
881 896
897 CheckAndAdjustLandingPoint(ref pos);
898
882 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f) 899 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f)
883 { 900 {
884 m_log.WarnFormat( 901 m_log.WarnFormat(
@@ -1043,6 +1060,7 @@ namespace OpenSim.Region.Framework.Scenes
1043 bool isFlying = Flying; 1060 bool isFlying = Flying;
1044 RemoveFromPhysicalScene(); 1061 RemoveFromPhysicalScene();
1045 Velocity = Vector3.Zero; 1062 Velocity = Vector3.Zero;
1063 CheckLandingPoint(ref pos);
1046 AbsolutePosition = pos; 1064 AbsolutePosition = pos;
1047 AddToPhysicalScene(isFlying); 1065 AddToPhysicalScene(isFlying);
1048 1066
@@ -1053,6 +1071,7 @@ namespace OpenSim.Region.Framework.Scenes
1053 { 1071 {
1054 bool isFlying = Flying; 1072 bool isFlying = Flying;
1055 RemoveFromPhysicalScene(); 1073 RemoveFromPhysicalScene();
1074 CheckLandingPoint(ref pos);
1056 AbsolutePosition = pos; 1075 AbsolutePosition = pos;
1057 AddToPhysicalScene(isFlying); 1076 AddToPhysicalScene(isFlying);
1058 1077
@@ -1818,6 +1837,7 @@ namespace OpenSim.Region.Framework.Scenes
1818 if (part.SitTargetAvatar == UUID) 1837 if (part.SitTargetAvatar == UUID)
1819 part.SitTargetAvatar = UUID.Zero; 1838 part.SitTargetAvatar = UUID.Zero;
1820 1839
1840 part.ParentGroup.DeleteAvatar(UUID);
1821 ParentPosition = part.GetWorldPosition(); 1841 ParentPosition = part.GetWorldPosition();
1822 ControllingClient.SendClearFollowCamProperties(part.ParentUUID); 1842 ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
1823 } 1843 }
@@ -2241,11 +2261,13 @@ namespace OpenSim.Region.Framework.Scenes
2241 m_pos = sitTargetPos + SIT_TARGET_ADJUSTMENT; 2261 m_pos = sitTargetPos + SIT_TARGET_ADJUSTMENT;
2242 Rotation = sitTargetOrient; 2262 Rotation = sitTargetOrient;
2243 ParentPosition = part.AbsolutePosition; 2263 ParentPosition = part.AbsolutePosition;
2264 part.ParentGroup.AddAvatar(UUID);
2244 } 2265 }
2245 else 2266 else
2246 { 2267 {
2247 m_pos -= part.AbsolutePosition; 2268 m_pos -= part.AbsolutePosition;
2248 ParentPosition = part.AbsolutePosition; 2269 ParentPosition = part.AbsolutePosition;
2270 part.ParentGroup.AddAvatar(UUID);
2249 2271
2250// m_log.DebugFormat( 2272// m_log.DebugFormat(
2251// "[SCENE PRESENCE]: Sitting {0} at position {1} ({2} + {3}) on part {4} {5} without sit target", 2273// "[SCENE PRESENCE]: Sitting {0} at position {1} ({2} + {3}) on part {4} {5} without sit target",
@@ -2741,6 +2763,9 @@ namespace OpenSim.Region.Framework.Scenes
2741 if (IsChildAgent) 2763 if (IsChildAgent)
2742 return; 2764 return;
2743 2765
2766 if (ParentID != 0)
2767 return;
2768
2744 Vector3 pos2 = AbsolutePosition; 2769 Vector3 pos2 = AbsolutePosition;
2745 Vector3 vel = Velocity; 2770 Vector3 vel = Velocity;
2746 int neighbor = 0; 2771 int neighbor = 0;
@@ -3101,30 +3126,28 @@ namespace OpenSim.Region.Framework.Scenes
3101 catch { } 3126 catch { }
3102 3127
3103 // Attachment objects 3128 // Attachment objects
3104 lock (m_attachments) 3129 List<SceneObjectGroup> attachments = GetAttachments();
3130 if (attachments.Count > 0)
3105 { 3131 {
3106 if (m_attachments.Count > 0) 3132 cAgent.AttachmentObjects = new List<ISceneObject>();
3107 { 3133 cAgent.AttachmentObjectStates = new List<string>();
3108 cAgent.AttachmentObjects = new List<ISceneObject>(); 3134// IScriptModule se = m_scene.RequestModuleInterface<IScriptModule>();
3109 cAgent.AttachmentObjectStates = new List<string>(); 3135 InTransitScriptStates.Clear();
3110 // IScriptModule se = m_scene.RequestModuleInterface<IScriptModule>();
3111 InTransitScriptStates.Clear();
3112 3136
3113 foreach (SceneObjectGroup sog in m_attachments) 3137 foreach (SceneObjectGroup sog in attachments)
3114 { 3138 {
3115 // We need to make a copy and pass that copy 3139 // We need to make a copy and pass that copy
3116 // because of transfers withn the same sim 3140 // because of transfers withn the same sim
3117 ISceneObject clone = sog.CloneForNewScene(); 3141 ISceneObject clone = sog.CloneForNewScene();
3118 // Attachment module assumes that GroupPosition holds the offsets...! 3142 // Attachment module assumes that GroupPosition holds the offsets...!
3119 ((SceneObjectGroup)clone).RootPart.GroupPosition = sog.RootPart.AttachedPos; 3143 ((SceneObjectGroup)clone).RootPart.GroupPosition = sog.RootPart.AttachedPos;
3120 ((SceneObjectGroup)clone).IsAttachment = false; 3144 ((SceneObjectGroup)clone).IsAttachment = false;
3121 cAgent.AttachmentObjects.Add(clone); 3145 cAgent.AttachmentObjects.Add(clone);
3122 string state = sog.GetStateSnapshot(); 3146 string state = sog.GetStateSnapshot();
3123 cAgent.AttachmentObjectStates.Add(state); 3147 cAgent.AttachmentObjectStates.Add(state);
3124 InTransitScriptStates.Add(state); 3148 InTransitScriptStates.Add(state);
3125 // Let's remove the scripts of the original object here 3149 // Let's remove the scripts of the original object here
3126 sog.RemoveScriptInstances(true); 3150 sog.RemoveScriptInstances(true);
3127 }
3128 } 3151 }
3129 } 3152 }
3130 } 3153 }
@@ -3347,6 +3370,8 @@ namespace OpenSim.Region.Framework.Scenes
3347 } 3370 }
3348 } 3371 }
3349 3372
3373 RaiseCollisionScriptEvents(coldata);
3374
3350 if (Invulnerable) 3375 if (Invulnerable)
3351 return; 3376 return;
3352 3377
@@ -3532,26 +3557,29 @@ namespace OpenSim.Region.Framework.Scenes
3532 /// <param name="args">The arguments for the event</param> 3557 /// <param name="args">The arguments for the event</param>
3533 public void SendScriptEventToAttachments(string eventName, Object[] args) 3558 public void SendScriptEventToAttachments(string eventName, Object[] args)
3534 { 3559 {
3535 if (m_scriptEngines.Length == 0) 3560 Util.FireAndForget(delegate(object x)
3536 return;
3537
3538 lock (m_attachments)
3539 { 3561 {
3540 foreach (SceneObjectGroup grp in m_attachments) 3562 if (m_scriptEngines.Length == 0)
3563 return;
3564
3565 lock (m_attachments)
3541 { 3566 {
3542 // 16384 is CHANGED_ANIMATION 3567 foreach (SceneObjectGroup grp in m_attachments)
3543 //
3544 // Send this to all attachment root prims
3545 //
3546 foreach (IScriptModule m in m_scriptEngines)
3547 { 3568 {
3548 if (m == null) // No script engine loaded 3569 // 16384 is CHANGED_ANIMATION
3549 continue; 3570 //
3571 // Send this to all attachment root prims
3572 //
3573 foreach (IScriptModule m in m_scriptEngines)
3574 {
3575 if (m == null) // No script engine loaded
3576 continue;
3550 3577
3551 m.PostObjectEvent(grp.RootPart.UUID, "changed", new Object[] { (int)Changed.ANIMATION }); 3578 m.PostObjectEvent(grp.RootPart.UUID, "changed", new Object[] { (int)Changed.ANIMATION });
3579 }
3552 } 3580 }
3553 } 3581 }
3554 } 3582 });
3555 } 3583 }
3556 3584
3557 internal void PushForce(Vector3 impulse) 3585 internal void PushForce(Vector3 impulse)
@@ -3783,5 +3811,221 @@ namespace OpenSim.Region.Framework.Scenes
3783 m_reprioritization_called = false; 3811 m_reprioritization_called = false;
3784 } 3812 }
3785 } 3813 }
3814
3815 private void CheckLandingPoint(ref Vector3 pos)
3816 {
3817 // Never constrain lures
3818 if ((TeleportFlags & TeleportFlags.ViaLure) != 0)
3819 return;
3820
3821 if (m_scene.RegionInfo.EstateSettings.AllowDirectTeleport)
3822 return;
3823
3824 ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y);
3825
3826 if (land.LandData.LandingType == (byte)LandingType.LandingPoint &&
3827 land.LandData.UserLocation != Vector3.Zero &&
3828 land.LandData.OwnerID != m_uuid &&
3829 (!m_scene.Permissions.IsGod(m_uuid)) &&
3830 (!m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid)))
3831 {
3832 float curr = Vector3.Distance(AbsolutePosition, pos);
3833 if (Vector3.Distance(land.LandData.UserLocation, pos) < curr)
3834 pos = land.LandData.UserLocation;
3835 else
3836 ControllingClient.SendAlertMessage("Can't teleport closer to destination");
3837 }
3838 }
3839
3840 private void CheckAndAdjustLandingPoint(ref Vector3 pos)
3841 {
3842 ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y);
3843 if (land != null)
3844 {
3845 // If we come in via login, landmark or map, we want to
3846 // honor landing points. If we come in via Lure, we want
3847 // to ignore them.
3848 if ((m_teleportFlags & (TeleportFlags.ViaLogin | TeleportFlags.ViaRegionID)) == (TeleportFlags.ViaLogin | TeleportFlags.ViaRegionID) ||
3849 (m_teleportFlags & TeleportFlags.ViaLandmark) != 0 ||
3850 (m_teleportFlags & TeleportFlags.ViaLocation) != 0)
3851 {
3852 // Don't restrict gods, estate managers, or land owners to
3853 // the TP point. This behaviour mimics agni.
3854 if (land.LandData.LandingType == (byte)LandingType.LandingPoint &&
3855 land.LandData.UserLocation != Vector3.Zero &&
3856 GodLevel < 200 &&
3857 ((land.LandData.OwnerID != m_uuid &&
3858 (!m_scene.Permissions.IsGod(m_uuid)) &&
3859 (!m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid))) || (m_teleportFlags & TeleportFlags.ViaLocation) != 0))
3860 {
3861 pos = land.LandData.UserLocation;
3862 }
3863 }
3864
3865 land.SendLandUpdateToClient(ControllingClient);
3866 }
3867 }
3868
3869 private void RaiseCollisionScriptEvents(Dictionary<uint, ContactPoint> coldata)
3870 {
3871 lock(m_collisionEventLock)
3872 {
3873 if (m_collisionEventFlag)
3874 return;
3875 m_collisionEventFlag = true;
3876 }
3877
3878 Util.FireAndForget(delegate(object x)
3879 {
3880 try
3881 {
3882 List<uint> thisHitColliders = new List<uint>();
3883 List<uint> endedColliders = new List<uint>();
3884 List<uint> startedColliders = new List<uint>();
3885
3886 foreach (uint localid in coldata.Keys)
3887 {
3888 thisHitColliders.Add(localid);
3889 if (!m_lastColliders.Contains(localid))
3890 {
3891 startedColliders.Add(localid);
3892 }
3893 //m_log.Debug("[SCENE PRESENCE]: Collided with:" + localid.ToString() + " at depth of: " + collissionswith[localid].ToString());
3894 }
3895
3896 // calculate things that ended colliding
3897 foreach (uint localID in m_lastColliders)
3898 {
3899 if (!thisHitColliders.Contains(localID))
3900 {
3901 endedColliders.Add(localID);
3902 }
3903 }
3904 //add the items that started colliding this time to the last colliders list.
3905 foreach (uint localID in startedColliders)
3906 {
3907 m_lastColliders.Add(localID);
3908 }
3909 // remove things that ended colliding from the last colliders list
3910 foreach (uint localID in endedColliders)
3911 {
3912 m_lastColliders.Remove(localID);
3913 }
3914
3915 // do event notification
3916 if (startedColliders.Count > 0)
3917 {
3918 ColliderArgs StartCollidingMessage = new ColliderArgs();
3919 List<DetectedObject> colliding = new List<DetectedObject>();
3920 foreach (uint localId in startedColliders)
3921 {
3922 if (localId == 0)
3923 continue;
3924
3925 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
3926 string data = "";
3927 if (obj != null)
3928 {
3929 DetectedObject detobj = new DetectedObject();
3930 detobj.keyUUID = obj.UUID;
3931 detobj.nameStr = obj.Name;
3932 detobj.ownerUUID = obj.OwnerID;
3933 detobj.posVector = obj.AbsolutePosition;
3934 detobj.rotQuat = obj.GetWorldRotation();
3935 detobj.velVector = obj.Velocity;
3936 detobj.colliderType = 0;
3937 detobj.groupUUID = obj.GroupID;
3938 colliding.Add(detobj);
3939 }
3940 }
3941
3942 if (colliding.Count > 0)
3943 {
3944 StartCollidingMessage.Colliders = colliding;
3945
3946 foreach (SceneObjectGroup att in GetAttachments())
3947 Scene.EventManager.TriggerScriptCollidingStart(att.LocalId, StartCollidingMessage);
3948 }
3949 }
3950
3951 if (endedColliders.Count > 0)
3952 {
3953 ColliderArgs EndCollidingMessage = new ColliderArgs();
3954 List<DetectedObject> colliding = new List<DetectedObject>();
3955 foreach (uint localId in endedColliders)
3956 {
3957 if (localId == 0)
3958 continue;
3959
3960 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
3961 string data = "";
3962 if (obj != null)
3963 {
3964 DetectedObject detobj = new DetectedObject();
3965 detobj.keyUUID = obj.UUID;
3966 detobj.nameStr = obj.Name;
3967 detobj.ownerUUID = obj.OwnerID;
3968 detobj.posVector = obj.AbsolutePosition;
3969 detobj.rotQuat = obj.GetWorldRotation();
3970 detobj.velVector = obj.Velocity;
3971 detobj.colliderType = 0;
3972 detobj.groupUUID = obj.GroupID;
3973 colliding.Add(detobj);
3974 }
3975 }
3976
3977 if (colliding.Count > 0)
3978 {
3979 EndCollidingMessage.Colliders = colliding;
3980
3981 foreach (SceneObjectGroup att in GetAttachments())
3982 Scene.EventManager.TriggerScriptCollidingEnd(att.LocalId, EndCollidingMessage);
3983 }
3984 }
3985
3986 if (thisHitColliders.Count > 0)
3987 {
3988 ColliderArgs CollidingMessage = new ColliderArgs();
3989 List<DetectedObject> colliding = new List<DetectedObject>();
3990 foreach (uint localId in thisHitColliders)
3991 {
3992 if (localId == 0)
3993 continue;
3994
3995 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
3996 string data = "";
3997 if (obj != null)
3998 {
3999 DetectedObject detobj = new DetectedObject();
4000 detobj.keyUUID = obj.UUID;
4001 detobj.nameStr = obj.Name;
4002 detobj.ownerUUID = obj.OwnerID;
4003 detobj.posVector = obj.AbsolutePosition;
4004 detobj.rotQuat = obj.GetWorldRotation();
4005 detobj.velVector = obj.Velocity;
4006 detobj.colliderType = 0;
4007 detobj.groupUUID = obj.GroupID;
4008 colliding.Add(detobj);
4009 }
4010 }
4011
4012 if (colliding.Count > 0)
4013 {
4014 CollidingMessage.Colliders = colliding;
4015
4016 lock (m_attachments)
4017 {
4018 foreach (SceneObjectGroup att in m_attachments)
4019 Scene.EventManager.TriggerScriptColliding(att.LocalId, CollidingMessage);
4020 }
4021 }
4022 }
4023 }
4024 finally
4025 {
4026 m_collisionEventFlag = false;
4027 }
4028 });
4029 }
3786 } 4030 }
3787} 4031}
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
index 60cc788..5f2f7d8 100644
--- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
+++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
@@ -345,6 +345,9 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
345 m_SOPXmlProcessors.Add("PayPrice2", ProcessPayPrice2); 345 m_SOPXmlProcessors.Add("PayPrice2", ProcessPayPrice2);
346 m_SOPXmlProcessors.Add("PayPrice3", ProcessPayPrice3); 346 m_SOPXmlProcessors.Add("PayPrice3", ProcessPayPrice3);
347 m_SOPXmlProcessors.Add("PayPrice4", ProcessPayPrice4); 347 m_SOPXmlProcessors.Add("PayPrice4", ProcessPayPrice4);
348
349 m_SOPXmlProcessors.Add("Buoyancy", ProcessBuoyancy);
350 m_SOPXmlProcessors.Add("VolumeDetectActive", ProcessVolumeDetectActive);
348 #endregion 351 #endregion
349 352
350 #region TaskInventoryXmlProcessors initialization 353 #region TaskInventoryXmlProcessors initialization
@@ -729,6 +732,16 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
729 obj.PayPrice[4] = (int)reader.ReadElementContentAsInt("PayPrice4", String.Empty); 732 obj.PayPrice[4] = (int)reader.ReadElementContentAsInt("PayPrice4", String.Empty);
730 } 733 }
731 734
735 private static void ProcessBuoyancy(SceneObjectPart obj, XmlTextReader reader)
736 {
737 obj.Buoyancy = (int)reader.ReadElementContentAsFloat("Buoyancy", String.Empty);
738 }
739
740 private static void ProcessVolumeDetectActive(SceneObjectPart obj, XmlTextReader reader)
741 {
742 obj.VolumeDetectActive = Util.ReadBoolean(reader);
743 }
744
732 #endregion 745 #endregion
733 746
734 #region TaskInventoryXmlProcessors 747 #region TaskInventoryXmlProcessors
@@ -1212,6 +1225,9 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1212 writer.WriteElementString("PayPrice3", sop.PayPrice[3].ToString()); 1225 writer.WriteElementString("PayPrice3", sop.PayPrice[3].ToString());
1213 writer.WriteElementString("PayPrice4", sop.PayPrice[4].ToString()); 1226 writer.WriteElementString("PayPrice4", sop.PayPrice[4].ToString());
1214 1227
1228 writer.WriteElementString("Buoyancy", sop.Buoyancy.ToString());
1229 writer.WriteElementString("VolumeDetectActive", sop.VolumeDetectActive.ToString().ToLower());
1230
1215 writer.WriteEndElement(); 1231 writer.WriteEndElement();
1216 } 1232 }
1217 1233
@@ -1496,12 +1512,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1496 { 1512 {
1497 TaskInventoryDictionary tinv = new TaskInventoryDictionary(); 1513 TaskInventoryDictionary tinv = new TaskInventoryDictionary();
1498 1514
1499 if (reader.IsEmptyElement)
1500 {
1501 reader.Read();
1502 return tinv;
1503 }
1504
1505 reader.ReadStartElement(name, String.Empty); 1515 reader.ReadStartElement(name, String.Empty);
1506 1516
1507 while (reader.Name == "TaskInventoryItem") 1517 while (reader.Name == "TaskInventoryItem")
@@ -1544,12 +1554,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1544 1554
1545 PrimitiveBaseShape shape = new PrimitiveBaseShape(); 1555 PrimitiveBaseShape shape = new PrimitiveBaseShape();
1546 1556
1547 if (reader.IsEmptyElement)
1548 {
1549 reader.Read();
1550 return shape;
1551 }
1552
1553 reader.ReadStartElement(name, String.Empty); // Shape 1557 reader.ReadStartElement(name, String.Empty); // Shape
1554 1558
1555 string nodeName = string.Empty; 1559 string nodeName = string.Empty;
diff --git a/OpenSim/Region/Framework/Scenes/UndoState.cs b/OpenSim/Region/Framework/Scenes/UndoState.cs
index 860172c..5ed3c79 100644
--- a/OpenSim/Region/Framework/Scenes/UndoState.cs
+++ b/OpenSim/Region/Framework/Scenes/UndoState.cs
@@ -30,12 +30,27 @@ using System.Reflection;
30using log4net; 30using log4net;
31using OpenMetaverse; 31using OpenMetaverse;
32using OpenSim.Region.Framework.Interfaces; 32using OpenSim.Region.Framework.Interfaces;
33using System;
33 34
34namespace OpenSim.Region.Framework.Scenes 35namespace OpenSim.Region.Framework.Scenes
35{ 36{
37 [Flags]
38 public enum UndoType
39 {
40 STATE_PRIM_POSITION = 1,
41 STATE_PRIM_ROTATION = 2,
42 STATE_PRIM_SCALE = 4,
43 STATE_PRIM_ALL = 7,
44 STATE_GROUP_POSITION = 8,
45 STATE_GROUP_ROTATION = 16,
46 STATE_GROUP_SCALE = 32,
47 STATE_GROUP_ALL = 56,
48 STATE_ALL = 63
49 }
50
36 public class UndoState 51 public class UndoState
37 { 52 {
38// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 53 // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
39 54
40 public Vector3 Position = Vector3.Zero; 55 public Vector3 Position = Vector3.Zero;
41 public Vector3 Scale = Vector3.Zero; 56 public Vector3 Scale = Vector3.Zero;
@@ -57,37 +72,37 @@ namespace OpenSim.Region.Framework.Scenes
57 { 72 {
58 ForGroup = forGroup; 73 ForGroup = forGroup;
59 74
60// if (ForGroup) 75 // if (ForGroup)
61 Position = part.ParentGroup.AbsolutePosition; 76 Position = part.ParentGroup.AbsolutePosition;
62// else 77 // else
63// Position = part.OffsetPosition; 78 // Position = part.OffsetPosition;
64 79
65// m_log.DebugFormat( 80 // m_log.DebugFormat(
66// "[UNDO STATE]: Storing undo position {0} for root part", Position); 81 // "[UNDO STATE]: Storing undo position {0} for root part", Position);
67 82
68 Rotation = part.RotationOffset; 83 Rotation = part.RotationOffset;
69 84
70// m_log.DebugFormat( 85 // m_log.DebugFormat(
71// "[UNDO STATE]: Storing undo rotation {0} for root part", Rotation); 86 // "[UNDO STATE]: Storing undo rotation {0} for root part", Rotation);
72 87
73 Scale = part.Shape.Scale; 88 Scale = part.Shape.Scale;
74 89
75// m_log.DebugFormat( 90 // m_log.DebugFormat(
76// "[UNDO STATE]: Storing undo scale {0} for root part", Scale); 91 // "[UNDO STATE]: Storing undo scale {0} for root part", Scale);
77 } 92 }
78 else 93 else
79 { 94 {
80 Position = part.OffsetPosition; 95 Position = part.OffsetPosition;
81// m_log.DebugFormat( 96 // m_log.DebugFormat(
82// "[UNDO STATE]: Storing undo position {0} for child part", Position); 97 // "[UNDO STATE]: Storing undo position {0} for child part", Position);
83 98
84 Rotation = part.RotationOffset; 99 Rotation = part.RotationOffset;
85// m_log.DebugFormat( 100 // m_log.DebugFormat(
86// "[UNDO STATE]: Storing undo rotation {0} for child part", Rotation); 101 // "[UNDO STATE]: Storing undo rotation {0} for child part", Rotation);
87 102
88 Scale = part.Shape.Scale; 103 Scale = part.Shape.Scale;
89// m_log.DebugFormat( 104 // m_log.DebugFormat(
90// "[UNDO STATE]: Storing undo scale {0} for child part", Scale); 105 // "[UNDO STATE]: Storing undo scale {0} for child part", Scale);
91 } 106 }
92 } 107 }
93 108
@@ -121,9 +136,9 @@ namespace OpenSim.Region.Framework.Scenes
121 136
122 if (part.ParentID == 0) 137 if (part.ParentID == 0)
123 { 138 {
124// m_log.DebugFormat( 139 // m_log.DebugFormat(
125// "[UNDO STATE]: Undoing position to {0} for root part {1} {2}", 140 // "[UNDO STATE]: Undoing position to {0} for root part {1} {2}",
126// Position, part.Name, part.LocalId); 141 // Position, part.Name, part.LocalId);
127 142
128 if (Position != Vector3.Zero) 143 if (Position != Vector3.Zero)
129 { 144 {
@@ -133,9 +148,9 @@ namespace OpenSim.Region.Framework.Scenes
133 part.ParentGroup.UpdateRootPosition(Position); 148 part.ParentGroup.UpdateRootPosition(Position);
134 } 149 }
135 150
136// m_log.DebugFormat( 151 // m_log.DebugFormat(
137// "[UNDO STATE]: Undoing rotation {0} to {1} for root part {2} {3}", 152 // "[UNDO STATE]: Undoing rotation {0} to {1} for root part {2} {3}",
138// part.RotationOffset, Rotation, part.Name, part.LocalId); 153 // part.RotationOffset, Rotation, part.Name, part.LocalId);
139 154
140 if (ForGroup) 155 if (ForGroup)
141 part.UpdateRotation(Rotation); 156 part.UpdateRotation(Rotation);
@@ -144,9 +159,9 @@ namespace OpenSim.Region.Framework.Scenes
144 159
145 if (Scale != Vector3.Zero) 160 if (Scale != Vector3.Zero)
146 { 161 {
147// m_log.DebugFormat( 162 // m_log.DebugFormat(
148// "[UNDO STATE]: Undoing scale {0} to {1} for root part {2} {3}", 163 // "[UNDO STATE]: Undoing scale {0} to {1} for root part {2} {3}",
149// part.Shape.Scale, Scale, part.Name, part.LocalId); 164 // part.Shape.Scale, Scale, part.Name, part.LocalId);
150 165
151 if (ForGroup) 166 if (ForGroup)
152 part.ParentGroup.GroupResize(Scale); 167 part.ParentGroup.GroupResize(Scale);
@@ -161,24 +176,24 @@ namespace OpenSim.Region.Framework.Scenes
161 // Note: Updating these properties on sop automatically schedules an update if needed 176 // Note: Updating these properties on sop automatically schedules an update if needed
162 if (Position != Vector3.Zero) 177 if (Position != Vector3.Zero)
163 { 178 {
164// m_log.DebugFormat( 179 // m_log.DebugFormat(
165// "[UNDO STATE]: Undoing position {0} to {1} for child part {2} {3}", 180 // "[UNDO STATE]: Undoing position {0} to {1} for child part {2} {3}",
166// part.OffsetPosition, Position, part.Name, part.LocalId); 181 // part.OffsetPosition, Position, part.Name, part.LocalId);
167 182
168 part.OffsetPosition = Position; 183 part.OffsetPosition = Position;
169 } 184 }
170 185
171// m_log.DebugFormat( 186 // m_log.DebugFormat(
172// "[UNDO STATE]: Undoing rotation {0} to {1} for child part {2} {3}", 187 // "[UNDO STATE]: Undoing rotation {0} to {1} for child part {2} {3}",
173// part.RotationOffset, Rotation, part.Name, part.LocalId); 188 // part.RotationOffset, Rotation, part.Name, part.LocalId);
174 189
175 part.UpdateRotation(Rotation); 190 part.UpdateRotation(Rotation);
176 191
177 if (Scale != Vector3.Zero) 192 if (Scale != Vector3.Zero)
178 { 193 {
179// m_log.DebugFormat( 194 // m_log.DebugFormat(
180// "[UNDO STATE]: Undoing scale {0} to {1} for child part {2} {3}", 195 // "[UNDO STATE]: Undoing scale {0} to {1} for child part {2} {3}",
181// part.Shape.Scale, Scale, part.Name, part.LocalId); 196 // part.Shape.Scale, Scale, part.Name, part.LocalId);
182 197
183 part.Resize(Scale); 198 part.Resize(Scale);
184 } 199 }
@@ -247,4 +262,4 @@ namespace OpenSim.Region.Framework.Scenes
247 m_terrainModule.UndoTerrain(m_terrainChannel); 262 m_terrainModule.UndoTerrain(m_terrainChannel);
248 } 263 }
249 } 264 }
250} \ No newline at end of file 265}
diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
index efb68a2..411e421 100644
--- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
+++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
@@ -87,10 +87,6 @@ namespace OpenSim.Region.Framework.Scenes
87 /// <param name="assetUuids">The assets gathered</param> 87 /// <param name="assetUuids">The assets gathered</param>
88 public void GatherAssetUuids(UUID assetUuid, AssetType assetType, IDictionary<UUID, AssetType> assetUuids) 88 public void GatherAssetUuids(UUID assetUuid, AssetType assetType, IDictionary<UUID, AssetType> assetUuids)
89 { 89 {
90 // avoid infinite loops
91 if (assetUuids.ContainsKey(assetUuid))
92 return;
93
94 try 90 try
95 { 91 {
96 assetUuids[assetUuid] = assetType; 92 assetUuids[assetUuid] = assetType;