aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework/Scenes')
-rw-r--r--OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs26
-rw-r--r--OpenSim/Region/Framework/Scenes/EntityManager.cs79
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs27
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs75
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs4
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs94
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs26
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs702
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs153
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs722
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs681
11 files changed, 1749 insertions, 840 deletions
diff --git a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
index de4c5fb..702a1e2 100644
--- a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
+++ b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
@@ -53,10 +53,11 @@ namespace OpenSim.Region.Framework.Scenes.Animation
53 { 53 {
54 get { return m_movementAnimation; } 54 get { return m_movementAnimation; }
55 } 55 }
56 protected string m_movementAnimation = "DEFAULT"; 56 // protected string m_movementAnimation = "DEFAULT"; //KF: 'DEFAULT' does not exist!
57 57 protected string m_movementAnimation = "CROUCH"; //KF: CROUCH ensures reliable Av Anim. init.
58 private int m_animTickFall; 58 private int m_animTickFall;
59 private int m_animTickJump; 59// private int m_animTickJump;
60 public int m_animTickJump; // ScenePresence has to see this to control +Z force
60 61
61 /// <value> 62 /// <value>
62 /// The scene presence that this animator applies to 63 /// The scene presence that this animator applies to
@@ -123,8 +124,6 @@ namespace OpenSim.Region.Framework.Scenes.Animation
123 /// </summary> 124 /// </summary>
124 public void TrySetMovementAnimation(string anim) 125 public void TrySetMovementAnimation(string anim)
125 { 126 {
126 //m_log.DebugFormat("Updating movement animation to {0}", anim);
127
128 if (!m_scenePresence.IsChildAgent) 127 if (!m_scenePresence.IsChildAgent)
129 { 128 {
130 if (m_animations.TrySetDefaultAnimation( 129 if (m_animations.TrySetDefaultAnimation(
@@ -146,10 +145,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
146 const float PREJUMP_DELAY = 0.25f; 145 const float PREJUMP_DELAY = 0.25f;
147 146
148 #region Inputs 147 #region Inputs
149 if (m_scenePresence.SitGround) 148
150 {
151 return "SIT_GROUND_CONSTRAINED";
152 }
153 AgentManager.ControlFlags controlFlags = (AgentManager.ControlFlags)m_scenePresence.AgentControlFlags; 149 AgentManager.ControlFlags controlFlags = (AgentManager.ControlFlags)m_scenePresence.AgentControlFlags;
154 PhysicsActor actor = m_scenePresence.PhysicsActor; 150 PhysicsActor actor = m_scenePresence.PhysicsActor;
155 151
@@ -159,11 +155,10 @@ namespace OpenSim.Region.Framework.Scenes.Animation
159 Vector3 left = Vector3.Transform(Vector3.UnitY, rotMatrix); 155 Vector3 left = Vector3.Transform(Vector3.UnitY, rotMatrix);
160 156
161 // Check control flags 157 // Check control flags
162 bool heldForward = 158 bool heldForward = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_AT_POS || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS);
163 (((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) || ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS)); 159 bool heldBack = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG);
164 bool heldBack = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG; 160 bool heldLeft = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS);
165 bool heldLeft = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS; 161 bool heldRight = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG);
166 bool heldRight = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG;
167 //bool heldTurnLeft = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT; 162 //bool heldTurnLeft = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT;
168 //bool heldTurnRight = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT; 163 //bool heldTurnRight = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT;
169 bool heldUp = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) == AgentManager.ControlFlags.AGENT_CONTROL_UP_POS; 164 bool heldUp = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) == AgentManager.ControlFlags.AGENT_CONTROL_UP_POS;
@@ -266,7 +261,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
266 m_animTickJump = Environment.TickCount; 261 m_animTickJump = Environment.TickCount;
267 return "PREJUMP"; 262 return "PREJUMP";
268 } 263 }
269 else if (Environment.TickCount - m_animTickJump > PREJUMP_DELAY * 1000.0f) 264 else if (Environment.TickCount - m_animTickJump > PREJUMP_DELAY * 800.0f)
270 { 265 {
271 // Start actual jump 266 // Start actual jump
272 if (m_animTickJump == -1) 267 if (m_animTickJump == -1)
@@ -316,7 +311,6 @@ namespace OpenSim.Region.Framework.Scenes.Animation
316 public void UpdateMovementAnimations() 311 public void UpdateMovementAnimations()
317 { 312 {
318 m_movementAnimation = GetMovementAnimation(); 313 m_movementAnimation = GetMovementAnimation();
319
320 if (m_movementAnimation == "PREJUMP" && !m_scenePresence.Scene.m_usePreJump) 314 if (m_movementAnimation == "PREJUMP" && !m_scenePresence.Scene.m_usePreJump)
321 { 315 {
322 // This was the previous behavior before PREJUMP 316 // This was the previous behavior before PREJUMP
diff --git a/OpenSim/Region/Framework/Scenes/EntityManager.cs b/OpenSim/Region/Framework/Scenes/EntityManager.cs
index 099fcce..c246e32 100644
--- a/OpenSim/Region/Framework/Scenes/EntityManager.cs
+++ b/OpenSim/Region/Framework/Scenes/EntityManager.cs
@@ -40,7 +40,7 @@ namespace OpenSim.Region.Framework.Scenes
40 private readonly Dictionary<UUID,EntityBase> m_eb_uuid = new Dictionary<UUID, EntityBase>(); 40 private readonly Dictionary<UUID,EntityBase> m_eb_uuid = new Dictionary<UUID, EntityBase>();
41 private readonly Dictionary<uint, EntityBase> m_eb_localID = new Dictionary<uint, EntityBase>(); 41 private readonly Dictionary<uint, EntityBase> m_eb_localID = new Dictionary<uint, EntityBase>();
42 //private readonly Dictionary<UUID, ScenePresence> m_pres_uuid = new Dictionary<UUID, ScenePresence>(); 42 //private readonly Dictionary<UUID, ScenePresence> m_pres_uuid = new Dictionary<UUID, ScenePresence>();
43 private readonly Object m_lock = new Object(); 43 private System.Threading.ReaderWriterLockSlim m_lock = new System.Threading.ReaderWriterLockSlim();
44 44
45 [Obsolete("Use Add() instead.")] 45 [Obsolete("Use Add() instead.")]
46 public void Add(UUID id, EntityBase eb) 46 public void Add(UUID id, EntityBase eb)
@@ -50,7 +50,8 @@ namespace OpenSim.Region.Framework.Scenes
50 50
51 public void Add(EntityBase entity) 51 public void Add(EntityBase entity)
52 { 52 {
53 lock (m_lock) 53 m_lock.EnterWriteLock();
54 try
54 { 55 {
55 try 56 try
56 { 57 {
@@ -62,11 +63,16 @@ namespace OpenSim.Region.Framework.Scenes
62 m_log.ErrorFormat("Add Entity failed: {0}", e.Message); 63 m_log.ErrorFormat("Add Entity failed: {0}", e.Message);
63 } 64 }
64 } 65 }
66 finally
67 {
68 m_lock.ExitWriteLock();
69 }
65 } 70 }
66 71
67 public void InsertOrReplace(EntityBase entity) 72 public void InsertOrReplace(EntityBase entity)
68 { 73 {
69 lock (m_lock) 74 m_lock.EnterWriteLock();
75 try
70 { 76 {
71 try 77 try
72 { 78 {
@@ -78,15 +84,24 @@ namespace OpenSim.Region.Framework.Scenes
78 m_log.ErrorFormat("Insert or Replace Entity failed: {0}", e.Message); 84 m_log.ErrorFormat("Insert or Replace Entity failed: {0}", e.Message);
79 } 85 }
80 } 86 }
87 finally
88 {
89 m_lock.ExitWriteLock();
90 }
81 } 91 }
82 92
83 public void Clear() 93 public void Clear()
84 { 94 {
85 lock (m_lock) 95 m_lock.EnterWriteLock();
96 try
86 { 97 {
87 m_eb_uuid.Clear(); 98 m_eb_uuid.Clear();
88 m_eb_localID.Clear(); 99 m_eb_localID.Clear();
89 } 100 }
101 finally
102 {
103 m_lock.ExitWriteLock();
104 }
90 } 105 }
91 106
92 public int Count 107 public int Count
@@ -123,7 +138,8 @@ namespace OpenSim.Region.Framework.Scenes
123 138
124 public bool Remove(uint localID) 139 public bool Remove(uint localID)
125 { 140 {
126 lock (m_lock) 141 m_lock.EnterWriteLock();
142 try
127 { 143 {
128 try 144 try
129 { 145 {
@@ -141,11 +157,16 @@ namespace OpenSim.Region.Framework.Scenes
141 return false; 157 return false;
142 } 158 }
143 } 159 }
160 finally
161 {
162 m_lock.ExitWriteLock();
163 }
144 } 164 }
145 165
146 public bool Remove(UUID id) 166 public bool Remove(UUID id)
147 { 167 {
148 lock (m_lock) 168 m_lock.EnterWriteLock();
169 try
149 { 170 {
150 try 171 try
151 { 172 {
@@ -163,13 +184,18 @@ namespace OpenSim.Region.Framework.Scenes
163 return false; 184 return false;
164 } 185 }
165 } 186 }
187 finally
188 {
189 m_lock.ExitWriteLock();
190 }
166 } 191 }
167 192
168 public List<EntityBase> GetAllByType<T>() 193 public List<EntityBase> GetAllByType<T>()
169 { 194 {
170 List<EntityBase> tmp = new List<EntityBase>(); 195 List<EntityBase> tmp = new List<EntityBase>();
171 196
172 lock (m_lock) 197 m_lock.EnterReadLock();
198 try
173 { 199 {
174 try 200 try
175 { 201 {
@@ -187,23 +213,33 @@ namespace OpenSim.Region.Framework.Scenes
187 tmp = null; 213 tmp = null;
188 } 214 }
189 } 215 }
216 finally
217 {
218 m_lock.ExitReadLock();
219 }
190 220
191 return tmp; 221 return tmp;
192 } 222 }
193 223
194 public List<EntityBase> GetEntities() 224 public List<EntityBase> GetEntities()
195 { 225 {
196 lock (m_lock) 226 m_lock.EnterReadLock();
227 try
197 { 228 {
198 return new List<EntityBase>(m_eb_uuid.Values); 229 return new List<EntityBase>(m_eb_uuid.Values);
199 } 230 }
231 finally
232 {
233 m_lock.ExitReadLock();
234 }
200 } 235 }
201 236
202 public EntityBase this[UUID id] 237 public EntityBase this[UUID id]
203 { 238 {
204 get 239 get
205 { 240 {
206 lock (m_lock) 241 m_lock.EnterReadLock();
242 try
207 { 243 {
208 EntityBase entity; 244 EntityBase entity;
209 if (m_eb_uuid.TryGetValue(id, out entity)) 245 if (m_eb_uuid.TryGetValue(id, out entity))
@@ -211,6 +247,10 @@ namespace OpenSim.Region.Framework.Scenes
211 else 247 else
212 return null; 248 return null;
213 } 249 }
250 finally
251 {
252 m_lock.ExitReadLock();
253 }
214 } 254 }
215 set 255 set
216 { 256 {
@@ -222,7 +262,8 @@ namespace OpenSim.Region.Framework.Scenes
222 { 262 {
223 get 263 get
224 { 264 {
225 lock (m_lock) 265 m_lock.EnterReadLock();
266 try
226 { 267 {
227 EntityBase entity; 268 EntityBase entity;
228 if (m_eb_localID.TryGetValue(localID, out entity)) 269 if (m_eb_localID.TryGetValue(localID, out entity))
@@ -230,6 +271,10 @@ namespace OpenSim.Region.Framework.Scenes
230 else 271 else
231 return null; 272 return null;
232 } 273 }
274 finally
275 {
276 m_lock.ExitReadLock();
277 }
233 } 278 }
234 set 279 set
235 { 280 {
@@ -239,18 +284,28 @@ namespace OpenSim.Region.Framework.Scenes
239 284
240 public bool TryGetValue(UUID key, out EntityBase obj) 285 public bool TryGetValue(UUID key, out EntityBase obj)
241 { 286 {
242 lock (m_lock) 287 m_lock.EnterReadLock();
288 try
243 { 289 {
244 return m_eb_uuid.TryGetValue(key, out obj); 290 return m_eb_uuid.TryGetValue(key, out obj);
245 } 291 }
292 finally
293 {
294 m_lock.ExitReadLock();
295 }
246 } 296 }
247 297
248 public bool TryGetValue(uint key, out EntityBase obj) 298 public bool TryGetValue(uint key, out EntityBase obj)
249 { 299 {
250 lock (m_lock) 300 m_lock.EnterReadLock();
301 try
251 { 302 {
252 return m_eb_localID.TryGetValue(key, out obj); 303 return m_eb_localID.TryGetValue(key, out obj);
253 } 304 }
305 finally
306 {
307 m_lock.ExitReadLock();
308 }
254 } 309 }
255 310
256 /// <summary> 311 /// <summary>
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index 64bdc99..5e1798b 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -94,6 +94,22 @@ namespace OpenSim.Region.Framework.Scenes
94 94
95 public void AddInventoryItem(UUID AgentID, InventoryItemBase item) 95 public void AddInventoryItem(UUID AgentID, InventoryItemBase item)
96 { 96 {
97 InventoryFolderBase folder;
98
99 if (item.Folder == UUID.Zero)
100 {
101 folder = InventoryService.GetFolderForType(AgentID, (AssetType)item.AssetType);
102 if (folder == null)
103 {
104 folder = InventoryService.GetRootFolder(AgentID);
105
106 if (folder == null)
107 return;
108 }
109
110 item.Folder = folder.ID;
111 }
112
97 if (InventoryService.AddItem(item)) 113 if (InventoryService.AddItem(item))
98 { 114 {
99 int userlevel = 0; 115 int userlevel = 0;
@@ -214,8 +230,7 @@ namespace OpenSim.Region.Framework.Scenes
214 { 230 {
215 // Needs to determine which engine was running it and use that 231 // Needs to determine which engine was running it and use that
216 // 232 //
217 part.Inventory.CreateScriptInstance(item.ItemID, 0, false, DefaultScriptEngine, 0); 233 errors = part.Inventory.CreateScriptInstanceEr(item.ItemID, 0, false, DefaultScriptEngine, 0);
218 errors = part.Inventory.GetScriptErrors(item.ItemID);
219 } 234 }
220 else 235 else
221 { 236 {
@@ -836,8 +851,12 @@ namespace OpenSim.Region.Framework.Scenes
836 public void RemoveTaskInventory(IClientAPI remoteClient, UUID itemID, uint localID) 851 public void RemoveTaskInventory(IClientAPI remoteClient, UUID itemID, uint localID)
837 { 852 {
838 SceneObjectPart part = GetSceneObjectPart(localID); 853 SceneObjectPart part = GetSceneObjectPart(localID);
839 SceneObjectGroup group = part.ParentGroup; 854 SceneObjectGroup group = null;
840 if (group != null) 855 if (part != null)
856 {
857 group = part.ParentGroup;
858 }
859 if (part != null && group != null)
841 { 860 {
842 TaskInventoryItem item = group.GetInventoryItem(localID, itemID); 861 TaskInventoryItem item = group.GetInventoryItem(localID, itemID);
843 if (item == null) 862 if (item == null)
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 9594e6b..7bea166 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -149,6 +149,20 @@ namespace OpenSim.Region.Framework.Scenes
149 149
150 public IXfer XferManager; 150 public IXfer XferManager;
151 151
152 protected ISnmpModule m_snmpService = null;
153 public ISnmpModule SnmpService
154 {
155 get
156 {
157 if (m_snmpService == null)
158 {
159 m_snmpService = RequestModuleInterface<ISnmpModule>();
160 }
161
162 return m_snmpService;
163 }
164 }
165
152 protected IAssetService m_AssetService; 166 protected IAssetService m_AssetService;
153 protected IAuthorizationService m_AuthorizationService; 167 protected IAuthorizationService m_AuthorizationService;
154 168
@@ -609,6 +623,8 @@ namespace OpenSim.Region.Framework.Scenes
609 623
610 // Load region settings 624 // Load region settings
611 m_regInfo.RegionSettings = m_storageManager.DataStore.LoadRegionSettings(m_regInfo.RegionID); 625 m_regInfo.RegionSettings = m_storageManager.DataStore.LoadRegionSettings(m_regInfo.RegionID);
626 m_regInfo.WindlightSettings = m_storageManager.DataStore.LoadRegionWindlightSettings(m_regInfo.RegionID);
627
612 if (m_storageManager.EstateDataStore != null) 628 if (m_storageManager.EstateDataStore != null)
613 { 629 {
614 m_regInfo.EstateSettings = m_storageManager.EstateDataStore.LoadEstateSettings(m_regInfo.RegionID, false); 630 m_regInfo.EstateSettings = m_storageManager.EstateDataStore.LoadEstateSettings(m_regInfo.RegionID, false);
@@ -711,7 +727,7 @@ namespace OpenSim.Region.Framework.Scenes
711 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false); 727 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false);
712 // TODO: Change default to true once the feature is supported 728 // TODO: Change default to true once the feature is supported
713 m_usePreJump = startupConfig.GetBoolean("enableprejump", false); 729 m_usePreJump = startupConfig.GetBoolean("enableprejump", false);
714 730 m_usePreJump = true; // Above line fails!?
715 m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys); 731 m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys);
716 if (RegionInfo.NonphysPrimMax > 0) 732 if (RegionInfo.NonphysPrimMax > 0)
717 { 733 {
@@ -1031,6 +1047,15 @@ namespace OpenSim.Region.Framework.Scenes
1031 /// <param name="seconds">float indicating duration before restart.</param> 1047 /// <param name="seconds">float indicating duration before restart.</param>
1032 public virtual void Restart(float seconds) 1048 public virtual void Restart(float seconds)
1033 { 1049 {
1050 Restart(seconds, true);
1051 }
1052
1053 /// <summary>
1054 /// Given float seconds, this will restart the region. showDialog will optionally alert the users.
1055 /// </summary>
1056 /// <param name="seconds">float indicating duration before restart.</param>
1057 public virtual void Restart(float seconds, bool showDialog)
1058 {
1034 // notifications are done in 15 second increments 1059 // notifications are done in 15 second increments
1035 // so .. if the number of seconds is less then 15 seconds, it's not really a restart request 1060 // so .. if the number of seconds is less then 15 seconds, it's not really a restart request
1036 // It's a 'Cancel restart' request. 1061 // It's a 'Cancel restart' request.
@@ -1051,8 +1076,11 @@ namespace OpenSim.Region.Framework.Scenes
1051 m_restartTimer.Elapsed += new ElapsedEventHandler(RestartTimer_Elapsed); 1076 m_restartTimer.Elapsed += new ElapsedEventHandler(RestartTimer_Elapsed);
1052 m_log.Info("[REGION]: Restarting Region in " + (seconds / 60) + " minutes"); 1077 m_log.Info("[REGION]: Restarting Region in " + (seconds / 60) + " minutes");
1053 m_restartTimer.Start(); 1078 m_restartTimer.Start();
1054 m_dialogModule.SendNotificationToUsersInRegion( 1079 if (showDialog)
1080 {
1081 m_dialogModule.SendNotificationToUsersInRegion(
1055 UUID.Random(), String.Empty, RegionInfo.RegionName + String.Format(": Restarting in {0} Minutes", (int)(seconds / 60.0))); 1082 UUID.Random(), String.Empty, RegionInfo.RegionName + String.Format(": Restarting in {0} Minutes", (int)(seconds / 60.0)));
1083 }
1056 } 1084 }
1057 } 1085 }
1058 1086
@@ -1408,16 +1436,16 @@ namespace OpenSim.Region.Framework.Scenes
1408 // Check if any objects have reached their targets 1436 // Check if any objects have reached their targets
1409 CheckAtTargets(); 1437 CheckAtTargets();
1410 1438
1411 // Update SceneObjectGroups that have scheduled themselves for updates
1412 // Objects queue their updates onto all scene presences
1413 if (m_frame % m_update_objects == 0)
1414 m_sceneGraph.UpdateObjectGroups();
1415
1416 // Run through all ScenePresences looking for updates 1439 // Run through all ScenePresences looking for updates
1417 // Presence updates and queued object updates for each presence are sent to clients 1440 // Presence updates and queued object updates for each presence are sent to clients
1418 if (m_frame % m_update_presences == 0) 1441 if (m_frame % m_update_presences == 0)
1419 m_sceneGraph.UpdatePresences(); 1442 m_sceneGraph.UpdatePresences();
1420 1443
1444 // Update SceneObjectGroups that have scheduled themselves for updates
1445 // Objects queue their updates onto all scene presences
1446 if (m_frame % m_update_objects == 0)
1447 m_sceneGraph.UpdateObjectGroups();
1448
1421 if (m_frame % m_update_coarse_locations == 0) 1449 if (m_frame % m_update_coarse_locations == 0)
1422 { 1450 {
1423 List<Vector3> coarseLocations; 1451 List<Vector3> coarseLocations;
@@ -2157,7 +2185,7 @@ namespace OpenSim.Region.Framework.Scenes
2157 public bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) 2185 public bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates)
2158 { 2186 {
2159 return m_sceneGraph.AddNewSceneObject(sceneObject, attachToBackup, sendClientUpdates); 2187 return m_sceneGraph.AddNewSceneObject(sceneObject, attachToBackup, sendClientUpdates);
2160 } 2188 }
2161 2189
2162 /// <summary> 2190 /// <summary>
2163 /// Delete every object from the scene. This does not include attachments worn by avatars. 2191 /// Delete every object from the scene. This does not include attachments worn by avatars.
@@ -3514,12 +3542,15 @@ namespace OpenSim.Region.Framework.Scenes
3514 { 3542 {
3515 // We have a zombie from a crashed session. Kill it. 3543 // We have a zombie from a crashed session. Kill it.
3516 m_log.DebugFormat("[SCENE]: Zombie scene presence detected for {0} in {1}", agent.AgentID, RegionInfo.RegionName); 3544 m_log.DebugFormat("[SCENE]: Zombie scene presence detected for {0} in {1}", agent.AgentID, RegionInfo.RegionName);
3517 sp.ControllingClient.Close(); 3545 sp.ControllingClient.Close(false);
3518 } 3546 }
3519 } 3547 }
3520 3548
3521 CapsModule.AddCapsHandler(agent.AgentID); 3549 CapsModule.AddCapsHandler(agent.AgentID);
3522 3550
3551 if ((teleportFlags & ((uint)TeleportFlags.ViaLandmark | (uint)TeleportFlags.ViaLocation | (uint)TeleportFlags.ViaLandmark | (uint)TeleportFlags.Default)) != 0)
3552 System.Threading.Thread.Sleep(2000);
3553
3523 if (!agent.child) 3554 if (!agent.child)
3524 { 3555 {
3525 if (TestBorderCross(agent.startpos,Cardinals.E)) 3556 if (TestBorderCross(agent.startpos,Cardinals.E))
@@ -3578,6 +3609,8 @@ namespace OpenSim.Region.Framework.Scenes
3578 } 3609 }
3579 } 3610 }
3580 // Honor parcel landing type and position. 3611 // Honor parcel landing type and position.
3612 /*
3613 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3581 if (land != null) 3614 if (land != null)
3582 { 3615 {
3583 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) 3616 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero)
@@ -3585,6 +3618,7 @@ namespace OpenSim.Region.Framework.Scenes
3585 agent.startpos = land.LandData.UserLocation; 3618 agent.startpos = land.LandData.UserLocation;
3586 } 3619 }
3587 } 3620 }
3621 */// This is now handled properly in ScenePresence.MakeRootAgent
3588 } 3622 }
3589 3623
3590 agent.teleportFlags = teleportFlags; 3624 agent.teleportFlags = teleportFlags;
@@ -3948,12 +3982,22 @@ namespace OpenSim.Region.Framework.Scenes
3948 return false; 3982 return false;
3949 } 3983 }
3950 3984
3985 public bool IncomingCloseAgent(UUID agentID)
3986 {
3987 return IncomingCloseAgent(agentID, false);
3988 }
3989
3990 public bool IncomingCloseChildAgent(UUID agentID)
3991 {
3992 return IncomingCloseAgent(agentID, true);
3993 }
3994
3951 /// <summary> 3995 /// <summary>
3952 /// Tell a single agent to disconnect from the region. 3996 /// Tell a single agent to disconnect from the region.
3953 /// </summary> 3997 /// </summary>
3954 /// <param name="regionHandle"></param>
3955 /// <param name="agentID"></param> 3998 /// <param name="agentID"></param>
3956 public bool IncomingCloseAgent(UUID agentID) 3999 /// <param name="childOnly"></param>
4000 public bool IncomingCloseAgent(UUID agentID, bool childOnly)
3957 { 4001 {
3958 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); 4002 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID);
3959 4003
@@ -3965,7 +4009,7 @@ namespace OpenSim.Region.Framework.Scenes
3965 { 4009 {
3966 m_sceneGraph.removeUserCount(false); 4010 m_sceneGraph.removeUserCount(false);
3967 } 4011 }
3968 else 4012 else if (!childOnly)
3969 { 4013 {
3970 m_sceneGraph.removeUserCount(true); 4014 m_sceneGraph.removeUserCount(true);
3971 } 4015 }
@@ -3981,9 +4025,12 @@ namespace OpenSim.Region.Framework.Scenes
3981 } 4025 }
3982 else 4026 else
3983 presence.ControllingClient.SendShutdownConnectionNotice(); 4027 presence.ControllingClient.SendShutdownConnectionNotice();
4028 presence.ControllingClient.Close(false);
4029 }
4030 else if (!childOnly)
4031 {
4032 presence.ControllingClient.Close(true);
3984 } 4033 }
3985
3986 presence.ControllingClient.Close();
3987 return true; 4034 return true;
3988 } 4035 }
3989 4036
diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
index bd8ccce..6309cd9 100644
--- a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
@@ -281,7 +281,7 @@ namespace OpenSim.Region.Framework.Scenes
281 uint x = 0, y = 0; 281 uint x = 0, y = 0;
282 Utils.LongToUInts(regionHandle, out x, out y); 282 Utils.LongToUInts(regionHandle, out x, out y);
283 GridRegion destination = m_scene.GridService.GetRegionByPosition(UUID.Zero, (int)x, (int)y); 283 GridRegion destination = m_scene.GridService.GetRegionByPosition(UUID.Zero, (int)x, (int)y);
284 m_scene.SimulationService.CloseAgent(destination, agentID); 284 m_scene.SimulationService.CloseChildAgent(destination, agentID);
285 } 285 }
286 286
287 private void SendCloseChildAgentCompleted(IAsyncResult iar) 287 private void SendCloseChildAgentCompleted(IAsyncResult iar)
@@ -300,7 +300,7 @@ namespace OpenSim.Region.Framework.Scenes
300 d); 300 d);
301 } 301 }
302 } 302 }
303 303
304 public List<GridRegion> RequestNamedRegions(string name, int maxNumber) 304 public List<GridRegion> RequestNamedRegions(string name, int maxNumber)
305 { 305 {
306 return m_scene.GridService.GetRegionsByName(UUID.Zero, name, maxNumber); 306 return m_scene.GridService.GetRegionsByName(UUID.Zero, name, maxNumber);
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index 673674d..80f9114 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -68,7 +68,7 @@ namespace OpenSim.Region.Framework.Scenes
68 68
69 #region Fields 69 #region Fields
70 70
71 protected object m_presenceLock = new object(); 71 protected OpenMetaverse.ReaderWriterLockSlim m_scenePresencesLock = new OpenMetaverse.ReaderWriterLockSlim();
72 protected Dictionary<UUID, ScenePresence> m_scenePresenceMap = new Dictionary<UUID, ScenePresence>(); 72 protected Dictionary<UUID, ScenePresence> m_scenePresenceMap = new Dictionary<UUID, ScenePresence>();
73 protected List<ScenePresence> m_scenePresenceArray = new List<ScenePresence>(); 73 protected List<ScenePresence> m_scenePresenceArray = new List<ScenePresence>();
74 74
@@ -133,13 +133,18 @@ namespace OpenSim.Region.Framework.Scenes
133 133
134 protected internal void Close() 134 protected internal void Close()
135 { 135 {
136 lock (m_presenceLock) 136 m_scenePresencesLock.EnterWriteLock();
137 try
137 { 138 {
138 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(); 139 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>();
139 List<ScenePresence> newlist = new List<ScenePresence>(); 140 List<ScenePresence> newlist = new List<ScenePresence>();
140 m_scenePresenceMap = newmap; 141 m_scenePresenceMap = newmap;
141 m_scenePresenceArray = newlist; 142 m_scenePresenceArray = newlist;
142 } 143 }
144 finally
145 {
146 m_scenePresencesLock.ExitWriteLock();
147 }
143 148
144 lock (m_dictionary_lock) 149 lock (m_dictionary_lock)
145 { 150 {
@@ -269,6 +274,30 @@ namespace OpenSim.Region.Framework.Scenes
269 protected internal bool AddRestoredSceneObject( 274 protected internal bool AddRestoredSceneObject(
270 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 275 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
271 { 276 {
277 // KF: Check for out-of-region, move inside and make static.
278 Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X,
279 sceneObject.RootPart.GroupPosition.Y,
280 sceneObject.RootPart.GroupPosition.Z);
281 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 ||
282 npos.X > Constants.RegionSize ||
283 npos.Y > Constants.RegionSize))
284 {
285 if (npos.X < 0.0) npos.X = 1.0f;
286 if (npos.Y < 0.0) npos.Y = 1.0f;
287 if (npos.Z < 0.0) npos.Z = 0.0f;
288 if (npos.X > Constants.RegionSize) npos.X = Constants.RegionSize - 1.0f;
289 if (npos.Y > Constants.RegionSize) npos.Y = Constants.RegionSize - 1.0f;
290
291 foreach (SceneObjectPart part in sceneObject.Children.Values)
292 {
293 part.GroupPosition = npos;
294 }
295 sceneObject.RootPart.Velocity = Vector3.Zero;
296 sceneObject.RootPart.AngularVelocity = Vector3.Zero;
297 sceneObject.RootPart.Acceleration = Vector3.Zero;
298 sceneObject.RootPart.Velocity = Vector3.Zero;
299 }
300
272 if (!alreadyPersisted) 301 if (!alreadyPersisted)
273 { 302 {
274 sceneObject.ForceInventoryPersistence(); 303 sceneObject.ForceInventoryPersistence();
@@ -565,7 +594,8 @@ namespace OpenSim.Region.Framework.Scenes
565 594
566 Entities[presence.UUID] = presence; 595 Entities[presence.UUID] = presence;
567 596
568 lock (m_presenceLock) 597 m_scenePresencesLock.EnterWriteLock();
598 try
569 { 599 {
570 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 600 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
571 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 601 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -589,6 +619,10 @@ namespace OpenSim.Region.Framework.Scenes
589 m_scenePresenceMap = newmap; 619 m_scenePresenceMap = newmap;
590 m_scenePresenceArray = newlist; 620 m_scenePresenceArray = newlist;
591 } 621 }
622 finally
623 {
624 m_scenePresencesLock.ExitWriteLock();
625 }
592 } 626 }
593 627
594 /// <summary> 628 /// <summary>
@@ -603,7 +637,8 @@ namespace OpenSim.Region.Framework.Scenes
603 agentID); 637 agentID);
604 } 638 }
605 639
606 lock (m_presenceLock) 640 m_scenePresencesLock.EnterWriteLock();
641 try
607 { 642 {
608 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 643 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
609 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 644 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -624,6 +659,10 @@ namespace OpenSim.Region.Framework.Scenes
624 m_log.WarnFormat("[SCENE] Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); 659 m_log.WarnFormat("[SCENE] Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID);
625 } 660 }
626 } 661 }
662 finally
663 {
664 m_scenePresencesLock.ExitWriteLock();
665 }
627 } 666 }
628 667
629 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) 668 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F)
@@ -1501,10 +1540,13 @@ namespace OpenSim.Region.Framework.Scenes
1501 /// <param name="childPrims"></param> 1540 /// <param name="childPrims"></param>
1502 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children) 1541 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children)
1503 { 1542 {
1543 SceneObjectGroup parentGroup = root.ParentGroup;
1544 if (parentGroup == null) return;
1504 Monitor.Enter(m_updateLock); 1545 Monitor.Enter(m_updateLock);
1546
1505 try 1547 try
1506 { 1548 {
1507 SceneObjectGroup parentGroup = root.ParentGroup; 1549 parentGroup.areUpdatesSuspended = true;
1508 1550
1509 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); 1551 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
1510 if (parentGroup != null) 1552 if (parentGroup != null)
@@ -1543,12 +1585,12 @@ namespace OpenSim.Region.Framework.Scenes
1543 // occur on link to invoke this elsewhere (such as object selection) 1585 // occur on link to invoke this elsewhere (such as object selection)
1544 parentGroup.RootPart.CreateSelected = true; 1586 parentGroup.RootPart.CreateSelected = true;
1545 parentGroup.TriggerScriptChangedEvent(Changed.LINK); 1587 parentGroup.TriggerScriptChangedEvent(Changed.LINK);
1546 parentGroup.HasGroupChanged = true;
1547 parentGroup.ScheduleGroupForFullUpdate();
1548
1549 } 1588 }
1550 finally 1589 finally
1551 { 1590 {
1591 parentGroup.areUpdatesSuspended = false;
1592 parentGroup.HasGroupChanged = true;
1593 parentGroup.ScheduleGroupForFullUpdate();
1552 Monitor.Exit(m_updateLock); 1594 Monitor.Exit(m_updateLock);
1553 } 1595 }
1554 } 1596 }
@@ -1585,11 +1627,22 @@ namespace OpenSim.Region.Framework.Scenes
1585 } 1627 }
1586 } 1628 }
1587 1629
1588 foreach (SceneObjectPart child in childParts) 1630 if (childParts.Count > 0)
1589 { 1631 {
1590 // Unlink all child parts from their groups 1632 try
1591 // 1633 {
1592 child.ParentGroup.DelinkFromGroup(child, true); 1634 childParts[0].ParentGroup.areUpdatesSuspended = true;
1635 foreach (SceneObjectPart child in childParts)
1636 {
1637 // Unlink all child parts from their groups
1638 //
1639 child.ParentGroup.DelinkFromGroup(child, true);
1640 }
1641 }
1642 finally
1643 {
1644 childParts[0].ParentGroup.areUpdatesSuspended = false;
1645 }
1593 } 1646 }
1594 1647
1595 foreach (SceneObjectPart root in rootParts) 1648 foreach (SceneObjectPart root in rootParts)
@@ -1613,10 +1666,21 @@ namespace OpenSim.Region.Framework.Scenes
1613 if (numChildren > 1) 1666 if (numChildren > 1)
1614 sendEventsToRemainder = false; 1667 sendEventsToRemainder = false;
1615 1668
1616 foreach (SceneObjectPart p in newSet) 1669 if (newSet.Count > 0)
1617 { 1670 {
1618 if (p != group.RootPart) 1671 try
1619 group.DelinkFromGroup(p, sendEventsToRemainder); 1672 {
1673 newSet[0].ParentGroup.areUpdatesSuspended = true;
1674 foreach (SceneObjectPart p in newSet)
1675 {
1676 if (p != group.RootPart)
1677 group.DelinkFromGroup(p, sendEventsToRemainder);
1678 }
1679 }
1680 finally
1681 {
1682 newSet[0].ParentGroup.areUpdatesSuspended = false;
1683 }
1620 } 1684 }
1621 1685
1622 // If there is more than one prim remaining, we 1686 // If there is more than one prim remaining, we
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
index f7e46af..1149a20 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
@@ -46,12 +46,12 @@ namespace OpenSim.Region.Framework.Scenes
46 /// </summary> 46 /// </summary>
47 public void ForceInventoryPersistence() 47 public void ForceInventoryPersistence()
48 { 48 {
49 lock (m_parts) 49 lockPartsForRead(true);
50 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
51 lockPartsForRead(false);
52 foreach (SceneObjectPart part in values)
50 { 53 {
51 foreach (SceneObjectPart part in m_parts.Values) 54 part.Inventory.ForceInventoryPersistence();
52 {
53 part.Inventory.ForceInventoryPersistence();
54 }
55 } 55 }
56 } 56 }
57 57
@@ -74,19 +74,17 @@ namespace OpenSim.Region.Framework.Scenes
74 /// <summary> 74 /// <summary>
75 /// Stop the scripts contained in all the prims in this group 75 /// Stop the scripts contained in all the prims in this group
76 /// </summary> 76 /// </summary>
77 /// <param name="sceneObjectBeingDeleted">
78 /// Should be true if these scripts are being removed because the scene
79 /// object is being deleted. This will prevent spurious updates to the client.
80 /// </param>
81 public void RemoveScriptInstances(bool sceneObjectBeingDeleted) 77 public void RemoveScriptInstances(bool sceneObjectBeingDeleted)
82 { 78 {
83 lock (m_parts) 79 lockPartsForRead(true);
80 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
81 lockPartsForRead(false);
82
83 foreach (SceneObjectPart part in values)
84 { 84 {
85 foreach (SceneObjectPart part in m_parts.Values) 85 part.Inventory.RemoveScriptInstances(sceneObjectBeingDeleted);
86 {
87 part.Inventory.RemoveScriptInstances(sceneObjectBeingDeleted);
88 }
89 } 86 }
87
90 } 88 }
91 89
92 /// <summary> 90 /// <summary>
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index e23f39f..66ad14f 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -104,8 +104,95 @@ namespace OpenSim.Region.Framework.Scenes
104 /// since the group's last persistent backup 104 /// since the group's last persistent backup
105 /// </summary> 105 /// </summary>
106 private bool m_hasGroupChanged = false; 106 private bool m_hasGroupChanged = false;
107 private long timeFirstChanged; 107 private long timeFirstChanged = 0;
108 private long timeLastChanged; 108 private long timeLastChanged = 0;
109 private long m_maxPersistTime = 0;
110 private long m_minPersistTime = 0;
111 private Random m_rand;
112 private bool m_suspendUpdates;
113
114 private System.Threading.ReaderWriterLockSlim m_partsLock = new System.Threading.ReaderWriterLockSlim();
115
116 public bool areUpdatesSuspended
117 {
118 get
119 {
120 return m_suspendUpdates;
121 }
122 set
123 {
124 m_suspendUpdates = value;
125 if (!value)
126 {
127 QueueForUpdateCheck();
128 }
129 }
130 }
131
132 public void lockPartsForRead(bool locked)
133 {
134 if (locked)
135 {
136 if (m_partsLock.RecursiveReadCount > 0)
137 {
138 m_log.Error("[SceneObjectGroup.m_parts] Recursive read lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue.");
139 m_partsLock.ExitReadLock();
140 }
141 if (m_partsLock.RecursiveWriteCount > 0)
142 {
143 m_log.Error("[SceneObjectGroup.m_parts] Recursive read lock requested (write lock exists on this thread). This should not happen and means something needs to be fixed.");
144 m_partsLock.ExitWriteLock();
145 }
146
147 while (!m_partsLock.TryEnterReadLock(60000))
148 {
149 m_log.Error("[SceneObjectGroup.m_parts] Thread lock detected while trying to aquire READ lock of m_parts in SceneObjectGroup. I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed.");
150 if (m_partsLock.IsWriteLockHeld)
151 {
152 m_partsLock = new System.Threading.ReaderWriterLockSlim();
153 }
154 }
155 }
156 else
157 {
158 if (m_partsLock.RecursiveReadCount > 0)
159 {
160 m_partsLock.ExitReadLock();
161 }
162 }
163 }
164 public void lockPartsForWrite(bool locked)
165 {
166 if (locked)
167 {
168 if (m_partsLock.RecursiveReadCount > 0)
169 {
170 m_log.Error("[SceneObjectGroup.m_parts] Recursive write lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue.");
171 m_partsLock.ExitReadLock();
172 }
173 if (m_partsLock.RecursiveWriteCount > 0)
174 {
175 m_log.Error("[SceneObjectGroup.m_parts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
176 m_partsLock.ExitWriteLock();
177 }
178
179 while (!m_partsLock.TryEnterWriteLock(60000))
180 {
181 m_log.Error("[SceneObjectGroup.m_parts] Thread lock detected while trying to aquire WRITE lock of m_scripts in XEngine. I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed.");
182 if (m_partsLock.IsWriteLockHeld)
183 {
184 m_partsLock = new System.Threading.ReaderWriterLockSlim();
185 }
186 }
187 }
188 else
189 {
190 if (m_partsLock.RecursiveWriteCount > 0)
191 {
192 m_partsLock.ExitWriteLock();
193 }
194 }
195 }
109 196
110 public bool HasGroupChanged 197 public bool HasGroupChanged
111 { 198 {
@@ -116,6 +203,32 @@ namespace OpenSim.Region.Framework.Scenes
116 timeLastChanged = DateTime.Now.Ticks; 203 timeLastChanged = DateTime.Now.Ticks;
117 if (!m_hasGroupChanged) 204 if (!m_hasGroupChanged)
118 timeFirstChanged = DateTime.Now.Ticks; 205 timeFirstChanged = DateTime.Now.Ticks;
206 if (m_rootPart != null && m_rootPart.UUID != null && m_scene != null)
207 {
208 if (m_rand == null)
209 {
210 byte[] val = new byte[16];
211 m_rootPart.UUID.ToBytes(val, 0);
212 m_rand = new Random(BitConverter.ToInt32(val, 0));
213 }
214
215 if (m_scene.GetRootAgentCount() == 0)
216 {
217 //If the region is empty, this change has been made by an automated process
218 //and thus we delay the persist time by a random amount between 1.5 and 2.5.
219
220 float factor = 1.5f + (float)(m_rand.NextDouble());
221 m_maxPersistTime = (long)((float)m_scene.m_persistAfter * factor);
222 m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * factor);
223 }
224 else
225 {
226 //If the region is not empty, we want to obey the minimum and maximum persist times
227 //but add a random factor so we stagger the object persistance a little
228 m_maxPersistTime = (long)((float)m_scene.m_persistAfter * (1.0d - (m_rand.NextDouble() / 5.0d))); //Multiply by 1.0-1.5
229 m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * (1.0d + (m_rand.NextDouble() / 2.0d))); //Multiply by 0.8-1.0
230 }
231 }
119 } 232 }
120 m_hasGroupChanged = value; 233 m_hasGroupChanged = value;
121 } 234 }
@@ -131,8 +244,19 @@ namespace OpenSim.Region.Framework.Scenes
131 return false; 244 return false;
132 if (m_scene.ShuttingDown) 245 if (m_scene.ShuttingDown)
133 return true; 246 return true;
247
248 if (m_minPersistTime == 0 || m_maxPersistTime == 0)
249 {
250 m_maxPersistTime = m_scene.m_persistAfter;
251 m_minPersistTime = m_scene.m_dontPersistBefore;
252 }
253
134 long currentTime = DateTime.Now.Ticks; 254 long currentTime = DateTime.Now.Ticks;
135 if (currentTime - timeLastChanged > m_scene.m_dontPersistBefore || currentTime - timeFirstChanged > m_scene.m_persistAfter) 255
256 if (timeLastChanged == 0) timeLastChanged = currentTime;
257 if (timeFirstChanged == 0) timeFirstChanged = currentTime;
258
259 if (currentTime - timeLastChanged > m_minPersistTime || currentTime - timeFirstChanged > m_maxPersistTime)
136 return true; 260 return true;
137 return false; 261 return false;
138 } 262 }
@@ -258,13 +382,16 @@ namespace OpenSim.Region.Framework.Scenes
258 set 382 set
259 { 383 {
260 m_regionHandle = value; 384 m_regionHandle = value;
261 lock (m_parts) 385 lockPartsForRead(true);
262 { 386 {
263 foreach (SceneObjectPart part in m_parts.Values) 387 foreach (SceneObjectPart part in m_parts.Values)
264 { 388 {
389
265 part.RegionHandle = m_regionHandle; 390 part.RegionHandle = m_regionHandle;
391
266 } 392 }
267 } 393 }
394 lockPartsForRead(false);
268 } 395 }
269 } 396 }
270 397
@@ -298,6 +425,9 @@ namespace OpenSim.Region.Framework.Scenes
298 { 425 {
299 m_scene.CrossPrimGroupIntoNewRegion(val, this, true); 426 m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
300 } 427 }
428
429 lockPartsForRead(true);
430
301 if (RootPart.GetStatusSandbox()) 431 if (RootPart.GetStatusSandbox())
302 { 432 {
303 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) 433 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10)
@@ -305,17 +435,18 @@ namespace OpenSim.Region.Framework.Scenes
305 RootPart.ScriptSetPhysicsStatus(false); 435 RootPart.ScriptSetPhysicsStatus(false);
306 Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"), 436 Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"),
307 ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false); 437 ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false);
438 lockPartsForRead(false);
308 return; 439 return;
309 } 440 }
310 } 441 }
311 lock (m_parts) 442
443 foreach (SceneObjectPart part in m_parts.Values)
312 { 444 {
313 foreach (SceneObjectPart part in m_parts.Values) 445 part.GroupPosition = val;
314 {
315 part.GroupPosition = val;
316 }
317 } 446 }
318 447
448 lockPartsForRead(false);
449
319 //if (m_rootPart.PhysActor != null) 450 //if (m_rootPart.PhysActor != null)
320 //{ 451 //{
321 //m_rootPart.PhysActor.Position = 452 //m_rootPart.PhysActor.Position =
@@ -457,6 +588,7 @@ namespace OpenSim.Region.Framework.Scenes
457 /// </summary> 588 /// </summary>
458 public SceneObjectGroup() 589 public SceneObjectGroup()
459 { 590 {
591
460 } 592 }
461 593
462 /// <summary> 594 /// <summary>
@@ -473,7 +605,7 @@ namespace OpenSim.Region.Framework.Scenes
473 /// Constructor. This object is added to the scene later via AttachToScene() 605 /// Constructor. This object is added to the scene later via AttachToScene()
474 /// </summary> 606 /// </summary>
475 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) 607 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape)
476 { 608 {
477 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero)); 609 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero));
478 } 610 }
479 611
@@ -504,13 +636,16 @@ namespace OpenSim.Region.Framework.Scenes
504 636
505 public void SetFromItemID(UUID AssetId) 637 public void SetFromItemID(UUID AssetId)
506 { 638 {
507 lock (m_parts) 639 lockPartsForRead(true);
508 { 640 {
509 foreach (SceneObjectPart part in m_parts.Values) 641 foreach (SceneObjectPart part in m_parts.Values)
510 { 642 {
643
511 part.FromItemID = AssetId; 644 part.FromItemID = AssetId;
645
512 } 646 }
513 } 647 }
648 lockPartsForRead(false);
514 } 649 }
515 650
516 public UUID GetFromItemID() 651 public UUID GetFromItemID()
@@ -579,10 +714,11 @@ namespace OpenSim.Region.Framework.Scenes
579 Vector3 maxScale = Vector3.Zero; 714 Vector3 maxScale = Vector3.Zero;
580 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f); 715 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f);
581 716
582 lock (m_parts) 717 lockPartsForRead(true);
583 { 718 {
584 foreach (SceneObjectPart part in m_parts.Values) 719 foreach (SceneObjectPart part in m_parts.Values)
585 { 720 {
721
586 Vector3 partscale = part.Scale; 722 Vector3 partscale = part.Scale;
587 Vector3 partoffset = part.OffsetPosition; 723 Vector3 partoffset = part.OffsetPosition;
588 724
@@ -593,8 +729,11 @@ namespace OpenSim.Region.Framework.Scenes
593 maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X; 729 maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X;
594 maxScale.Y = (partscale.Y + partoffset.Y > maxScale.Y) ? partscale.Y + partoffset.Y : maxScale.Y; 730 maxScale.Y = (partscale.Y + partoffset.Y > maxScale.Y) ? partscale.Y + partoffset.Y : maxScale.Y;
595 maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z; 731 maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z;
732
596 } 733 }
597 } 734 }
735 lockPartsForRead(false);
736
598 finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X; 737 finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X;
599 finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y; 738 finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y;
600 finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z; 739 finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z;
@@ -610,10 +749,11 @@ namespace OpenSim.Region.Framework.Scenes
610 749
611 EntityIntersection result = new EntityIntersection(); 750 EntityIntersection result = new EntityIntersection();
612 751
613 lock (m_parts) 752 lockPartsForRead(true);
614 { 753 {
615 foreach (SceneObjectPart part in m_parts.Values) 754 foreach (SceneObjectPart part in m_parts.Values)
616 { 755 {
756
617 // Temporary commented to stop compiler warning 757 // Temporary commented to stop compiler warning
618 //Vector3 partPosition = 758 //Vector3 partPosition =
619 // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z); 759 // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z);
@@ -641,8 +781,10 @@ namespace OpenSim.Region.Framework.Scenes
641 result.distance = inter.distance; 781 result.distance = inter.distance;
642 } 782 }
643 } 783 }
784
644 } 785 }
645 } 786 }
787 lockPartsForRead(false);
646 return result; 788 return result;
647 } 789 }
648 790
@@ -661,10 +803,11 @@ namespace OpenSim.Region.Framework.Scenes
661 minY = 256f; 803 minY = 256f;
662 minZ = 8192f; 804 minZ = 8192f;
663 805
664 lock(m_parts); 806 lockPartsForRead(true);
665 { 807 {
666 foreach (SceneObjectPart part in m_parts.Values) 808 foreach (SceneObjectPart part in m_parts.Values)
667 { 809 {
810
668 Vector3 worldPos = part.GetWorldPosition(); 811 Vector3 worldPos = part.GetWorldPosition();
669 Vector3 offset = worldPos - AbsolutePosition; 812 Vector3 offset = worldPos - AbsolutePosition;
670 Quaternion worldRot; 813 Quaternion worldRot;
@@ -723,6 +866,8 @@ namespace OpenSim.Region.Framework.Scenes
723 backBottomRight.Y = orig.Y + (part.Scale.Y / 2); 866 backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
724 backBottomRight.Z = orig.Z - (part.Scale.Z / 2); 867 backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
725 868
869
870
726 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z); 871 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
727 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z); 872 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
728 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z); 873 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
@@ -894,6 +1039,7 @@ namespace OpenSim.Region.Framework.Scenes
894 minZ = backBottomLeft.Z; 1039 minZ = backBottomLeft.Z;
895 } 1040 }
896 } 1041 }
1042 lockPartsForRead(false);
897 } 1043 }
898 1044
899 public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight) 1045 public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight)
@@ -929,21 +1075,29 @@ namespace OpenSim.Region.Framework.Scenes
929 1075
930 public void SaveScriptedState(XmlTextWriter writer) 1076 public void SaveScriptedState(XmlTextWriter writer)
931 { 1077 {
1078 SaveScriptedState(writer, false);
1079 }
1080
1081 public void SaveScriptedState(XmlTextWriter writer, bool oldIDs)
1082 {
932 XmlDocument doc = new XmlDocument(); 1083 XmlDocument doc = new XmlDocument();
933 Dictionary<UUID,string> states = new Dictionary<UUID,string>(); 1084 Dictionary<UUID,string> states = new Dictionary<UUID,string>();
934 1085
935 // Capture script state while holding the lock 1086 // Capture script state while holding the lock
936 lock (m_parts) 1087 lockPartsForRead(true);
937 { 1088 {
938 foreach (SceneObjectPart part in m_parts.Values) 1089 foreach (SceneObjectPart part in m_parts.Values)
939 { 1090 {
940 Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates(); 1091
1092 Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates(oldIDs);
941 foreach (UUID itemid in pstates.Keys) 1093 foreach (UUID itemid in pstates.Keys)
942 { 1094 {
943 states.Add(itemid, pstates[itemid]); 1095 states.Add(itemid, pstates[itemid]);
944 } 1096 }
1097
945 } 1098 }
946 } 1099 }
1100 lockPartsForRead(false);
947 1101
948 if (states.Count > 0) 1102 if (states.Count > 0)
949 { 1103 {
@@ -1112,13 +1266,16 @@ namespace OpenSim.Region.Framework.Scenes
1112 1266
1113 public override void UpdateMovement() 1267 public override void UpdateMovement()
1114 { 1268 {
1115 lock (m_parts) 1269 lockPartsForRead(true);
1116 { 1270 {
1117 foreach (SceneObjectPart part in m_parts.Values) 1271 foreach (SceneObjectPart part in m_parts.Values)
1118 { 1272 {
1273
1119 part.UpdateMovement(); 1274 part.UpdateMovement();
1275
1120 } 1276 }
1121 } 1277 }
1278 lockPartsForRead(false);
1122 } 1279 }
1123 1280
1124 public ushort GetTimeDilation() 1281 public ushort GetTimeDilation()
@@ -1162,7 +1319,7 @@ namespace OpenSim.Region.Framework.Scenes
1162 /// <param name="part"></param> 1319 /// <param name="part"></param>
1163 public void AddPart(SceneObjectPart part) 1320 public void AddPart(SceneObjectPart part)
1164 { 1321 {
1165 lock (m_parts) 1322 lockPartsForWrite(true);
1166 { 1323 {
1167 part.SetParent(this); 1324 part.SetParent(this);
1168 m_parts.Add(part.UUID, part); 1325 m_parts.Add(part.UUID, part);
@@ -1172,6 +1329,7 @@ namespace OpenSim.Region.Framework.Scenes
1172 if (part.LinkNum == 2 && RootPart != null) 1329 if (part.LinkNum == 2 && RootPart != null)
1173 RootPart.LinkNum = 1; 1330 RootPart.LinkNum = 1;
1174 } 1331 }
1332 lockPartsForWrite(false);
1175 } 1333 }
1176 1334
1177 /// <summary> 1335 /// <summary>
@@ -1179,28 +1337,33 @@ namespace OpenSim.Region.Framework.Scenes
1179 /// </summary> 1337 /// </summary>
1180 private void UpdateParentIDs() 1338 private void UpdateParentIDs()
1181 { 1339 {
1182 lock (m_parts) 1340 lockPartsForRead(true);
1183 { 1341 {
1184 foreach (SceneObjectPart part in m_parts.Values) 1342 foreach (SceneObjectPart part in m_parts.Values)
1185 { 1343 {
1344
1186 if (part.UUID != m_rootPart.UUID) 1345 if (part.UUID != m_rootPart.UUID)
1187 { 1346 {
1188 part.ParentID = m_rootPart.LocalId; 1347 part.ParentID = m_rootPart.LocalId;
1189 } 1348 }
1349
1190 } 1350 }
1191 } 1351 }
1352 lockPartsForRead(false);
1192 } 1353 }
1193 1354
1194 public void RegenerateFullIDs() 1355 public void RegenerateFullIDs()
1195 { 1356 {
1196 lock (m_parts) 1357 lockPartsForRead(true);
1197 { 1358 {
1198 foreach (SceneObjectPart part in m_parts.Values) 1359 foreach (SceneObjectPart part in m_parts.Values)
1199 { 1360 {
1361
1200 part.UUID = UUID.Random(); 1362 part.UUID = UUID.Random();
1201 1363
1202 } 1364 }
1203 } 1365 }
1366 lockPartsForRead(false);
1204 } 1367 }
1205 1368
1206 // helper provided for parts. 1369 // helper provided for parts.
@@ -1281,27 +1444,32 @@ namespace OpenSim.Region.Framework.Scenes
1281 1444
1282 DetachFromBackup(); 1445 DetachFromBackup();
1283 1446
1284 lock (m_parts) 1447 lockPartsForRead(true);
1448 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1449 lockPartsForRead(false);
1450
1451 foreach (SceneObjectPart part in values)
1285 { 1452 {
1286 foreach (SceneObjectPart part in m_parts.Values)
1287 {
1288// part.Inventory.RemoveScriptInstances(); 1453// part.Inventory.RemoveScriptInstances();
1289 Scene.ForEachScenePresence(delegate(ScenePresence avatar) 1454
1455 Scene.ForEachScenePresence(delegate (ScenePresence sp)
1456 {
1457 if (sp.ParentID == LocalId)
1290 { 1458 {
1291 if (avatar.ParentID == LocalId) 1459 sp.StandUp();
1292 { 1460 }
1293 avatar.StandUp();
1294 }
1295 1461
1296 if (!silent) 1462 if (!silent)
1297 { 1463 {
1298 part.UpdateFlag = 0; 1464 part.UpdateFlag = 0;
1299 if (part == m_rootPart) 1465 if (part == m_rootPart)
1300 avatar.ControllingClient.SendKillObject(m_regionHandle, part.LocalId); 1466 sp.ControllingClient.SendKillObject(m_regionHandle, part.LocalId);
1301 } 1467 }
1302 }); 1468 });
1303 } 1469
1304 } 1470 }
1471
1472
1305 } 1473 }
1306 1474
1307 public void AddScriptLPS(int count) 1475 public void AddScriptLPS(int count)
@@ -1326,17 +1494,20 @@ namespace OpenSim.Region.Framework.Scenes
1326 1494
1327 scriptEvents aggregateScriptEvents=0; 1495 scriptEvents aggregateScriptEvents=0;
1328 1496
1329 lock (m_parts) 1497 lockPartsForRead(true);
1330 { 1498 {
1331 foreach (SceneObjectPart part in m_parts.Values) 1499 foreach (SceneObjectPart part in m_parts.Values)
1332 { 1500 {
1501
1333 if (part == null) 1502 if (part == null)
1334 continue; 1503 continue;
1335 if (part != RootPart) 1504 if (part != RootPart)
1336 part.ObjectFlags = objectflagupdate; 1505 part.ObjectFlags = objectflagupdate;
1337 aggregateScriptEvents |= part.AggregateScriptEvents; 1506 aggregateScriptEvents |= part.AggregateScriptEvents;
1507
1338 } 1508 }
1339 } 1509 }
1510 lockPartsForRead(false);
1340 1511
1341 m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0); 1512 m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0);
1342 m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0); 1513 m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0);
@@ -1378,42 +1549,52 @@ namespace OpenSim.Region.Framework.Scenes
1378 /// <param name="m_physicalPrim"></param> 1549 /// <param name="m_physicalPrim"></param>
1379 public void ApplyPhysics(bool m_physicalPrim) 1550 public void ApplyPhysics(bool m_physicalPrim)
1380 { 1551 {
1381 lock (m_parts) 1552 lockPartsForRead(true);
1553
1554 if (m_parts.Count > 1)
1382 { 1555 {
1383 if (m_parts.Count > 1) 1556 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1557 lockPartsForRead(false);
1558 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1559 foreach (SceneObjectPart part in values)
1384 { 1560 {
1385 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim); 1561
1386 foreach (SceneObjectPart part in m_parts.Values) 1562 if (part.LocalId != m_rootPart.LocalId)
1387 { 1563 {
1388 if (part.LocalId != m_rootPart.LocalId) 1564 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
1389 {
1390 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
1391 }
1392 } 1565 }
1393 1566
1394 // Hack to get the physics scene geometries in the right spot
1395 ResetChildPrimPhysicsPositions();
1396 }
1397 else
1398 {
1399 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1400 } 1567 }
1568 // Hack to get the physics scene geometries in the right spot
1569 ResetChildPrimPhysicsPositions();
1570 }
1571 else
1572 {
1573 lockPartsForRead(false);
1574 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1401 } 1575 }
1402 } 1576 }
1403 1577
1404 public void SetOwnerId(UUID userId) 1578 public void SetOwnerId(UUID userId)
1405 { 1579 {
1406 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); 1580 ForEachPart(delegate(SceneObjectPart part)
1581 {
1582
1583 part.OwnerID = userId;
1584
1585 });
1407 } 1586 }
1408 1587
1409 public void ForEachPart(Action<SceneObjectPart> whatToDo) 1588 public void ForEachPart(Action<SceneObjectPart> whatToDo)
1410 { 1589 {
1411 lock (m_parts) 1590 lockPartsForRead(true);
1591 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1592 lockPartsForRead(false);
1593 foreach (SceneObjectPart part in values)
1412 { 1594 {
1413 foreach (SceneObjectPart part in m_parts.Values) 1595
1414 { 1596 whatToDo(part);
1415 whatToDo(part); 1597
1416 }
1417 } 1598 }
1418 } 1599 }
1419 1600
@@ -1511,15 +1692,17 @@ namespace OpenSim.Region.Framework.Scenes
1511 RootPart.SendFullUpdate( 1692 RootPart.SendFullUpdate(
1512 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID)); 1693 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID));
1513 1694
1514 lock (m_parts) 1695 lockPartsForRead(true);
1515 { 1696 {
1516 foreach (SceneObjectPart part in m_parts.Values) 1697 foreach (SceneObjectPart part in m_parts.Values)
1517 { 1698 {
1699
1518 if (part != RootPart) 1700 if (part != RootPart)
1519 part.SendFullUpdate( 1701 part.SendFullUpdate(
1520 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID)); 1702 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID));
1521 } 1703 }
1522 } 1704 }
1705 lockPartsForRead(false);
1523 } 1706 }
1524 1707
1525 #region Copying 1708 #region Copying
@@ -1588,10 +1771,11 @@ namespace OpenSim.Region.Framework.Scenes
1588 1771
1589 List<SceneObjectPart> partList; 1772 List<SceneObjectPart> partList;
1590 1773
1591 lock (m_parts) 1774 lockPartsForRead(true);
1592 { 1775
1593 partList = new List<SceneObjectPart>(m_parts.Values); 1776 partList = new List<SceneObjectPart>(m_parts.Values);
1594 } 1777
1778 lockPartsForRead(false);
1595 1779
1596 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) 1780 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1597 { 1781 {
@@ -1814,13 +1998,40 @@ namespace OpenSim.Region.Framework.Scenes
1814 } 1998 }
1815 } 1999 }
1816 2000
2001 public void rotLookAt(Quaternion target, float strength, float damping)
2002 {
2003 SceneObjectPart rootpart = m_rootPart;
2004 if (rootpart != null)
2005 {
2006 if (IsAttachment)
2007 {
2008 /*
2009 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
2010 if (avatar != null)
2011 {
2012 Rotate the Av?
2013 } */
2014 }
2015 else
2016 {
2017 if (rootpart.PhysActor != null)
2018 { // APID must be implemented in your physics system for this to function.
2019 rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W);
2020 rootpart.PhysActor.APIDStrength = strength;
2021 rootpart.PhysActor.APIDDamping = damping;
2022 rootpart.PhysActor.APIDActive = true;
2023 }
2024 }
2025 }
2026 }
2027
1817 public void stopLookAt() 2028 public void stopLookAt()
1818 { 2029 {
1819 SceneObjectPart rootpart = m_rootPart; 2030 SceneObjectPart rootpart = m_rootPart;
1820 if (rootpart != null) 2031 if (rootpart != null)
1821 { 2032 {
1822 if (rootpart.PhysActor != null) 2033 if (rootpart.PhysActor != null)
1823 { 2034 { // APID must be implemented in your physics system for this to function.
1824 rootpart.PhysActor.APIDActive = false; 2035 rootpart.PhysActor.APIDActive = false;
1825 } 2036 }
1826 } 2037 }
@@ -1888,10 +2099,11 @@ namespace OpenSim.Region.Framework.Scenes
1888 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 2099 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
1889 newPart.SetParent(this); 2100 newPart.SetParent(this);
1890 2101
1891 lock (m_parts) 2102 lockPartsForWrite(true);
1892 { 2103 {
1893 m_parts.Add(newPart.UUID, newPart); 2104 m_parts.Add(newPart.UUID, newPart);
1894 } 2105 }
2106 lockPartsForWrite(false);
1895 2107
1896 SetPartAsNonRoot(newPart); 2108 SetPartAsNonRoot(newPart);
1897 2109
@@ -1954,7 +2166,7 @@ namespace OpenSim.Region.Framework.Scenes
1954 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0) 2166 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
1955 // return; 2167 // return;
1956 2168
1957 lock (m_parts) 2169 lockPartsForRead(true);
1958 { 2170 {
1959 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0); 2171 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0);
1960 2172
@@ -1974,9 +2186,12 @@ namespace OpenSim.Region.Framework.Scenes
1974 { 2186 {
1975 if (!IsSelected) 2187 if (!IsSelected)
1976 part.UpdateLookAt(); 2188 part.UpdateLookAt();
2189
1977 part.SendScheduledUpdates(); 2190 part.SendScheduledUpdates();
2191
1978 } 2192 }
1979 } 2193 }
2194 lockPartsForRead(false);
1980 } 2195 }
1981 2196
1982 public void ScheduleFullUpdateToAvatar(ScenePresence presence) 2197 public void ScheduleFullUpdateToAvatar(ScenePresence presence)
@@ -1985,27 +2200,29 @@ namespace OpenSim.Region.Framework.Scenes
1985 2200
1986 RootPart.AddFullUpdateToAvatar(presence); 2201 RootPart.AddFullUpdateToAvatar(presence);
1987 2202
1988 lock (m_parts) 2203 lockPartsForRead(true);
1989 { 2204 {
1990 foreach (SceneObjectPart part in m_parts.Values) 2205 foreach (SceneObjectPart part in m_parts.Values)
1991 { 2206 {
2207
1992 if (part != RootPart) 2208 if (part != RootPart)
1993 part.AddFullUpdateToAvatar(presence); 2209 part.AddFullUpdateToAvatar(presence);
2210
1994 } 2211 }
1995 } 2212 }
2213 lockPartsForRead(false);
1996 } 2214 }
1997 2215
1998 public void ScheduleTerseUpdateToAvatar(ScenePresence presence) 2216 public void ScheduleTerseUpdateToAvatar(ScenePresence presence)
1999 { 2217 {
2000// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1} just to avatar {2}", Name, UUID, presence.Name); 2218 lockPartsForRead(true);
2001 2219
2002 lock (m_parts) 2220 foreach (SceneObjectPart part in m_parts.Values)
2003 { 2221 {
2004 foreach (SceneObjectPart part in m_parts.Values) 2222 part.AddTerseUpdateToAvatar(presence);
2005 {
2006 part.AddTerseUpdateToAvatar(presence);
2007 }
2008 } 2223 }
2224
2225 lockPartsForRead(false);
2009 } 2226 }
2010 2227
2011 /// <summary> 2228 /// <summary>
@@ -2019,14 +2236,17 @@ namespace OpenSim.Region.Framework.Scenes
2019 checkAtTargets(); 2236 checkAtTargets();
2020 RootPart.ScheduleFullUpdate(); 2237 RootPart.ScheduleFullUpdate();
2021 2238
2022 lock (m_parts) 2239 lockPartsForRead(true);
2023 { 2240 {
2024 foreach (SceneObjectPart part in m_parts.Values) 2241 foreach (SceneObjectPart part in m_parts.Values)
2025 { 2242 {
2243
2026 if (part != RootPart) 2244 if (part != RootPart)
2027 part.ScheduleFullUpdate(); 2245 part.ScheduleFullUpdate();
2246
2028 } 2247 }
2029 } 2248 }
2249 lockPartsForRead(false);
2030 } 2250 }
2031 2251
2032 /// <summary> 2252 /// <summary>
@@ -2034,37 +2254,38 @@ namespace OpenSim.Region.Framework.Scenes
2034 /// </summary> 2254 /// </summary>
2035 public void ScheduleGroupForTerseUpdate() 2255 public void ScheduleGroupForTerseUpdate()
2036 { 2256 {
2037// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1}", Name, UUID); 2257 lockPartsForRead(true);
2038 2258 foreach (SceneObjectPart part in m_parts.Values)
2039 lock (m_parts)
2040 { 2259 {
2041 foreach (SceneObjectPart part in m_parts.Values) 2260 part.ScheduleTerseUpdate();
2042 {
2043 part.ScheduleTerseUpdate();
2044 }
2045 } 2261 }
2262
2263 lockPartsForRead(false);
2046 } 2264 }
2047 2265
2048 /// <summary> 2266 /// <summary>
2049 /// Immediately send a full update for this scene object. 2267 /// Immediately send a full update for this scene object.
2050 /// </summary> 2268 /// </summary>
2051 public void SendGroupFullUpdate() 2269 public void SendGroupFullUpdate()
2052 { 2270 {
2053 if (IsDeleted) 2271 if (IsDeleted)
2054 return; 2272 return;
2055 2273
2056// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); 2274// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID);
2057 2275
2058 RootPart.SendFullUpdateToAllClients(); 2276 RootPart.SendFullUpdateToAllClients();
2059 2277
2060 lock (m_parts) 2278 lockPartsForRead(true);
2061 { 2279 {
2062 foreach (SceneObjectPart part in m_parts.Values) 2280 foreach (SceneObjectPart part in m_parts.Values)
2063 { 2281 {
2282
2064 if (part != RootPart) 2283 if (part != RootPart)
2065 part.SendFullUpdateToAllClients(); 2284 part.SendFullUpdateToAllClients();
2285
2066 } 2286 }
2067 } 2287 }
2288 lockPartsForRead(false);
2068 } 2289 }
2069 2290
2070 /// <summary> 2291 /// <summary>
@@ -2096,14 +2317,15 @@ namespace OpenSim.Region.Framework.Scenes
2096 { 2317 {
2097 if (IsDeleted) 2318 if (IsDeleted)
2098 return; 2319 return;
2099 2320
2100 lock (m_parts) 2321 lockPartsForRead(true);
2101 { 2322 {
2102 foreach (SceneObjectPart part in m_parts.Values) 2323 foreach (SceneObjectPart part in m_parts.Values)
2103 { 2324 {
2104 part.SendTerseUpdateToAllClients(); 2325 part.SendTerseUpdateToAllClients();
2105 } 2326 }
2106 } 2327 }
2328 lockPartsForRead(false);
2107 } 2329 }
2108 2330
2109 #endregion 2331 #endregion
@@ -2117,16 +2339,18 @@ namespace OpenSim.Region.Framework.Scenes
2117 /// <returns>null if no child part with that linknum or child part</returns> 2339 /// <returns>null if no child part with that linknum or child part</returns>
2118 public SceneObjectPart GetLinkNumPart(int linknum) 2340 public SceneObjectPart GetLinkNumPart(int linknum)
2119 { 2341 {
2120 lock (m_parts) 2342 lockPartsForRead(true);
2121 { 2343 {
2122 foreach (SceneObjectPart part in m_parts.Values) 2344 foreach (SceneObjectPart part in m_parts.Values)
2123 { 2345 {
2124 if (part.LinkNum == linknum) 2346 if (part.LinkNum == linknum)
2125 { 2347 {
2348 lockPartsForRead(false);
2126 return part; 2349 return part;
2127 } 2350 }
2128 } 2351 }
2129 } 2352 }
2353 lockPartsForRead(false);
2130 2354
2131 return null; 2355 return null;
2132 } 2356 }
@@ -2154,17 +2378,19 @@ namespace OpenSim.Region.Framework.Scenes
2154 public SceneObjectPart GetChildPart(uint localID) 2378 public SceneObjectPart GetChildPart(uint localID)
2155 { 2379 {
2156 //m_log.DebugFormat("Entered looking for {0}", localID); 2380 //m_log.DebugFormat("Entered looking for {0}", localID);
2157 lock (m_parts) 2381 lockPartsForRead(true);
2158 { 2382 {
2159 foreach (SceneObjectPart part in m_parts.Values) 2383 foreach (SceneObjectPart part in m_parts.Values)
2160 { 2384 {
2161 //m_log.DebugFormat("Found {0}", part.LocalId); 2385 //m_log.DebugFormat("Found {0}", part.LocalId);
2162 if (part.LocalId == localID) 2386 if (part.LocalId == localID)
2163 { 2387 {
2388 lockPartsForRead(false);
2164 return part; 2389 return part;
2165 } 2390 }
2166 } 2391 }
2167 } 2392 }
2393 lockPartsForRead(false);
2168 2394
2169 return null; 2395 return null;
2170 } 2396 }
@@ -2194,17 +2420,19 @@ namespace OpenSim.Region.Framework.Scenes
2194 public bool HasChildPrim(uint localID) 2420 public bool HasChildPrim(uint localID)
2195 { 2421 {
2196 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID); 2422 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID);
2197 lock (m_parts) 2423 lockPartsForRead(true);
2198 { 2424 {
2199 foreach (SceneObjectPart part in m_parts.Values) 2425 foreach (SceneObjectPart part in m_parts.Values)
2200 { 2426 {
2201 //m_log.DebugFormat("Found {0}", part.LocalId); 2427 //m_log.DebugFormat("Found {0}", part.LocalId);
2202 if (part.LocalId == localID) 2428 if (part.LocalId == localID)
2203 { 2429 {
2430 lockPartsForRead(false);
2204 return true; 2431 return true;
2205 } 2432 }
2206 } 2433 }
2207 } 2434 }
2435 lockPartsForRead(false);
2208 2436
2209 return false; 2437 return false;
2210 } 2438 }
@@ -2254,53 +2482,57 @@ namespace OpenSim.Region.Framework.Scenes
2254 if (m_rootPart.LinkNum == 0) 2482 if (m_rootPart.LinkNum == 0)
2255 m_rootPart.LinkNum = 1; 2483 m_rootPart.LinkNum = 1;
2256 2484
2257 lock (m_parts) 2485 lockPartsForWrite(true);
2258 { 2486
2259 m_parts.Add(linkPart.UUID, linkPart); 2487 m_parts.Add(linkPart.UUID, linkPart);
2488
2489 lockPartsForWrite(false);
2260 2490
2261 // Insert in terms of link numbers, the new links 2491 // Insert in terms of link numbers, the new links
2262 // before the current ones (with the exception of 2492 // before the current ones (with the exception of
2263 // the root prim. Shuffle the old ones up 2493 // the root prim. Shuffle the old ones up
2264 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts) 2494 lockPartsForRead(true);
2495 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts)
2496 {
2497 if (kvp.Value.LinkNum != 1)
2265 { 2498 {
2266 if (kvp.Value.LinkNum != 1) 2499 // Don't update root prim link number
2267 { 2500 kvp.Value.LinkNum += objectGroup.PrimCount;
2268 // Don't update root prim link number
2269 kvp.Value.LinkNum += objectGroup.PrimCount;
2270 }
2271 } 2501 }
2502 }
2503 lockPartsForRead(false);
2272 2504
2273 linkPart.LinkNum = 2; 2505 linkPart.LinkNum = 2;
2274 2506
2275 linkPart.SetParent(this); 2507 linkPart.SetParent(this);
2276 linkPart.CreateSelected = true; 2508 linkPart.CreateSelected = true;
2277 2509
2278 //if (linkPart.PhysActor != null) 2510 //if (linkPart.PhysActor != null)
2279 //{ 2511 //{
2280 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); 2512 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
2281 2513
2282 //linkPart.PhysActor = null; 2514 //linkPart.PhysActor = null;
2283 //} 2515 //}
2284 2516
2285 //TODO: rest of parts 2517 //TODO: rest of parts
2286 int linkNum = 3; 2518 int linkNum = 3;
2287 foreach (SceneObjectPart part in objectGroup.Children.Values) 2519 foreach (SceneObjectPart part in objectGroup.Children.Values)
2520 {
2521 if (part.UUID != objectGroup.m_rootPart.UUID)
2288 { 2522 {
2289 if (part.UUID != objectGroup.m_rootPart.UUID) 2523 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2290 {
2291 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2292 }
2293 part.ClearUndoState();
2294 } 2524 }
2525 part.ClearUndoState();
2295 } 2526 }
2296 2527
2297 m_scene.UnlinkSceneObject(objectGroup.UUID, true); 2528 m_scene.UnlinkSceneObject(objectGroup.UUID, true);
2298 objectGroup.m_isDeleted = true; 2529 objectGroup.m_isDeleted = true;
2530
2531 objectGroup.lockPartsForWrite(true);
2299 2532
2300 lock (objectGroup.m_parts) 2533 objectGroup.m_parts.Clear();
2301 { 2534
2302 objectGroup.m_parts.Clear(); 2535 objectGroup.lockPartsForWrite(false);
2303 }
2304 2536
2305 // Can't do this yet since backup still makes use of the root part without any synchronization 2537 // Can't do this yet since backup still makes use of the root part without any synchronization
2306// objectGroup.m_rootPart = null; 2538// objectGroup.m_rootPart = null;
@@ -2370,11 +2602,12 @@ namespace OpenSim.Region.Framework.Scenes
2370 Quaternion worldRot = linkPart.GetWorldRotation(); 2602 Quaternion worldRot = linkPart.GetWorldRotation();
2371 2603
2372 // Remove the part from this object 2604 // Remove the part from this object
2373 lock (m_parts) 2605 lockPartsForWrite(true);
2374 { 2606 {
2375 m_parts.Remove(linkPart.UUID); 2607 m_parts.Remove(linkPart.UUID);
2376 } 2608 }
2377 2609 lockPartsForWrite(false);
2610 lockPartsForRead(true);
2378 if (m_parts.Count == 1 && RootPart != null) //Single prim is left 2611 if (m_parts.Count == 1 && RootPart != null) //Single prim is left
2379 RootPart.LinkNum = 0; 2612 RootPart.LinkNum = 0;
2380 else 2613 else
@@ -2385,6 +2618,7 @@ namespace OpenSim.Region.Framework.Scenes
2385 p.LinkNum--; 2618 p.LinkNum--;
2386 } 2619 }
2387 } 2620 }
2621 lockPartsForRead(false);
2388 2622
2389 linkPart.ParentID = 0; 2623 linkPart.ParentID = 0;
2390 linkPart.LinkNum = 0; 2624 linkPart.LinkNum = 0;
@@ -2706,9 +2940,12 @@ namespace OpenSim.Region.Framework.Scenes
2706 2940
2707 if (selectionPart != null) 2941 if (selectionPart != null)
2708 { 2942 {
2709 lock (m_parts) 2943 lockPartsForRead(true);
2944 List<SceneObjectPart> parts = new List<SceneObjectPart>(m_parts.Values);
2945 lockPartsForRead(false);
2946 foreach (SceneObjectPart part in parts)
2710 { 2947 {
2711 foreach (SceneObjectPart part in m_parts.Values) 2948 if (part.Scale.X > 10.0 || part.Scale.Y > 10.0 || part.Scale.Z > 10.0)
2712 { 2949 {
2713 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax || 2950 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax ||
2714 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax || 2951 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax ||
@@ -2718,12 +2955,13 @@ namespace OpenSim.Region.Framework.Scenes
2718 break; 2955 break;
2719 } 2956 }
2720 } 2957 }
2958 }
2721 2959
2722 foreach (SceneObjectPart part in m_parts.Values) 2960 foreach (SceneObjectPart part in parts)
2723 { 2961 {
2724 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect); 2962 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
2725 }
2726 } 2963 }
2964
2727 } 2965 }
2728 } 2966 }
2729 2967
@@ -2809,11 +3047,9 @@ namespace OpenSim.Region.Framework.Scenes
2809 scale.Y = m_scene.m_maxNonphys; 3047 scale.Y = m_scene.m_maxNonphys;
2810 if (scale.Z > m_scene.m_maxNonphys) 3048 if (scale.Z > m_scene.m_maxNonphys)
2811 scale.Z = m_scene.m_maxNonphys; 3049 scale.Z = m_scene.m_maxNonphys;
2812
2813 SceneObjectPart part = GetChildPart(localID); 3050 SceneObjectPart part = GetChildPart(localID);
2814 if (part != null) 3051 if (part != null)
2815 { 3052 {
2816 part.Resize(scale);
2817 if (part.PhysActor != null) 3053 if (part.PhysActor != null)
2818 { 3054 {
2819 if (part.PhysActor.IsPhysical) 3055 if (part.PhysActor.IsPhysical)
@@ -2828,7 +3064,7 @@ namespace OpenSim.Region.Framework.Scenes
2828 part.PhysActor.Size = scale; 3064 part.PhysActor.Size = scale;
2829 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); 3065 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
2830 } 3066 }
2831 //if (part.UUID != m_rootPart.UUID) 3067 part.Resize(scale);
2832 3068
2833 HasGroupChanged = true; 3069 HasGroupChanged = true;
2834 ScheduleGroupForFullUpdate(); 3070 ScheduleGroupForFullUpdate();
@@ -2870,73 +3106,71 @@ namespace OpenSim.Region.Framework.Scenes
2870 float y = (scale.Y / part.Scale.Y); 3106 float y = (scale.Y / part.Scale.Y);
2871 float z = (scale.Z / part.Scale.Z); 3107 float z = (scale.Z / part.Scale.Z);
2872 3108
2873 lock (m_parts) 3109 lockPartsForRead(true);
3110 if (x > 1.0f || y > 1.0f || z > 1.0f)
2874 { 3111 {
2875 if (x > 1.0f || y > 1.0f || z > 1.0f) 3112 foreach (SceneObjectPart obPart in m_parts.Values)
2876 { 3113 {
2877 foreach (SceneObjectPart obPart in m_parts.Values) 3114 if (obPart.UUID != m_rootPart.UUID)
2878 { 3115 {
2879 if (obPart.UUID != m_rootPart.UUID) 3116 Vector3 oldSize = new Vector3(obPart.Scale);
2880 { 3117 obPart.IgnoreUndoUpdate = true;
2881 obPart.IgnoreUndoUpdate = true;
2882 Vector3 oldSize = new Vector3(obPart.Scale);
2883 3118
2884 float f = 1.0f; 3119 float f = 1.0f;
2885 float a = 1.0f; 3120 float a = 1.0f;
2886 3121
2887 if (part.PhysActor != null && part.PhysActor.IsPhysical) 3122 if (part.PhysActor != null && part.PhysActor.IsPhysical)
3123 {
3124 if (oldSize.X*x > m_scene.m_maxPhys)
2888 { 3125 {
2889 if (oldSize.X*x > m_scene.m_maxPhys) 3126 f = m_scene.m_maxPhys / oldSize.X;
2890 { 3127 a = f / x;
2891 f = m_scene.m_maxPhys / oldSize.X; 3128 x *= a;
2892 a = f / x; 3129 y *= a;
2893 x *= a; 3130 z *= a;
2894 y *= a;
2895 z *= a;
2896 }
2897 if (oldSize.Y*y > m_scene.m_maxPhys)
2898 {
2899 f = m_scene.m_maxPhys / oldSize.Y;
2900 a = f / y;
2901 x *= a;
2902 y *= a;
2903 z *= a;
2904 }
2905 if (oldSize.Z*z > m_scene.m_maxPhys)
2906 {
2907 f = m_scene.m_maxPhys / oldSize.Z;
2908 a = f / z;
2909 x *= a;
2910 y *= a;
2911 z *= a;
2912 }
2913 } 3131 }
2914 else 3132 if (oldSize.Y*y > m_scene.m_maxPhys)
2915 { 3133 {
2916 if (oldSize.X*x > m_scene.m_maxNonphys) 3134 f = m_scene.m_maxPhys / oldSize.Y;
2917 { 3135 a = f / y;
2918 f = m_scene.m_maxNonphys / oldSize.X; 3136 x *= a;
2919 a = f / x; 3137 y *= a;
2920 x *= a; 3138 z *= a;
2921 y *= a; 3139 }
2922 z *= a; 3140 if (oldSize.Z*z > m_scene.m_maxPhys)
2923 } 3141 {
2924 if (oldSize.Y*y > m_scene.m_maxNonphys) 3142 f = m_scene.m_maxPhys / oldSize.Z;
2925 { 3143 a = f / z;
2926 f = m_scene.m_maxNonphys / oldSize.Y; 3144 x *= a;
2927 a = f / y; 3145 y *= a;
2928 x *= a; 3146 z *= a;
2929 y *= a; 3147 }
2930 z *= a; 3148 }
2931 } 3149 else
2932 if (oldSize.Z*z > m_scene.m_maxNonphys) 3150 {
2933 { 3151 if (oldSize.X*x > m_scene.m_maxNonphys)
2934 f = m_scene.m_maxNonphys / oldSize.Z; 3152 {
2935 a = f / z; 3153 f = m_scene.m_maxNonphys / oldSize.X;
2936 x *= a; 3154 a = f / x;
2937 y *= a; 3155 x *= a;
2938 z *= a; 3156 y *= a;
2939 } 3157 z *= a;
3158 }
3159 if (oldSize.Y*y > m_scene.m_maxNonphys)
3160 {
3161 f = m_scene.m_maxNonphys / oldSize.Y;
3162 a = f / y;
3163 x *= a;
3164 y *= a;
3165 z *= a;
3166 }
3167 if (oldSize.Z*z > m_scene.m_maxNonphys)
3168 {
3169 f = m_scene.m_maxNonphys / oldSize.Z;
3170 a = f / z;
3171 x *= a;
3172 y *= a;
3173 z *= a;
2940 } 3174 }
2941 obPart.IgnoreUndoUpdate = false; 3175 obPart.IgnoreUndoUpdate = false;
2942 obPart.StoreUndoState(); 3176 obPart.StoreUndoState();
@@ -2944,6 +3178,7 @@ namespace OpenSim.Region.Framework.Scenes
2944 } 3178 }
2945 } 3179 }
2946 } 3180 }
3181 lockPartsForRead(false);
2947 3182
2948 Vector3 prevScale = part.Scale; 3183 Vector3 prevScale = part.Scale;
2949 prevScale.X *= x; 3184 prevScale.X *= x;
@@ -2951,7 +3186,7 @@ namespace OpenSim.Region.Framework.Scenes
2951 prevScale.Z *= z; 3186 prevScale.Z *= z;
2952 part.Resize(prevScale); 3187 part.Resize(prevScale);
2953 3188
2954 lock (m_parts) 3189 lockPartsForRead(true);
2955 { 3190 {
2956 foreach (SceneObjectPart obPart in m_parts.Values) 3191 foreach (SceneObjectPart obPart in m_parts.Values)
2957 { 3192 {
@@ -2973,6 +3208,7 @@ namespace OpenSim.Region.Framework.Scenes
2973 obPart.StoreUndoState(); 3208 obPart.StoreUndoState();
2974 } 3209 }
2975 } 3210 }
3211 lockPartsForRead(false);
2976 3212
2977 if (part.PhysActor != null) 3213 if (part.PhysActor != null)
2978 { 3214 {
@@ -3075,7 +3311,7 @@ namespace OpenSim.Region.Framework.Scenes
3075 axDiff *= Quaternion.Inverse(partRotation); 3311 axDiff *= Quaternion.Inverse(partRotation);
3076 diff = axDiff; 3312 diff = axDiff;
3077 3313
3078 lock (m_parts) 3314 lockPartsForRead(true);
3079 { 3315 {
3080 foreach (SceneObjectPart obPart in m_parts.Values) 3316 foreach (SceneObjectPart obPart in m_parts.Values)
3081 { 3317 {
@@ -3085,6 +3321,7 @@ namespace OpenSim.Region.Framework.Scenes
3085 } 3321 }
3086 } 3322 }
3087 } 3323 }
3324 lockPartsForRead(false);
3088 3325
3089 AbsolutePosition = newPos; 3326 AbsolutePosition = newPos;
3090 3327
@@ -3218,25 +3455,25 @@ namespace OpenSim.Region.Framework.Scenes
3218 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); 3455 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
3219 } 3456 }
3220 3457
3221 lock (m_parts) 3458 lockPartsForRead(true);
3459
3460 foreach (SceneObjectPart prim in m_parts.Values)
3222 { 3461 {
3223 foreach (SceneObjectPart prim in m_parts.Values) 3462 if (prim.UUID != m_rootPart.UUID)
3224 { 3463 {
3225 if (prim.UUID != m_rootPart.UUID) 3464 prim.IgnoreUndoUpdate = true;
3226 { 3465 Vector3 axPos = prim.OffsetPosition;
3227 prim.IgnoreUndoUpdate = true; 3466 axPos *= oldParentRot;
3228 Vector3 axPos = prim.OffsetPosition; 3467 axPos *= Quaternion.Inverse(axRot);
3229 axPos *= oldParentRot; 3468 prim.OffsetPosition = axPos;
3230 axPos *= Quaternion.Inverse(axRot); 3469 Quaternion primsRot = prim.RotationOffset;
3231 prim.OffsetPosition = axPos; 3470 Quaternion newRot = primsRot * oldParentRot;
3232 Quaternion primsRot = prim.RotationOffset; 3471 newRot *= Quaternion.Inverse(axRot);
3233 Quaternion newRot = primsRot * oldParentRot; 3472 prim.RotationOffset = newRot;
3234 newRot *= Quaternion.Inverse(axRot); 3473 prim.ScheduleTerseUpdate();
3235 prim.RotationOffset = newRot;
3236 prim.ScheduleTerseUpdate();
3237 }
3238 } 3474 }
3239 } 3475 }
3476
3240 foreach (SceneObjectPart childpart in Children.Values) 3477 foreach (SceneObjectPart childpart in Children.Values)
3241 { 3478 {
3242 if (childpart != m_rootPart) 3479 if (childpart != m_rootPart)
@@ -3245,6 +3482,9 @@ namespace OpenSim.Region.Framework.Scenes
3245 childpart.StoreUndoState(); 3482 childpart.StoreUndoState();
3246 } 3483 }
3247 } 3484 }
3485
3486 lockPartsForRead(false);
3487
3248 m_rootPart.ScheduleTerseUpdate(); 3488 m_rootPart.ScheduleTerseUpdate();
3249 } 3489 }
3250 3490
@@ -3366,7 +3606,7 @@ namespace OpenSim.Region.Framework.Scenes
3366 if (atTargets.Count > 0) 3606 if (atTargets.Count > 0)
3367 { 3607 {
3368 uint[] localids = new uint[0]; 3608 uint[] localids = new uint[0];
3369 lock (m_parts) 3609 lockPartsForRead(true);
3370 { 3610 {
3371 localids = new uint[m_parts.Count]; 3611 localids = new uint[m_parts.Count];
3372 int cntr = 0; 3612 int cntr = 0;
@@ -3376,6 +3616,7 @@ namespace OpenSim.Region.Framework.Scenes
3376 cntr++; 3616 cntr++;
3377 } 3617 }
3378 } 3618 }
3619 lockPartsForRead(false);
3379 3620
3380 for (int ctr = 0; ctr < localids.Length; ctr++) 3621 for (int ctr = 0; ctr < localids.Length; ctr++)
3381 { 3622 {
@@ -3394,7 +3635,7 @@ namespace OpenSim.Region.Framework.Scenes
3394 { 3635 {
3395 //trigger not_at_target 3636 //trigger not_at_target
3396 uint[] localids = new uint[0]; 3637 uint[] localids = new uint[0];
3397 lock (m_parts) 3638 lockPartsForRead(true);
3398 { 3639 {
3399 localids = new uint[m_parts.Count]; 3640 localids = new uint[m_parts.Count];
3400 int cntr = 0; 3641 int cntr = 0;
@@ -3404,7 +3645,8 @@ namespace OpenSim.Region.Framework.Scenes
3404 cntr++; 3645 cntr++;
3405 } 3646 }
3406 } 3647 }
3407 3648 lockPartsForRead(false);
3649
3408 for (int ctr = 0; ctr < localids.Length; ctr++) 3650 for (int ctr = 0; ctr < localids.Length; ctr++)
3409 { 3651 {
3410 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]); 3652 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]);
@@ -3445,7 +3687,8 @@ namespace OpenSim.Region.Framework.Scenes
3445 if (atRotTargets.Count > 0) 3687 if (atRotTargets.Count > 0)
3446 { 3688 {
3447 uint[] localids = new uint[0]; 3689 uint[] localids = new uint[0];
3448 lock (m_parts) 3690 lockPartsForRead(true);
3691 try
3449 { 3692 {
3450 localids = new uint[m_parts.Count]; 3693 localids = new uint[m_parts.Count];
3451 int cntr = 0; 3694 int cntr = 0;
@@ -3455,6 +3698,10 @@ namespace OpenSim.Region.Framework.Scenes
3455 cntr++; 3698 cntr++;
3456 } 3699 }
3457 } 3700 }
3701 finally
3702 {
3703 lockPartsForRead(false);
3704 }
3458 3705
3459 for (int ctr = 0; ctr < localids.Length; ctr++) 3706 for (int ctr = 0; ctr < localids.Length; ctr++)
3460 { 3707 {
@@ -3473,7 +3720,8 @@ namespace OpenSim.Region.Framework.Scenes
3473 { 3720 {
3474 //trigger not_at_target 3721 //trigger not_at_target
3475 uint[] localids = new uint[0]; 3722 uint[] localids = new uint[0];
3476 lock (m_parts) 3723 lockPartsForRead(true);
3724 try
3477 { 3725 {
3478 localids = new uint[m_parts.Count]; 3726 localids = new uint[m_parts.Count];
3479 int cntr = 0; 3727 int cntr = 0;
@@ -3483,6 +3731,10 @@ namespace OpenSim.Region.Framework.Scenes
3483 cntr++; 3731 cntr++;
3484 } 3732 }
3485 } 3733 }
3734 finally
3735 {
3736 lockPartsForRead(false);
3737 }
3486 3738
3487 for (int ctr = 0; ctr < localids.Length; ctr++) 3739 for (int ctr = 0; ctr < localids.Length; ctr++)
3488 { 3740 {
@@ -3496,19 +3748,20 @@ namespace OpenSim.Region.Framework.Scenes
3496 public float GetMass() 3748 public float GetMass()
3497 { 3749 {
3498 float retmass = 0f; 3750 float retmass = 0f;
3499 lock (m_parts) 3751 lockPartsForRead(true);
3500 { 3752 {
3501 foreach (SceneObjectPart part in m_parts.Values) 3753 foreach (SceneObjectPart part in m_parts.Values)
3502 { 3754 {
3503 retmass += part.GetMass(); 3755 retmass += part.GetMass();
3504 } 3756 }
3505 } 3757 }
3758 lockPartsForRead(false);
3506 return retmass; 3759 return retmass;
3507 } 3760 }
3508 3761
3509 public void CheckSculptAndLoad() 3762 public void CheckSculptAndLoad()
3510 { 3763 {
3511 lock (m_parts) 3764 lockPartsForRead(true);
3512 { 3765 {
3513 if (!IsDeleted) 3766 if (!IsDeleted)
3514 { 3767 {
@@ -3533,6 +3786,7 @@ namespace OpenSim.Region.Framework.Scenes
3533 } 3786 }
3534 } 3787 }
3535 } 3788 }
3789 lockPartsForRead(false);
3536 } 3790 }
3537 3791
3538 protected void AssetReceived(string id, Object sender, AssetBase asset) 3792 protected void AssetReceived(string id, Object sender, AssetBase asset)
@@ -3553,7 +3807,7 @@ namespace OpenSim.Region.Framework.Scenes
3553 /// <param name="client"></param> 3807 /// <param name="client"></param>
3554 public void SetGroup(UUID GroupID, IClientAPI client) 3808 public void SetGroup(UUID GroupID, IClientAPI client)
3555 { 3809 {
3556 lock (m_parts) 3810 lockPartsForRead(true);
3557 { 3811 {
3558 foreach (SceneObjectPart part in m_parts.Values) 3812 foreach (SceneObjectPart part in m_parts.Values)
3559 { 3813 {
@@ -3563,6 +3817,7 @@ namespace OpenSim.Region.Framework.Scenes
3563 3817
3564 HasGroupChanged = true; 3818 HasGroupChanged = true;
3565 } 3819 }
3820 lockPartsForRead(false);
3566 3821
3567 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled 3822 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled
3568 // for the same object with very different properties. The caller must schedule the update. 3823 // for the same object with very different properties. The caller must schedule the update.
@@ -3584,11 +3839,12 @@ namespace OpenSim.Region.Framework.Scenes
3584 3839
3585 public void SetAttachmentPoint(byte point) 3840 public void SetAttachmentPoint(byte point)
3586 { 3841 {
3587 lock (m_parts) 3842 lockPartsForRead(true);
3588 { 3843 {
3589 foreach (SceneObjectPart part in m_parts.Values) 3844 foreach (SceneObjectPart part in m_parts.Values)
3590 part.SetAttachmentPoint(point); 3845 part.SetAttachmentPoint(point);
3591 } 3846 }
3847 lockPartsForRead(false);
3592 } 3848 }
3593 3849
3594 #region ISceneObject 3850 #region ISceneObject
@@ -3622,6 +3878,14 @@ namespace OpenSim.Region.Framework.Scenes
3622 SetFromItemID(uuid); 3878 SetFromItemID(uuid);
3623 } 3879 }
3624 3880
3881 public void ResetOwnerChangeFlag()
3882 {
3883 ForEachPart(delegate(SceneObjectPart part)
3884 {
3885 part.ResetOwnerChangeFlag();
3886 });
3887 }
3888
3625 #endregion 3889 #endregion
3626 } 3890 }
3627} 3891}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 38b2dc2..e4a36ef 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -147,7 +147,7 @@ namespace OpenSim.Region.Framework.Scenes
147 147
148 // TODO: This needs to be persisted in next XML version update! 148 // TODO: This needs to be persisted in next XML version update!
149 [XmlIgnore] 149 [XmlIgnore]
150 public readonly int[] PayPrice = {-2,-2,-2,-2,-2}; 150 public int[] PayPrice = {-2,-2,-2,-2,-2};
151 [XmlIgnore] 151 [XmlIgnore]
152 public PhysicsActor PhysActor; 152 public PhysicsActor PhysActor;
153 153
@@ -274,6 +274,7 @@ namespace OpenSim.Region.Framework.Scenes
274 private Quaternion m_sitTargetOrientation = Quaternion.Identity; 274 private Quaternion m_sitTargetOrientation = Quaternion.Identity;
275 private Vector3 m_sitTargetPosition; 275 private Vector3 m_sitTargetPosition;
276 private string m_sitAnimation = "SIT"; 276 private string m_sitAnimation = "SIT";
277 private bool m_occupied; // KF if any av is sitting on this prim
277 private string m_text = String.Empty; 278 private string m_text = String.Empty;
278 private string m_touchName = String.Empty; 279 private string m_touchName = String.Empty;
279 private readonly UndoStack<UndoState> m_undo = new UndoStack<UndoState>(5); 280 private readonly UndoStack<UndoState> m_undo = new UndoStack<UndoState>(5);
@@ -453,12 +454,16 @@ namespace OpenSim.Region.Framework.Scenes
453 } 454 }
454 455
455 /// <value> 456 /// <value>
456 /// Access should be via Inventory directly - this property temporarily remains for xml serialization purposes 457 /// Get the inventory list
457 /// </value> 458 /// </value>
458 public TaskInventoryDictionary TaskInventory 459 public TaskInventoryDictionary TaskInventory
459 { 460 {
460 get { return m_inventory.Items; } 461 get {
461 set { m_inventory.Items = value; } 462 return m_inventory.Items;
463 }
464 set {
465 m_inventory.Items = value;
466 }
462 } 467 }
463 468
464 public uint ObjectFlags 469 public uint ObjectFlags
@@ -587,14 +592,12 @@ namespace OpenSim.Region.Framework.Scenes
587 set { m_LoopSoundSlavePrims = value; } 592 set { m_LoopSoundSlavePrims = value; }
588 } 593 }
589 594
590 [XmlIgnore]
591 public Byte[] TextureAnimation 595 public Byte[] TextureAnimation
592 { 596 {
593 get { return m_TextureAnimation; } 597 get { return m_TextureAnimation; }
594 set { m_TextureAnimation = value; } 598 set { m_TextureAnimation = value; }
595 } 599 }
596 600
597 [XmlIgnore]
598 public Byte[] ParticleSystem 601 public Byte[] ParticleSystem
599 { 602 {
600 get { return m_particleSystem; } 603 get { return m_particleSystem; }
@@ -648,7 +651,6 @@ namespace OpenSim.Region.Framework.Scenes
648 set 651 set
649 { 652 {
650 m_groupPosition = value; 653 m_groupPosition = value;
651
652 PhysicsActor actor = PhysActor; 654 PhysicsActor actor = PhysActor;
653 if (actor != null) 655 if (actor != null)
654 { 656 {
@@ -835,7 +837,16 @@ namespace OpenSim.Region.Framework.Scenes
835 /// <summary></summary> 837 /// <summary></summary>
836 public Vector3 Acceleration 838 public Vector3 Acceleration
837 { 839 {
838 get { return m_acceleration; } 840 get
841 {
842 PhysicsActor actor = PhysActor;
843 if (actor != null)
844 {
845 m_acceleration = actor.Acceleration;
846 }
847 return m_acceleration;
848 }
849
839 set { m_acceleration = value; } 850 set { m_acceleration = value; }
840 } 851 }
841 852
@@ -986,7 +997,8 @@ namespace OpenSim.Region.Framework.Scenes
986 if (IsAttachment) 997 if (IsAttachment)
987 return GroupPosition; 998 return GroupPosition;
988 999
989 return m_offsetPosition + m_groupPosition; } 1000// return m_offsetPosition + m_groupPosition; }
1001 return m_groupPosition + (m_offsetPosition * ParentGroup.RootPart.RotationOffset) ; } //KF: Rotation was ignored!
990 } 1002 }
991 1003
992 public SceneObjectGroup ParentGroup 1004 public SceneObjectGroup ParentGroup
@@ -1137,6 +1149,13 @@ namespace OpenSim.Region.Framework.Scenes
1137 get { return _flags; } 1149 get { return _flags; }
1138 set { _flags = value; } 1150 set { _flags = value; }
1139 } 1151 }
1152
1153 [XmlIgnore]
1154 public bool IsOccupied // KF If an av is sittingon this prim
1155 {
1156 get { return m_occupied; }
1157 set { m_occupied = value; }
1158 }
1140 1159
1141 [XmlIgnore] 1160 [XmlIgnore]
1142 public UUID SitTargetAvatar 1161 public UUID SitTargetAvatar
@@ -1212,14 +1231,6 @@ namespace OpenSim.Region.Framework.Scenes
1212 } 1231 }
1213 } 1232 }
1214 1233
1215 /// <summary>
1216 /// Clear all pending updates of parts to clients
1217 /// </summary>
1218 private void ClearUpdateSchedule()
1219 {
1220 m_updateFlag = 0;
1221 }
1222
1223 private void SendObjectPropertiesToClient(UUID AgentID) 1234 private void SendObjectPropertiesToClient(UUID AgentID)
1224 { 1235 {
1225 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar) 1236 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
@@ -1962,12 +1973,17 @@ namespace OpenSim.Region.Framework.Scenes
1962 public Vector3 GetWorldPosition() 1973 public Vector3 GetWorldPosition()
1963 { 1974 {
1964 Quaternion parentRot = ParentGroup.RootPart.RotationOffset; 1975 Quaternion parentRot = ParentGroup.RootPart.RotationOffset;
1965
1966 Vector3 axPos = OffsetPosition; 1976 Vector3 axPos = OffsetPosition;
1967
1968 axPos *= parentRot; 1977 axPos *= parentRot;
1969 Vector3 translationOffsetPosition = axPos; 1978 Vector3 translationOffsetPosition = axPos;
1970 return GroupPosition + translationOffsetPosition; 1979 if(_parentID == 0)
1980 {
1981 return GroupPosition;
1982 }
1983 else
1984 {
1985 return ParentGroup.AbsolutePosition + translationOffsetPosition; //KF: Fix child prim position
1986 }
1971 } 1987 }
1972 1988
1973 /// <summary> 1989 /// <summary>
@@ -1978,7 +1994,7 @@ namespace OpenSim.Region.Framework.Scenes
1978 { 1994 {
1979 Quaternion newRot; 1995 Quaternion newRot;
1980 1996
1981 if (this.LinkNum == 0) 1997 if (this.LinkNum < 2) //KF Single or root prim
1982 { 1998 {
1983 newRot = RotationOffset; 1999 newRot = RotationOffset;
1984 } 2000 }
@@ -2624,17 +2640,18 @@ namespace OpenSim.Region.Framework.Scenes
2624 //Trys to fetch sound id from prim's inventory. 2640 //Trys to fetch sound id from prim's inventory.
2625 //Prim's inventory doesn't support non script items yet 2641 //Prim's inventory doesn't support non script items yet
2626 2642
2627 lock (TaskInventory) 2643 TaskInventory.LockItemsForRead(true);
2644
2645 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2628 { 2646 {
2629 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 2647 if (item.Value.Name == sound)
2630 { 2648 {
2631 if (item.Value.Name == sound) 2649 soundID = item.Value.ItemID;
2632 { 2650 break;
2633 soundID = item.Value.ItemID;
2634 break;
2635 }
2636 } 2651 }
2637 } 2652 }
2653
2654 TaskInventory.LockItemsForRead(false);
2638 } 2655 }
2639 2656
2640 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence sp) 2657 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence sp)
@@ -2703,38 +2720,7 @@ namespace OpenSim.Region.Framework.Scenes
2703 2720
2704 public void RotLookAt(Quaternion target, float strength, float damping) 2721 public void RotLookAt(Quaternion target, float strength, float damping)
2705 { 2722 {
2706 rotLookAt(target, strength, damping); 2723 m_parentGroup.rotLookAt(target, strength, damping); // This calls method in SceneObjectGroup.
2707 }
2708
2709 public void rotLookAt(Quaternion target, float strength, float damping)
2710 {
2711 if (IsAttachment)
2712 {
2713 /*
2714 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
2715 if (avatar != null)
2716 {
2717 Rotate the Av?
2718 } */
2719 }
2720 else
2721 {
2722 APIDDamp = damping;
2723 APIDStrength = strength;
2724 APIDTarget = target;
2725 }
2726 }
2727
2728 public void startLookAt(Quaternion rot, float damp, float strength)
2729 {
2730 APIDDamp = damp;
2731 APIDStrength = strength;
2732 APIDTarget = rot;
2733 }
2734
2735 public void stopLookAt()
2736 {
2737 APIDTarget = Quaternion.Identity;
2738 } 2724 }
2739 2725
2740 /// <summary> 2726 /// <summary>
@@ -2746,7 +2732,10 @@ namespace OpenSim.Region.Framework.Scenes
2746 2732
2747 if (m_parentGroup != null) 2733 if (m_parentGroup != null)
2748 { 2734 {
2749 m_parentGroup.QueueForUpdateCheck(); 2735 if (!m_parentGroup.areUpdatesSuspended)
2736 {
2737 m_parentGroup.QueueForUpdateCheck();
2738 }
2750 } 2739 }
2751 2740
2752 int timeNow = Util.UnixTimeSinceEpoch(); 2741 int timeNow = Util.UnixTimeSinceEpoch();
@@ -2963,8 +2952,8 @@ namespace OpenSim.Region.Framework.Scenes
2963 { 2952 {
2964 const float ROTATION_TOLERANCE = 0.01f; 2953 const float ROTATION_TOLERANCE = 0.01f;
2965 const float VELOCITY_TOLERANCE = 0.001f; 2954 const float VELOCITY_TOLERANCE = 0.001f;
2966 const float POSITION_TOLERANCE = 0.05f; 2955 const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary
2967 const int TIME_MS_TOLERANCE = 3000; 2956 const int TIME_MS_TOLERANCE = 200; //llSetPos has a 200ms delay. This should NOT be 3 seconds.
2968 2957
2969 if (m_updateFlag == 1) 2958 if (m_updateFlag == 1)
2970 { 2959 {
@@ -2978,7 +2967,7 @@ namespace OpenSim.Region.Framework.Scenes
2978 Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE) 2967 Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE)
2979 { 2968 {
2980 AddTerseUpdateToAllAvatars(); 2969 AddTerseUpdateToAllAvatars();
2981 ClearUpdateSchedule(); 2970
2982 2971
2983 // This causes the Scene to 'poll' physical objects every couple of frames 2972 // This causes the Scene to 'poll' physical objects every couple of frames
2984 // bad, so it's been replaced by an event driven method. 2973 // bad, so it's been replaced by an event driven method.
@@ -2996,16 +2985,18 @@ namespace OpenSim.Region.Framework.Scenes
2996 m_lastAngularVelocity = AngularVelocity; 2985 m_lastAngularVelocity = AngularVelocity;
2997 m_lastTerseSent = Environment.TickCount; 2986 m_lastTerseSent = Environment.TickCount;
2998 } 2987 }
2988 //Moved this outside of the if clause so updates don't get blocked.. *sigh*
2989 m_updateFlag = 0; //Why were we calling a function to do this? Inefficient! *screams*
2999 } 2990 }
3000 else 2991 else
3001 { 2992 {
3002 if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes 2993 if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes
3003 { 2994 {
3004 AddFullUpdateToAllAvatars(); 2995 AddFullUpdateToAllAvatars();
3005 ClearUpdateSchedule(); 2996 m_updateFlag = 0; //Same here
3006 } 2997 }
3007 } 2998 }
3008 ClearUpdateSchedule(); 2999 m_updateFlag = 0;
3009 } 3000 }
3010 3001
3011 /// <summary> 3002 /// <summary>
@@ -3032,17 +3023,16 @@ namespace OpenSim.Region.Framework.Scenes
3032 if (!UUID.TryParse(sound, out soundID)) 3023 if (!UUID.TryParse(sound, out soundID))
3033 { 3024 {
3034 // search sound file from inventory 3025 // search sound file from inventory
3035 lock (TaskInventory) 3026 TaskInventory.LockItemsForRead(true);
3027 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
3036 { 3028 {
3037 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 3029 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound)
3038 { 3030 {
3039 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound) 3031 soundID = item.Value.ItemID;
3040 { 3032 break;
3041 soundID = item.Value.ItemID;
3042 break;
3043 }
3044 } 3033 }
3045 } 3034 }
3035 TaskInventory.LockItemsForRead(false);
3046 } 3036 }
3047 3037
3048 if (soundID == UUID.Zero) 3038 if (soundID == UUID.Zero)
@@ -3477,7 +3467,7 @@ namespace OpenSim.Region.Framework.Scenes
3477 3467
3478 public void StopLookAt() 3468 public void StopLookAt()
3479 { 3469 {
3480 m_parentGroup.stopLookAt(); 3470 m_parentGroup.stopLookAt(); // This calls method in SceneObjectGroup.
3481 3471
3482 m_parentGroup.ScheduleGroupForTerseUpdate(); 3472 m_parentGroup.ScheduleGroupForTerseUpdate();
3483 } 3473 }
@@ -4471,8 +4461,9 @@ namespace OpenSim.Region.Framework.Scenes
4471 { 4461 {
4472 m_shape.TextureEntry = textureEntry; 4462 m_shape.TextureEntry = textureEntry;
4473 TriggerScriptChangedEvent(Changed.TEXTURE); 4463 TriggerScriptChangedEvent(Changed.TEXTURE);
4474 4464 m_updateFlag = 1;
4475 ParentGroup.HasGroupChanged = true; 4465 ParentGroup.HasGroupChanged = true;
4466
4476 //This is madness.. 4467 //This is madness..
4477 //ParentGroup.ScheduleGroupForFullUpdate(); 4468 //ParentGroup.ScheduleGroupForFullUpdate();
4478 //This is sparta 4469 //This is sparta
@@ -4717,5 +4708,17 @@ namespace OpenSim.Region.Framework.Scenes
4717 Color color = Color; 4708 Color color = Color;
4718 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A)); 4709 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A));
4719 } 4710 }
4711
4712 public void ResetOwnerChangeFlag()
4713 {
4714 List<UUID> inv = Inventory.GetInventoryList();
4715
4716 foreach (UUID itemID in inv)
4717 {
4718 TaskInventoryItem item = Inventory.GetInventoryItem(itemID);
4719 item.OwnerChanged = false;
4720 Inventory.UpdateInventoryItem(item);
4721 }
4722 }
4720 } 4723 }
4721} 4724}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index 8b83b06..c4cff12 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
@@ -45,6 +45,8 @@ namespace OpenSim.Region.Framework.Scenes
45 45
46 private string m_inventoryFileName = String.Empty; 46 private string m_inventoryFileName = String.Empty;
47 private int m_inventoryFileNameSerial = 0; 47 private int m_inventoryFileNameSerial = 0;
48
49 private Dictionary<UUID, ArrayList> m_scriptErrors = new Dictionary<UUID, ArrayList>();
48 50
49 /// <value> 51 /// <value>
50 /// The part to which the inventory belongs. 52 /// The part to which the inventory belongs.
@@ -81,7 +83,9 @@ namespace OpenSim.Region.Framework.Scenes
81 /// </value> 83 /// </value>
82 protected internal TaskInventoryDictionary Items 84 protected internal TaskInventoryDictionary Items
83 { 85 {
84 get { return m_items; } 86 get {
87 return m_items;
88 }
85 set 89 set
86 { 90 {
87 m_items = value; 91 m_items = value;
@@ -117,22 +121,25 @@ namespace OpenSim.Region.Framework.Scenes
117 /// <param name="linkNum">Link number for the part</param> 121 /// <param name="linkNum">Link number for the part</param>
118 public void ResetInventoryIDs() 122 public void ResetInventoryIDs()
119 { 123 {
120 lock (Items) 124 m_items.LockItemsForWrite(true);
125
126 if (0 == Items.Count)
121 { 127 {
122 if (0 == Items.Count) 128 m_items.LockItemsForWrite(false);
123 return; 129 return;
130 }
124 131
125 HasInventoryChanged = true; 132 HasInventoryChanged = true;
126 m_part.ParentGroup.HasGroupChanged = true; 133 m_part.ParentGroup.HasGroupChanged = true;
127 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values); 134 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
128 Items.Clear(); 135 Items.Clear();
129 136
130 foreach (TaskInventoryItem item in items) 137 foreach (TaskInventoryItem item in items)
131 { 138 {
132 item.ResetIDs(m_part.UUID); 139 item.ResetIDs(m_part.UUID);
133 Items.Add(item.ItemID, item); 140 Items.Add(item.ItemID, item);
134 }
135 } 141 }
142 m_items.LockItemsForWrite(false);
136 } 143 }
137 144
138 /// <summary> 145 /// <summary>
@@ -141,25 +148,25 @@ namespace OpenSim.Region.Framework.Scenes
141 /// <param name="ownerId"></param> 148 /// <param name="ownerId"></param>
142 public void ChangeInventoryOwner(UUID ownerId) 149 public void ChangeInventoryOwner(UUID ownerId)
143 { 150 {
144 lock (Items) 151 m_items.LockItemsForWrite(true);
152 if (0 == Items.Count)
145 { 153 {
146 if (0 == Items.Count) 154 m_items.LockItemsForWrite(false);
147 { 155 return;
148 return; 156 }
149 }
150 157
151 HasInventoryChanged = true; 158 HasInventoryChanged = true;
152 m_part.ParentGroup.HasGroupChanged = true; 159 m_part.ParentGroup.HasGroupChanged = true;
153 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values); 160 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
154 foreach (TaskInventoryItem item in items) 161 foreach (TaskInventoryItem item in items)
162 {
163 if (ownerId != item.OwnerID)
155 { 164 {
156 if (ownerId != item.OwnerID) 165 item.LastOwnerID = item.OwnerID;
157 { 166 item.OwnerID = ownerId;
158 item.LastOwnerID = item.OwnerID;
159 item.OwnerID = ownerId;
160 }
161 } 167 }
162 } 168 }
169 m_items.LockItemsForWrite(false);
163 } 170 }
164 171
165 /// <summary> 172 /// <summary>
@@ -168,24 +175,24 @@ namespace OpenSim.Region.Framework.Scenes
168 /// <param name="groupID"></param> 175 /// <param name="groupID"></param>
169 public void ChangeInventoryGroup(UUID groupID) 176 public void ChangeInventoryGroup(UUID groupID)
170 { 177 {
171 lock (Items) 178 m_items.LockItemsForWrite(true);
179 if (0 == Items.Count)
172 { 180 {
173 if (0 == Items.Count) 181 m_items.LockItemsForWrite(false);
174 { 182 return;
175 return; 183 }
176 }
177 184
178 HasInventoryChanged = true; 185 HasInventoryChanged = true;
179 m_part.ParentGroup.HasGroupChanged = true; 186 m_part.ParentGroup.HasGroupChanged = true;
180 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values); 187 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
181 foreach (TaskInventoryItem item in items) 188 foreach (TaskInventoryItem item in items)
189 {
190 if (groupID != item.GroupID)
182 { 191 {
183 if (groupID != item.GroupID) 192 item.GroupID = groupID;
184 {
185 item.GroupID = groupID;
186 }
187 } 193 }
188 } 194 }
195 m_items.LockItemsForWrite(false);
189 } 196 }
190 197
191 /// <summary> 198 /// <summary>
@@ -193,14 +200,14 @@ namespace OpenSim.Region.Framework.Scenes
193 /// </summary> 200 /// </summary>
194 public void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource) 201 public void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource)
195 { 202 {
196 lock (m_items) 203 Items.LockItemsForRead(true);
204 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
205 Items.LockItemsForRead(false);
206 foreach (TaskInventoryItem item in items)
197 { 207 {
198 foreach (TaskInventoryItem item in Items.Values) 208 if ((int)InventoryType.LSL == item.InvType)
199 { 209 {
200 if ((int)InventoryType.LSL == item.InvType) 210 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource);
201 {
202 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource);
203 }
204 } 211 }
205 } 212 }
206 } 213 }
@@ -235,16 +242,20 @@ namespace OpenSim.Region.Framework.Scenes
235 /// </param> 242 /// </param>
236 public void RemoveScriptInstances(bool sceneObjectBeingDeleted) 243 public void RemoveScriptInstances(bool sceneObjectBeingDeleted)
237 { 244 {
238 lock (Items) 245 Items.LockItemsForRead(true);
246 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
247 Items.LockItemsForRead(false);
248
249 foreach (TaskInventoryItem item in items)
239 { 250 {
240 foreach (TaskInventoryItem item in Items.Values) 251 if ((int)InventoryType.LSL == item.InvType)
241 { 252 {
242 if ((int)InventoryType.LSL == item.InvType) 253 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted);
243 { 254 m_part.RemoveScriptEvents(item.ItemID);
244 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted);
245 }
246 } 255 }
247 } 256 }
257
258
248 } 259 }
249 260
250 /// <summary> 261 /// <summary>
@@ -260,7 +271,10 @@ namespace OpenSim.Region.Framework.Scenes
260 // item.Name, item.ItemID, Name, UUID); 271 // item.Name, item.ItemID, Name, UUID);
261 272
262 if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID)) 273 if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID))
274 {
275 StoreScriptError(item.ItemID, "no permission");
263 return; 276 return;
277 }
264 278
265 m_part.AddFlag(PrimFlags.Scripted); 279 m_part.AddFlag(PrimFlags.Scripted);
266 280
@@ -269,14 +283,13 @@ namespace OpenSim.Region.Framework.Scenes
269 if (stateSource == 1 && // Prim crossing 283 if (stateSource == 1 && // Prim crossing
270 m_part.ParentGroup.Scene.m_trustBinaries) 284 m_part.ParentGroup.Scene.m_trustBinaries)
271 { 285 {
272 lock (m_items) 286 m_items.LockItemsForWrite(true);
273 { 287 m_items[item.ItemID].PermsMask = 0;
274 m_items[item.ItemID].PermsMask = 0; 288 m_items[item.ItemID].PermsGranter = UUID.Zero;
275 m_items[item.ItemID].PermsGranter = UUID.Zero; 289 m_items.LockItemsForWrite(false);
276 }
277
278 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 290 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
279 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource); 291 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource);
292 StoreScriptErrors(item.ItemID, null);
280 m_part.ParentGroup.AddActiveScriptCount(1); 293 m_part.ParentGroup.AddActiveScriptCount(1);
281 m_part.ScheduleFullUpdate(); 294 m_part.ScheduleFullUpdate();
282 return; 295 return;
@@ -285,6 +298,8 @@ namespace OpenSim.Region.Framework.Scenes
285 AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString()); 298 AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString());
286 if (null == asset) 299 if (null == asset)
287 { 300 {
301 string msg = String.Format("asset ID {0} could not be found", item.AssetID);
302 StoreScriptError(item.ItemID, msg);
288 m_log.ErrorFormat( 303 m_log.ErrorFormat(
289 "[PRIM INVENTORY]: " + 304 "[PRIM INVENTORY]: " +
290 "Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found", 305 "Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found",
@@ -296,15 +311,17 @@ namespace OpenSim.Region.Framework.Scenes
296 if (m_part.ParentGroup.m_savedScriptState != null) 311 if (m_part.ParentGroup.m_savedScriptState != null)
297 RestoreSavedScriptState(item.OldItemID, item.ItemID); 312 RestoreSavedScriptState(item.OldItemID, item.ItemID);
298 313
299 lock (m_items) 314 m_items.LockItemsForWrite(true);
300 { 315
301 m_items[item.ItemID].PermsMask = 0; 316 m_items[item.ItemID].PermsMask = 0;
302 m_items[item.ItemID].PermsGranter = UUID.Zero; 317 m_items[item.ItemID].PermsGranter = UUID.Zero;
303 } 318
319 m_items.LockItemsForWrite(false);
304 320
305 string script = Utils.BytesToString(asset.Data); 321 string script = Utils.BytesToString(asset.Data);
306 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 322 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
307 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource); 323 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource);
324 StoreScriptErrors(item.ItemID, null);
308 m_part.ParentGroup.AddActiveScriptCount(1); 325 m_part.ParentGroup.AddActiveScriptCount(1);
309 m_part.ScheduleFullUpdate(); 326 m_part.ScheduleFullUpdate();
310 } 327 }
@@ -368,27 +385,145 @@ namespace OpenSim.Region.Framework.Scenes
368 385
369 /// <summary> 386 /// <summary>
370 /// Start a script which is in this prim's inventory. 387 /// Start a script which is in this prim's inventory.
388 /// Some processing may occur in the background, but this routine returns asap.
371 /// </summary> 389 /// </summary>
372 /// <param name="itemId"> 390 /// <param name="itemId">
373 /// A <see cref="UUID"/> 391 /// A <see cref="UUID"/>
374 /// </param> 392 /// </param>
375 public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource) 393 public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
376 { 394 {
377 lock (m_items) 395 lock (m_scriptErrors)
396 {
397 // Indicate to CreateScriptInstanceInternal() we don't want it to wait for completion
398 m_scriptErrors.Remove(itemId);
399 }
400 CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
401 }
402
403 private void CreateScriptInstanceInternal(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
404 {
405 m_items.LockItemsForRead(true);
406 if (m_items.ContainsKey(itemId))
378 { 407 {
379 if (m_items.ContainsKey(itemId)) 408 if (m_items.ContainsKey(itemId))
380 { 409 {
410 m_items.LockItemsForRead(false);
381 CreateScriptInstance(m_items[itemId], startParam, postOnRez, engine, stateSource); 411 CreateScriptInstance(m_items[itemId], startParam, postOnRez, engine, stateSource);
382 } 412 }
383 else 413 else
384 { 414 {
415 m_items.LockItemsForRead(false);
416 string msg = String.Format("couldn't be found for prim {0}, {1} at {2} in {3}", m_part.Name, m_part.UUID,
417 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
418 StoreScriptError(itemId, msg);
385 m_log.ErrorFormat( 419 m_log.ErrorFormat(
386 "[PRIM INVENTORY]: " + 420 "[PRIM INVENTORY]: " +
387 "Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}", 421 "Couldn't start script with ID {0} since it {1}", itemId, msg);
388 itemId, m_part.Name, m_part.UUID,
389 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
390 } 422 }
391 } 423 }
424 else
425 {
426 m_items.LockItemsForRead(false);
427 string msg = String.Format("couldn't be found for prim {0}, {1}", m_part.Name, m_part.UUID);
428 StoreScriptError(itemId, msg);
429 m_log.ErrorFormat(
430 "[PRIM INVENTORY]: " +
431 "Couldn't start script with ID {0} since it {1}", itemId, msg);
432 }
433
434 }
435
436 /// <summary>
437 /// Start a script which is in this prim's inventory and return any compilation error messages.
438 /// </summary>
439 /// <param name="itemId">
440 /// A <see cref="UUID"/>
441 /// </param>
442 public ArrayList CreateScriptInstanceEr(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
443 {
444 ArrayList errors;
445
446 // Indicate to CreateScriptInstanceInternal() we want it to
447 // post any compilation/loading error messages
448 lock (m_scriptErrors)
449 {
450 m_scriptErrors[itemId] = null;
451 }
452
453 // Perform compilation/loading
454 CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
455
456 // Wait for and retrieve any errors
457 lock (m_scriptErrors)
458 {
459 while ((errors = m_scriptErrors[itemId]) == null)
460 {
461 if (!System.Threading.Monitor.Wait(m_scriptErrors, 15000))
462 {
463 m_log.ErrorFormat(
464 "[PRIM INVENTORY]: " +
465 "timedout waiting for script {0} errors", itemId);
466 errors = m_scriptErrors[itemId];
467 if (errors == null)
468 {
469 errors = new ArrayList(1);
470 errors.Add("timedout waiting for errors");
471 }
472 break;
473 }
474 }
475 m_scriptErrors.Remove(itemId);
476 }
477 return errors;
478 }
479
480 // Signal to CreateScriptInstanceEr() that compilation/loading is complete
481 private void StoreScriptErrors(UUID itemId, ArrayList errors)
482 {
483 lock (m_scriptErrors)
484 {
485 // If compilation/loading initiated via CreateScriptInstance(),
486 // it does not want the errors, so just get out
487 if (!m_scriptErrors.ContainsKey(itemId))
488 {
489 return;
490 }
491
492 // Initiated via CreateScriptInstanceEr(), if we know what the
493 // errors are, save them and wake CreateScriptInstanceEr().
494 if (errors != null)
495 {
496 m_scriptErrors[itemId] = errors;
497 System.Threading.Monitor.PulseAll(m_scriptErrors);
498 return;
499 }
500 }
501
502 // Initiated via CreateScriptInstanceEr() but we don't know what
503 // the errors are yet, so retrieve them from the script engine.
504 // This may involve some waiting internal to GetScriptErrors().
505 errors = GetScriptErrors(itemId);
506
507 // Get a default non-null value to indicate success.
508 if (errors == null)
509 {
510 errors = new ArrayList();
511 }
512
513 // Post to CreateScriptInstanceEr() and wake it up
514 lock (m_scriptErrors)
515 {
516 m_scriptErrors[itemId] = errors;
517 System.Threading.Monitor.PulseAll(m_scriptErrors);
518 }
519 }
520
521 // Like StoreScriptErrors(), but just posts a single string message
522 private void StoreScriptError(UUID itemId, string message)
523 {
524 ArrayList errors = new ArrayList(1);
525 errors.Add(message);
526 StoreScriptErrors(itemId, errors);
392 } 527 }
393 528
394 /// <summary> 529 /// <summary>
@@ -401,15 +536,7 @@ namespace OpenSim.Region.Framework.Scenes
401 /// </param> 536 /// </param>
402 public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted) 537 public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted)
403 { 538 {
404 bool scriptPresent = false; 539 if (m_items.ContainsKey(itemId))
405
406 lock (m_items)
407 {
408 if (m_items.ContainsKey(itemId))
409 scriptPresent = true;
410 }
411
412 if (scriptPresent)
413 { 540 {
414 if (!sceneObjectBeingDeleted) 541 if (!sceneObjectBeingDeleted)
415 m_part.RemoveScriptEvents(itemId); 542 m_part.RemoveScriptEvents(itemId);
@@ -435,11 +562,16 @@ namespace OpenSim.Region.Framework.Scenes
435 /// <returns></returns> 562 /// <returns></returns>
436 private bool InventoryContainsName(string name) 563 private bool InventoryContainsName(string name)
437 { 564 {
438 foreach (TaskInventoryItem item in Items.Values) 565 m_items.LockItemsForRead(true);
566 foreach (TaskInventoryItem item in m_items.Values)
439 { 567 {
440 if (item.Name == name) 568 if (item.Name == name)
569 {
570 m_items.LockItemsForRead(false);
441 return true; 571 return true;
572 }
442 } 573 }
574 m_items.LockItemsForRead(false);
443 return false; 575 return false;
444 } 576 }
445 577
@@ -481,13 +613,9 @@ namespace OpenSim.Region.Framework.Scenes
481 /// <param name="item"></param> 613 /// <param name="item"></param>
482 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop) 614 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop)
483 { 615 {
484 List<TaskInventoryItem> il; 616 m_items.LockItemsForRead(true);
485 617 List<TaskInventoryItem> il = new List<TaskInventoryItem>(m_items.Values);
486 lock (m_items) 618 m_items.LockItemsForRead(false);
487 {
488 il = new List<TaskInventoryItem>(m_items.Values);
489 }
490
491 foreach (TaskInventoryItem i in il) 619 foreach (TaskInventoryItem i in il)
492 { 620 {
493 if (i.Name == item.Name) 621 if (i.Name == item.Name)
@@ -525,15 +653,14 @@ namespace OpenSim.Region.Framework.Scenes
525 item.Name = name; 653 item.Name = name;
526 item.GroupID = m_part.GroupID; 654 item.GroupID = m_part.GroupID;
527 655
528 lock (m_items) 656 m_items.LockItemsForWrite(true);
529 { 657 m_items.Add(item.ItemID, item);
530 m_items.Add(item.ItemID, item); 658 m_items.LockItemsForWrite(false);
531
532 if (allowedDrop) 659 if (allowedDrop)
533 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP); 660 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP);
534 else 661 else
535 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 662 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
536 } 663
537 664
538 m_inventorySerial++; 665 m_inventorySerial++;
539 //m_inventorySerial += 2; 666 //m_inventorySerial += 2;
@@ -550,14 +677,13 @@ namespace OpenSim.Region.Framework.Scenes
550 /// <param name="items"></param> 677 /// <param name="items"></param>
551 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items) 678 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items)
552 { 679 {
553 lock (m_items) 680 m_items.LockItemsForWrite(true);
681 foreach (TaskInventoryItem item in items)
554 { 682 {
555 foreach (TaskInventoryItem item in items) 683 m_items.Add(item.ItemID, item);
556 { 684 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
557 m_items.Add(item.ItemID, item);
558 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
559 }
560 } 685 }
686 m_items.LockItemsForWrite(false);
561 687
562 m_inventorySerial++; 688 m_inventorySerial++;
563 } 689 }
@@ -570,10 +696,9 @@ namespace OpenSim.Region.Framework.Scenes
570 public TaskInventoryItem GetInventoryItem(UUID itemId) 696 public TaskInventoryItem GetInventoryItem(UUID itemId)
571 { 697 {
572 TaskInventoryItem item; 698 TaskInventoryItem item;
573 699 m_items.LockItemsForRead(true);
574 lock (m_items) 700 m_items.TryGetValue(itemId, out item);
575 m_items.TryGetValue(itemId, out item); 701 m_items.LockItemsForRead(false);
576
577 return item; 702 return item;
578 } 703 }
579 704
@@ -589,15 +714,16 @@ namespace OpenSim.Region.Framework.Scenes
589 { 714 {
590 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(); 715 IList<TaskInventoryItem> items = new List<TaskInventoryItem>();
591 716
592 lock (m_items) 717 m_items.LockItemsForRead(true);
718
719 foreach (TaskInventoryItem item in m_items.Values)
593 { 720 {
594 foreach (TaskInventoryItem item in m_items.Values) 721 if (item.Name == name)
595 { 722 items.Add(item);
596 if (item.Name == name)
597 items.Add(item);
598 }
599 } 723 }
600 724
725 m_items.LockItemsForRead(false);
726
601 return items; 727 return items;
602 } 728 }
603 729
@@ -614,45 +740,54 @@ namespace OpenSim.Region.Framework.Scenes
614 740
615 public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents) 741 public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents)
616 { 742 {
617 lock(m_items) 743 m_items.LockItemsForWrite(true);
744
745 if (m_items.ContainsKey(item.ItemID))
618 { 746 {
619 if (m_items.ContainsKey(item.ItemID)) 747 item.ParentID = m_part.UUID;
748 item.ParentPartID = m_part.UUID;
749 item.Flags = m_items[item.ItemID].Flags;
750
751 // If group permissions have been set on, check that the groupID is up to date in case it has
752 // changed since permissions were last set.
753 if (item.GroupPermissions != (uint)PermissionMask.None)
754 item.GroupID = m_part.GroupID;
755
756 if (item.AssetID == UUID.Zero)
620 { 757 {
621 if (m_items.ContainsKey(item.ItemID)) 758 item.AssetID = m_items[item.ItemID].AssetID;
622 { 759 }
623 item.ParentID = m_part.UUID; 760 else if ((InventoryType)item.Type == InventoryType.Notecard)
624 item.ParentPartID = m_part.UUID; 761 {
625 item.Flags = m_items[item.ItemID].Flags; 762 ScenePresence presence = m_part.ParentGroup.Scene.GetScenePresence(item.OwnerID);
626 763
627 // If group permissions have been set on, check that the groupID is up to date in case it has 764 if (presence != null)
628 // changed since permissions were last set.
629 if (item.GroupPermissions != (uint)PermissionMask.None)
630 item.GroupID = m_part.GroupID;
631
632 if (item.AssetID == UUID.Zero)
633 {
634 item.AssetID = m_items[item.ItemID].AssetID;
635 }
636 m_items[item.ItemID] = item;
637 m_inventorySerial++;
638 if (fireScriptEvents)
639 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
640 HasInventoryChanged = true;
641 m_part.ParentGroup.HasGroupChanged = true;
642 return true;
643 }
644 else
645 { 765 {
646 m_log.ErrorFormat( 766 presence.ControllingClient.SendAgentAlertMessage(
647 "[PRIM INVENTORY]: " + 767 "Notecard saved", false);
648 "Tried to retrieve item ID {0} from prim {1}, {2} at {3} in {4} but the item does not exist in this inventory",
649 item.ItemID, m_part.Name, m_part.UUID,
650 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
651 } 768 }
652
653 } 769 }
654 return false; 770
771 m_items[item.ItemID] = item;
772 m_inventorySerial++;
773 if (fireScriptEvents)
774 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
775 HasInventoryChanged = true;
776 m_part.ParentGroup.HasGroupChanged = true;
777 m_items.LockItemsForWrite(false);
778 return true;
655 } 779 }
780 else
781 {
782 m_log.ErrorFormat(
783 "[PRIM INVENTORY]: " +
784 "Tried to retrieve item ID {0} from prim {1}, {2} at {3} in {4} but the item does not exist in this inventory",
785 item.ItemID, m_part.Name, m_part.UUID,
786 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
787 }
788 m_items.LockItemsForWrite(false);
789
790 return false;
656 } 791 }
657 792
658 /// <summary> 793 /// <summary>
@@ -663,52 +798,53 @@ namespace OpenSim.Region.Framework.Scenes
663 /// in this prim's inventory.</returns> 798 /// in this prim's inventory.</returns>
664 public int RemoveInventoryItem(UUID itemID) 799 public int RemoveInventoryItem(UUID itemID)
665 { 800 {
666 lock (m_items) 801 m_items.LockItemsForRead(true);
802
803 if (m_items.ContainsKey(itemID))
667 { 804 {
668 if (m_items.ContainsKey(itemID)) 805 int type = m_items[itemID].InvType;
806 m_items.LockItemsForRead(false);
807 if (type == 10) // Script
669 { 808 {
670 int type = m_items[itemID].InvType; 809 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID);
671 if (type == 10) // Script 810 }
672 { 811 m_items.LockItemsForWrite(true);
673 m_part.RemoveScriptEvents(itemID); 812 m_items.Remove(itemID);
674 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID); 813 m_items.LockItemsForWrite(false);
675 } 814 m_inventorySerial++;
676 m_items.Remove(itemID); 815 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
677 m_inventorySerial++;
678 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
679
680 HasInventoryChanged = true;
681 m_part.ParentGroup.HasGroupChanged = true;
682 816
683 int scriptcount = 0; 817 HasInventoryChanged = true;
684 lock (m_items) 818 m_part.ParentGroup.HasGroupChanged = true;
685 {
686 foreach (TaskInventoryItem item in m_items.Values)
687 {
688 if (item.Type == 10)
689 {
690 scriptcount++;
691 }
692 }
693 }
694 819
695 if (scriptcount <= 0) 820 int scriptcount = 0;
821 m_items.LockItemsForRead(true);
822 foreach (TaskInventoryItem item in m_items.Values)
823 {
824 if (item.Type == 10)
696 { 825 {
697 m_part.RemFlag(PrimFlags.Scripted); 826 scriptcount++;
698 } 827 }
699
700 m_part.ScheduleFullUpdate();
701
702 return type;
703 } 828 }
704 else 829 m_items.LockItemsForRead(false);
830
831
832 if (scriptcount <= 0)
705 { 833 {
706 m_log.ErrorFormat( 834 m_part.RemFlag(PrimFlags.Scripted);
707 "[PRIM INVENTORY]: " +
708 "Tried to remove item ID {0} from prim {1}, {2} at {3} in {4} but the item does not exist in this inventory",
709 itemID, m_part.Name, m_part.UUID,
710 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
711 } 835 }
836
837 m_part.ScheduleFullUpdate();
838
839 return type;
840 }
841 else
842 {
843 m_items.LockItemsForRead(false);
844 m_log.ErrorFormat(
845 "[PRIM INVENTORY]: " +
846 "Tried to remove item ID {0} from prim {1}, {2} but the item does not exist in this inventory",
847 itemID, m_part.Name, m_part.UUID);
712 } 848 }
713 849
714 return -1; 850 return -1;
@@ -762,53 +898,54 @@ namespace OpenSim.Region.Framework.Scenes
762 // isn't available (such as drag from prim inventory to agent inventory) 898 // isn't available (such as drag from prim inventory to agent inventory)
763 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero); 899 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero);
764 900
765 lock (m_items) 901 m_items.LockItemsForRead(true);
902
903 foreach (TaskInventoryItem item in m_items.Values)
766 { 904 {
767 foreach (TaskInventoryItem item in m_items.Values) 905 UUID ownerID = item.OwnerID;
768 { 906 uint everyoneMask = 0;
769 UUID ownerID = item.OwnerID; 907 uint baseMask = item.BasePermissions;
770 uint everyoneMask = 0; 908 uint ownerMask = item.CurrentPermissions;
771 uint baseMask = item.BasePermissions; 909 uint groupMask = item.GroupPermissions;
772 uint ownerMask = item.CurrentPermissions;
773 uint groupMask = item.GroupPermissions;
774 910
775 invString.AddItemStart(); 911 invString.AddItemStart();
776 invString.AddNameValueLine("item_id", item.ItemID.ToString()); 912 invString.AddNameValueLine("item_id", item.ItemID.ToString());
777 invString.AddNameValueLine("parent_id", m_part.UUID.ToString()); 913 invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
778 914
779 invString.AddPermissionsStart(); 915 invString.AddPermissionsStart();
780 916
781 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask)); 917 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask));
782 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask)); 918 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask));
783 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask)); 919 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask));
784 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask)); 920 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask));
785 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions)); 921 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
786 922
787 invString.AddNameValueLine("creator_id", item.CreatorID.ToString()); 923 invString.AddNameValueLine("creator_id", item.CreatorID.ToString());
788 invString.AddNameValueLine("owner_id", ownerID.ToString()); 924 invString.AddNameValueLine("owner_id", ownerID.ToString());
789 925
790 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString()); 926 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString());
791 927
792 invString.AddNameValueLine("group_id", item.GroupID.ToString()); 928 invString.AddNameValueLine("group_id", item.GroupID.ToString());
793 invString.AddSectionEnd(); 929 invString.AddSectionEnd();
794 930
795 invString.AddNameValueLine("asset_id", item.AssetID.ToString()); 931 invString.AddNameValueLine("asset_id", item.AssetID.ToString());
796 invString.AddNameValueLine("type", TaskInventoryItem.Types[item.Type]); 932 invString.AddNameValueLine("type", TaskInventoryItem.Types[item.Type]);
797 invString.AddNameValueLine("inv_type", TaskInventoryItem.InvTypes[item.InvType]); 933 invString.AddNameValueLine("inv_type", TaskInventoryItem.InvTypes[item.InvType]);
798 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags)); 934 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags));
799 935
800 invString.AddSaleStart(); 936 invString.AddSaleStart();
801 invString.AddNameValueLine("sale_type", "not"); 937 invString.AddNameValueLine("sale_type", "not");
802 invString.AddNameValueLine("sale_price", "0"); 938 invString.AddNameValueLine("sale_price", "0");
803 invString.AddSectionEnd(); 939 invString.AddSectionEnd();
804 940
805 invString.AddNameValueLine("name", item.Name + "|"); 941 invString.AddNameValueLine("name", item.Name + "|");
806 invString.AddNameValueLine("desc", item.Description + "|"); 942 invString.AddNameValueLine("desc", item.Description + "|");
807 943
808 invString.AddNameValueLine("creation_date", item.CreationDate.ToString()); 944 invString.AddNameValueLine("creation_date", item.CreationDate.ToString());
809 invString.AddSectionEnd(); 945 invString.AddSectionEnd();
810 }
811 } 946 }
947 int count = m_items.Count;
948 m_items.LockItemsForRead(false);
812 949
813 fileData = Utils.StringToBytes(invString.BuildString); 950 fileData = Utils.StringToBytes(invString.BuildString);
814 951
@@ -829,10 +966,9 @@ namespace OpenSim.Region.Framework.Scenes
829 { 966 {
830 if (HasInventoryChanged) 967 if (HasInventoryChanged)
831 { 968 {
832 lock (Items) 969 Items.LockItemsForRead(true);
833 { 970 datastore.StorePrimInventory(m_part.UUID, Items.Values);
834 datastore.StorePrimInventory(m_part.UUID, Items.Values); 971 Items.LockItemsForRead(false);
835 }
836 972
837 HasInventoryChanged = false; 973 HasInventoryChanged = false;
838 } 974 }
@@ -901,90 +1037,76 @@ namespace OpenSim.Region.Framework.Scenes
901 { 1037 {
902 uint mask=0x7fffffff; 1038 uint mask=0x7fffffff;
903 1039
904 lock (m_items) 1040 foreach (TaskInventoryItem item in m_items.Values)
905 { 1041 {
906 foreach (TaskInventoryItem item in m_items.Values) 1042 if (item.InvType != (int)InventoryType.Object)
907 { 1043 {
908 if (item.InvType != (int)InventoryType.Object) 1044 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0)
909 { 1045 mask &= ~((uint)PermissionMask.Copy >> 13);
910 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0) 1046 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0)
911 mask &= ~((uint)PermissionMask.Copy >> 13); 1047 mask &= ~((uint)PermissionMask.Transfer >> 13);
912 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0) 1048 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0)
913 mask &= ~((uint)PermissionMask.Transfer >> 13); 1049 mask &= ~((uint)PermissionMask.Modify >> 13);
914 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0) 1050 }
915 mask &= ~((uint)PermissionMask.Modify >> 13); 1051 else
916 } 1052 {
917 else 1053 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
918 { 1054 mask &= ~((uint)PermissionMask.Copy >> 13);
919 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0) 1055 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
920 mask &= ~((uint)PermissionMask.Copy >> 13); 1056 mask &= ~((uint)PermissionMask.Transfer >> 13);
921 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0) 1057 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
922 mask &= ~((uint)PermissionMask.Transfer >> 13); 1058 mask &= ~((uint)PermissionMask.Modify >> 13);
923 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
924 mask &= ~((uint)PermissionMask.Modify >> 13);
925 }
926
927 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
928 mask &= ~(uint)PermissionMask.Copy;
929 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
930 mask &= ~(uint)PermissionMask.Transfer;
931 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
932 mask &= ~(uint)PermissionMask.Modify;
933 } 1059 }
1060
1061 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
1062 mask &= ~(uint)PermissionMask.Copy;
1063 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
1064 mask &= ~(uint)PermissionMask.Transfer;
1065 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
1066 mask &= ~(uint)PermissionMask.Modify;
934 } 1067 }
935
936 return mask; 1068 return mask;
937 } 1069 }
938 1070
939 public void ApplyNextOwnerPermissions() 1071 public void ApplyNextOwnerPermissions()
940 { 1072 {
941 lock (m_items) 1073 foreach (TaskInventoryItem item in m_items.Values)
942 { 1074 {
943 foreach (TaskInventoryItem item in m_items.Values) 1075 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0)
944 { 1076 {
945 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0) 1077 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
946 { 1078 item.CurrentPermissions &= ~(uint)PermissionMask.Copy;
947 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0) 1079 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
948 item.CurrentPermissions &= ~(uint)PermissionMask.Copy; 1080 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer;
949 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0) 1081 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
950 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer; 1082 item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
951 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0) 1083 item.CurrentPermissions |= 8;
952 item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
953 item.CurrentPermissions |= 8;
954 }
955 item.CurrentPermissions &= item.NextPermissions;
956 item.BasePermissions &= item.NextPermissions;
957 item.EveryonePermissions &= item.NextPermissions;
958 item.OwnerChanged = true;
959 } 1084 }
1085 item.OwnerChanged = true;
1086 item.CurrentPermissions &= item.NextPermissions;
1087 item.BasePermissions &= item.NextPermissions;
1088 item.EveryonePermissions &= item.NextPermissions;
960 } 1089 }
961 } 1090 }
962 1091
963 public void ApplyGodPermissions(uint perms) 1092 public void ApplyGodPermissions(uint perms)
964 { 1093 {
965 lock (m_items) 1094 foreach (TaskInventoryItem item in m_items.Values)
966 { 1095 {
967 foreach (TaskInventoryItem item in m_items.Values) 1096 item.CurrentPermissions = perms;
968 { 1097 item.BasePermissions = perms;
969 item.CurrentPermissions = perms;
970 item.BasePermissions = perms;
971 }
972 } 1098 }
973 } 1099 }
974 1100
975 public bool ContainsScripts() 1101 public bool ContainsScripts()
976 { 1102 {
977 lock (m_items) 1103 foreach (TaskInventoryItem item in m_items.Values)
978 { 1104 {
979 foreach (TaskInventoryItem item in m_items.Values) 1105 if (item.InvType == (int)InventoryType.LSL)
980 { 1106 {
981 if (item.InvType == (int)InventoryType.LSL) 1107 return true;
982 {
983 return true;
984 }
985 } 1108 }
986 } 1109 }
987
988 return false; 1110 return false;
989 } 1111 }
990 1112
@@ -992,46 +1114,52 @@ namespace OpenSim.Region.Framework.Scenes
992 { 1114 {
993 List<UUID> ret = new List<UUID>(); 1115 List<UUID> ret = new List<UUID>();
994 1116
995 lock (m_items) 1117 foreach (TaskInventoryItem item in m_items.Values)
996 { 1118 ret.Add(item.ItemID);
997 foreach (TaskInventoryItem item in m_items.Values)
998 ret.Add(item.ItemID);
999 }
1000 1119
1001 return ret; 1120 return ret;
1002 } 1121 }
1003 1122
1004 public Dictionary<UUID, string> GetScriptStates() 1123 public Dictionary<UUID, string> GetScriptStates()
1005 { 1124 {
1125 return GetScriptStates(false);
1126 }
1127
1128 public Dictionary<UUID, string> GetScriptStates(bool oldIDs)
1129 {
1006 IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>(); 1130 IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>();
1007 1131
1008 Dictionary<UUID, string> ret = new Dictionary<UUID, string>(); 1132 Dictionary<UUID, string> ret = new Dictionary<UUID, string>();
1009 if (engines == null) // No engine at all 1133 if (engines == null) // No engine at all
1010 return ret; 1134 return ret;
1011 1135
1012 lock (m_items) 1136 foreach (TaskInventoryItem item in m_items.Values)
1013 { 1137 {
1014 foreach (TaskInventoryItem item in m_items.Values) 1138 if (item.InvType == (int)InventoryType.LSL)
1015 { 1139 {
1016 if (item.InvType == (int)InventoryType.LSL) 1140 foreach (IScriptModule e in engines)
1017 { 1141 {
1018 foreach (IScriptModule e in engines) 1142 if (e != null)
1019 { 1143 {
1020 if (e != null) 1144 string n = e.GetXMLState(item.ItemID);
1145 if (n != String.Empty)
1021 { 1146 {
1022 string n = e.GetXMLState(item.ItemID); 1147 if (oldIDs)
1023 if (n != String.Empty) 1148 {
1149 if (!ret.ContainsKey(item.OldItemID))
1150 ret[item.OldItemID] = n;
1151 }
1152 else
1024 { 1153 {
1025 if (!ret.ContainsKey(item.ItemID)) 1154 if (!ret.ContainsKey(item.ItemID))
1026 ret[item.ItemID] = n; 1155 ret[item.ItemID] = n;
1027 break;
1028 } 1156 }
1157 break;
1029 } 1158 }
1030 } 1159 }
1031 } 1160 }
1032 } 1161 }
1033 } 1162 }
1034
1035 return ret; 1163 return ret;
1036 } 1164 }
1037 1165
@@ -1041,25 +1169,27 @@ namespace OpenSim.Region.Framework.Scenes
1041 if (engines == null) 1169 if (engines == null)
1042 return; 1170 return;
1043 1171
1044 lock (m_items) 1172
1173 Items.LockItemsForRead(true);
1174
1175 foreach (TaskInventoryItem item in m_items.Values)
1045 { 1176 {
1046 foreach (TaskInventoryItem item in m_items.Values) 1177 if (item.InvType == (int)InventoryType.LSL)
1047 { 1178 {
1048 if (item.InvType == (int)InventoryType.LSL) 1179 foreach (IScriptModule engine in engines)
1049 { 1180 {
1050 foreach (IScriptModule engine in engines) 1181 if (engine != null)
1051 { 1182 {
1052 if (engine != null) 1183 if (item.OwnerChanged)
1053 { 1184 engine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.OWNER });
1054 if (item.OwnerChanged) 1185 item.OwnerChanged = false;
1055 engine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.OWNER }); 1186 engine.ResumeScript(item.ItemID);
1056 item.OwnerChanged = false;
1057 engine.ResumeScript(item.ItemID);
1058 }
1059 } 1187 }
1060 } 1188 }
1061 } 1189 }
1062 } 1190 }
1191
1192 Items.LockItemsForRead(false);
1063 } 1193 }
1064 } 1194 }
1065} 1195}
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 15b9446..8cd3ac6 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.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 System.Reflection; 31using System.Reflection;
31using System.Timers; 32using System.Timers;
@@ -73,7 +74,7 @@ namespace OpenSim.Region.Framework.Scenes
73// { 74// {
74// m_log.Debug("[ScenePresence] Destructor called"); 75// m_log.Debug("[ScenePresence] Destructor called");
75// } 76// }
76 77
77 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 78 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
78 79
79 private static readonly byte[] BAKE_INDICES = new byte[] { 8, 9, 10, 11, 19, 20 }; 80 private static readonly byte[] BAKE_INDICES = new byte[] { 8, 9, 10, 11, 19, 20 };
@@ -89,7 +90,9 @@ namespace OpenSim.Region.Framework.Scenes
89 /// rotation, prim cut, prim twist, prim taper, and prim shear. See mantis 90 /// rotation, prim cut, prim twist, prim taper, and prim shear. See mantis
90 /// issue #1716 91 /// issue #1716
91 /// </summary> 92 /// </summary>
92 private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.1f, 0.0f, 0.3f); 93// private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.1f, 0.0f, 0.3f);
94 // Value revised by KF 091121 by comparison with SL.
95 private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.0f, 0.0f, 0.418f);
93 96
94 public UUID currentParcelUUID = UUID.Zero; 97 public UUID currentParcelUUID = UUID.Zero;
95 98
@@ -123,8 +126,11 @@ namespace OpenSim.Region.Framework.Scenes
123 public Vector3 lastKnownAllowedPosition; 126 public Vector3 lastKnownAllowedPosition;
124 public bool sentMessageAboutRestrictedParcelFlyingDown; 127 public bool sentMessageAboutRestrictedParcelFlyingDown;
125 public Vector4 CollisionPlane = Vector4.UnitW; 128 public Vector4 CollisionPlane = Vector4.UnitW;
126 129
130 private Vector3 m_avInitialPos; // used to calculate unscripted sit rotation
131 private Vector3 m_avUnscriptedSitPos; // for non-scripted prims
127 private Vector3 m_lastPosition; 132 private Vector3 m_lastPosition;
133 private Vector3 m_lastWorldPosition;
128 private Quaternion m_lastRotation; 134 private Quaternion m_lastRotation;
129 private Vector3 m_lastVelocity; 135 private Vector3 m_lastVelocity;
130 //private int m_lastTerseSent; 136 //private int m_lastTerseSent;
@@ -157,7 +163,6 @@ namespace OpenSim.Region.Framework.Scenes
157 private int m_perfMonMS; 163 private int m_perfMonMS;
158 164
159 private bool m_setAlwaysRun; 165 private bool m_setAlwaysRun;
160
161 private bool m_forceFly; 166 private bool m_forceFly;
162 private bool m_flyDisabled; 167 private bool m_flyDisabled;
163 168
@@ -181,7 +186,8 @@ namespace OpenSim.Region.Framework.Scenes
181 protected RegionInfo m_regionInfo; 186 protected RegionInfo m_regionInfo;
182 protected ulong crossingFromRegion; 187 protected ulong crossingFromRegion;
183 188
184 private readonly Vector3[] Dir_Vectors = new Vector3[9]; 189 private readonly Vector3[] Dir_Vectors = new Vector3[11];
190 private bool m_isNudging = false;
185 191
186 // Position of agent's camera in world (region cordinates) 192 // Position of agent's camera in world (region cordinates)
187 protected Vector3 m_CameraCenter; 193 protected Vector3 m_CameraCenter;
@@ -206,6 +212,7 @@ namespace OpenSim.Region.Framework.Scenes
206 private bool m_autopilotMoving; 212 private bool m_autopilotMoving;
207 private Vector3 m_autoPilotTarget; 213 private Vector3 m_autoPilotTarget;
208 private bool m_sitAtAutoTarget; 214 private bool m_sitAtAutoTarget;
215 private Vector3 m_initialSitTarget = Vector3.Zero; //KF: First estimate of where to sit
209 216
210 private string m_nextSitAnimation = String.Empty; 217 private string m_nextSitAnimation = String.Empty;
211 218
@@ -216,6 +223,9 @@ namespace OpenSim.Region.Framework.Scenes
216 private bool m_followCamAuto; 223 private bool m_followCamAuto;
217 224
218 private int m_movementUpdateCount; 225 private int m_movementUpdateCount;
226 private int m_lastColCount = -1; //KF: Look for Collision chnages
227 private int m_updateCount = 0; //KF: Update Anims for a while
228 private static readonly int UPDATE_COUNT = 10; // how many frames to update for
219 private const int NumMovementsBetweenRayCast = 5; 229 private const int NumMovementsBetweenRayCast = 5;
220 230
221 private bool CameraConstraintActive; 231 private bool CameraConstraintActive;
@@ -243,7 +253,9 @@ namespace OpenSim.Region.Framework.Scenes
243 DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS, 253 DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS,
244 DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG, 254 DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG,
245 DIR_CONTROL_FLAG_FORWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS, 255 DIR_CONTROL_FLAG_FORWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS,
246 DIR_CONTROL_FLAG_BACKWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG, 256 DIR_CONTROL_FLAG_BACK_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG,
257 DIR_CONTROL_FLAG_LEFT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS,
258 DIR_CONTROL_FLAG_RIGHT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG,
247 DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG 259 DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG
248 } 260 }
249 261
@@ -450,7 +462,8 @@ namespace OpenSim.Region.Framework.Scenes
450 get 462 get
451 { 463 {
452 PhysicsActor actor = m_physicsActor; 464 PhysicsActor actor = m_physicsActor;
453 if (actor != null) 465// if (actor != null)
466 if ((actor != null) && (m_parentID == 0)) // KF Do NOT update m_pos here if Av is sitting!
454 m_pos = actor.Position; 467 m_pos = actor.Position;
455 468
456 return m_parentPosition + m_pos; 469 return m_parentPosition + m_pos;
@@ -471,7 +484,8 @@ namespace OpenSim.Region.Framework.Scenes
471 } 484 }
472 } 485 }
473 486
474 m_pos = value; 487 if (m_parentID == 0) // KF Do NOT update m_pos here if Av is sitting!
488 m_pos = value;
475 m_parentPosition = Vector3.Zero; 489 m_parentPosition = Vector3.Zero;
476 } 490 }
477 } 491 }
@@ -669,7 +683,7 @@ namespace OpenSim.Region.Framework.Scenes
669 CreateSceneViewer(); 683 CreateSceneViewer();
670 m_animator = new ScenePresenceAnimator(this); 684 m_animator = new ScenePresenceAnimator(this);
671 } 685 }
672 686
673 private ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo) : this() 687 private ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo) : this()
674 { 688 {
675 m_rootRegionHandle = reginfo.RegionHandle; 689 m_rootRegionHandle = reginfo.RegionHandle;
@@ -701,16 +715,16 @@ namespace OpenSim.Region.Framework.Scenes
701 m_reprioritization_timer.AutoReset = false; 715 m_reprioritization_timer.AutoReset = false;
702 716
703 AdjustKnownSeeds(); 717 AdjustKnownSeeds();
704
705 // TODO: I think, this won't send anything, as we are still a child here...
706 Animator.TrySetMovementAnimation("STAND"); 718 Animator.TrySetMovementAnimation("STAND");
707
708 // we created a new ScenePresence (a new child agent) in a fresh region. 719 // we created a new ScenePresence (a new child agent) in a fresh region.
709 // Request info about all the (root) agents in this region 720 // Request info about all the (root) agents in this region
710 // Note: This won't send data *to* other clients in that region (children don't send) 721 // Note: This won't send data *to* other clients in that region (children don't send)
711 SendInitialFullUpdateToAllClients(); 722 SendInitialFullUpdateToAllClients();
712
713 RegisterToEvents(); 723 RegisterToEvents();
724 if (m_controllingClient != null)
725 {
726 m_controllingClient.ProcessPendingPackets();
727 }
714 SetDirectionVectors(); 728 SetDirectionVectors();
715 } 729 }
716 730
@@ -760,25 +774,47 @@ namespace OpenSim.Region.Framework.Scenes
760 Dir_Vectors[3] = -Vector3.UnitY; //RIGHT 774 Dir_Vectors[3] = -Vector3.UnitY; //RIGHT
761 Dir_Vectors[4] = Vector3.UnitZ; //UP 775 Dir_Vectors[4] = Vector3.UnitZ; //UP
762 Dir_Vectors[5] = -Vector3.UnitZ; //DOWN 776 Dir_Vectors[5] = -Vector3.UnitZ; //DOWN
763 Dir_Vectors[8] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge 777 Dir_Vectors[6] = new Vector3(0.5f, 0f, 0f); //FORWARD_NUDGE
764 Dir_Vectors[6] = Vector3.UnitX*2; //FORWARD 778 Dir_Vectors[7] = new Vector3(-0.5f, 0f, 0f); //BACK_NUDGE
765 Dir_Vectors[7] = -Vector3.UnitX; //BACK 779 Dir_Vectors[8] = new Vector3(0f, 0.5f, 0f); //LEFT_NUDGE
780 Dir_Vectors[9] = new Vector3(0f, -0.5f, 0f); //RIGHT_NUDGE
781 Dir_Vectors[10] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge
766 } 782 }
767 783
768 private Vector3[] GetWalkDirectionVectors() 784 private Vector3[] GetWalkDirectionVectors()
769 { 785 {
770 Vector3[] vector = new Vector3[9]; 786 Vector3[] vector = new Vector3[11];
771 vector[0] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD 787 vector[0] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD
772 vector[1] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK 788 vector[1] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK
773 vector[2] = Vector3.UnitY; //LEFT 789 vector[2] = Vector3.UnitY; //LEFT
774 vector[3] = -Vector3.UnitY; //RIGHT 790 vector[3] = -Vector3.UnitY; //RIGHT
775 vector[4] = new Vector3(m_CameraAtAxis.Z, 0f, m_CameraUpAxis.Z); //UP 791 vector[4] = new Vector3(m_CameraAtAxis.Z, 0f, m_CameraUpAxis.Z); //UP
776 vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN 792 vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN
777 vector[8] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_Nudge 793 vector[6] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD_NUDGE
778 vector[6] = (new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z) * 2); //FORWARD Nudge 794 vector[7] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK_NUDGE
779 vector[7] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK Nudge 795 vector[8] = Vector3.UnitY; //LEFT_NUDGE
796 vector[9] = -Vector3.UnitY; //RIGHT_NUDGE
797 vector[10] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_NUDGE
780 return vector; 798 return vector;
781 } 799 }
800
801 private bool[] GetDirectionIsNudge()
802 {
803 bool[] isNudge = new bool[11];
804 isNudge[0] = false; //FORWARD
805 isNudge[1] = false; //BACK
806 isNudge[2] = false; //LEFT
807 isNudge[3] = false; //RIGHT
808 isNudge[4] = false; //UP
809 isNudge[5] = false; //DOWN
810 isNudge[6] = true; //FORWARD_NUDGE
811 isNudge[7] = true; //BACK_NUDGE
812 isNudge[8] = true; //LEFT_NUDGE
813 isNudge[9] = true; //RIGHT_NUDGE
814 isNudge[10] = true; //DOWN_Nudge
815 return isNudge;
816 }
817
782 818
783 #endregion 819 #endregion
784 820
@@ -821,7 +857,6 @@ namespace OpenSim.Region.Framework.Scenes
821 m_grouptitle = gm.GetGroupTitle(m_uuid); 857 m_grouptitle = gm.GetGroupTitle(m_uuid);
822 858
823 m_rootRegionHandle = m_scene.RegionInfo.RegionHandle; 859 m_rootRegionHandle = m_scene.RegionInfo.RegionHandle;
824
825 m_scene.SetRootAgentScene(m_uuid); 860 m_scene.SetRootAgentScene(m_uuid);
826 861
827 // Moved this from SendInitialData to ensure that m_appearance is initialized 862 // Moved this from SendInitialData to ensure that m_appearance is initialized
@@ -840,6 +875,52 @@ namespace OpenSim.Region.Framework.Scenes
840 pos.Y = crossedBorder.BorderLine.Z - 1; 875 pos.Y = crossedBorder.BorderLine.Z - 1;
841 } 876 }
842 877
878 //If they're TP'ing in or logging in, we haven't had time to add any known child regions yet.
879 //This has the unfortunate consequence that if somebody is TP'ing who is already a child agent,
880 //they'll bypass the landing point. But I can't think of any decent way of fixing this.
881 if (KnownChildRegionHandles.Count == 0)
882 {
883 ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y);
884 if (land != null)
885 {
886 //Don't restrict gods, estate managers, or land owners to the TP point. This behaviour mimics agni.
887 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero && UserLevel < 200 && !m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid) && land.LandData.OwnerID != m_uuid)
888 {
889 pos = land.LandData.UserLocation;
890 }
891 }
892 }
893
894 if (pos.X < 0 || pos.Y < 0 || pos.Z < 0)
895 {
896 Vector3 emergencyPos = new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 128);
897
898 if (pos.X < 0)
899 {
900 emergencyPos.X = (int)Constants.RegionSize + pos.X;
901 if (!(pos.Y < 0))
902 emergencyPos.Y = pos.Y;
903 if (!(pos.Z < 0))
904 emergencyPos.Z = pos.Z;
905 }
906 if (pos.Y < 0)
907 {
908 emergencyPos.Y = (int)Constants.RegionSize + pos.Y;
909 if (!(pos.X < 0))
910 emergencyPos.X = pos.X;
911 if (!(pos.Z < 0))
912 emergencyPos.Z = pos.Z;
913 }
914 if (pos.Z < 0)
915 {
916 emergencyPos.Z = 128;
917 if (!(pos.Y < 0))
918 emergencyPos.Y = pos.Y;
919 if (!(pos.X < 0))
920 emergencyPos.X = pos.X;
921 }
922 }
923
843 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f) 924 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f)
844 { 925 {
845 m_log.WarnFormat( 926 m_log.WarnFormat(
@@ -972,9 +1053,10 @@ namespace OpenSim.Region.Framework.Scenes
972 public void Teleport(Vector3 pos) 1053 public void Teleport(Vector3 pos)
973 { 1054 {
974 bool isFlying = false; 1055 bool isFlying = false;
1056
975 if (m_physicsActor != null) 1057 if (m_physicsActor != null)
976 isFlying = m_physicsActor.Flying; 1058 isFlying = m_physicsActor.Flying;
977 1059
978 RemoveFromPhysicalScene(); 1060 RemoveFromPhysicalScene();
979 Velocity = Vector3.Zero; 1061 Velocity = Vector3.Zero;
980 AbsolutePosition = pos; 1062 AbsolutePosition = pos;
@@ -986,6 +1068,7 @@ namespace OpenSim.Region.Framework.Scenes
986 } 1068 }
987 1069
988 SendTerseUpdateToAllClients(); 1070 SendTerseUpdateToAllClients();
1071
989 } 1072 }
990 1073
991 public void TeleportWithMomentum(Vector3 pos) 1074 public void TeleportWithMomentum(Vector3 pos)
@@ -1030,7 +1113,9 @@ namespace OpenSim.Region.Framework.Scenes
1030 { 1113 {
1031 AbsolutePosition = AbsolutePosition + new Vector3(0f, 0f, (1.56f / 6f)); 1114 AbsolutePosition = AbsolutePosition + new Vector3(0f, 0f, (1.56f / 6f));
1032 } 1115 }
1033 1116
1117 m_updateCount = UPDATE_COUNT; //KF: Trigger Anim updates to catch falling anim.
1118
1034 ControllingClient.SendPrimUpdate(this, PrimUpdateFlags.Position); 1119 ControllingClient.SendPrimUpdate(this, PrimUpdateFlags.Position);
1035 //ControllingClient.SendAvatarTerseUpdate(new SendAvatarTerseData(m_rootRegionHandle, (ushort)(m_scene.TimeDilation * ushort.MaxValue), LocalId, 1120 //ControllingClient.SendAvatarTerseUpdate(new SendAvatarTerseData(m_rootRegionHandle, (ushort)(m_scene.TimeDilation * ushort.MaxValue), LocalId,
1036 // AbsolutePosition, Velocity, Vector3.Zero, m_bodyRot, new Vector4(0,0,1,AbsolutePosition.Z - 0.5f), m_uuid, null, GetUpdatePriority(ControllingClient))); 1121 // AbsolutePosition, Velocity, Vector3.Zero, m_bodyRot, new Vector4(0,0,1,AbsolutePosition.Z - 0.5f), m_uuid, null, GetUpdatePriority(ControllingClient)));
@@ -1117,7 +1202,6 @@ namespace OpenSim.Region.Framework.Scenes
1117 pos.Z = ground + 1.5f; 1202 pos.Z = ground + 1.5f;
1118 AbsolutePosition = pos; 1203 AbsolutePosition = pos;
1119 } 1204 }
1120
1121 m_isChildAgent = false; 1205 m_isChildAgent = false;
1122 bool m_flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); 1206 bool m_flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);
1123 MakeRootAgent(AbsolutePosition, m_flying); 1207 MakeRootAgent(AbsolutePosition, m_flying);
@@ -1216,6 +1300,7 @@ namespace OpenSim.Region.Framework.Scenes
1216 m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999902"); 1300 m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999902");
1217 1301
1218 m_pos = m_LastFinitePos; 1302 m_pos = m_LastFinitePos;
1303
1219 if (!m_pos.IsFinite()) 1304 if (!m_pos.IsFinite())
1220 { 1305 {
1221 m_pos.X = 127f; 1306 m_pos.X = 127f;
@@ -1282,7 +1367,6 @@ namespace OpenSim.Region.Framework.Scenes
1282 m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(m_CameraCenter - posAdjusted), Vector3.Distance(m_CameraCenter, posAdjusted) + 0.3f, RayCastCameraCallback); 1367 m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(m_CameraCenter - posAdjusted), Vector3.Distance(m_CameraCenter, posAdjusted) + 0.3f, RayCastCameraCallback);
1283 } 1368 }
1284 } 1369 }
1285
1286 lock (scriptedcontrols) 1370 lock (scriptedcontrols)
1287 { 1371 {
1288 if (scriptedcontrols.Count > 0) 1372 if (scriptedcontrols.Count > 0)
@@ -1297,6 +1381,9 @@ namespace OpenSim.Region.Framework.Scenes
1297 1381
1298 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0) 1382 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0)
1299 { 1383 {
1384 m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick.
1385 Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED");
1386
1300 // TODO: This doesn't prevent the user from walking yet. 1387 // TODO: This doesn't prevent the user from walking yet.
1301 // Setting parent ID would fix this, if we knew what value 1388 // Setting parent ID would fix this, if we knew what value
1302 // to use. Or we could add a m_isSitting variable. 1389 // to use. Or we could add a m_isSitting variable.
@@ -1351,6 +1438,11 @@ namespace OpenSim.Region.Framework.Scenes
1351 update_rotation = true; 1438 update_rotation = true;
1352 } 1439 }
1353 1440
1441 //guilty until proven innocent..
1442 bool Nudging = true;
1443 //Basically, if there is at least one non-nudge control then we don't need
1444 //to worry about stopping the avatar
1445
1354 if (m_parentID == 0) 1446 if (m_parentID == 0)
1355 { 1447 {
1356 bool bAllowUpdateMoveToPosition = false; 1448 bool bAllowUpdateMoveToPosition = false;
@@ -1365,9 +1457,12 @@ namespace OpenSim.Region.Framework.Scenes
1365 else 1457 else
1366 dirVectors = Dir_Vectors; 1458 dirVectors = Dir_Vectors;
1367 1459
1368 // The fact that m_movementflag is a byte needs to be fixed 1460 bool[] isNudge = GetDirectionIsNudge();
1369 // it really should be a uint 1461
1370 uint nudgehack = 250; 1462
1463
1464
1465
1371 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS) 1466 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS)
1372 { 1467 {
1373 if (((uint)flags & (uint)DCF) != 0) 1468 if (((uint)flags & (uint)DCF) != 0)
@@ -1377,40 +1472,28 @@ namespace OpenSim.Region.Framework.Scenes
1377 try 1472 try
1378 { 1473 {
1379 agent_control_v3 += dirVectors[i]; 1474 agent_control_v3 += dirVectors[i];
1380 //m_log.DebugFormat("[Motion]: {0}, {1}",i, dirVectors[i]); 1475 if (isNudge[i] == false)
1476 {
1477 Nudging = false;
1478 }
1381 } 1479 }
1382 catch (IndexOutOfRangeException) 1480 catch (IndexOutOfRangeException)
1383 { 1481 {
1384 // Why did I get this? 1482 // Why did I get this?
1385 } 1483 }
1386 1484
1387 if ((m_movementflag & (byte)(uint)DCF) == 0) 1485 if ((m_movementflag & (uint)DCF) == 0)
1388 { 1486 {
1389 if (DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
1390 {
1391 m_movementflag |= (byte)nudgehack;
1392 }
1393 m_movementflag += (byte)(uint)DCF; 1487 m_movementflag += (byte)(uint)DCF;
1394 update_movementflag = true; 1488 update_movementflag = true;
1395 } 1489 }
1396 } 1490 }
1397 else 1491 else
1398 { 1492 {
1399 if ((m_movementflag & (byte)(uint)DCF) != 0 || 1493 if ((m_movementflag & (uint)DCF) != 0)
1400 ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
1401 && ((m_movementflag & (byte)nudgehack) == nudgehack))
1402 ) // This or is for Nudge forward
1403 { 1494 {
1404 m_movementflag -= ((byte)(uint)DCF); 1495 m_movementflag -= (byte)(uint)DCF;
1405
1406 update_movementflag = true; 1496 update_movementflag = true;
1407 /*
1408 if ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
1409 && ((m_movementflag & (byte)nudgehack) == nudgehack))
1410 {
1411 m_log.Debug("Removed Hack flag");
1412 }
1413 */
1414 } 1497 }
1415 else 1498 else
1416 { 1499 {
@@ -1419,7 +1502,6 @@ namespace OpenSim.Region.Framework.Scenes
1419 } 1502 }
1420 i++; 1503 i++;
1421 } 1504 }
1422
1423 //Paupaw:Do Proper PID for Autopilot here 1505 //Paupaw:Do Proper PID for Autopilot here
1424 if (bResetMoveToPosition) 1506 if (bResetMoveToPosition)
1425 { 1507 {
@@ -1454,6 +1536,9 @@ namespace OpenSim.Region.Framework.Scenes
1454 // Ignore z component of vector 1536 // Ignore z component of vector
1455 Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f); 1537 Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f);
1456 LocalVectorToTarget2D.Normalize(); 1538 LocalVectorToTarget2D.Normalize();
1539
1540 //We're not nudging
1541 Nudging = false;
1457 agent_control_v3 += LocalVectorToTarget2D; 1542 agent_control_v3 += LocalVectorToTarget2D;
1458 1543
1459 // update avatar movement flags. the avatar coordinate system is as follows: 1544 // update avatar movement flags. the avatar coordinate system is as follows:
@@ -1542,13 +1627,13 @@ namespace OpenSim.Region.Framework.Scenes
1542 // m_log.DebugFormat( 1627 // m_log.DebugFormat(
1543 // "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3); 1628 // "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3);
1544 1629
1545 AddNewMovement(agent_control_v3, q); 1630 AddNewMovement(agent_control_v3, q, Nudging);
1546 1631
1547 1632
1548 } 1633 }
1549 } 1634 }
1550 1635
1551 if (update_movementflag && ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) == 0) && (m_parentID == 0) && !SitGround) 1636 if (update_movementflag && !SitGround)
1552 Animator.UpdateMovementAnimations(); 1637 Animator.UpdateMovementAnimations();
1553 1638
1554 m_scene.EventManager.TriggerOnClientMovement(this); 1639 m_scene.EventManager.TriggerOnClientMovement(this);
@@ -1563,7 +1648,6 @@ namespace OpenSim.Region.Framework.Scenes
1563 m_sitAtAutoTarget = false; 1648 m_sitAtAutoTarget = false;
1564 PrimitiveBaseShape proxy = PrimitiveBaseShape.Default; 1649 PrimitiveBaseShape proxy = PrimitiveBaseShape.Default;
1565 //proxy.PCode = (byte)PCode.ParticleSystem; 1650 //proxy.PCode = (byte)PCode.ParticleSystem;
1566
1567 proxyObjectGroup = new SceneObjectGroup(UUID, Pos, Rotation, proxy); 1651 proxyObjectGroup = new SceneObjectGroup(UUID, Pos, Rotation, proxy);
1568 proxyObjectGroup.AttachToScene(m_scene); 1652 proxyObjectGroup.AttachToScene(m_scene);
1569 1653
@@ -1605,7 +1689,7 @@ namespace OpenSim.Region.Framework.Scenes
1605 } 1689 }
1606 m_moveToPositionInProgress = true; 1690 m_moveToPositionInProgress = true;
1607 m_moveToPositionTarget = new Vector3(locx, locy, locz); 1691 m_moveToPositionTarget = new Vector3(locx, locy, locz);
1608 } 1692 }
1609 catch (Exception ex) 1693 catch (Exception ex)
1610 { 1694 {
1611 //Why did I get this error? 1695 //Why did I get this error?
@@ -1627,7 +1711,7 @@ namespace OpenSim.Region.Framework.Scenes
1627 Velocity = Vector3.Zero; 1711 Velocity = Vector3.Zero;
1628 SendFullUpdateToAllClients(); 1712 SendFullUpdateToAllClients();
1629 1713
1630 //HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); 1714 HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); //KF ??
1631 } 1715 }
1632 //ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false); 1716 //ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false);
1633 m_requestedSitTargetUUID = UUID.Zero; 1717 m_requestedSitTargetUUID = UUID.Zero;
@@ -1664,50 +1748,82 @@ namespace OpenSim.Region.Framework.Scenes
1664 1748
1665 if (m_parentID != 0) 1749 if (m_parentID != 0)
1666 { 1750 {
1667 m_log.Debug("StandupCode Executed");
1668 SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID); 1751 SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID);
1669 if (part != null) 1752 if (part != null)
1670 { 1753 {
1754 part.TaskInventory.LockItemsForRead(true);
1671 TaskInventoryDictionary taskIDict = part.TaskInventory; 1755 TaskInventoryDictionary taskIDict = part.TaskInventory;
1672 if (taskIDict != null) 1756 if (taskIDict != null)
1673 { 1757 {
1674 lock (taskIDict) 1758 foreach (UUID taskID in taskIDict.Keys)
1675 { 1759 {
1676 foreach (UUID taskID in taskIDict.Keys) 1760 UnRegisterControlEventsToScript(LocalId, taskID);
1677 { 1761 taskIDict[taskID].PermsMask &= ~(
1678 UnRegisterControlEventsToScript(LocalId, taskID); 1762 2048 | //PERMISSION_CONTROL_CAMERA
1679 taskIDict[taskID].PermsMask &= ~( 1763 4); // PERMISSION_TAKE_CONTROLS
1680 2048 | //PERMISSION_CONTROL_CAMERA
1681 4); // PERMISSION_TAKE_CONTROLS
1682 }
1683 } 1764 }
1684
1685 } 1765 }
1766 part.TaskInventory.LockItemsForRead(false);
1686 // Reset sit target. 1767 // Reset sit target.
1687 if (part.GetAvatarOnSitTarget() == UUID) 1768 if (part.GetAvatarOnSitTarget() == UUID)
1688 part.SetAvatarOnSitTarget(UUID.Zero); 1769 part.SetAvatarOnSitTarget(UUID.Zero);
1689
1690 m_parentPosition = part.GetWorldPosition(); 1770 m_parentPosition = part.GetWorldPosition();
1691 ControllingClient.SendClearFollowCamProperties(part.ParentUUID); 1771 ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
1692 } 1772 }
1773 // part.GetWorldRotation() is the rotation of the object being sat on
1774 // Rotation is the sittiing Av's rotation
1693 1775
1694 if (m_physicsActor == null) 1776 Quaternion partRot;
1777// if (part.LinkNum == 1)
1778// { // Root prim of linkset
1779// partRot = part.ParentGroup.RootPart.RotationOffset;
1780// }
1781// else
1782// { // single or child prim
1783
1784// }
1785 if (part == null) //CW: Part may be gone. llDie() for example.
1695 { 1786 {
1696 AddToPhysicalScene(false); 1787 partRot = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
1788 }
1789 else
1790 {
1791 partRot = part.GetWorldRotation();
1697 } 1792 }
1698 1793
1699 m_pos += m_parentPosition + new Vector3(0.0f, 0.0f, 2.0f*m_sitAvatarHeight); 1794 Quaternion partIRot = Quaternion.Inverse(partRot);
1700 m_parentPosition = Vector3.Zero; 1795
1796 Quaternion avatarRot = Quaternion.Inverse(Quaternion.Inverse(Rotation) * partIRot); // world or. of the av
1797 Vector3 avStandUp = new Vector3(1.0f, 0f, 0f) * avatarRot; // 1M infront of av
1701 1798
1702 m_parentID = 0; 1799
1800 if (m_physicsActor == null)
1801 {
1802 AddToPhysicalScene(false);
1803 }
1804 //CW: If the part isn't null then we can set the current position
1805 if (part != null)
1806 {
1807 Vector3 avWorldStandUp = avStandUp + part.GetWorldPosition() + (m_pos * partRot); // + av sit offset!
1808 AbsolutePosition = avWorldStandUp; //KF: Fix stand up.
1809 part.IsOccupied = false;
1810 }
1811 else
1812 {
1813 //CW: Since the part doesn't exist, a coarse standup position isn't an issue
1814 AbsolutePosition = m_lastWorldPosition;
1815 }
1816
1817 m_parentPosition = Vector3.Zero;
1818 m_parentID = 0;
1703 SendFullUpdateToAllClients(); 1819 SendFullUpdateToAllClients();
1704 m_requestedSitTargetID = 0; 1820 m_requestedSitTargetID = 0;
1821
1705 if ((m_physicsActor != null) && (m_avHeight > 0)) 1822 if ((m_physicsActor != null) && (m_avHeight > 0))
1706 { 1823 {
1707 SetHeight(m_avHeight); 1824 SetHeight(m_avHeight);
1708 } 1825 }
1709 } 1826 }
1710
1711 Animator.TrySetMovementAnimation("STAND"); 1827 Animator.TrySetMovementAnimation("STAND");
1712 } 1828 }
1713 1829
@@ -1738,13 +1854,9 @@ namespace OpenSim.Region.Framework.Scenes
1738 Vector3 avSitOffSet = part.SitTargetPosition; 1854 Vector3 avSitOffSet = part.SitTargetPosition;
1739 Quaternion avSitOrientation = part.SitTargetOrientation; 1855 Quaternion avSitOrientation = part.SitTargetOrientation;
1740 UUID avOnTargetAlready = part.GetAvatarOnSitTarget(); 1856 UUID avOnTargetAlready = part.GetAvatarOnSitTarget();
1741 1857 bool SitTargetOccupied = (avOnTargetAlready != UUID.Zero);
1742 bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero)); 1858 bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored.
1743 bool SitTargetisSet = 1859 if (SitTargetisSet && !SitTargetOccupied)
1744 (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f && avSitOrientation.W == 1f &&
1745 avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f));
1746
1747 if (SitTargetisSet && SitTargetUnOccupied)
1748 { 1860 {
1749 //switch the target to this prim 1861 //switch the target to this prim
1750 return part; 1862 return part;
@@ -1758,84 +1870,153 @@ namespace OpenSim.Region.Framework.Scenes
1758 private void SendSitResponse(IClientAPI remoteClient, UUID targetID, Vector3 offset, Quaternion pSitOrientation) 1870 private void SendSitResponse(IClientAPI remoteClient, UUID targetID, Vector3 offset, Quaternion pSitOrientation)
1759 { 1871 {
1760 bool autopilot = true; 1872 bool autopilot = true;
1873 Vector3 autopilotTarget = new Vector3();
1874 Quaternion sitOrientation = Quaternion.Identity;
1761 Vector3 pos = new Vector3(); 1875 Vector3 pos = new Vector3();
1762 Quaternion sitOrientation = pSitOrientation;
1763 Vector3 cameraEyeOffset = Vector3.Zero; 1876 Vector3 cameraEyeOffset = Vector3.Zero;
1764 Vector3 cameraAtOffset = Vector3.Zero; 1877 Vector3 cameraAtOffset = Vector3.Zero;
1765 bool forceMouselook = false; 1878 bool forceMouselook = false;
1766 1879
1767 //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID); 1880 //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID);
1768 SceneObjectPart part = FindNextAvailableSitTarget(targetID); 1881 SceneObjectPart part = FindNextAvailableSitTarget(targetID);
1769 if (part != null) 1882 if (part == null) return;
1770 { 1883
1771 // TODO: determine position to sit at based on scene geometry; don't trust offset from client 1884 // TODO: determine position to sit at based on scene geometry; don't trust offset from client
1772 // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it 1885 // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it
1773 1886
1774 // Is a sit target available? 1887 // part is the prim to sit on
1775 Vector3 avSitOffSet = part.SitTargetPosition; 1888 // offset is the world-ref vector distance from that prim center to the click-spot
1776 Quaternion avSitOrientation = part.SitTargetOrientation; 1889 // UUID is the UUID of the Avatar doing the clicking
1777 UUID avOnTargetAlready = part.GetAvatarOnSitTarget(); 1890
1778 1891 m_avInitialPos = AbsolutePosition; // saved to calculate unscripted sit rotation
1779 bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero)); 1892
1780 bool SitTargetisSet = 1893 // Is a sit target available?
1781 (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f && 1894 Vector3 avSitOffSet = part.SitTargetPosition;
1782 ( 1895 Quaternion avSitOrientation = part.SitTargetOrientation;
1783 avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f && avSitOrientation.W == 1f // Valid Zero Rotation quaternion 1896
1784 || avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 1f && avSitOrientation.W == 0f // W-Z Mapping was invalid at one point 1897 bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored.
1785 || avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f && avSitOrientation.W == 0f // Invalid Quaternion 1898 // Quaternion partIRot = Quaternion.Inverse(part.GetWorldRotation());
1786 ) 1899 Quaternion partRot;
1787 )); 1900// if (part.LinkNum == 1)
1788 1901// { // Root prim of linkset
1789 if (SitTargetisSet && SitTargetUnOccupied) 1902// partRot = part.ParentGroup.RootPart.RotationOffset;
1790 { 1903// }
1791 part.SetAvatarOnSitTarget(UUID); 1904// else
1792 offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); 1905// { // single or child prim
1793 sitOrientation = avSitOrientation; 1906 partRot = part.GetWorldRotation();
1794 autopilot = false; 1907// }
1795 } 1908 Quaternion partIRot = Quaternion.Inverse(partRot);
1796 1909//Console.WriteLine("SendSitResponse offset=" + offset + " Occup=" + part.IsOccupied + " TargSet=" + SitTargetisSet);
1797 pos = part.AbsolutePosition + offset; 1910 // Sit analysis rewritten by KF 091125
1798 //if (Math.Abs(part.AbsolutePosition.Z - AbsolutePosition.Z) > 1) 1911 if (SitTargetisSet) // scipted sit
1799 //{ 1912 {
1800 // offset = pos; 1913 if (!part.IsOccupied)
1801 //autopilot = false; 1914 {
1802 //} 1915//Console.WriteLine("Scripted, unoccupied");
1803 if (m_physicsActor != null) 1916 part.SetAvatarOnSitTarget(UUID); // set that Av will be on it
1804 { 1917 offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); // change ofset to the scripted one
1805 // If we're not using the client autopilot, we're immediately warping the avatar to the location 1918 sitOrientation = avSitOrientation; // Change rotatione to the scripted one
1806 // We can remove the physicsActor until they stand up. 1919 autopilot = false; // Jump direct to scripted llSitPos()
1807 m_sitAvatarHeight = m_physicsActor.Size.Z; 1920 }
1808 1921 else
1809 if (autopilot) 1922 {
1810 { 1923//Console.WriteLine("Scripted, occupied");
1811 if (Util.GetDistanceTo(AbsolutePosition, pos) < 4.5) 1924 return;
1812 { 1925 }
1813 autopilot = false; 1926 }
1927 else // Not Scripted
1928 {
1929 if ( (Math.Abs(offset.X) > 0.5f) || (Math.Abs(offset.Y) > 0.5f) )
1930 {
1931 // large prim & offset, ignore if other Avs sitting
1932// offset.Z -= 0.05f;
1933 m_avUnscriptedSitPos = offset * partIRot; // (non-zero) sit where clicked
1934 autopilotTarget = part.AbsolutePosition + offset; // World location of clicked point
1935
1936//Console.WriteLine(" offset ={0}", offset);
1937//Console.WriteLine(" UnscriptedSitPos={0}", m_avUnscriptedSitPos);
1938//Console.WriteLine(" autopilotTarget={0}", autopilotTarget);
1939
1940 }
1941 else // small offset
1942 {
1943//Console.WriteLine("Small offset");
1944 if (!part.IsOccupied)
1945 {
1946 m_avUnscriptedSitPos = Vector3.Zero; // Zero = Sit on prim center
1947 autopilotTarget = part.AbsolutePosition;
1948//Console.WriteLine("UsSmall autopilotTarget={0}", autopilotTarget);
1949 }
1950 else return; // occupied small
1951 } // end large/small
1952 } // end Scripted/not
1953 cameraAtOffset = part.GetCameraAtOffset();
1954 cameraEyeOffset = part.GetCameraEyeOffset();
1955 forceMouselook = part.GetForceMouselook();
1956 if(cameraAtOffset == Vector3.Zero) cameraAtOffset = new Vector3(0f, 0f, 0.1f); //
1957 if(cameraEyeOffset == Vector3.Zero) cameraEyeOffset = new Vector3(0f, 0f, 0.1f); //
1814 1958
1815 RemoveFromPhysicalScene(); 1959 if (m_physicsActor != null)
1816 AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight); 1960 {
1817 } 1961 // If we're not using the client autopilot, we're immediately warping the avatar to the location
1818 } 1962 // We can remove the physicsActor until they stand up.
1819 else 1963 m_sitAvatarHeight = m_physicsActor.Size.Z;
1964 if (autopilot)
1965 { // its not a scripted sit
1966// if (Util.GetDistanceTo(AbsolutePosition, autopilotTarget) < 4.5)
1967 if( (Math.Abs(AbsolutePosition.X - autopilotTarget.X) < 2.0f) && (Math.Abs(AbsolutePosition.Y - autopilotTarget.Y) < 2.0f) )
1820 { 1968 {
1969 autopilot = false; // close enough
1970 m_lastWorldPosition = m_pos; /* CW - This give us a position to return the avatar to if the part is killed before standup.
1971 Not using the part's position because returning the AV to the last known standing
1972 position is likely to be more friendly, isn't it? */
1821 RemoveFromPhysicalScene(); 1973 RemoveFromPhysicalScene();
1822 } 1974 AbsolutePosition = autopilotTarget + new Vector3(0.0f, 0.0f, (m_sitAvatarHeight / 2.0f)); // Warp av to over sit target
1975 } // else the autopilot will get us close
1976 }
1977 else
1978 { // its a scripted sit
1979 m_lastWorldPosition = part.AbsolutePosition; /* CW - This give us a position to return the avatar to if the part is killed before standup.
1980 I *am* using the part's position this time because we have no real idea how far away
1981 the avatar is from the sit target. */
1982 RemoveFromPhysicalScene();
1823 } 1983 }
1824
1825 cameraAtOffset = part.GetCameraAtOffset();
1826 cameraEyeOffset = part.GetCameraEyeOffset();
1827 forceMouselook = part.GetForceMouselook();
1828 } 1984 }
1829 1985 else return; // physactor is null!
1830 ControllingClient.SendSitResponse(targetID, offset, sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook); 1986
1831 m_requestedSitTargetUUID = targetID; 1987 Vector3 offsetr; // = offset * partIRot;
1988 // KF: In a linkset, offsetr needs to be relative to the group root! 091208
1989 // offsetr = (part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) + (offset * partIRot);
1990 // if (part.LinkNum < 2) 091216 All this was necessary because of the GetWorldRotation error.
1991 // { // Single, or Root prim of linkset, target is ClickOffset * RootRot
1992 offsetr = offset * partIRot;
1993//
1994 // else
1995 // { // Child prim, offset is (ChildOffset * RootRot) + (ClickOffset * ChildRot)
1996 // offsetr = //(part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) +
1997 // (offset * partRot);
1998 // }
1999
2000//Console.WriteLine(" ");
2001//Console.WriteLine("link number ={0}", part.LinkNum);
2002//Console.WriteLine("Prim offset ={0}", part.OffsetPosition );
2003//Console.WriteLine("Root Rotate ={0}", part.ParentGroup.RootPart.RotationOffset);
2004//Console.WriteLine("Click offst ={0}", offset);
2005//Console.WriteLine("Prim Rotate ={0}", part.GetWorldRotation());
2006//Console.WriteLine("offsetr ={0}", offsetr);
2007//Console.WriteLine("Camera At ={0}", cameraAtOffset);
2008//Console.WriteLine("Camera Eye ={0}", cameraEyeOffset);
2009
2010 ControllingClient.SendSitResponse(part.UUID, offsetr, sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook);
2011 m_requestedSitTargetUUID = part.UUID; //KF: Correct autopilot target
1832 // This calls HandleAgentSit twice, once from here, and the client calls 2012 // This calls HandleAgentSit twice, once from here, and the client calls
1833 // HandleAgentSit itself after it gets to the location 2013 // HandleAgentSit itself after it gets to the location
1834 // It doesn't get to the location until we've moved them there though 2014 // It doesn't get to the location until we've moved them there though
1835 // which happens in HandleAgentSit :P 2015 // which happens in HandleAgentSit :P
1836 m_autopilotMoving = autopilot; 2016 m_autopilotMoving = autopilot;
1837 m_autoPilotTarget = pos; 2017 m_autoPilotTarget = autopilotTarget;
1838 m_sitAtAutoTarget = autopilot; 2018 m_sitAtAutoTarget = autopilot;
2019 m_initialSitTarget = autopilotTarget;
1839 if (!autopilot) 2020 if (!autopilot)
1840 HandleAgentSit(remoteClient, UUID); 2021 HandleAgentSit(remoteClient, UUID);
1841 } 2022 }
@@ -2130,31 +2311,66 @@ namespace OpenSim.Region.Framework.Scenes
2130 { 2311 {
2131 if (part != null) 2312 if (part != null)
2132 { 2313 {
2314//Console.WriteLine("Link #{0}, Rot {1}", part.LinkNum, part.GetWorldRotation());
2133 if (part.GetAvatarOnSitTarget() == UUID) 2315 if (part.GetAvatarOnSitTarget() == UUID)
2134 { 2316 {
2317//Console.WriteLine("Scripted Sit");
2318 // Scripted sit
2135 Vector3 sitTargetPos = part.SitTargetPosition; 2319 Vector3 sitTargetPos = part.SitTargetPosition;
2136 Quaternion sitTargetOrient = part.SitTargetOrientation; 2320 Quaternion sitTargetOrient = part.SitTargetOrientation;
2137
2138 //Quaternion vq = new Quaternion(sitTargetPos.X, sitTargetPos.Y+0.2f, sitTargetPos.Z+0.2f, 0);
2139 //Quaternion nq = new Quaternion(-sitTargetOrient.X, -sitTargetOrient.Y, -sitTargetOrient.Z, sitTargetOrient.w);
2140
2141 //Quaternion result = (sitTargetOrient * vq) * nq;
2142
2143 m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z); 2321 m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z);
2144 m_pos += SIT_TARGET_ADJUSTMENT; 2322 m_pos += SIT_TARGET_ADJUSTMENT;
2145 m_bodyRot = sitTargetOrient; 2323 m_bodyRot = sitTargetOrient;
2146 //Rotation = sitTargetOrient;
2147 m_parentPosition = part.AbsolutePosition; 2324 m_parentPosition = part.AbsolutePosition;
2148 2325 part.IsOccupied = true;
2149 //SendTerseUpdateToAllClients(); 2326Console.WriteLine("Scripted Sit ofset {0}", m_pos);
2150 } 2327 }
2151 else 2328 else
2152 { 2329 {
2153 m_pos -= part.AbsolutePosition; 2330 // if m_avUnscriptedSitPos is zero then Av sits above center
2331 // Else Av sits at m_avUnscriptedSitPos
2332
2333 // Non-scripted sit by Kitto Flora 21Nov09
2334 // Calculate angle of line from prim to Av
2335 Quaternion partIRot;
2336// if (part.LinkNum == 1)
2337// { // Root prim of linkset
2338// partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset);
2339// }
2340// else
2341// { // single or child prim
2342 partIRot = Quaternion.Inverse(part.GetWorldRotation());
2343// }
2344 Vector3 sitTargetPos= part.AbsolutePosition + m_avUnscriptedSitPos;
2345 float y_diff = (m_avInitialPos.Y - sitTargetPos.Y);
2346 float x_diff = ( m_avInitialPos.X - sitTargetPos.X);
2347 if(Math.Abs(x_diff) < 0.001f) x_diff = 0.001f; // avoid div by 0
2348 if(Math.Abs(y_diff) < 0.001f) y_diff = 0.001f; // avoid pol flip at 0
2349 float sit_angle = (float)Math.Atan2( (double)y_diff, (double)x_diff);
2350 // NOTE: when sitting m_ pos and m_bodyRot are *relative* to the prim location/rotation, not 'World'.
2351 // Av sits at world euler <0,0, z>, translated by part rotation
2352 m_bodyRot = partIRot * Quaternion.CreateFromEulers(0f, 0f, sit_angle); // sit at 0,0,inv-click
2353
2154 m_parentPosition = part.AbsolutePosition; 2354 m_parentPosition = part.AbsolutePosition;
2155 } 2355 part.IsOccupied = true;
2156 } 2356 m_pos = new Vector3(0f, 0f, 0.05f) + // corrections to get Sit Animation
2157 else 2357 (new Vector3(0.0f, 0f, 0.61f) * partIRot) + // located on center
2358 (new Vector3(0.34f, 0f, 0.0f) * m_bodyRot) +
2359 m_avUnscriptedSitPos; // adds click offset, if any
2360 //Set up raytrace to find top surface of prim
2361 Vector3 size = part.Scale;
2362 float mag = 2.0f; // 0.1f + (float)Math.Sqrt((size.X * size.X) + (size.Y * size.Y) + (size.Z * size.Z));
2363 Vector3 start = part.AbsolutePosition + new Vector3(0f, 0f, mag);
2364 Vector3 down = new Vector3(0f, 0f, -1f);
2365//Console.WriteLine("st={0} do={1} ma={2}", start, down, mag);
2366 m_scene.PhysicsScene.RaycastWorld(
2367 start, // Vector3 position,
2368 down, // Vector3 direction,
2369 mag, // float length,
2370 SitAltitudeCallback); // retMethod
2371 } // end scripted/not
2372 }
2373 else // no Av
2158 { 2374 {
2159 return; 2375 return;
2160 } 2376 }
@@ -2166,11 +2382,39 @@ namespace OpenSim.Region.Framework.Scenes
2166 2382
2167 Animator.TrySetMovementAnimation(sitAnimation); 2383 Animator.TrySetMovementAnimation(sitAnimation);
2168 SendFullUpdateToAllClients(); 2384 SendFullUpdateToAllClients();
2169 // This may seem stupid, but Our Full updates don't send avatar rotation :P
2170 // So we're also sending a terse update (which has avatar rotation)
2171 // [Update] We do now.
2172 //SendTerseUpdateToAllClients();
2173 } 2385 }
2386
2387 public void SitAltitudeCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 normal)
2388 {
2389 // KF: 091202 There appears to be a bug in Prim Edit Size - the process sometimes make a prim that RayTrace no longer
2390 // sees. Take/re-rez, or sim restart corrects the condition. Result of bug is incorrect sit height.
2391 if(hitYN)
2392 {
2393 // m_pos = Av offset from prim center to make look like on center
2394 // m_parentPosition = Actual center pos of prim
2395 // collisionPoint = spot on prim where we want to sit
2396 // collisionPoint.Z = global sit surface height
2397 SceneObjectPart part = m_scene.GetSceneObjectPart(localid);
2398 Quaternion partIRot;
2399// if (part.LinkNum == 1)
2400/// { // Root prim of linkset
2401// partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset);
2402// }
2403// else
2404// { // single or child prim
2405 partIRot = Quaternion.Inverse(part.GetWorldRotation());
2406// }
2407 if (m_initialSitTarget != null)
2408 {
2409 float offZ = collisionPoint.Z - m_initialSitTarget.Z;
2410 Vector3 offset = new Vector3(0.0f, 0.0f, offZ) * partIRot; // Altitude correction
2411 //Console.WriteLine("sitPoint={0}, offset={1}", sitPoint, offset);
2412 m_pos += offset;
2413 // ControllingClient.SendClearFollowCamProperties(part.UUID);
2414 }
2415
2416 }
2417 } // End SitAltitudeCallback KF.
2174 2418
2175 /// <summary> 2419 /// <summary>
2176 /// Event handler for the 'Always run' setting on the client 2420 /// Event handler for the 'Always run' setting on the client
@@ -2200,7 +2444,7 @@ namespace OpenSim.Region.Framework.Scenes
2200 /// </summary> 2444 /// </summary>
2201 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param> 2445 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param>
2202 /// <param name="rotation">The direction in which this avatar should now face. 2446 /// <param name="rotation">The direction in which this avatar should now face.
2203 public void AddNewMovement(Vector3 vec, Quaternion rotation) 2447 public void AddNewMovement(Vector3 vec, Quaternion rotation, bool Nudging)
2204 { 2448 {
2205 if (m_isChildAgent) 2449 if (m_isChildAgent)
2206 { 2450 {
@@ -2241,10 +2485,11 @@ namespace OpenSim.Region.Framework.Scenes
2241 Rotation = rotation; 2485 Rotation = rotation;
2242 Vector3 direc = vec * rotation; 2486 Vector3 direc = vec * rotation;
2243 direc.Normalize(); 2487 direc.Normalize();
2488 PhysicsActor actor = m_physicsActor;
2489 if ((vec.Z == 0f) && !actor.Flying) direc.Z = 0f; // Prevent camera WASD up.
2244 2490
2245 direc *= 0.03f * 128f * m_speedModifier; 2491 direc *= 0.03f * 128f * m_speedModifier;
2246 2492
2247 PhysicsActor actor = m_physicsActor;
2248 if (actor != null) 2493 if (actor != null)
2249 { 2494 {
2250 if (actor.Flying) 2495 if (actor.Flying)
@@ -2266,18 +2511,25 @@ namespace OpenSim.Region.Framework.Scenes
2266 { 2511 {
2267 if (direc.Z > 2.0f) 2512 if (direc.Z > 2.0f)
2268 { 2513 {
2269 direc.Z *= 3.0f; 2514 if(m_animator.m_animTickJump == -1)
2270 2515 {
2271 // TODO: PreJump and jump happen too quickly. Many times prejump gets ignored. 2516 direc.Z *= 3.0f; // jump
2272 Animator.TrySetMovementAnimation("PREJUMP"); 2517 }
2273 Animator.TrySetMovementAnimation("JUMP"); 2518 else
2519 {
2520 direc.Z *= 0.1f; // prejump
2521 }
2522 /* Animations are controlled via GetMovementAnimation() in ScenePresenceAnimator.cs
2523 Animator.TrySetMovementAnimation("PREJUMP");
2524 Animator.TrySetMovementAnimation("JUMP");
2525 */
2274 } 2526 }
2275 } 2527 }
2276 } 2528 }
2277 2529
2278 // TODO: Add the force instead of only setting it to support multiple forces per frame? 2530 // TODO: Add the force instead of only setting it to support multiple forces per frame?
2279 m_forceToApply = direc; 2531 m_forceToApply = direc;
2280 2532 m_isNudging = Nudging;
2281 m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); 2533 m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
2282 } 2534 }
2283 2535
@@ -2292,7 +2544,7 @@ namespace OpenSim.Region.Framework.Scenes
2292 const float POSITION_TOLERANCE = 0.05f; 2544 const float POSITION_TOLERANCE = 0.05f;
2293 //const int TIME_MS_TOLERANCE = 3000; 2545 //const int TIME_MS_TOLERANCE = 3000;
2294 2546
2295 SendPrimUpdates(); 2547
2296 2548
2297 if (m_isChildAgent == false) 2549 if (m_isChildAgent == false)
2298 { 2550 {
@@ -2322,6 +2574,9 @@ namespace OpenSim.Region.Framework.Scenes
2322 CheckForBorderCrossing(); 2574 CheckForBorderCrossing();
2323 CheckForSignificantMovement(); // sends update to the modules. 2575 CheckForSignificantMovement(); // sends update to the modules.
2324 } 2576 }
2577
2578 //Sending prim updates AFTER the avatar terse updates are sent
2579 SendPrimUpdates();
2325 } 2580 }
2326 2581
2327 #endregion 2582 #endregion
@@ -3094,6 +3349,7 @@ namespace OpenSim.Region.Framework.Scenes
3094 m_callbackURI = cAgent.CallbackURI; 3349 m_callbackURI = cAgent.CallbackURI;
3095 3350
3096 m_pos = cAgent.Position; 3351 m_pos = cAgent.Position;
3352
3097 m_velocity = cAgent.Velocity; 3353 m_velocity = cAgent.Velocity;
3098 m_CameraCenter = cAgent.Center; 3354 m_CameraCenter = cAgent.Center;
3099 //m_avHeight = cAgent.Size.Z; 3355 //m_avHeight = cAgent.Size.Z;
@@ -3182,14 +3438,25 @@ namespace OpenSim.Region.Framework.Scenes
3182 { 3438 {
3183 if (m_forceToApply.HasValue) 3439 if (m_forceToApply.HasValue)
3184 { 3440 {
3185 Vector3 force = m_forceToApply.Value;
3186 3441
3442 Vector3 force = m_forceToApply.Value;
3187 m_updateflag = true; 3443 m_updateflag = true;
3188// movementvector = force;
3189 Velocity = force; 3444 Velocity = force;
3190 3445
3191 m_forceToApply = null; 3446 m_forceToApply = null;
3192 } 3447 }
3448 else
3449 {
3450 if (m_isNudging)
3451 {
3452 Vector3 force = Vector3.Zero;
3453
3454 m_updateflag = true;
3455 Velocity = force;
3456 m_isNudging = false;
3457 m_updateCount = UPDATE_COUNT; //KF: Update anims to pickup "STAND"
3458 }
3459 }
3193 } 3460 }
3194 3461
3195 public override void SetText(string text, Vector3 color, double alpha) 3462 public override void SetText(string text, Vector3 color, double alpha)
@@ -3240,18 +3507,29 @@ namespace OpenSim.Region.Framework.Scenes
3240 { 3507 {
3241 if (e == null) 3508 if (e == null)
3242 return; 3509 return;
3243 3510
3244 //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f)) 3511 // The Physics Scene will send (spam!) updates every 500 ms grep: m_physicsActor.SubscribeEvents(
3245 // The Physics Scene will send updates every 500 ms grep: m_physicsActor.SubscribeEvents(
3246 // as of this comment the interval is set in AddToPhysicalScene 3512 // as of this comment the interval is set in AddToPhysicalScene
3247 if (Animator!=null) 3513 if (Animator!=null)
3248 Animator.UpdateMovementAnimations(); 3514 {
3515 if (m_updateCount > 0) //KF: DO NOT call UpdateMovementAnimations outside of the m_updateCount wrapper,
3516 { // else its will lock out other animation changes, like ground sit.
3517 Animator.UpdateMovementAnimations();
3518 m_updateCount--;
3519 }
3520 }
3249 3521
3250 CollisionEventUpdate collisionData = (CollisionEventUpdate)e; 3522 CollisionEventUpdate collisionData = (CollisionEventUpdate)e;
3251 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList; 3523 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList;
3252 3524
3253 CollisionPlane = Vector4.UnitW; 3525 CollisionPlane = Vector4.UnitW;
3254 3526
3527 if (m_lastColCount != coldata.Count)
3528 {
3529 m_updateCount = UPDATE_COUNT;
3530 m_lastColCount = coldata.Count;
3531 }
3532
3255 if (coldata.Count != 0 && Animator != null) 3533 if (coldata.Count != 0 && Animator != null)
3256 { 3534 {
3257 switch (Animator.CurrentMovementAnimation) 3535 switch (Animator.CurrentMovementAnimation)
@@ -3455,7 +3733,10 @@ namespace OpenSim.Region.Framework.Scenes
3455 m_scene = scene; 3733 m_scene = scene;
3456 3734
3457 RegisterToEvents(); 3735 RegisterToEvents();
3458 3736 if (m_controllingClient != null)
3737 {
3738 m_controllingClient.ProcessPendingPackets();
3739 }
3459 /* 3740 /*
3460 AbsolutePosition = client.StartPos; 3741 AbsolutePosition = client.StartPos;
3461 3742
@@ -3686,6 +3967,32 @@ namespace OpenSim.Region.Framework.Scenes
3686 return; 3967 return;
3687 } 3968 }
3688 3969
3970 XmlDocument doc = new XmlDocument();
3971 string stateData = String.Empty;
3972
3973 IAttachmentsService attServ = m_scene.RequestModuleInterface<IAttachmentsService>();
3974 if (attServ != null)
3975 {
3976 m_log.DebugFormat("[ATTACHMENT]: Loading attachment data from attachment service");
3977 stateData = attServ.Get(ControllingClient.AgentId.ToString());
3978 doc.LoadXml(stateData);
3979 }
3980
3981 Dictionary<UUID, string> itemData = new Dictionary<UUID, string>();
3982
3983 XmlNodeList nodes = doc.GetElementsByTagName("Attachment");
3984 if (nodes.Count > 0)
3985 {
3986 foreach (XmlNode n in nodes)
3987 {
3988 XmlElement elem = (XmlElement)n;
3989 string itemID = elem.GetAttribute("ItemID");
3990 string xml = elem.InnerXml;
3991
3992 itemData[new UUID(itemID)] = xml;
3993 }
3994 }
3995
3689 List<int> attPoints = m_appearance.GetAttachedPoints(); 3996 List<int> attPoints = m_appearance.GetAttachedPoints();
3690 foreach (int p in attPoints) 3997 foreach (int p in attPoints)
3691 { 3998 {
@@ -3705,9 +4012,26 @@ namespace OpenSim.Region.Framework.Scenes
3705 4012
3706 try 4013 try
3707 { 4014 {
3708 // Rez from inventory 4015 string xmlData;
3709 UUID asset 4016 XmlDocument d = new XmlDocument();
3710 = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p); 4017 UUID asset;
4018 if (itemData.TryGetValue(itemID, out xmlData))
4019 {
4020 d.LoadXml(xmlData);
4021 m_log.InfoFormat("[ATTACHMENT]: Found saved state for item {0}, loading it", itemID);
4022
4023 // Rez from inventory
4024 asset
4025 = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p, true, d);
4026
4027 }
4028 else
4029 {
4030 // Rez from inventory (with a null doc to let
4031 // CHANGED_OWNER happen)
4032 asset
4033 = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p, true, null);
4034 }
3711 4035
3712 m_log.InfoFormat( 4036 m_log.InfoFormat(
3713 "[ATTACHMENT]: Rezzed attachment in point {0} from item {1} and asset {2} ({3})", 4037 "[ATTACHMENT]: Rezzed attachment in point {0} from item {1} and asset {2} ({3})",
@@ -3744,5 +4068,16 @@ namespace OpenSim.Region.Framework.Scenes
3744 m_reprioritization_called = false; 4068 m_reprioritization_called = false;
3745 } 4069 }
3746 } 4070 }
4071
4072 private Vector3 Quat2Euler(Quaternion rot){
4073 float x = Utils.RAD_TO_DEG * (float)Math.Atan2((double)((2.0f * rot.X * rot.W) - (2.0f * rot.Y * rot.Z)) ,
4074 (double)(1 - (2.0f * rot.X * rot.X) - (2.0f * rot.Z * rot.Z)));
4075 float y = Utils.RAD_TO_DEG * (float)Math.Asin ((double)((2.0f * rot.X * rot.Y) + (2.0f * rot.Z * rot.W)));
4076 float z = Utils.RAD_TO_DEG * (float)Math.Atan2(((double)(2.0f * rot.Y * rot.W) - (2.0f * rot.X * rot.Z)) ,
4077 (double)(1 - (2.0f * rot.Y * rot.Y) - (2.0f * rot.Z * rot.Z)));
4078 return(new Vector3(x,y,z));
4079 }
4080
4081
3747 } 4082 }
3748} 4083}