aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework')
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEntityInventory.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/ISnmpModule.cs18
-rw-r--r--OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs27
-rw-r--r--OpenSim/Region/Framework/Scenes/EntityManager.cs79
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs11
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs48
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs24
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs26
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs655
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs133
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs677
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs580
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneViewer.cs2
14 files changed, 1490 insertions, 794 deletions
diff --git a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
index 2b90960..4dd50d6 100644
--- a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
@@ -105,6 +105,8 @@ namespace OpenSim.Region.Framework.Interfaces
105 /// <param name="stateSource"></param> 105 /// <param name="stateSource"></param>
106 void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource); 106 void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource);
107 107
108 ArrayList CreateScriptInstanceEr(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource);
109
108 /// <summary> 110 /// <summary>
109 /// Stop a script which is in this prim's inventory. 111 /// Stop a script which is in this prim's inventory.
110 /// </summary> 112 /// </summary>
diff --git a/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs b/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs
new file mode 100644
index 0000000..8a83fe9
--- /dev/null
+++ b/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs
@@ -0,0 +1,18 @@
1///////////////////////////////////////////////////////////////////
2//
3// (c) Careminster LImited, Melanie Thielker and the Meta7 Team
4//
5// This file is not open source. All rights reserved
6// Mod 2
7
8using OpenSim.Region.Framework.Scenes;
9
10public interface ISnmpModule
11{
12 void Trap(int code, string Message, Scene scene);
13 void Critical(string Message, Scene scene);
14 void Warning(string Message, Scene scene);
15 void Major(string Message, Scene scene);
16 void ColdStart(int step , Scene scene);
17 void Shutdown(int step , Scene scene);
18}
diff --git a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
index de4c5fb..31ca2ab 100644
--- a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
+++ b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
@@ -53,8 +53,8 @@ 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 60
@@ -123,17 +123,22 @@ namespace OpenSim.Region.Framework.Scenes.Animation
123 /// </summary> 123 /// </summary>
124 public void TrySetMovementAnimation(string anim) 124 public void TrySetMovementAnimation(string anim)
125 { 125 {
126 //m_log.DebugFormat("Updating movement animation to {0}", anim); 126//Console.WriteLine("Updating movement animation to {0}", anim);
127 127
128 if (!m_scenePresence.IsChildAgent) 128 if (!m_scenePresence.IsChildAgent)
129 { 129 {
130 if (m_animations.TrySetDefaultAnimation( 130 if (m_animations.TrySetDefaultAnimation(
131 anim, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, m_scenePresence.UUID)) 131 anim, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, m_scenePresence.UUID))
132 { 132 {
133//Console.WriteLine("TSMA {0} success.", anim);
133 // 16384 is CHANGED_ANIMATION 134 // 16384 is CHANGED_ANIMATION
134 m_scenePresence.SendScriptEventToAttachments("changed", new Object[] { 16384 }); 135 m_scenePresence.SendScriptEventToAttachments("changed", new Object[] { 16384 });
135 SendAnimPack(); 136 SendAnimPack();
136 } 137 }
138 else
139 {
140//Console.WriteLine("TSMA {0} fail.", anim);
141 }
137 } 142 }
138 } 143 }
139 144
@@ -146,10 +151,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
146 const float PREJUMP_DELAY = 0.25f; 151 const float PREJUMP_DELAY = 0.25f;
147 152
148 #region Inputs 153 #region Inputs
149 if (m_scenePresence.SitGround) 154
150 {
151 return "SIT_GROUND_CONSTRAINED";
152 }
153 AgentManager.ControlFlags controlFlags = (AgentManager.ControlFlags)m_scenePresence.AgentControlFlags; 155 AgentManager.ControlFlags controlFlags = (AgentManager.ControlFlags)m_scenePresence.AgentControlFlags;
154 PhysicsActor actor = m_scenePresence.PhysicsActor; 156 PhysicsActor actor = m_scenePresence.PhysicsActor;
155 157
@@ -159,11 +161,10 @@ namespace OpenSim.Region.Framework.Scenes.Animation
159 Vector3 left = Vector3.Transform(Vector3.UnitY, rotMatrix); 161 Vector3 left = Vector3.Transform(Vector3.UnitY, rotMatrix);
160 162
161 // Check control flags 163 // Check control flags
162 bool heldForward = 164 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)); 165 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; 166 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; 167 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; 168 //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; 169 //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; 170 bool heldUp = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) == AgentManager.ControlFlags.AGENT_CONTROL_UP_POS;
@@ -316,7 +317,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
316 public void UpdateMovementAnimations() 317 public void UpdateMovementAnimations()
317 { 318 {
318 m_movementAnimation = GetMovementAnimation(); 319 m_movementAnimation = GetMovementAnimation();
319 320//Console.WriteLine("UMA got {0}", m_movementAnimation);
320 if (m_movementAnimation == "PREJUMP" && !m_scenePresence.Scene.m_usePreJump) 321 if (m_movementAnimation == "PREJUMP" && !m_scenePresence.Scene.m_usePreJump)
321 { 322 {
322 // This was the previous behavior before PREJUMP 323 // 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 15b5230..e6e414f 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -214,8 +214,7 @@ namespace OpenSim.Region.Framework.Scenes
214 { 214 {
215 // Needs to determine which engine was running it and use that 215 // Needs to determine which engine was running it and use that
216 // 216 //
217 part.Inventory.CreateScriptInstance(item.ItemID, 0, false, DefaultScriptEngine, 0); 217 errors = part.Inventory.CreateScriptInstanceEr(item.ItemID, 0, false, DefaultScriptEngine, 0);
218 errors = part.Inventory.GetScriptErrors(item.ItemID);
219 } 218 }
220 else 219 else
221 { 220 {
@@ -815,8 +814,12 @@ namespace OpenSim.Region.Framework.Scenes
815 public void RemoveTaskInventory(IClientAPI remoteClient, UUID itemID, uint localID) 814 public void RemoveTaskInventory(IClientAPI remoteClient, UUID itemID, uint localID)
816 { 815 {
817 SceneObjectPart part = GetSceneObjectPart(localID); 816 SceneObjectPart part = GetSceneObjectPart(localID);
818 SceneObjectGroup group = part.ParentGroup; 817 SceneObjectGroup group = null;
819 if (group != null) 818 if (part != null)
819 {
820 group = part.ParentGroup;
821 }
822 if (part != null && group != null)
820 { 823 {
821 TaskInventoryItem item = group.GetInventoryItem(localID, itemID); 824 TaskInventoryItem item = group.GetInventoryItem(localID, itemID);
822 if (item == null) 825 if (item == null)
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 57587be..58f890f 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -156,6 +156,20 @@ namespace OpenSim.Region.Framework.Scenes
156 156
157 public IXfer XferManager; 157 public IXfer XferManager;
158 158
159 protected ISnmpModule m_snmpService = null;
160 public ISnmpModule SnmpService
161 {
162 get
163 {
164 if (m_snmpService == null)
165 {
166 m_snmpService = RequestModuleInterface<ISnmpModule>();
167 }
168
169 return m_snmpService;
170 }
171 }
172
159 protected IAssetService m_AssetService; 173 protected IAssetService m_AssetService;
160 protected IAuthorizationService m_AuthorizationService; 174 protected IAuthorizationService m_AuthorizationService;
161 175
@@ -602,6 +616,8 @@ namespace OpenSim.Region.Framework.Scenes
602 616
603 // Load region settings 617 // Load region settings
604 m_regInfo.RegionSettings = m_storageManager.DataStore.LoadRegionSettings(m_regInfo.RegionID); 618 m_regInfo.RegionSettings = m_storageManager.DataStore.LoadRegionSettings(m_regInfo.RegionID);
619 m_regInfo.WindlightSettings = m_storageManager.DataStore.LoadRegionWindlightSettings(m_regInfo.RegionID);
620
605 if (m_storageManager.EstateDataStore != null) 621 if (m_storageManager.EstateDataStore != null)
606 { 622 {
607 m_regInfo.EstateSettings = m_storageManager.EstateDataStore.LoadEstateSettings(m_regInfo.RegionID, false); 623 m_regInfo.EstateSettings = m_storageManager.EstateDataStore.LoadEstateSettings(m_regInfo.RegionID, false);
@@ -1016,6 +1032,15 @@ namespace OpenSim.Region.Framework.Scenes
1016 /// <param name="seconds">float indicating duration before restart.</param> 1032 /// <param name="seconds">float indicating duration before restart.</param>
1017 public virtual void Restart(float seconds) 1033 public virtual void Restart(float seconds)
1018 { 1034 {
1035 Restart(seconds, true);
1036 }
1037
1038 /// <summary>
1039 /// Given float seconds, this will restart the region. showDialog will optionally alert the users.
1040 /// </summary>
1041 /// <param name="seconds">float indicating duration before restart.</param>
1042 public virtual void Restart(float seconds, bool showDialog)
1043 {
1019 // notifications are done in 15 second increments 1044 // notifications are done in 15 second increments
1020 // so .. if the number of seconds is less then 15 seconds, it's not really a restart request 1045 // so .. if the number of seconds is less then 15 seconds, it's not really a restart request
1021 // It's a 'Cancel restart' request. 1046 // It's a 'Cancel restart' request.
@@ -1036,8 +1061,11 @@ namespace OpenSim.Region.Framework.Scenes
1036 m_restartTimer.Elapsed += new ElapsedEventHandler(RestartTimer_Elapsed); 1061 m_restartTimer.Elapsed += new ElapsedEventHandler(RestartTimer_Elapsed);
1037 m_log.Info("[REGION]: Restarting Region in " + (seconds / 60) + " minutes"); 1062 m_log.Info("[REGION]: Restarting Region in " + (seconds / 60) + " minutes");
1038 m_restartTimer.Start(); 1063 m_restartTimer.Start();
1039 m_dialogModule.SendNotificationToUsersInRegion( 1064 if (showDialog)
1065 {
1066 m_dialogModule.SendNotificationToUsersInRegion(
1040 UUID.Random(), String.Empty, RegionInfo.RegionName + String.Format(": Restarting in {0} Minutes", (int)(seconds / 60.0))); 1067 UUID.Random(), String.Empty, RegionInfo.RegionName + String.Format(": Restarting in {0} Minutes", (int)(seconds / 60.0)));
1068 }
1041 } 1069 }
1042 } 1070 }
1043 1071
@@ -1393,16 +1421,16 @@ namespace OpenSim.Region.Framework.Scenes
1393 // Check if any objects have reached their targets 1421 // Check if any objects have reached their targets
1394 CheckAtTargets(); 1422 CheckAtTargets();
1395 1423
1396 // Update SceneObjectGroups that have scheduled themselves for updates
1397 // Objects queue their updates onto all scene presences
1398 if (m_frame % m_update_objects == 0)
1399 m_sceneGraph.UpdateObjectGroups();
1400
1401 // Run through all ScenePresences looking for updates 1424 // Run through all ScenePresences looking for updates
1402 // Presence updates and queued object updates for each presence are sent to clients 1425 // Presence updates and queued object updates for each presence are sent to clients
1403 if (m_frame % m_update_presences == 0) 1426 if (m_frame % m_update_presences == 0)
1404 m_sceneGraph.UpdatePresences(); 1427 m_sceneGraph.UpdatePresences();
1405 1428
1429 // Update SceneObjectGroups that have scheduled themselves for updates
1430 // Objects queue their updates onto all scene presences
1431 if (m_frame % m_update_objects == 0)
1432 m_sceneGraph.UpdateObjectGroups();
1433
1406 int tmpPhysicsMS2 = Util.EnvironmentTickCount(); 1434 int tmpPhysicsMS2 = Util.EnvironmentTickCount();
1407 if ((m_frame % m_update_physics == 0) && m_physics_enabled) 1435 if ((m_frame % m_update_physics == 0) && m_physics_enabled)
1408 m_sceneGraph.UpdatePreparePhysics(); 1436 m_sceneGraph.UpdatePreparePhysics();
@@ -2102,7 +2130,7 @@ namespace OpenSim.Region.Framework.Scenes
2102 public bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) 2130 public bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates)
2103 { 2131 {
2104 return m_sceneGraph.AddNewSceneObject(sceneObject, attachToBackup, sendClientUpdates); 2132 return m_sceneGraph.AddNewSceneObject(sceneObject, attachToBackup, sendClientUpdates);
2105 } 2133 }
2106 2134
2107 /// <summary> 2135 /// <summary>
2108 /// Delete every object from the scene 2136 /// Delete every object from the scene
@@ -3412,6 +3440,9 @@ namespace OpenSim.Region.Framework.Scenes
3412 3440
3413 CapsModule.AddCapsHandler(agent.AgentID); 3441 CapsModule.AddCapsHandler(agent.AgentID);
3414 3442
3443 if ((teleportFlags & ((uint)TeleportFlags.ViaLandmark | (uint)TeleportFlags.ViaLocation | (uint)TeleportFlags.ViaLandmark | (uint)TeleportFlags.Default)) != 0)
3444 System.Threading.Thread.Sleep(2000);
3445
3415 if (!agent.child) 3446 if (!agent.child)
3416 { 3447 {
3417 if (TestBorderCross(agent.startpos,Cardinals.E)) 3448 if (TestBorderCross(agent.startpos,Cardinals.E))
@@ -3470,6 +3501,8 @@ namespace OpenSim.Region.Framework.Scenes
3470 } 3501 }
3471 } 3502 }
3472 // Honor parcel landing type and position. 3503 // Honor parcel landing type and position.
3504 /*
3505 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3473 if (land != null) 3506 if (land != null)
3474 { 3507 {
3475 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) 3508 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero)
@@ -3477,6 +3510,7 @@ namespace OpenSim.Region.Framework.Scenes
3477 agent.startpos = land.LandData.UserLocation; 3510 agent.startpos = land.LandData.UserLocation;
3478 } 3511 }
3479 } 3512 }
3513 */// This is now handled properly in ScenePresence.MakeRootAgent
3480 } 3514 }
3481 3515
3482 agent.teleportFlags = teleportFlags; 3516 agent.teleportFlags = teleportFlags;
diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
index bd8ccce..9d0e6f4 100644
--- a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
@@ -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 1421d0e..3ac34d3 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -225,6 +225,30 @@ namespace OpenSim.Region.Framework.Scenes
225 protected internal bool AddRestoredSceneObject( 225 protected internal bool AddRestoredSceneObject(
226 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted) 226 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted)
227 { 227 {
228 // KF: Check for out-of-region, move inside and make static.
229 Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X,
230 sceneObject.RootPart.GroupPosition.Y,
231 sceneObject.RootPart.GroupPosition.Z);
232 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 ||
233 npos.X > Constants.RegionSize ||
234 npos.Y > Constants.RegionSize))
235 {
236 if (npos.X < 0.0) npos.X = 1.0f;
237 if (npos.Y < 0.0) npos.Y = 1.0f;
238 if (npos.Z < 0.0) npos.Z = 0.0f;
239 if (npos.X > Constants.RegionSize) npos.X = Constants.RegionSize - 1.0f;
240 if (npos.Y > Constants.RegionSize) npos.Y = Constants.RegionSize - 1.0f;
241
242 foreach (SceneObjectPart part in sceneObject.Children.Values)
243 {
244 part.GroupPosition = npos;
245 }
246 sceneObject.RootPart.Velocity = Vector3.Zero;
247 sceneObject.RootPart.AngularVelocity = Vector3.Zero;
248 sceneObject.RootPart.Acceleration = Vector3.Zero;
249 sceneObject.RootPart.Velocity = Vector3.Zero;
250 }
251
228 if (!alreadyPersisted) 252 if (!alreadyPersisted)
229 { 253 {
230 sceneObject.ForceInventoryPersistence(); 254 sceneObject.ForceInventoryPersistence();
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 8aefd50..84c3719 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -104,8 +104,78 @@ 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
113 private System.Threading.ReaderWriterLockSlim m_partsLock = new System.Threading.ReaderWriterLockSlim();
114
115 public void lockPartsForRead(bool locked)
116 {
117 if (locked)
118 {
119 if (m_partsLock.RecursiveReadCount > 0)
120 {
121 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.");
122 m_partsLock.ExitReadLock();
123 }
124 if (m_partsLock.RecursiveWriteCount > 0)
125 {
126 m_log.Error("[SceneObjectGroup.m_parts] Recursive read lock requested. This should not happen and means something needs to be fixed.");
127 m_partsLock.ExitWriteLock();
128 }
129
130 while (!m_partsLock.TryEnterReadLock(60000))
131 {
132 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.");
133 if (m_partsLock.IsWriteLockHeld)
134 {
135 m_partsLock = new System.Threading.ReaderWriterLockSlim();
136 }
137 }
138 }
139 else
140 {
141 if (m_partsLock.RecursiveReadCount > 0)
142 {
143 m_partsLock.ExitReadLock();
144 }
145 }
146 }
147 public void lockPartsForWrite(bool locked)
148 {
149 if (locked)
150 {
151 if (m_partsLock.RecursiveReadCount > 0)
152 {
153 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.");
154 m_partsLock.ExitReadLock();
155 }
156 if (m_partsLock.RecursiveWriteCount > 0)
157 {
158 m_log.Error("[SceneObjectGroup.m_parts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
159 m_partsLock.ExitWriteLock();
160 }
161
162 while (!m_partsLock.TryEnterWriteLock(60000))
163 {
164 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.");
165 if (m_partsLock.IsWriteLockHeld)
166 {
167 m_partsLock = new System.Threading.ReaderWriterLockSlim();
168 }
169 }
170 }
171 else
172 {
173 if (m_partsLock.RecursiveWriteCount > 0)
174 {
175 m_partsLock.ExitWriteLock();
176 }
177 }
178 }
109 179
110 public bool HasGroupChanged 180 public bool HasGroupChanged
111 { 181 {
@@ -116,6 +186,32 @@ namespace OpenSim.Region.Framework.Scenes
116 timeLastChanged = DateTime.Now.Ticks; 186 timeLastChanged = DateTime.Now.Ticks;
117 if (!m_hasGroupChanged) 187 if (!m_hasGroupChanged)
118 timeFirstChanged = DateTime.Now.Ticks; 188 timeFirstChanged = DateTime.Now.Ticks;
189 if (m_rootPart != null && m_rootPart.UUID != null && m_scene != null)
190 {
191 if (m_rand == null)
192 {
193 byte[] val = new byte[16];
194 m_rootPart.UUID.ToBytes(val, 0);
195 m_rand = new Random(BitConverter.ToInt32(val, 0));
196 }
197
198 if (m_scene.GetRootAgentCount() == 0)
199 {
200 //If the region is empty, this change has been made by an automated process
201 //and thus we delay the persist time by a random amount between 1.5 and 2.5.
202
203 float factor = 1.5f + (float)(m_rand.NextDouble());
204 m_maxPersistTime = (long)((float)m_scene.m_persistAfter * factor);
205 m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * factor);
206 }
207 else
208 {
209 //If the region is not empty, we want to obey the minimum and maximum persist times
210 //but add a random factor so we stagger the object persistance a little
211 m_maxPersistTime = (long)((float)m_scene.m_persistAfter * (1.0d - (m_rand.NextDouble() / 5.0d))); //Multiply by 1.0-1.5
212 m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * (1.0d + (m_rand.NextDouble() / 2.0d))); //Multiply by 0.8-1.0
213 }
214 }
119 } 215 }
120 m_hasGroupChanged = value; 216 m_hasGroupChanged = value;
121 } 217 }
@@ -131,8 +227,19 @@ namespace OpenSim.Region.Framework.Scenes
131 return false; 227 return false;
132 if (m_scene.ShuttingDown) 228 if (m_scene.ShuttingDown)
133 return true; 229 return true;
230
231 if (m_minPersistTime == 0 || m_maxPersistTime == 0)
232 {
233 m_maxPersistTime = m_scene.m_persistAfter;
234 m_minPersistTime = m_scene.m_dontPersistBefore;
235 }
236
134 long currentTime = DateTime.Now.Ticks; 237 long currentTime = DateTime.Now.Ticks;
135 if (currentTime - timeLastChanged > m_scene.m_dontPersistBefore || currentTime - timeFirstChanged > m_scene.m_persistAfter) 238
239 if (timeLastChanged == 0) timeLastChanged = currentTime;
240 if (timeFirstChanged == 0) timeFirstChanged = currentTime;
241
242 if (currentTime - timeLastChanged > m_minPersistTime || currentTime - timeFirstChanged > m_maxPersistTime)
136 return true; 243 return true;
137 return false; 244 return false;
138 } 245 }
@@ -258,13 +365,16 @@ namespace OpenSim.Region.Framework.Scenes
258 set 365 set
259 { 366 {
260 m_regionHandle = value; 367 m_regionHandle = value;
261 lock (m_parts) 368 lockPartsForRead(true);
262 { 369 {
263 foreach (SceneObjectPart part in m_parts.Values) 370 foreach (SceneObjectPart part in m_parts.Values)
264 { 371 {
372
265 part.RegionHandle = m_regionHandle; 373 part.RegionHandle = m_regionHandle;
374
266 } 375 }
267 } 376 }
377 lockPartsForRead(false);
268 } 378 }
269 } 379 }
270 380
@@ -298,6 +408,9 @@ namespace OpenSim.Region.Framework.Scenes
298 { 408 {
299 m_scene.CrossPrimGroupIntoNewRegion(val, this, true); 409 m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
300 } 410 }
411
412 lockPartsForRead(true);
413
301 if (RootPart.GetStatusSandbox()) 414 if (RootPart.GetStatusSandbox())
302 { 415 {
303 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) 416 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10)
@@ -305,17 +418,18 @@ namespace OpenSim.Region.Framework.Scenes
305 RootPart.ScriptSetPhysicsStatus(false); 418 RootPart.ScriptSetPhysicsStatus(false);
306 Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"), 419 Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"),
307 ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false); 420 ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false);
421 lockPartsForRead(false);
308 return; 422 return;
309 } 423 }
310 } 424 }
311 lock (m_parts) 425
426 foreach (SceneObjectPart part in m_parts.Values)
312 { 427 {
313 foreach (SceneObjectPart part in m_parts.Values) 428 part.GroupPosition = val;
314 {
315 part.GroupPosition = val;
316 }
317 } 429 }
318 430
431 lockPartsForRead(false);
432
319 //if (m_rootPart.PhysActor != null) 433 //if (m_rootPart.PhysActor != null)
320 //{ 434 //{
321 //m_rootPart.PhysActor.Position = 435 //m_rootPart.PhysActor.Position =
@@ -457,6 +571,7 @@ namespace OpenSim.Region.Framework.Scenes
457 /// </summary> 571 /// </summary>
458 public SceneObjectGroup() 572 public SceneObjectGroup()
459 { 573 {
574
460 } 575 }
461 576
462 /// <summary> 577 /// <summary>
@@ -473,7 +588,7 @@ namespace OpenSim.Region.Framework.Scenes
473 /// Constructor. This object is added to the scene later via AttachToScene() 588 /// Constructor. This object is added to the scene later via AttachToScene()
474 /// </summary> 589 /// </summary>
475 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) 590 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape)
476 { 591 {
477 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero)); 592 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero));
478 } 593 }
479 594
@@ -504,13 +619,16 @@ namespace OpenSim.Region.Framework.Scenes
504 619
505 public void SetFromItemID(UUID AssetId) 620 public void SetFromItemID(UUID AssetId)
506 { 621 {
507 lock (m_parts) 622 lockPartsForRead(true);
508 { 623 {
509 foreach (SceneObjectPart part in m_parts.Values) 624 foreach (SceneObjectPart part in m_parts.Values)
510 { 625 {
626
511 part.FromItemID = AssetId; 627 part.FromItemID = AssetId;
628
512 } 629 }
513 } 630 }
631 lockPartsForRead(false);
514 } 632 }
515 633
516 public UUID GetFromItemID() 634 public UUID GetFromItemID()
@@ -579,10 +697,11 @@ namespace OpenSim.Region.Framework.Scenes
579 Vector3 maxScale = Vector3.Zero; 697 Vector3 maxScale = Vector3.Zero;
580 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f); 698 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f);
581 699
582 lock (m_parts) 700 lockPartsForRead(true);
583 { 701 {
584 foreach (SceneObjectPart part in m_parts.Values) 702 foreach (SceneObjectPart part in m_parts.Values)
585 { 703 {
704
586 Vector3 partscale = part.Scale; 705 Vector3 partscale = part.Scale;
587 Vector3 partoffset = part.OffsetPosition; 706 Vector3 partoffset = part.OffsetPosition;
588 707
@@ -593,8 +712,11 @@ namespace OpenSim.Region.Framework.Scenes
593 maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X; 712 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; 713 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; 714 maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z;
715
596 } 716 }
597 } 717 }
718 lockPartsForRead(false);
719
598 finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X; 720 finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X;
599 finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y; 721 finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y;
600 finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z; 722 finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z;
@@ -610,10 +732,11 @@ namespace OpenSim.Region.Framework.Scenes
610 732
611 EntityIntersection result = new EntityIntersection(); 733 EntityIntersection result = new EntityIntersection();
612 734
613 lock (m_parts) 735 lockPartsForRead(true);
614 { 736 {
615 foreach (SceneObjectPart part in m_parts.Values) 737 foreach (SceneObjectPart part in m_parts.Values)
616 { 738 {
739
617 // Temporary commented to stop compiler warning 740 // Temporary commented to stop compiler warning
618 //Vector3 partPosition = 741 //Vector3 partPosition =
619 // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z); 742 // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z);
@@ -641,8 +764,10 @@ namespace OpenSim.Region.Framework.Scenes
641 result.distance = inter.distance; 764 result.distance = inter.distance;
642 } 765 }
643 } 766 }
767
644 } 768 }
645 } 769 }
770 lockPartsForRead(false);
646 return result; 771 return result;
647 } 772 }
648 773
@@ -655,10 +780,11 @@ namespace OpenSim.Region.Framework.Scenes
655 public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight) 780 public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight)
656 { 781 {
657 float maxX = -256f, maxY = -256f, maxZ = -256f, minX = 256f, minY = 256f, minZ = 256f; 782 float maxX = -256f, maxY = -256f, maxZ = -256f, minX = 256f, minY = 256f, minZ = 256f;
658 lock (m_parts) 783 lockPartsForRead(true);
659 { 784 {
660 foreach (SceneObjectPart part in m_parts.Values) 785 foreach (SceneObjectPart part in m_parts.Values)
661 { 786 {
787
662 Vector3 worldPos = part.GetWorldPosition(); 788 Vector3 worldPos = part.GetWorldPosition();
663 Vector3 offset = worldPos - AbsolutePosition; 789 Vector3 offset = worldPos - AbsolutePosition;
664 Quaternion worldRot; 790 Quaternion worldRot;
@@ -717,6 +843,8 @@ namespace OpenSim.Region.Framework.Scenes
717 backBottomRight.Y = orig.Y + (part.Scale.Y / 2); 843 backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
718 backBottomRight.Z = orig.Z - (part.Scale.Z / 2); 844 backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
719 845
846
847
720 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z); 848 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
721 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z); 849 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
722 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z); 850 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
@@ -888,6 +1016,7 @@ namespace OpenSim.Region.Framework.Scenes
888 minZ = backBottomLeft.Z; 1016 minZ = backBottomLeft.Z;
889 } 1017 }
890 } 1018 }
1019 lockPartsForRead(false);
891 1020
892 Vector3 boundingBox = new Vector3(maxX - minX, maxY - minY, maxZ - minZ); 1021 Vector3 boundingBox = new Vector3(maxX - minX, maxY - minY, maxZ - minZ);
893 1022
@@ -916,17 +1045,20 @@ namespace OpenSim.Region.Framework.Scenes
916 Dictionary<UUID,string> states = new Dictionary<UUID,string>(); 1045 Dictionary<UUID,string> states = new Dictionary<UUID,string>();
917 1046
918 // Capture script state while holding the lock 1047 // Capture script state while holding the lock
919 lock (m_parts) 1048 lockPartsForRead(true);
920 { 1049 {
921 foreach (SceneObjectPart part in m_parts.Values) 1050 foreach (SceneObjectPart part in m_parts.Values)
922 { 1051 {
1052
923 Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates(); 1053 Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates();
924 foreach (UUID itemid in pstates.Keys) 1054 foreach (UUID itemid in pstates.Keys)
925 { 1055 {
926 states.Add(itemid, pstates[itemid]); 1056 states.Add(itemid, pstates[itemid]);
927 } 1057 }
1058
928 } 1059 }
929 } 1060 }
1061 lockPartsForRead(false);
930 1062
931 if (states.Count > 0) 1063 if (states.Count > 0)
932 { 1064 {
@@ -1094,13 +1226,16 @@ namespace OpenSim.Region.Framework.Scenes
1094 1226
1095 public override void UpdateMovement() 1227 public override void UpdateMovement()
1096 { 1228 {
1097 lock (m_parts) 1229 lockPartsForRead(true);
1098 { 1230 {
1099 foreach (SceneObjectPart part in m_parts.Values) 1231 foreach (SceneObjectPart part in m_parts.Values)
1100 { 1232 {
1233
1101 part.UpdateMovement(); 1234 part.UpdateMovement();
1235
1102 } 1236 }
1103 } 1237 }
1238 lockPartsForRead(false);
1104 } 1239 }
1105 1240
1106 public ushort GetTimeDilation() 1241 public ushort GetTimeDilation()
@@ -1144,7 +1279,7 @@ namespace OpenSim.Region.Framework.Scenes
1144 /// <param name="part"></param> 1279 /// <param name="part"></param>
1145 public void AddPart(SceneObjectPart part) 1280 public void AddPart(SceneObjectPart part)
1146 { 1281 {
1147 lock (m_parts) 1282 lockPartsForWrite(true);
1148 { 1283 {
1149 part.SetParent(this); 1284 part.SetParent(this);
1150 m_parts.Add(part.UUID, part); 1285 m_parts.Add(part.UUID, part);
@@ -1154,6 +1289,7 @@ namespace OpenSim.Region.Framework.Scenes
1154 if (part.LinkNum == 2 && RootPart != null) 1289 if (part.LinkNum == 2 && RootPart != null)
1155 RootPart.LinkNum = 1; 1290 RootPart.LinkNum = 1;
1156 } 1291 }
1292 lockPartsForWrite(false);
1157 } 1293 }
1158 1294
1159 /// <summary> 1295 /// <summary>
@@ -1161,28 +1297,33 @@ namespace OpenSim.Region.Framework.Scenes
1161 /// </summary> 1297 /// </summary>
1162 private void UpdateParentIDs() 1298 private void UpdateParentIDs()
1163 { 1299 {
1164 lock (m_parts) 1300 lockPartsForRead(true);
1165 { 1301 {
1166 foreach (SceneObjectPart part in m_parts.Values) 1302 foreach (SceneObjectPart part in m_parts.Values)
1167 { 1303 {
1304
1168 if (part.UUID != m_rootPart.UUID) 1305 if (part.UUID != m_rootPart.UUID)
1169 { 1306 {
1170 part.ParentID = m_rootPart.LocalId; 1307 part.ParentID = m_rootPart.LocalId;
1171 } 1308 }
1309
1172 } 1310 }
1173 } 1311 }
1312 lockPartsForRead(false);
1174 } 1313 }
1175 1314
1176 public void RegenerateFullIDs() 1315 public void RegenerateFullIDs()
1177 { 1316 {
1178 lock (m_parts) 1317 lockPartsForRead(true);
1179 { 1318 {
1180 foreach (SceneObjectPart part in m_parts.Values) 1319 foreach (SceneObjectPart part in m_parts.Values)
1181 { 1320 {
1321
1182 part.UUID = UUID.Random(); 1322 part.UUID = UUID.Random();
1183 1323
1184 } 1324 }
1185 } 1325 }
1326 lockPartsForRead(false);
1186 } 1327 }
1187 1328
1188 // helper provided for parts. 1329 // helper provided for parts.
@@ -1263,27 +1404,32 @@ namespace OpenSim.Region.Framework.Scenes
1263 1404
1264 DetachFromBackup(); 1405 DetachFromBackup();
1265 1406
1266 lock (m_parts) 1407 lockPartsForRead(true);
1408 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1409 lockPartsForRead(false);
1410
1411 foreach (SceneObjectPart part in values)
1267 { 1412 {
1268 foreach (SceneObjectPart part in m_parts.Values)
1269 {
1270// part.Inventory.RemoveScriptInstances(); 1413// part.Inventory.RemoveScriptInstances();
1271 Scene.ForEachScenePresence(delegate(ScenePresence avatar) 1414
1415 Scene.ForEachScenePresence(delegate (ScenePresence sp)
1416 {
1417 if (sp.ParentID == LocalId)
1272 { 1418 {
1273 if (avatar.ParentID == LocalId) 1419 sp.StandUp();
1274 { 1420 }
1275 avatar.StandUp();
1276 }
1277 1421
1278 if (!silent) 1422 if (!silent)
1279 { 1423 {
1280 part.UpdateFlag = 0; 1424 part.UpdateFlag = 0;
1281 if (part == m_rootPart) 1425 if (part == m_rootPart)
1282 avatar.ControllingClient.SendKillObject(m_regionHandle, part.LocalId); 1426 sp.ControllingClient.SendKillObject(m_regionHandle, part.LocalId);
1283 } 1427 }
1284 }); 1428 });
1285 } 1429
1286 } 1430 }
1431
1432
1287 } 1433 }
1288 1434
1289 public void AddScriptLPS(int count) 1435 public void AddScriptLPS(int count)
@@ -1308,17 +1454,20 @@ namespace OpenSim.Region.Framework.Scenes
1308 1454
1309 scriptEvents aggregateScriptEvents=0; 1455 scriptEvents aggregateScriptEvents=0;
1310 1456
1311 lock (m_parts) 1457 lockPartsForRead(true);
1312 { 1458 {
1313 foreach (SceneObjectPart part in m_parts.Values) 1459 foreach (SceneObjectPart part in m_parts.Values)
1314 { 1460 {
1461
1315 if (part == null) 1462 if (part == null)
1316 continue; 1463 continue;
1317 if (part != RootPart) 1464 if (part != RootPart)
1318 part.ObjectFlags = objectflagupdate; 1465 part.ObjectFlags = objectflagupdate;
1319 aggregateScriptEvents |= part.AggregateScriptEvents; 1466 aggregateScriptEvents |= part.AggregateScriptEvents;
1467
1320 } 1468 }
1321 } 1469 }
1470 lockPartsForRead(false);
1322 1471
1323 m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0); 1472 m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0);
1324 m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0); 1473 m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0);
@@ -1360,42 +1509,52 @@ namespace OpenSim.Region.Framework.Scenes
1360 /// <param name="m_physicalPrim"></param> 1509 /// <param name="m_physicalPrim"></param>
1361 public void ApplyPhysics(bool m_physicalPrim) 1510 public void ApplyPhysics(bool m_physicalPrim)
1362 { 1511 {
1363 lock (m_parts) 1512 lockPartsForRead(true);
1513
1514 if (m_parts.Count > 1)
1364 { 1515 {
1365 if (m_parts.Count > 1) 1516 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1517 lockPartsForRead(false);
1518 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1519 foreach (SceneObjectPart part in values)
1366 { 1520 {
1367 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim); 1521
1368 foreach (SceneObjectPart part in m_parts.Values) 1522 if (part.LocalId != m_rootPart.LocalId)
1369 { 1523 {
1370 if (part.LocalId != m_rootPart.LocalId) 1524 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
1371 {
1372 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
1373 }
1374 } 1525 }
1375 1526
1376 // Hack to get the physics scene geometries in the right spot
1377 ResetChildPrimPhysicsPositions();
1378 }
1379 else
1380 {
1381 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1382 } 1527 }
1528 // Hack to get the physics scene geometries in the right spot
1529 ResetChildPrimPhysicsPositions();
1530 }
1531 else
1532 {
1533 lockPartsForRead(false);
1534 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1383 } 1535 }
1384 } 1536 }
1385 1537
1386 public void SetOwnerId(UUID userId) 1538 public void SetOwnerId(UUID userId)
1387 { 1539 {
1388 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); 1540 ForEachPart(delegate(SceneObjectPart part)
1541 {
1542
1543 part.OwnerID = userId;
1544
1545 });
1389 } 1546 }
1390 1547
1391 public void ForEachPart(Action<SceneObjectPart> whatToDo) 1548 public void ForEachPart(Action<SceneObjectPart> whatToDo)
1392 { 1549 {
1393 lock (m_parts) 1550 lockPartsForRead(true);
1551 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1552 lockPartsForRead(false);
1553 foreach (SceneObjectPart part in values)
1394 { 1554 {
1395 foreach (SceneObjectPart part in m_parts.Values) 1555
1396 { 1556 whatToDo(part);
1397 whatToDo(part); 1557
1398 }
1399 } 1558 }
1400 } 1559 }
1401 1560
@@ -1493,10 +1652,11 @@ namespace OpenSim.Region.Framework.Scenes
1493 RootPart.SendFullUpdate( 1652 RootPart.SendFullUpdate(
1494 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID)); 1653 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID));
1495 1654
1496 lock (m_parts) 1655 lockPartsForRead(true);
1497 { 1656 {
1498 foreach (SceneObjectPart part in m_parts.Values) 1657 foreach (SceneObjectPart part in m_parts.Values)
1499 { 1658 {
1659
1500 if (part != RootPart) 1660 if (part != RootPart)
1501 part.SendFullUpdate( 1661 part.SendFullUpdate(
1502 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID)); 1662 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID));
@@ -1570,10 +1730,11 @@ namespace OpenSim.Region.Framework.Scenes
1570 1730
1571 List<SceneObjectPart> partList; 1731 List<SceneObjectPart> partList;
1572 1732
1573 lock (m_parts) 1733 lockPartsForRead(true);
1574 { 1734
1575 partList = new List<SceneObjectPart>(m_parts.Values); 1735 partList = new List<SceneObjectPart>(m_parts.Values);
1576 } 1736
1737 lockPartsForRead(false);
1577 1738
1578 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) 1739 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1579 { 1740 {
@@ -1796,13 +1957,40 @@ namespace OpenSim.Region.Framework.Scenes
1796 } 1957 }
1797 } 1958 }
1798 1959
1960 public void rotLookAt(Quaternion target, float strength, float damping)
1961 {
1962 SceneObjectPart rootpart = m_rootPart;
1963 if (rootpart != null)
1964 {
1965 if (IsAttachment)
1966 {
1967 /*
1968 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
1969 if (avatar != null)
1970 {
1971 Rotate the Av?
1972 } */
1973 }
1974 else
1975 {
1976 if (rootpart.PhysActor != null)
1977 { // APID must be implemented in your physics system for this to function.
1978 rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W);
1979 rootpart.PhysActor.APIDStrength = strength;
1980 rootpart.PhysActor.APIDDamping = damping;
1981 rootpart.PhysActor.APIDActive = true;
1982 }
1983 }
1984 }
1985 }
1986
1799 public void stopLookAt() 1987 public void stopLookAt()
1800 { 1988 {
1801 SceneObjectPart rootpart = m_rootPart; 1989 SceneObjectPart rootpart = m_rootPart;
1802 if (rootpart != null) 1990 if (rootpart != null)
1803 { 1991 {
1804 if (rootpart.PhysActor != null) 1992 if (rootpart.PhysActor != null)
1805 { 1993 { // APID must be implemented in your physics system for this to function.
1806 rootpart.PhysActor.APIDActive = false; 1994 rootpart.PhysActor.APIDActive = false;
1807 } 1995 }
1808 } 1996 }
@@ -1870,10 +2058,11 @@ namespace OpenSim.Region.Framework.Scenes
1870 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 2058 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
1871 newPart.SetParent(this); 2059 newPart.SetParent(this);
1872 2060
1873 lock (m_parts) 2061 lockPartsForWrite(true);
1874 { 2062 {
1875 m_parts.Add(newPart.UUID, newPart); 2063 m_parts.Add(newPart.UUID, newPart);
1876 } 2064 }
2065 lockPartsForWrite(false);
1877 2066
1878 SetPartAsNonRoot(newPart); 2067 SetPartAsNonRoot(newPart);
1879 2068
@@ -1936,7 +2125,7 @@ namespace OpenSim.Region.Framework.Scenes
1936 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0) 2125 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
1937 // return; 2126 // return;
1938 2127
1939 lock (m_parts) 2128 lockPartsForRead(true);
1940 { 2129 {
1941 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0); 2130 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0);
1942 2131
@@ -1956,9 +2145,12 @@ namespace OpenSim.Region.Framework.Scenes
1956 { 2145 {
1957 if (!IsSelected) 2146 if (!IsSelected)
1958 part.UpdateLookAt(); 2147 part.UpdateLookAt();
2148
1959 part.SendScheduledUpdates(); 2149 part.SendScheduledUpdates();
2150
1960 } 2151 }
1961 } 2152 }
2153 lockPartsForRead(false);
1962 } 2154 }
1963 2155
1964 public void ScheduleFullUpdateToAvatar(ScenePresence presence) 2156 public void ScheduleFullUpdateToAvatar(ScenePresence presence)
@@ -1967,27 +2159,29 @@ namespace OpenSim.Region.Framework.Scenes
1967 2159
1968 RootPart.AddFullUpdateToAvatar(presence); 2160 RootPart.AddFullUpdateToAvatar(presence);
1969 2161
1970 lock (m_parts) 2162 lockPartsForRead(true);
1971 { 2163 {
1972 foreach (SceneObjectPart part in m_parts.Values) 2164 foreach (SceneObjectPart part in m_parts.Values)
1973 { 2165 {
2166
1974 if (part != RootPart) 2167 if (part != RootPart)
1975 part.AddFullUpdateToAvatar(presence); 2168 part.AddFullUpdateToAvatar(presence);
2169
1976 } 2170 }
1977 } 2171 }
2172 lockPartsForRead(false);
1978 } 2173 }
1979 2174
1980 public void ScheduleTerseUpdateToAvatar(ScenePresence presence) 2175 public void ScheduleTerseUpdateToAvatar(ScenePresence presence)
1981 { 2176 {
1982// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1} just to avatar {2}", Name, UUID, presence.Name); 2177 lockPartsForRead(true);
1983 2178
1984 lock (m_parts) 2179 foreach (SceneObjectPart part in m_parts.Values)
1985 { 2180 {
1986 foreach (SceneObjectPart part in m_parts.Values) 2181 part.AddTerseUpdateToAvatar(presence);
1987 {
1988 part.AddTerseUpdateToAvatar(presence);
1989 }
1990 } 2182 }
2183
2184 lockPartsForRead(false);
1991 } 2185 }
1992 2186
1993 /// <summary> 2187 /// <summary>
@@ -2000,14 +2194,17 @@ namespace OpenSim.Region.Framework.Scenes
2000 checkAtTargets(); 2194 checkAtTargets();
2001 RootPart.ScheduleFullUpdate(); 2195 RootPart.ScheduleFullUpdate();
2002 2196
2003 lock (m_parts) 2197 lockPartsForRead(true);
2004 { 2198 {
2005 foreach (SceneObjectPart part in m_parts.Values) 2199 foreach (SceneObjectPart part in m_parts.Values)
2006 { 2200 {
2201
2007 if (part != RootPart) 2202 if (part != RootPart)
2008 part.ScheduleFullUpdate(); 2203 part.ScheduleFullUpdate();
2204
2009 } 2205 }
2010 } 2206 }
2207 lockPartsForRead(false);
2011 } 2208 }
2012 2209
2013 /// <summary> 2210 /// <summary>
@@ -2015,37 +2212,38 @@ namespace OpenSim.Region.Framework.Scenes
2015 /// </summary> 2212 /// </summary>
2016 public void ScheduleGroupForTerseUpdate() 2213 public void ScheduleGroupForTerseUpdate()
2017 { 2214 {
2018// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1}", Name, UUID); 2215 lockPartsForRead(true);
2019 2216 foreach (SceneObjectPart part in m_parts.Values)
2020 lock (m_parts)
2021 { 2217 {
2022 foreach (SceneObjectPart part in m_parts.Values) 2218 part.ScheduleTerseUpdate();
2023 {
2024 part.ScheduleTerseUpdate();
2025 }
2026 } 2219 }
2220
2221 lockPartsForRead(false);
2027 } 2222 }
2028 2223
2029 /// <summary> 2224 /// <summary>
2030 /// Immediately send a full update for this scene object. 2225 /// Immediately send a full update for this scene object.
2031 /// </summary> 2226 /// </summary>
2032 public void SendGroupFullUpdate() 2227 public void SendGroupFullUpdate()
2033 { 2228 {
2034 if (IsDeleted) 2229 if (IsDeleted)
2035 return; 2230 return;
2036 2231
2037// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); 2232// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID);
2038 2233
2039 RootPart.SendFullUpdateToAllClients(); 2234 RootPart.SendFullUpdateToAllClients();
2040 2235
2041 lock (m_parts) 2236 lockPartsForRead(true);
2042 { 2237 {
2043 foreach (SceneObjectPart part in m_parts.Values) 2238 foreach (SceneObjectPart part in m_parts.Values)
2044 { 2239 {
2240
2045 if (part != RootPart) 2241 if (part != RootPart)
2046 part.SendFullUpdateToAllClients(); 2242 part.SendFullUpdateToAllClients();
2243
2047 } 2244 }
2048 } 2245 }
2246 lockPartsForRead(false);
2049 } 2247 }
2050 2248
2051 /// <summary> 2249 /// <summary>
@@ -2077,14 +2275,15 @@ namespace OpenSim.Region.Framework.Scenes
2077 { 2275 {
2078 if (IsDeleted) 2276 if (IsDeleted)
2079 return; 2277 return;
2080 2278
2081 lock (m_parts) 2279 lockPartsForRead(true);
2082 { 2280 {
2083 foreach (SceneObjectPart part in m_parts.Values) 2281 foreach (SceneObjectPart part in m_parts.Values)
2084 { 2282 {
2085 part.SendTerseUpdateToAllClients(); 2283 part.SendTerseUpdateToAllClients();
2086 } 2284 }
2087 } 2285 }
2286 lockPartsForRead(false);
2088 } 2287 }
2089 2288
2090 #endregion 2289 #endregion
@@ -2098,16 +2297,18 @@ namespace OpenSim.Region.Framework.Scenes
2098 /// <returns>null if no child part with that linknum or child part</returns> 2297 /// <returns>null if no child part with that linknum or child part</returns>
2099 public SceneObjectPart GetLinkNumPart(int linknum) 2298 public SceneObjectPart GetLinkNumPart(int linknum)
2100 { 2299 {
2101 lock (m_parts) 2300 lockPartsForRead(true);
2102 { 2301 {
2103 foreach (SceneObjectPart part in m_parts.Values) 2302 foreach (SceneObjectPart part in m_parts.Values)
2104 { 2303 {
2105 if (part.LinkNum == linknum) 2304 if (part.LinkNum == linknum)
2106 { 2305 {
2306 lockPartsForRead(false);
2107 return part; 2307 return part;
2108 } 2308 }
2109 } 2309 }
2110 } 2310 }
2311 lockPartsForRead(false);
2111 2312
2112 return null; 2313 return null;
2113 } 2314 }
@@ -2135,17 +2336,19 @@ namespace OpenSim.Region.Framework.Scenes
2135 public SceneObjectPart GetChildPart(uint localID) 2336 public SceneObjectPart GetChildPart(uint localID)
2136 { 2337 {
2137 //m_log.DebugFormat("Entered looking for {0}", localID); 2338 //m_log.DebugFormat("Entered looking for {0}", localID);
2138 lock (m_parts) 2339 lockPartsForRead(true);
2139 { 2340 {
2140 foreach (SceneObjectPart part in m_parts.Values) 2341 foreach (SceneObjectPart part in m_parts.Values)
2141 { 2342 {
2142 //m_log.DebugFormat("Found {0}", part.LocalId); 2343 //m_log.DebugFormat("Found {0}", part.LocalId);
2143 if (part.LocalId == localID) 2344 if (part.LocalId == localID)
2144 { 2345 {
2346 lockPartsForRead(false);
2145 return part; 2347 return part;
2146 } 2348 }
2147 } 2349 }
2148 } 2350 }
2351 lockPartsForRead(false);
2149 2352
2150 return null; 2353 return null;
2151 } 2354 }
@@ -2175,17 +2378,19 @@ namespace OpenSim.Region.Framework.Scenes
2175 public bool HasChildPrim(uint localID) 2378 public bool HasChildPrim(uint localID)
2176 { 2379 {
2177 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID); 2380 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID);
2178 lock (m_parts) 2381 lockPartsForRead(true);
2179 { 2382 {
2180 foreach (SceneObjectPart part in m_parts.Values) 2383 foreach (SceneObjectPart part in m_parts.Values)
2181 { 2384 {
2182 //m_log.DebugFormat("Found {0}", part.LocalId); 2385 //m_log.DebugFormat("Found {0}", part.LocalId);
2183 if (part.LocalId == localID) 2386 if (part.LocalId == localID)
2184 { 2387 {
2388 lockPartsForRead(false);
2185 return true; 2389 return true;
2186 } 2390 }
2187 } 2391 }
2188 } 2392 }
2393 lockPartsForRead(false);
2189 2394
2190 return false; 2395 return false;
2191 } 2396 }
@@ -2235,53 +2440,57 @@ namespace OpenSim.Region.Framework.Scenes
2235 if (m_rootPart.LinkNum == 0) 2440 if (m_rootPart.LinkNum == 0)
2236 m_rootPart.LinkNum = 1; 2441 m_rootPart.LinkNum = 1;
2237 2442
2238 lock (m_parts) 2443 lockPartsForWrite(true);
2239 { 2444
2240 m_parts.Add(linkPart.UUID, linkPart); 2445 m_parts.Add(linkPart.UUID, linkPart);
2446
2447 lockPartsForWrite(false);
2241 2448
2242 // Insert in terms of link numbers, the new links 2449 // Insert in terms of link numbers, the new links
2243 // before the current ones (with the exception of 2450 // before the current ones (with the exception of
2244 // the root prim. Shuffle the old ones up 2451 // the root prim. Shuffle the old ones up
2245 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts) 2452 lockPartsForRead(true);
2453 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts)
2454 {
2455 if (kvp.Value.LinkNum != 1)
2246 { 2456 {
2247 if (kvp.Value.LinkNum != 1) 2457 // Don't update root prim link number
2248 { 2458 kvp.Value.LinkNum += objectGroup.PrimCount;
2249 // Don't update root prim link number
2250 kvp.Value.LinkNum += objectGroup.PrimCount;
2251 }
2252 } 2459 }
2460 }
2461 lockPartsForRead(false);
2253 2462
2254 linkPart.LinkNum = 2; 2463 linkPart.LinkNum = 2;
2255 2464
2256 linkPart.SetParent(this); 2465 linkPart.SetParent(this);
2257 linkPart.AddFlag(PrimFlags.CreateSelected); 2466 linkPart.AddFlag(PrimFlags.CreateSelected);
2258 2467
2259 //if (linkPart.PhysActor != null) 2468 //if (linkPart.PhysActor != null)
2260 //{ 2469 //{
2261 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); 2470 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
2262 2471
2263 //linkPart.PhysActor = null; 2472 //linkPart.PhysActor = null;
2264 //} 2473 //}
2265 2474
2266 //TODO: rest of parts 2475 //TODO: rest of parts
2267 int linkNum = 3; 2476 int linkNum = 3;
2268 foreach (SceneObjectPart part in objectGroup.Children.Values) 2477 foreach (SceneObjectPart part in objectGroup.Children.Values)
2478 {
2479 if (part.UUID != objectGroup.m_rootPart.UUID)
2269 { 2480 {
2270 if (part.UUID != objectGroup.m_rootPart.UUID) 2481 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2271 {
2272 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2273 }
2274 part.ClearUndoState();
2275 } 2482 }
2483 part.ClearUndoState();
2276 } 2484 }
2277 2485
2278 m_scene.UnlinkSceneObject(objectGroup.UUID, true); 2486 m_scene.UnlinkSceneObject(objectGroup.UUID, true);
2279 objectGroup.m_isDeleted = true; 2487 objectGroup.m_isDeleted = true;
2488
2489 objectGroup.lockPartsForWrite(true);
2280 2490
2281 lock (objectGroup.m_parts) 2491 objectGroup.m_parts.Clear();
2282 { 2492
2283 objectGroup.m_parts.Clear(); 2493 objectGroup.lockPartsForWrite(false);
2284 }
2285 2494
2286 // Can't do this yet since backup still makes use of the root part without any synchronization 2495 // Can't do this yet since backup still makes use of the root part without any synchronization
2287// objectGroup.m_rootPart = null; 2496// objectGroup.m_rootPart = null;
@@ -2351,11 +2560,12 @@ namespace OpenSim.Region.Framework.Scenes
2351 Quaternion worldRot = linkPart.GetWorldRotation(); 2560 Quaternion worldRot = linkPart.GetWorldRotation();
2352 2561
2353 // Remove the part from this object 2562 // Remove the part from this object
2354 lock (m_parts) 2563 lockPartsForWrite(true);
2355 { 2564 {
2356 m_parts.Remove(linkPart.UUID); 2565 m_parts.Remove(linkPart.UUID);
2357 } 2566 }
2358 2567 lockPartsForWrite(false);
2568 lockPartsForRead(true);
2359 if (m_parts.Count == 1 && RootPart != null) //Single prim is left 2569 if (m_parts.Count == 1 && RootPart != null) //Single prim is left
2360 RootPart.LinkNum = 0; 2570 RootPart.LinkNum = 0;
2361 else 2571 else
@@ -2366,6 +2576,7 @@ namespace OpenSim.Region.Framework.Scenes
2366 p.LinkNum--; 2576 p.LinkNum--;
2367 } 2577 }
2368 } 2578 }
2579 lockPartsForRead(false);
2369 2580
2370 linkPart.ParentID = 0; 2581 linkPart.ParentID = 0;
2371 linkPart.LinkNum = 0; 2582 linkPart.LinkNum = 0;
@@ -2687,9 +2898,12 @@ namespace OpenSim.Region.Framework.Scenes
2687 2898
2688 if (selectionPart != null) 2899 if (selectionPart != null)
2689 { 2900 {
2690 lock (m_parts) 2901 lockPartsForRead(true);
2902 List<SceneObjectPart> parts = new List<SceneObjectPart>(m_parts.Values);
2903 lockPartsForRead(false);
2904 foreach (SceneObjectPart part in parts)
2691 { 2905 {
2692 foreach (SceneObjectPart part in m_parts.Values) 2906 if (part.Scale.X > 10.0 || part.Scale.Y > 10.0 || part.Scale.Z > 10.0)
2693 { 2907 {
2694 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax || 2908 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax ||
2695 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax || 2909 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax ||
@@ -2699,12 +2913,13 @@ namespace OpenSim.Region.Framework.Scenes
2699 break; 2913 break;
2700 } 2914 }
2701 } 2915 }
2916 }
2702 2917
2703 foreach (SceneObjectPart part in m_parts.Values) 2918 foreach (SceneObjectPart part in parts)
2704 { 2919 {
2705 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect); 2920 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
2706 }
2707 } 2921 }
2922
2708 } 2923 }
2709 } 2924 }
2710 2925
@@ -2790,11 +3005,9 @@ namespace OpenSim.Region.Framework.Scenes
2790 scale.Y = m_scene.m_maxNonphys; 3005 scale.Y = m_scene.m_maxNonphys;
2791 if (scale.Z > m_scene.m_maxNonphys) 3006 if (scale.Z > m_scene.m_maxNonphys)
2792 scale.Z = m_scene.m_maxNonphys; 3007 scale.Z = m_scene.m_maxNonphys;
2793
2794 SceneObjectPart part = GetChildPart(localID); 3008 SceneObjectPart part = GetChildPart(localID);
2795 if (part != null) 3009 if (part != null)
2796 { 3010 {
2797 part.Resize(scale);
2798 if (part.PhysActor != null) 3011 if (part.PhysActor != null)
2799 { 3012 {
2800 if (part.PhysActor.IsPhysical) 3013 if (part.PhysActor.IsPhysical)
@@ -2809,7 +3022,7 @@ namespace OpenSim.Region.Framework.Scenes
2809 part.PhysActor.Size = scale; 3022 part.PhysActor.Size = scale;
2810 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); 3023 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
2811 } 3024 }
2812 //if (part.UUID != m_rootPart.UUID) 3025 part.Resize(scale);
2813 3026
2814 HasGroupChanged = true; 3027 HasGroupChanged = true;
2815 ScheduleGroupForFullUpdate(); 3028 ScheduleGroupForFullUpdate();
@@ -2851,73 +3064,71 @@ namespace OpenSim.Region.Framework.Scenes
2851 float y = (scale.Y / part.Scale.Y); 3064 float y = (scale.Y / part.Scale.Y);
2852 float z = (scale.Z / part.Scale.Z); 3065 float z = (scale.Z / part.Scale.Z);
2853 3066
2854 lock (m_parts) 3067 lockPartsForRead(true);
3068 if (x > 1.0f || y > 1.0f || z > 1.0f)
2855 { 3069 {
2856 if (x > 1.0f || y > 1.0f || z > 1.0f) 3070 foreach (SceneObjectPart obPart in m_parts.Values)
2857 { 3071 {
2858 foreach (SceneObjectPart obPart in m_parts.Values) 3072 if (obPart.UUID != m_rootPart.UUID)
2859 { 3073 {
2860 if (obPart.UUID != m_rootPart.UUID) 3074 Vector3 oldSize = new Vector3(obPart.Scale);
2861 { 3075 obPart.IgnoreUndoUpdate = true;
2862 obPart.IgnoreUndoUpdate = true;
2863 Vector3 oldSize = new Vector3(obPart.Scale);
2864 3076
2865 float f = 1.0f; 3077 float f = 1.0f;
2866 float a = 1.0f; 3078 float a = 1.0f;
2867 3079
2868 if (part.PhysActor != null && part.PhysActor.IsPhysical) 3080 if (part.PhysActor != null && part.PhysActor.IsPhysical)
3081 {
3082 if (oldSize.X*x > m_scene.m_maxPhys)
2869 { 3083 {
2870 if (oldSize.X*x > m_scene.m_maxPhys) 3084 f = m_scene.m_maxPhys / oldSize.X;
2871 { 3085 a = f / x;
2872 f = m_scene.m_maxPhys / oldSize.X; 3086 x *= a;
2873 a = f / x; 3087 y *= a;
2874 x *= a; 3088 z *= a;
2875 y *= a;
2876 z *= a;
2877 }
2878 if (oldSize.Y*y > m_scene.m_maxPhys)
2879 {
2880 f = m_scene.m_maxPhys / oldSize.Y;
2881 a = f / y;
2882 x *= a;
2883 y *= a;
2884 z *= a;
2885 }
2886 if (oldSize.Z*z > m_scene.m_maxPhys)
2887 {
2888 f = m_scene.m_maxPhys / oldSize.Z;
2889 a = f / z;
2890 x *= a;
2891 y *= a;
2892 z *= a;
2893 }
2894 } 3089 }
2895 else 3090 if (oldSize.Y*y > m_scene.m_maxPhys)
3091 {
3092 f = m_scene.m_maxPhys / oldSize.Y;
3093 a = f / y;
3094 x *= a;
3095 y *= a;
3096 z *= a;
3097 }
3098 if (oldSize.Z*z > m_scene.m_maxPhys)
3099 {
3100 f = m_scene.m_maxPhys / oldSize.Z;
3101 a = f / z;
3102 x *= a;
3103 y *= a;
3104 z *= a;
3105 }
3106 }
3107 else
3108 {
3109 if (oldSize.X*x > m_scene.m_maxNonphys)
2896 { 3110 {
2897 if (oldSize.X*x > m_scene.m_maxNonphys) 3111 f = m_scene.m_maxNonphys / oldSize.X;
2898 { 3112 a = f / x;
2899 f = m_scene.m_maxNonphys / oldSize.X; 3113 x *= a;
2900 a = f / x; 3114 y *= a;
2901 x *= a; 3115 z *= a;
2902 y *= a; 3116 }
2903 z *= a; 3117 if (oldSize.Y*y > m_scene.m_maxNonphys)
2904 } 3118 {
2905 if (oldSize.Y*y > m_scene.m_maxNonphys) 3119 f = m_scene.m_maxNonphys / oldSize.Y;
2906 { 3120 a = f / y;
2907 f = m_scene.m_maxNonphys / oldSize.Y; 3121 x *= a;
2908 a = f / y; 3122 y *= a;
2909 x *= a; 3123 z *= a;
2910 y *= a; 3124 }
2911 z *= a; 3125 if (oldSize.Z*z > m_scene.m_maxNonphys)
2912 } 3126 {
2913 if (oldSize.Z*z > m_scene.m_maxNonphys) 3127 f = m_scene.m_maxNonphys / oldSize.Z;
2914 { 3128 a = f / z;
2915 f = m_scene.m_maxNonphys / oldSize.Z; 3129 x *= a;
2916 a = f / z; 3130 y *= a;
2917 x *= a; 3131 z *= a;
2918 y *= a;
2919 z *= a;
2920 }
2921 } 3132 }
2922 obPart.IgnoreUndoUpdate = false; 3133 obPart.IgnoreUndoUpdate = false;
2923 obPart.StoreUndoState(); 3134 obPart.StoreUndoState();
@@ -2925,6 +3136,7 @@ namespace OpenSim.Region.Framework.Scenes
2925 } 3136 }
2926 } 3137 }
2927 } 3138 }
3139 lockPartsForRead(false);
2928 3140
2929 Vector3 prevScale = part.Scale; 3141 Vector3 prevScale = part.Scale;
2930 prevScale.X *= x; 3142 prevScale.X *= x;
@@ -2932,7 +3144,7 @@ namespace OpenSim.Region.Framework.Scenes
2932 prevScale.Z *= z; 3144 prevScale.Z *= z;
2933 part.Resize(prevScale); 3145 part.Resize(prevScale);
2934 3146
2935 lock (m_parts) 3147 lockPartsForRead(true);
2936 { 3148 {
2937 foreach (SceneObjectPart obPart in m_parts.Values) 3149 foreach (SceneObjectPart obPart in m_parts.Values)
2938 { 3150 {
@@ -2954,6 +3166,7 @@ namespace OpenSim.Region.Framework.Scenes
2954 obPart.StoreUndoState(); 3166 obPart.StoreUndoState();
2955 } 3167 }
2956 } 3168 }
3169 lockPartsForRead(false);
2957 3170
2958 if (part.PhysActor != null) 3171 if (part.PhysActor != null)
2959 { 3172 {
@@ -3056,7 +3269,7 @@ namespace OpenSim.Region.Framework.Scenes
3056 axDiff *= Quaternion.Inverse(partRotation); 3269 axDiff *= Quaternion.Inverse(partRotation);
3057 diff = axDiff; 3270 diff = axDiff;
3058 3271
3059 lock (m_parts) 3272 lockPartsForRead(true);
3060 { 3273 {
3061 foreach (SceneObjectPart obPart in m_parts.Values) 3274 foreach (SceneObjectPart obPart in m_parts.Values)
3062 { 3275 {
@@ -3066,6 +3279,7 @@ namespace OpenSim.Region.Framework.Scenes
3066 } 3279 }
3067 } 3280 }
3068 } 3281 }
3282 lockPartsForRead(false);
3069 3283
3070 AbsolutePosition = newPos; 3284 AbsolutePosition = newPos;
3071 3285
@@ -3199,25 +3413,25 @@ namespace OpenSim.Region.Framework.Scenes
3199 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); 3413 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
3200 } 3414 }
3201 3415
3202 lock (m_parts) 3416 lockPartsForRead(true);
3417
3418 foreach (SceneObjectPart prim in m_parts.Values)
3203 { 3419 {
3204 foreach (SceneObjectPart prim in m_parts.Values) 3420 if (prim.UUID != m_rootPart.UUID)
3205 { 3421 {
3206 if (prim.UUID != m_rootPart.UUID) 3422 prim.IgnoreUndoUpdate = true;
3207 { 3423 Vector3 axPos = prim.OffsetPosition;
3208 prim.IgnoreUndoUpdate = true; 3424 axPos *= oldParentRot;
3209 Vector3 axPos = prim.OffsetPosition; 3425 axPos *= Quaternion.Inverse(axRot);
3210 axPos *= oldParentRot; 3426 prim.OffsetPosition = axPos;
3211 axPos *= Quaternion.Inverse(axRot); 3427 Quaternion primsRot = prim.RotationOffset;
3212 prim.OffsetPosition = axPos; 3428 Quaternion newRot = primsRot * oldParentRot;
3213 Quaternion primsRot = prim.RotationOffset; 3429 newRot *= Quaternion.Inverse(axRot);
3214 Quaternion newRot = primsRot * oldParentRot; 3430 prim.RotationOffset = newRot;
3215 newRot *= Quaternion.Inverse(axRot); 3431 prim.ScheduleTerseUpdate();
3216 prim.RotationOffset = newRot;
3217 prim.ScheduleTerseUpdate();
3218 }
3219 } 3432 }
3220 } 3433 }
3434
3221 foreach (SceneObjectPart childpart in Children.Values) 3435 foreach (SceneObjectPart childpart in Children.Values)
3222 { 3436 {
3223 if (childpart != m_rootPart) 3437 if (childpart != m_rootPart)
@@ -3226,6 +3440,9 @@ namespace OpenSim.Region.Framework.Scenes
3226 childpart.StoreUndoState(); 3440 childpart.StoreUndoState();
3227 } 3441 }
3228 } 3442 }
3443
3444 lockPartsForRead(false);
3445
3229 m_rootPart.ScheduleTerseUpdate(); 3446 m_rootPart.ScheduleTerseUpdate();
3230 } 3447 }
3231 3448
@@ -3347,7 +3564,7 @@ namespace OpenSim.Region.Framework.Scenes
3347 if (atTargets.Count > 0) 3564 if (atTargets.Count > 0)
3348 { 3565 {
3349 uint[] localids = new uint[0]; 3566 uint[] localids = new uint[0];
3350 lock (m_parts) 3567 lockPartsForRead(true);
3351 { 3568 {
3352 localids = new uint[m_parts.Count]; 3569 localids = new uint[m_parts.Count];
3353 int cntr = 0; 3570 int cntr = 0;
@@ -3357,6 +3574,7 @@ namespace OpenSim.Region.Framework.Scenes
3357 cntr++; 3574 cntr++;
3358 } 3575 }
3359 } 3576 }
3577 lockPartsForRead(false);
3360 3578
3361 for (int ctr = 0; ctr < localids.Length; ctr++) 3579 for (int ctr = 0; ctr < localids.Length; ctr++)
3362 { 3580 {
@@ -3375,7 +3593,7 @@ namespace OpenSim.Region.Framework.Scenes
3375 { 3593 {
3376 //trigger not_at_target 3594 //trigger not_at_target
3377 uint[] localids = new uint[0]; 3595 uint[] localids = new uint[0];
3378 lock (m_parts) 3596 lockPartsForRead(true);
3379 { 3597 {
3380 localids = new uint[m_parts.Count]; 3598 localids = new uint[m_parts.Count];
3381 int cntr = 0; 3599 int cntr = 0;
@@ -3385,7 +3603,8 @@ namespace OpenSim.Region.Framework.Scenes
3385 cntr++; 3603 cntr++;
3386 } 3604 }
3387 } 3605 }
3388 3606 lockPartsForRead(false);
3607
3389 for (int ctr = 0; ctr < localids.Length; ctr++) 3608 for (int ctr = 0; ctr < localids.Length; ctr++)
3390 { 3609 {
3391 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]); 3610 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]);
@@ -3477,19 +3696,20 @@ namespace OpenSim.Region.Framework.Scenes
3477 public float GetMass() 3696 public float GetMass()
3478 { 3697 {
3479 float retmass = 0f; 3698 float retmass = 0f;
3480 lock (m_parts) 3699 lockPartsForRead(true);
3481 { 3700 {
3482 foreach (SceneObjectPart part in m_parts.Values) 3701 foreach (SceneObjectPart part in m_parts.Values)
3483 { 3702 {
3484 retmass += part.GetMass(); 3703 retmass += part.GetMass();
3485 } 3704 }
3486 } 3705 }
3706 lockPartsForRead(false);
3487 return retmass; 3707 return retmass;
3488 } 3708 }
3489 3709
3490 public void CheckSculptAndLoad() 3710 public void CheckSculptAndLoad()
3491 { 3711 {
3492 lock (m_parts) 3712 lockPartsForRead(true);
3493 { 3713 {
3494 if (!IsDeleted) 3714 if (!IsDeleted)
3495 { 3715 {
@@ -3514,6 +3734,7 @@ namespace OpenSim.Region.Framework.Scenes
3514 } 3734 }
3515 } 3735 }
3516 } 3736 }
3737 lockPartsForRead(false);
3517 } 3738 }
3518 3739
3519 protected void AssetReceived(string id, Object sender, AssetBase asset) 3740 protected void AssetReceived(string id, Object sender, AssetBase asset)
@@ -3534,7 +3755,7 @@ namespace OpenSim.Region.Framework.Scenes
3534 /// <param name="client"></param> 3755 /// <param name="client"></param>
3535 public void SetGroup(UUID GroupID, IClientAPI client) 3756 public void SetGroup(UUID GroupID, IClientAPI client)
3536 { 3757 {
3537 lock (m_parts) 3758 lockPartsForRead(true);
3538 { 3759 {
3539 foreach (SceneObjectPart part in m_parts.Values) 3760 foreach (SceneObjectPart part in m_parts.Values)
3540 { 3761 {
@@ -3544,6 +3765,7 @@ namespace OpenSim.Region.Framework.Scenes
3544 3765
3545 HasGroupChanged = true; 3766 HasGroupChanged = true;
3546 } 3767 }
3768 lockPartsForRead(false);
3547 3769
3548 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled 3770 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled
3549 // for the same object with very different properties. The caller must schedule the update. 3771 // for the same object with very different properties. The caller must schedule the update.
@@ -3565,11 +3787,12 @@ namespace OpenSim.Region.Framework.Scenes
3565 3787
3566 public void SetAttachmentPoint(byte point) 3788 public void SetAttachmentPoint(byte point)
3567 { 3789 {
3568 lock (m_parts) 3790 lockPartsForRead(true);
3569 { 3791 {
3570 foreach (SceneObjectPart part in m_parts.Values) 3792 foreach (SceneObjectPart part in m_parts.Values)
3571 part.SetAttachmentPoint(point); 3793 part.SetAttachmentPoint(point);
3572 } 3794 }
3795 lockPartsForRead(false);
3573 } 3796 }
3574 3797
3575 #region ISceneObject 3798 #region ISceneObject
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 46eadee..4b2641c 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);
@@ -452,12 +453,16 @@ namespace OpenSim.Region.Framework.Scenes
452 } 453 }
453 454
454 /// <value> 455 /// <value>
455 /// Access should be via Inventory directly - this property temporarily remains for xml serialization purposes 456 /// Get the inventory list
456 /// </value> 457 /// </value>
457 public TaskInventoryDictionary TaskInventory 458 public TaskInventoryDictionary TaskInventory
458 { 459 {
459 get { return m_inventory.Items; } 460 get {
460 set { m_inventory.Items = value; } 461 return m_inventory.Items;
462 }
463 set {
464 m_inventory.Items = value;
465 }
461 } 466 }
462 467
463 public uint ObjectFlags 468 public uint ObjectFlags
@@ -586,14 +591,12 @@ namespace OpenSim.Region.Framework.Scenes
586 set { m_LoopSoundSlavePrims = value; } 591 set { m_LoopSoundSlavePrims = value; }
587 } 592 }
588 593
589 [XmlIgnore]
590 public Byte[] TextureAnimation 594 public Byte[] TextureAnimation
591 { 595 {
592 get { return m_TextureAnimation; } 596 get { return m_TextureAnimation; }
593 set { m_TextureAnimation = value; } 597 set { m_TextureAnimation = value; }
594 } 598 }
595 599
596 [XmlIgnore]
597 public Byte[] ParticleSystem 600 public Byte[] ParticleSystem
598 { 601 {
599 get { return m_particleSystem; } 602 get { return m_particleSystem; }
@@ -647,7 +650,6 @@ namespace OpenSim.Region.Framework.Scenes
647 set 650 set
648 { 651 {
649 m_groupPosition = value; 652 m_groupPosition = value;
650
651 PhysicsActor actor = PhysActor; 653 PhysicsActor actor = PhysActor;
652 if (actor != null) 654 if (actor != null)
653 { 655 {
@@ -816,7 +818,16 @@ namespace OpenSim.Region.Framework.Scenes
816 /// <summary></summary> 818 /// <summary></summary>
817 public Vector3 Acceleration 819 public Vector3 Acceleration
818 { 820 {
819 get { return m_acceleration; } 821 get
822 {
823 PhysicsActor actor = PhysActor;
824 if (actor != null)
825 {
826 m_acceleration = actor.Acceleration;
827 }
828 return m_acceleration;
829 }
830
820 set { m_acceleration = value; } 831 set { m_acceleration = value; }
821 } 832 }
822 833
@@ -960,7 +971,8 @@ namespace OpenSim.Region.Framework.Scenes
960 if (IsAttachment) 971 if (IsAttachment)
961 return GroupPosition; 972 return GroupPosition;
962 973
963 return m_offsetPosition + m_groupPosition; } 974// return m_offsetPosition + m_groupPosition; }
975 return m_groupPosition + (m_offsetPosition * ParentGroup.RootPart.RotationOffset) ; } //KF: Rotation was ignored!
964 } 976 }
965 977
966 public SceneObjectGroup ParentGroup 978 public SceneObjectGroup ParentGroup
@@ -1112,6 +1124,13 @@ namespace OpenSim.Region.Framework.Scenes
1112 get { return _flags; } 1124 get { return _flags; }
1113 set { _flags = value; } 1125 set { _flags = value; }
1114 } 1126 }
1127
1128 [XmlIgnore]
1129 public bool IsOccupied // KF If an av is sittingon this prim
1130 {
1131 get { return m_occupied; }
1132 set { m_occupied = value; }
1133 }
1115 1134
1116 [XmlIgnore] 1135 [XmlIgnore]
1117 public UUID SitTargetAvatar 1136 public UUID SitTargetAvatar
@@ -1187,14 +1206,6 @@ namespace OpenSim.Region.Framework.Scenes
1187 } 1206 }
1188 } 1207 }
1189 1208
1190 /// <summary>
1191 /// Clear all pending updates of parts to clients
1192 /// </summary>
1193 private void ClearUpdateSchedule()
1194 {
1195 m_updateFlag = 0;
1196 }
1197
1198 private void SendObjectPropertiesToClient(UUID AgentID) 1209 private void SendObjectPropertiesToClient(UUID AgentID)
1199 { 1210 {
1200 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar) 1211 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
@@ -1934,12 +1945,17 @@ namespace OpenSim.Region.Framework.Scenes
1934 public Vector3 GetWorldPosition() 1945 public Vector3 GetWorldPosition()
1935 { 1946 {
1936 Quaternion parentRot = ParentGroup.RootPart.RotationOffset; 1947 Quaternion parentRot = ParentGroup.RootPart.RotationOffset;
1937
1938 Vector3 axPos = OffsetPosition; 1948 Vector3 axPos = OffsetPosition;
1939
1940 axPos *= parentRot; 1949 axPos *= parentRot;
1941 Vector3 translationOffsetPosition = axPos; 1950 Vector3 translationOffsetPosition = axPos;
1942 return GroupPosition + translationOffsetPosition; 1951 if(_parentID == 0)
1952 {
1953 return GroupPosition;
1954 }
1955 else
1956 {
1957 return ParentGroup.AbsolutePosition + translationOffsetPosition; //KF: Fix child prim position
1958 }
1943 } 1959 }
1944 1960
1945 /// <summary> 1961 /// <summary>
@@ -1950,7 +1966,7 @@ namespace OpenSim.Region.Framework.Scenes
1950 { 1966 {
1951 Quaternion newRot; 1967 Quaternion newRot;
1952 1968
1953 if (this.LinkNum == 0) 1969 if (this.LinkNum < 2) //KF Single or root prim
1954 { 1970 {
1955 newRot = RotationOffset; 1971 newRot = RotationOffset;
1956 } 1972 }
@@ -2596,17 +2612,18 @@ namespace OpenSim.Region.Framework.Scenes
2596 //Trys to fetch sound id from prim's inventory. 2612 //Trys to fetch sound id from prim's inventory.
2597 //Prim's inventory doesn't support non script items yet 2613 //Prim's inventory doesn't support non script items yet
2598 2614
2599 lock (TaskInventory) 2615 TaskInventory.LockItemsForRead(true);
2616
2617 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2600 { 2618 {
2601 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 2619 if (item.Value.Name == sound)
2602 { 2620 {
2603 if (item.Value.Name == sound) 2621 soundID = item.Value.ItemID;
2604 { 2622 break;
2605 soundID = item.Value.ItemID;
2606 break;
2607 }
2608 } 2623 }
2609 } 2624 }
2625
2626 TaskInventory.LockItemsForRead(false);
2610 } 2627 }
2611 2628
2612 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence sp) 2629 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence sp)
@@ -2675,38 +2692,7 @@ namespace OpenSim.Region.Framework.Scenes
2675 2692
2676 public void RotLookAt(Quaternion target, float strength, float damping) 2693 public void RotLookAt(Quaternion target, float strength, float damping)
2677 { 2694 {
2678 rotLookAt(target, strength, damping); 2695 m_parentGroup.rotLookAt(target, strength, damping); // This calls method in SceneObjectGroup.
2679 }
2680
2681 public void rotLookAt(Quaternion target, float strength, float damping)
2682 {
2683 if (IsAttachment)
2684 {
2685 /*
2686 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
2687 if (avatar != null)
2688 {
2689 Rotate the Av?
2690 } */
2691 }
2692 else
2693 {
2694 APIDDamp = damping;
2695 APIDStrength = strength;
2696 APIDTarget = target;
2697 }
2698 }
2699
2700 public void startLookAt(Quaternion rot, float damp, float strength)
2701 {
2702 APIDDamp = damp;
2703 APIDStrength = strength;
2704 APIDTarget = rot;
2705 }
2706
2707 public void stopLookAt()
2708 {
2709 APIDTarget = Quaternion.Identity;
2710 } 2696 }
2711 2697
2712 /// <summary> 2698 /// <summary>
@@ -2939,8 +2925,8 @@ namespace OpenSim.Region.Framework.Scenes
2939 { 2925 {
2940 const float ROTATION_TOLERANCE = 0.01f; 2926 const float ROTATION_TOLERANCE = 0.01f;
2941 const float VELOCITY_TOLERANCE = 0.001f; 2927 const float VELOCITY_TOLERANCE = 0.001f;
2942 const float POSITION_TOLERANCE = 0.05f; 2928 const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary
2943 const int TIME_MS_TOLERANCE = 3000; 2929 const int TIME_MS_TOLERANCE = 200; //llSetPos has a 200ms delay. This should NOT be 3 seconds.
2944 2930
2945 if (m_updateFlag == 1) 2931 if (m_updateFlag == 1)
2946 { 2932 {
@@ -2954,7 +2940,7 @@ namespace OpenSim.Region.Framework.Scenes
2954 Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE) 2940 Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE)
2955 { 2941 {
2956 AddTerseUpdateToAllAvatars(); 2942 AddTerseUpdateToAllAvatars();
2957 ClearUpdateSchedule(); 2943
2958 2944
2959 // This causes the Scene to 'poll' physical objects every couple of frames 2945 // This causes the Scene to 'poll' physical objects every couple of frames
2960 // bad, so it's been replaced by an event driven method. 2946 // bad, so it's been replaced by an event driven method.
@@ -2972,16 +2958,18 @@ namespace OpenSim.Region.Framework.Scenes
2972 m_lastAngularVelocity = AngularVelocity; 2958 m_lastAngularVelocity = AngularVelocity;
2973 m_lastTerseSent = Environment.TickCount; 2959 m_lastTerseSent = Environment.TickCount;
2974 } 2960 }
2961 //Moved this outside of the if clause so updates don't get blocked.. *sigh*
2962 m_updateFlag = 0; //Why were we calling a function to do this? Inefficient! *screams*
2975 } 2963 }
2976 else 2964 else
2977 { 2965 {
2978 if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes 2966 if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes
2979 { 2967 {
2980 AddFullUpdateToAllAvatars(); 2968 AddFullUpdateToAllAvatars();
2981 ClearUpdateSchedule(); 2969 m_updateFlag = 0; //Same here
2982 } 2970 }
2983 } 2971 }
2984 ClearUpdateSchedule(); 2972 m_updateFlag = 0;
2985 } 2973 }
2986 2974
2987 /// <summary> 2975 /// <summary>
@@ -3008,17 +2996,16 @@ namespace OpenSim.Region.Framework.Scenes
3008 if (!UUID.TryParse(sound, out soundID)) 2996 if (!UUID.TryParse(sound, out soundID))
3009 { 2997 {
3010 // search sound file from inventory 2998 // search sound file from inventory
3011 lock (TaskInventory) 2999 TaskInventory.LockItemsForRead(true);
3000 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
3012 { 3001 {
3013 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 3002 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound)
3014 { 3003 {
3015 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound) 3004 soundID = item.Value.ItemID;
3016 { 3005 break;
3017 soundID = item.Value.ItemID;
3018 break;
3019 }
3020 } 3006 }
3021 } 3007 }
3008 TaskInventory.LockItemsForRead(false);
3022 } 3009 }
3023 3010
3024 if (soundID == UUID.Zero) 3011 if (soundID == UUID.Zero)
@@ -3453,7 +3440,7 @@ namespace OpenSim.Region.Framework.Scenes
3453 3440
3454 public void StopLookAt() 3441 public void StopLookAt()
3455 { 3442 {
3456 m_parentGroup.stopLookAt(); 3443 m_parentGroup.stopLookAt(); // This calls method in SceneObjectGroup.
3457 3444
3458 m_parentGroup.ScheduleGroupForTerseUpdate(); 3445 m_parentGroup.ScheduleGroupForTerseUpdate();
3459 } 3446 }
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index 3b1b567..04df35a 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",
@@ -305,6 +320,7 @@ namespace OpenSim.Region.Framework.Scenes
305 string script = Utils.BytesToString(asset.Data); 320 string script = Utils.BytesToString(asset.Data);
306 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 321 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
307 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource); 322 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource);
323 StoreScriptErrors(item.ItemID, null);
308 m_part.ParentGroup.AddActiveScriptCount(1); 324 m_part.ParentGroup.AddActiveScriptCount(1);
309 m_part.ScheduleFullUpdate(); 325 m_part.ScheduleFullUpdate();
310 } 326 }
@@ -368,27 +384,145 @@ namespace OpenSim.Region.Framework.Scenes
368 384
369 /// <summary> 385 /// <summary>
370 /// Start a script which is in this prim's inventory. 386 /// Start a script which is in this prim's inventory.
387 /// Some processing may occur in the background, but this routine returns asap.
371 /// </summary> 388 /// </summary>
372 /// <param name="itemId"> 389 /// <param name="itemId">
373 /// A <see cref="UUID"/> 390 /// A <see cref="UUID"/>
374 /// </param> 391 /// </param>
375 public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource) 392 public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
376 { 393 {
377 lock (m_items) 394 lock (m_scriptErrors)
395 {
396 // Indicate to CreateScriptInstanceInternal() we don't want it to wait for completion
397 m_scriptErrors.Remove(itemId);
398 }
399 CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
400 }
401
402 private void CreateScriptInstanceInternal(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
403 {
404 m_items.LockItemsForRead(true);
405 if (m_items.ContainsKey(itemId))
378 { 406 {
379 if (m_items.ContainsKey(itemId)) 407 if (m_items.ContainsKey(itemId))
380 { 408 {
409 m_items.LockItemsForRead(false);
381 CreateScriptInstance(m_items[itemId], startParam, postOnRez, engine, stateSource); 410 CreateScriptInstance(m_items[itemId], startParam, postOnRez, engine, stateSource);
382 } 411 }
383 else 412 else
384 { 413 {
414 m_items.LockItemsForRead(false);
415 string msg = String.Format("couldn't be found for prim {0}, {1} at {2} in {3}", m_part.Name, m_part.UUID,
416 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
417 StoreScriptError(itemId, msg);
385 m_log.ErrorFormat( 418 m_log.ErrorFormat(
386 "[PRIM INVENTORY]: " + 419 "[PRIM INVENTORY]: " +
387 "Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}", 420 "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 } 421 }
391 } 422 }
423 else
424 {
425 m_items.LockItemsForRead(false);
426 string msg = String.Format("couldn't be found for prim {0}, {1}", m_part.Name, m_part.UUID);
427 StoreScriptError(itemId, msg);
428 m_log.ErrorFormat(
429 "[PRIM INVENTORY]: " +
430 "Couldn't start script with ID {0} since it {1}", itemId, msg);
431 }
432
433 }
434
435 /// <summary>
436 /// Start a script which is in this prim's inventory and return any compilation error messages.
437 /// </summary>
438 /// <param name="itemId">
439 /// A <see cref="UUID"/>
440 /// </param>
441 public ArrayList CreateScriptInstanceEr(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
442 {
443 ArrayList errors;
444
445 // Indicate to CreateScriptInstanceInternal() we want it to
446 // post any compilation/loading error messages
447 lock (m_scriptErrors)
448 {
449 m_scriptErrors[itemId] = null;
450 }
451
452 // Perform compilation/loading
453 CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
454
455 // Wait for and retrieve any errors
456 lock (m_scriptErrors)
457 {
458 while ((errors = m_scriptErrors[itemId]) == null)
459 {
460 if (!System.Threading.Monitor.Wait(m_scriptErrors, 15000))
461 {
462 m_log.ErrorFormat(
463 "[PRIM INVENTORY]: " +
464 "timedout waiting for script {0} errors", itemId);
465 errors = m_scriptErrors[itemId];
466 if (errors == null)
467 {
468 errors = new ArrayList(1);
469 errors.Add("timedout waiting for errors");
470 }
471 break;
472 }
473 }
474 m_scriptErrors.Remove(itemId);
475 }
476 return errors;
477 }
478
479 // Signal to CreateScriptInstanceEr() that compilation/loading is complete
480 private void StoreScriptErrors(UUID itemId, ArrayList errors)
481 {
482 lock (m_scriptErrors)
483 {
484 // If compilation/loading initiated via CreateScriptInstance(),
485 // it does not want the errors, so just get out
486 if (!m_scriptErrors.ContainsKey(itemId))
487 {
488 return;
489 }
490
491 // Initiated via CreateScriptInstanceEr(), if we know what the
492 // errors are, save them and wake CreateScriptInstanceEr().
493 if (errors != null)
494 {
495 m_scriptErrors[itemId] = errors;
496 System.Threading.Monitor.PulseAll(m_scriptErrors);
497 return;
498 }
499 }
500
501 // Initiated via CreateScriptInstanceEr() but we don't know what
502 // the errors are yet, so retrieve them from the script engine.
503 // This may involve some waiting internal to GetScriptErrors().
504 errors = GetScriptErrors(itemId);
505
506 // Get a default non-null value to indicate success.
507 if (errors == null)
508 {
509 errors = new ArrayList();
510 }
511
512 // Post to CreateScriptInstanceEr() and wake it up
513 lock (m_scriptErrors)
514 {
515 m_scriptErrors[itemId] = errors;
516 System.Threading.Monitor.PulseAll(m_scriptErrors);
517 }
518 }
519
520 // Like StoreScriptErrors(), but just posts a single string message
521 private void StoreScriptError(UUID itemId, string message)
522 {
523 ArrayList errors = new ArrayList(1);
524 errors.Add(message);
525 StoreScriptErrors(itemId, errors);
392 } 526 }
393 527
394 /// <summary> 528 /// <summary>
@@ -401,15 +535,7 @@ namespace OpenSim.Region.Framework.Scenes
401 /// </param> 535 /// </param>
402 public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted) 536 public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted)
403 { 537 {
404 bool scriptPresent = false; 538 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 { 539 {
414 if (!sceneObjectBeingDeleted) 540 if (!sceneObjectBeingDeleted)
415 m_part.RemoveScriptEvents(itemId); 541 m_part.RemoveScriptEvents(itemId);
@@ -435,11 +561,16 @@ namespace OpenSim.Region.Framework.Scenes
435 /// <returns></returns> 561 /// <returns></returns>
436 private bool InventoryContainsName(string name) 562 private bool InventoryContainsName(string name)
437 { 563 {
438 foreach (TaskInventoryItem item in Items.Values) 564 m_items.LockItemsForRead(true);
565 foreach (TaskInventoryItem item in m_items.Values)
439 { 566 {
440 if (item.Name == name) 567 if (item.Name == name)
568 {
569 m_items.LockItemsForRead(false);
441 return true; 570 return true;
571 }
442 } 572 }
573 m_items.LockItemsForRead(false);
443 return false; 574 return false;
444 } 575 }
445 576
@@ -481,13 +612,9 @@ namespace OpenSim.Region.Framework.Scenes
481 /// <param name="item"></param> 612 /// <param name="item"></param>
482 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop) 613 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop)
483 { 614 {
484 List<TaskInventoryItem> il; 615 m_items.LockItemsForRead(true);
485 616 List<TaskInventoryItem> il = new List<TaskInventoryItem>(m_items.Values);
486 lock (m_items) 617 m_items.LockItemsForRead(false);
487 {
488 il = new List<TaskInventoryItem>(m_items.Values);
489 }
490
491 foreach (TaskInventoryItem i in il) 618 foreach (TaskInventoryItem i in il)
492 { 619 {
493 if (i.Name == item.Name) 620 if (i.Name == item.Name)
@@ -525,15 +652,14 @@ namespace OpenSim.Region.Framework.Scenes
525 item.Name = name; 652 item.Name = name;
526 item.GroupID = m_part.GroupID; 653 item.GroupID = m_part.GroupID;
527 654
528 lock (m_items) 655 m_items.LockItemsForWrite(true);
529 { 656 m_items.Add(item.ItemID, item);
530 m_items.Add(item.ItemID, item); 657 m_items.LockItemsForWrite(false);
531
532 if (allowedDrop) 658 if (allowedDrop)
533 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP); 659 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP);
534 else 660 else
535 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 661 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
536 } 662
537 663
538 m_inventorySerial++; 664 m_inventorySerial++;
539 //m_inventorySerial += 2; 665 //m_inventorySerial += 2;
@@ -550,14 +676,13 @@ namespace OpenSim.Region.Framework.Scenes
550 /// <param name="items"></param> 676 /// <param name="items"></param>
551 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items) 677 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items)
552 { 678 {
553 lock (m_items) 679 m_items.LockItemsForWrite(true);
680 foreach (TaskInventoryItem item in items)
554 { 681 {
555 foreach (TaskInventoryItem item in items) 682 m_items.Add(item.ItemID, item);
556 { 683 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
557 m_items.Add(item.ItemID, item);
558 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
559 }
560 } 684 }
685 m_items.LockItemsForWrite(false);
561 686
562 m_inventorySerial++; 687 m_inventorySerial++;
563 } 688 }
@@ -570,10 +695,9 @@ namespace OpenSim.Region.Framework.Scenes
570 public TaskInventoryItem GetInventoryItem(UUID itemId) 695 public TaskInventoryItem GetInventoryItem(UUID itemId)
571 { 696 {
572 TaskInventoryItem item; 697 TaskInventoryItem item;
573 698 m_items.LockItemsForRead(true);
574 lock (m_items) 699 m_items.TryGetValue(itemId, out item);
575 m_items.TryGetValue(itemId, out item); 700 m_items.LockItemsForRead(false);
576
577 return item; 701 return item;
578 } 702 }
579 703
@@ -609,41 +733,51 @@ namespace OpenSim.Region.Framework.Scenes
609 /// <returns>false if the item did not exist, true if the update occurred successfully</returns> 733 /// <returns>false if the item did not exist, true if the update occurred successfully</returns>
610 public bool UpdateInventoryItem(TaskInventoryItem item) 734 public bool UpdateInventoryItem(TaskInventoryItem item)
611 { 735 {
612 lock (m_items) 736 m_items.LockItemsForWrite(true);
737
738 if (m_items.ContainsKey(item.ItemID))
613 { 739 {
614 if (m_items.ContainsKey(item.ItemID)) 740 item.ParentID = m_part.UUID;
615 { 741 item.ParentPartID = m_part.UUID;
616 item.ParentID = m_part.UUID; 742 item.Flags = m_items[item.ItemID].Flags;
617 item.ParentPartID = m_part.UUID; 743
618 item.Flags = m_items[item.ItemID].Flags; 744 // If group permissions have been set on, check that the groupID is up to date in case it has
619 745 // changed since permissions were last set.
620 // If group permissions have been set on, check that the groupID is up to date in case it has 746 if (item.GroupPermissions != (uint)PermissionMask.None)
621 // changed since permissions were last set. 747 item.GroupID = m_part.GroupID;
622 if (item.GroupPermissions != (uint)PermissionMask.None)
623 item.GroupID = m_part.GroupID;
624 748
625 if (item.AssetID == UUID.Zero) 749 if (item.AssetID == UUID.Zero)
626 { 750 {
627 item.AssetID = m_items[item.ItemID].AssetID; 751 item.AssetID = m_items[item.ItemID].AssetID;
628 }
629
630 m_items[item.ItemID] = item;
631 m_inventorySerial++;
632 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
633 HasInventoryChanged = true;
634 m_part.ParentGroup.HasGroupChanged = true;
635
636 return true;
637 } 752 }
638 else 753 else if ((InventoryType)item.Type == InventoryType.Notecard)
639 { 754 {
640 m_log.ErrorFormat( 755 ScenePresence presence = m_part.ParentGroup.Scene.GetScenePresence(item.OwnerID);
641 "[PRIM INVENTORY]: " + 756
642 "Tried to retrieve item ID {0} from prim {1}, {2} at {3} in {4} but the item does not exist in this inventory", 757 if (presence != null)
643 item.ItemID, m_part.Name, m_part.UUID, 758 {
644 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 759 presence.ControllingClient.SendAgentAlertMessage(
760 "Notecard saved", false);
761 }
645 } 762 }
763
764 m_items[item.ItemID] = item;
765 m_inventorySerial++;
766 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
767 HasInventoryChanged = true;
768 m_part.ParentGroup.HasGroupChanged = true;
769 m_items.LockItemsForWrite(false);
770 return true;
646 } 771 }
772 else
773 {
774 m_log.ErrorFormat(
775 "[PRIM INVENTORY]: " +
776 "Tried to retrieve item ID {0} from prim {1}, {2} at {3} in {4} but the item does not exist in this inventory",
777 item.ItemID, m_part.Name, m_part.UUID,
778 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
779 }
780 m_items.LockItemsForWrite(false);
647 781
648 return false; 782 return false;
649 } 783 }
@@ -656,53 +790,54 @@ namespace OpenSim.Region.Framework.Scenes
656 /// in this prim's inventory.</returns> 790 /// in this prim's inventory.</returns>
657 public int RemoveInventoryItem(UUID itemID) 791 public int RemoveInventoryItem(UUID itemID)
658 { 792 {
659 lock (m_items) 793 m_items.LockItemsForRead(true);
794
795 if (m_items.ContainsKey(itemID))
660 { 796 {
661 if (m_items.ContainsKey(itemID)) 797 int type = m_items[itemID].InvType;
798 m_items.LockItemsForRead(false);
799 if (type == 10) // Script
662 { 800 {
663 int type = m_items[itemID].InvType; 801 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID);
664 if (type == 10) // Script 802 }
665 { 803 m_items.LockItemsForWrite(true);
666 m_part.RemoveScriptEvents(itemID); 804 m_items.Remove(itemID);
667 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID); 805 m_items.LockItemsForWrite(false);
668 } 806 m_inventorySerial++;
669 m_items.Remove(itemID); 807 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
670 m_inventorySerial++;
671 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
672
673 HasInventoryChanged = true;
674 m_part.ParentGroup.HasGroupChanged = true;
675 808
676 int scriptcount = 0; 809 HasInventoryChanged = true;
677 lock (m_items) 810 m_part.ParentGroup.HasGroupChanged = true;
678 {
679 foreach (TaskInventoryItem item in m_items.Values)
680 {
681 if (item.Type == 10)
682 {
683 scriptcount++;
684 }
685 }
686 }
687 811
688 if (scriptcount <= 0) 812 int scriptcount = 0;
813 m_items.LockItemsForRead(true);
814 foreach (TaskInventoryItem item in m_items.Values)
815 {
816 if (item.Type == 10)
689 { 817 {
690 m_part.RemFlag(PrimFlags.Scripted); 818 scriptcount++;
691 } 819 }
692
693 m_part.ScheduleFullUpdate();
694
695 return type;
696 } 820 }
697 else 821 m_items.LockItemsForRead(false);
822
823
824 if (scriptcount <= 0)
698 { 825 {
699 m_log.ErrorFormat( 826 m_part.RemFlag(PrimFlags.Scripted);
700 "[PRIM INVENTORY]: " +
701 "Tried to remove item ID {0} from prim {1}, {2} at {3} in {4} but the item does not exist in this inventory",
702 itemID, m_part.Name, m_part.UUID,
703 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
704 } 827 }
828
829 m_part.ScheduleFullUpdate();
830
831 return type;
832 }
833 else
834 {
835 m_log.ErrorFormat(
836 "[PRIM INVENTORY]: " +
837 "Tried to remove item ID {0} from prim {1}, {2} but the item does not exist in this inventory",
838 itemID, m_part.Name, m_part.UUID);
705 } 839 }
840 m_items.LockItemsForWrite(false);
706 841
707 return -1; 842 return -1;
708 } 843 }
@@ -755,53 +890,54 @@ namespace OpenSim.Region.Framework.Scenes
755 // isn't available (such as drag from prim inventory to agent inventory) 890 // isn't available (such as drag from prim inventory to agent inventory)
756 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero); 891 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero);
757 892
758 lock (m_items) 893 m_items.LockItemsForRead(true);
894
895 foreach (TaskInventoryItem item in m_items.Values)
759 { 896 {
760 foreach (TaskInventoryItem item in m_items.Values) 897 UUID ownerID = item.OwnerID;
761 { 898 uint everyoneMask = 0;
762 UUID ownerID = item.OwnerID; 899 uint baseMask = item.BasePermissions;
763 uint everyoneMask = 0; 900 uint ownerMask = item.CurrentPermissions;
764 uint baseMask = item.BasePermissions; 901 uint groupMask = item.GroupPermissions;
765 uint ownerMask = item.CurrentPermissions;
766 uint groupMask = item.GroupPermissions;
767 902
768 invString.AddItemStart(); 903 invString.AddItemStart();
769 invString.AddNameValueLine("item_id", item.ItemID.ToString()); 904 invString.AddNameValueLine("item_id", item.ItemID.ToString());
770 invString.AddNameValueLine("parent_id", m_part.UUID.ToString()); 905 invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
771 906
772 invString.AddPermissionsStart(); 907 invString.AddPermissionsStart();
773 908
774 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask)); 909 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask));
775 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask)); 910 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask));
776 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask)); 911 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask));
777 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask)); 912 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask));
778 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions)); 913 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
779 914
780 invString.AddNameValueLine("creator_id", item.CreatorID.ToString()); 915 invString.AddNameValueLine("creator_id", item.CreatorID.ToString());
781 invString.AddNameValueLine("owner_id", ownerID.ToString()); 916 invString.AddNameValueLine("owner_id", ownerID.ToString());
782 917
783 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString()); 918 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString());
784 919
785 invString.AddNameValueLine("group_id", item.GroupID.ToString()); 920 invString.AddNameValueLine("group_id", item.GroupID.ToString());
786 invString.AddSectionEnd(); 921 invString.AddSectionEnd();
787 922
788 invString.AddNameValueLine("asset_id", item.AssetID.ToString()); 923 invString.AddNameValueLine("asset_id", item.AssetID.ToString());
789 invString.AddNameValueLine("type", TaskInventoryItem.Types[item.Type]); 924 invString.AddNameValueLine("type", TaskInventoryItem.Types[item.Type]);
790 invString.AddNameValueLine("inv_type", TaskInventoryItem.InvTypes[item.InvType]); 925 invString.AddNameValueLine("inv_type", TaskInventoryItem.InvTypes[item.InvType]);
791 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags)); 926 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags));
792 927
793 invString.AddSaleStart(); 928 invString.AddSaleStart();
794 invString.AddNameValueLine("sale_type", "not"); 929 invString.AddNameValueLine("sale_type", "not");
795 invString.AddNameValueLine("sale_price", "0"); 930 invString.AddNameValueLine("sale_price", "0");
796 invString.AddSectionEnd(); 931 invString.AddSectionEnd();
797 932
798 invString.AddNameValueLine("name", item.Name + "|"); 933 invString.AddNameValueLine("name", item.Name + "|");
799 invString.AddNameValueLine("desc", item.Description + "|"); 934 invString.AddNameValueLine("desc", item.Description + "|");
800 935
801 invString.AddNameValueLine("creation_date", item.CreationDate.ToString()); 936 invString.AddNameValueLine("creation_date", item.CreationDate.ToString());
802 invString.AddSectionEnd(); 937 invString.AddSectionEnd();
803 }
804 } 938 }
939 int count = m_items.Count;
940 m_items.LockItemsForRead(false);
805 941
806 fileData = Utils.StringToBytes(invString.BuildString); 942 fileData = Utils.StringToBytes(invString.BuildString);
807 943
@@ -822,10 +958,9 @@ namespace OpenSim.Region.Framework.Scenes
822 { 958 {
823 if (HasInventoryChanged) 959 if (HasInventoryChanged)
824 { 960 {
825 lock (Items) 961 Items.LockItemsForRead(true);
826 { 962 datastore.StorePrimInventory(m_part.UUID, Items.Values);
827 datastore.StorePrimInventory(m_part.UUID, Items.Values); 963 Items.LockItemsForRead(false);
828 }
829 964
830 HasInventoryChanged = false; 965 HasInventoryChanged = false;
831 } 966 }
@@ -894,61 +1029,54 @@ namespace OpenSim.Region.Framework.Scenes
894 { 1029 {
895 uint mask=0x7fffffff; 1030 uint mask=0x7fffffff;
896 1031
897 lock (m_items) 1032 foreach (TaskInventoryItem item in m_items.Values)
898 { 1033 {
899 foreach (TaskInventoryItem item in m_items.Values) 1034 if (item.InvType != (int)InventoryType.Object)
900 { 1035 {
901 if (item.InvType != (int)InventoryType.Object) 1036 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0)
902 { 1037 mask &= ~((uint)PermissionMask.Copy >> 13);
903 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0) 1038 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0)
904 mask &= ~((uint)PermissionMask.Copy >> 13); 1039 mask &= ~((uint)PermissionMask.Transfer >> 13);
905 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0) 1040 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0)
906 mask &= ~((uint)PermissionMask.Transfer >> 13); 1041 mask &= ~((uint)PermissionMask.Modify >> 13);
907 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0)
908 mask &= ~((uint)PermissionMask.Modify >> 13);
909 }
910 else
911 {
912 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
913 mask &= ~((uint)PermissionMask.Copy >> 13);
914 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
915 mask &= ~((uint)PermissionMask.Transfer >> 13);
916 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
917 mask &= ~((uint)PermissionMask.Modify >> 13);
918 }
919
920 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
921 mask &= ~(uint)PermissionMask.Copy;
922 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
923 mask &= ~(uint)PermissionMask.Transfer;
924 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
925 mask &= ~(uint)PermissionMask.Modify;
926 } 1042 }
1043 else
1044 {
1045 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
1046 mask &= ~((uint)PermissionMask.Copy >> 13);
1047 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
1048 mask &= ~((uint)PermissionMask.Transfer >> 13);
1049 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1050 mask &= ~((uint)PermissionMask.Modify >> 13);
1051 }
1052
1053 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
1054 mask &= ~(uint)PermissionMask.Copy;
1055 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
1056 mask &= ~(uint)PermissionMask.Transfer;
1057 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
1058 mask &= ~(uint)PermissionMask.Modify;
927 } 1059 }
928
929 return mask; 1060 return mask;
930 } 1061 }
931 1062
932 public void ApplyNextOwnerPermissions() 1063 public void ApplyNextOwnerPermissions()
933 { 1064 {
934 lock (m_items) 1065 foreach (TaskInventoryItem item in m_items.Values)
935 { 1066 {
936 foreach (TaskInventoryItem item in m_items.Values) 1067 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0)
937 { 1068 {
938 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0) 1069 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
939 { 1070 item.CurrentPermissions &= ~(uint)PermissionMask.Copy;
940 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0) 1071 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
941 item.CurrentPermissions &= ~(uint)PermissionMask.Copy; 1072 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer;
942 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0) 1073 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
943 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer; 1074 item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
944 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0) 1075 item.CurrentPermissions |= 8;
945 item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
946 item.CurrentPermissions |= 8;
947 }
948 item.CurrentPermissions &= item.NextPermissions;
949 item.BasePermissions &= item.NextPermissions;
950 item.EveryonePermissions &= item.NextPermissions;
951 } 1076 }
1077 item.CurrentPermissions &= item.NextPermissions;
1078 item.BasePermissions &= item.NextPermissions;
1079 item.EveryonePermissions &= item.NextPermissions;
952 } 1080 }
953 1081
954 m_part.TriggerScriptChangedEvent(Changed.OWNER); 1082 m_part.TriggerScriptChangedEvent(Changed.OWNER);
@@ -956,29 +1084,22 @@ namespace OpenSim.Region.Framework.Scenes
956 1084
957 public void ApplyGodPermissions(uint perms) 1085 public void ApplyGodPermissions(uint perms)
958 { 1086 {
959 lock (m_items) 1087 foreach (TaskInventoryItem item in m_items.Values)
960 { 1088 {
961 foreach (TaskInventoryItem item in m_items.Values) 1089 item.CurrentPermissions = perms;
962 { 1090 item.BasePermissions = perms;
963 item.CurrentPermissions = perms;
964 item.BasePermissions = perms;
965 }
966 } 1091 }
967 } 1092 }
968 1093
969 public bool ContainsScripts() 1094 public bool ContainsScripts()
970 { 1095 {
971 lock (m_items) 1096 foreach (TaskInventoryItem item in m_items.Values)
972 { 1097 {
973 foreach (TaskInventoryItem item in m_items.Values) 1098 if (item.InvType == (int)InventoryType.LSL)
974 { 1099 {
975 if (item.InvType == (int)InventoryType.LSL) 1100 return true;
976 {
977 return true;
978 }
979 } 1101 }
980 } 1102 }
981
982 return false; 1103 return false;
983 } 1104 }
984 1105
@@ -986,11 +1107,8 @@ namespace OpenSim.Region.Framework.Scenes
986 { 1107 {
987 List<UUID> ret = new List<UUID>(); 1108 List<UUID> ret = new List<UUID>();
988 1109
989 lock (m_items) 1110 foreach (TaskInventoryItem item in m_items.Values)
990 { 1111 ret.Add(item.ItemID);
991 foreach (TaskInventoryItem item in m_items.Values)
992 ret.Add(item.ItemID);
993 }
994 1112
995 return ret; 1113 return ret;
996 } 1114 }
@@ -1003,29 +1121,25 @@ namespace OpenSim.Region.Framework.Scenes
1003 if (engines == null) // No engine at all 1121 if (engines == null) // No engine at all
1004 return ret; 1122 return ret;
1005 1123
1006 lock (m_items) 1124 foreach (TaskInventoryItem item in m_items.Values)
1007 { 1125 {
1008 foreach (TaskInventoryItem item in m_items.Values) 1126 if (item.InvType == (int)InventoryType.LSL)
1009 { 1127 {
1010 if (item.InvType == (int)InventoryType.LSL) 1128 foreach (IScriptModule e in engines)
1011 { 1129 {
1012 foreach (IScriptModule e in engines) 1130 if (e != null)
1013 { 1131 {
1014 if (e != null) 1132 string n = e.GetXMLState(item.ItemID);
1133 if (n != String.Empty)
1015 { 1134 {
1016 string n = e.GetXMLState(item.ItemID); 1135 if (!ret.ContainsKey(item.ItemID))
1017 if (n != String.Empty) 1136 ret[item.ItemID] = n;
1018 { 1137 break;
1019 if (!ret.ContainsKey(item.ItemID))
1020 ret[item.ItemID] = n;
1021 break;
1022 }
1023 } 1138 }
1024 } 1139 }
1025 } 1140 }
1026 } 1141 }
1027 } 1142 }
1028
1029 return ret; 1143 return ret;
1030 } 1144 }
1031 1145
@@ -1036,20 +1150,21 @@ namespace OpenSim.Region.Framework.Scenes
1036 return; 1150 return;
1037 1151
1038 1152
1039 lock (m_items) 1153 Items.LockItemsForRead(true);
1154
1155 foreach (TaskInventoryItem item in m_items.Values)
1040 { 1156 {
1041 foreach (TaskInventoryItem item in m_items.Values) 1157 if (item.InvType == (int)InventoryType.LSL)
1042 { 1158 {
1043 if (item.InvType == (int)InventoryType.LSL) 1159 foreach (IScriptModule engine in engines)
1044 { 1160 {
1045 foreach (IScriptModule engine in engines) 1161 if (engine != null)
1046 { 1162 engine.ResumeScript(item.ItemID);
1047 if (engine != null)
1048 engine.ResumeScript(item.ItemID);
1049 }
1050 } 1163 }
1051 } 1164 }
1052 } 1165 }
1166
1167 Items.LockItemsForRead(false);
1053 } 1168 }
1054 } 1169 }
1055} 1170}
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 3efb45f..c220bf0 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -73,7 +73,7 @@ namespace OpenSim.Region.Framework.Scenes
73// { 73// {
74// m_log.Debug("[ScenePresence] Destructor called"); 74// m_log.Debug("[ScenePresence] Destructor called");
75// } 75// }
76 76
77 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 77 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
78 78
79 private static readonly byte[] BAKE_INDICES = new byte[] { 8, 9, 10, 11, 19, 20 }; 79 private static readonly byte[] BAKE_INDICES = new byte[] { 8, 9, 10, 11, 19, 20 };
@@ -89,7 +89,9 @@ namespace OpenSim.Region.Framework.Scenes
89 /// rotation, prim cut, prim twist, prim taper, and prim shear. See mantis 89 /// rotation, prim cut, prim twist, prim taper, and prim shear. See mantis
90 /// issue #1716 90 /// issue #1716
91 /// </summary> 91 /// </summary>
92 private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.1f, 0.0f, 0.3f); 92// private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.1f, 0.0f, 0.3f);
93 // Value revised by KF 091121 by comparison with SL.
94 private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.0f, 0.0f, 0.418f);
93 95
94 public UUID currentParcelUUID = UUID.Zero; 96 public UUID currentParcelUUID = UUID.Zero;
95 97
@@ -123,8 +125,11 @@ namespace OpenSim.Region.Framework.Scenes
123 public Vector3 lastKnownAllowedPosition; 125 public Vector3 lastKnownAllowedPosition;
124 public bool sentMessageAboutRestrictedParcelFlyingDown; 126 public bool sentMessageAboutRestrictedParcelFlyingDown;
125 public Vector4 CollisionPlane = Vector4.UnitW; 127 public Vector4 CollisionPlane = Vector4.UnitW;
126 128
127 private Vector3 m_lastPosition; 129 private Vector3 m_avInitialPos; // used to calculate unscripted sit rotation
130 private Vector3 m_avUnscriptedSitPos; // for non-scripted prims
131 private Vector3 m_lastPosition;
132 private Vector3 m_lastWorldPosition;
128 private Quaternion m_lastRotation; 133 private Quaternion m_lastRotation;
129 private Vector3 m_lastVelocity; 134 private Vector3 m_lastVelocity;
130 //private int m_lastTerseSent; 135 //private int m_lastTerseSent;
@@ -134,7 +139,6 @@ namespace OpenSim.Region.Framework.Scenes
134 private Vector3? m_forceToApply; 139 private Vector3? m_forceToApply;
135 private uint m_requestedSitTargetID; 140 private uint m_requestedSitTargetID;
136 private UUID m_requestedSitTargetUUID; 141 private UUID m_requestedSitTargetUUID;
137 public bool SitGround = false;
138 142
139 private SendCourseLocationsMethod m_sendCourseLocationsMethod; 143 private SendCourseLocationsMethod m_sendCourseLocationsMethod;
140 144
@@ -157,7 +161,6 @@ namespace OpenSim.Region.Framework.Scenes
157 private int m_perfMonMS; 161 private int m_perfMonMS;
158 162
159 private bool m_setAlwaysRun; 163 private bool m_setAlwaysRun;
160
161 private bool m_forceFly; 164 private bool m_forceFly;
162 private bool m_flyDisabled; 165 private bool m_flyDisabled;
163 166
@@ -183,7 +186,8 @@ namespace OpenSim.Region.Framework.Scenes
183 protected RegionInfo m_regionInfo; 186 protected RegionInfo m_regionInfo;
184 protected ulong crossingFromRegion; 187 protected ulong crossingFromRegion;
185 188
186 private readonly Vector3[] Dir_Vectors = new Vector3[9]; 189 private readonly Vector3[] Dir_Vectors = new Vector3[11];
190 private bool m_isNudging = false;
187 191
188 // Position of agent's camera in world (region cordinates) 192 // Position of agent's camera in world (region cordinates)
189 protected Vector3 m_CameraCenter; 193 protected Vector3 m_CameraCenter;
@@ -208,6 +212,7 @@ namespace OpenSim.Region.Framework.Scenes
208 private bool m_autopilotMoving; 212 private bool m_autopilotMoving;
209 private Vector3 m_autoPilotTarget; 213 private Vector3 m_autoPilotTarget;
210 private bool m_sitAtAutoTarget; 214 private bool m_sitAtAutoTarget;
215 private Vector3 m_initialSitTarget; //KF: First estimate of where to sit
211 216
212 private string m_nextSitAnimation = String.Empty; 217 private string m_nextSitAnimation = String.Empty;
213 218
@@ -218,6 +223,9 @@ namespace OpenSim.Region.Framework.Scenes
218 private bool m_followCamAuto; 223 private bool m_followCamAuto;
219 224
220 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
221 229
222 private const int NumMovementsBetweenRayCast = 5; 230 private const int NumMovementsBetweenRayCast = 5;
223 231
@@ -246,7 +254,9 @@ namespace OpenSim.Region.Framework.Scenes
246 DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS, 254 DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS,
247 DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG, 255 DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG,
248 DIR_CONTROL_FLAG_FORWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS, 256 DIR_CONTROL_FLAG_FORWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS,
249 DIR_CONTROL_FLAG_BACKWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG, 257 DIR_CONTROL_FLAG_BACK_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG,
258 DIR_CONTROL_FLAG_LEFT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS,
259 DIR_CONTROL_FLAG_RIGHT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG,
250 DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG 260 DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG
251 } 261 }
252 262
@@ -453,7 +463,8 @@ namespace OpenSim.Region.Framework.Scenes
453 get 463 get
454 { 464 {
455 PhysicsActor actor = m_physicsActor; 465 PhysicsActor actor = m_physicsActor;
456 if (actor != null) 466// if (actor != null)
467 if ((actor != null) && (m_parentID == 0)) // KF Do NOT update m_pos here if Av is sitting!
457 m_pos = actor.Position; 468 m_pos = actor.Position;
458 469
459 return m_parentPosition + m_pos; 470 return m_parentPosition + m_pos;
@@ -474,7 +485,8 @@ namespace OpenSim.Region.Framework.Scenes
474 } 485 }
475 } 486 }
476 487
477 m_pos = value; 488 if (m_parentID == 0) // KF Do NOT update m_pos here if Av is sitting!
489 m_pos = value;
478 m_parentPosition = Vector3.Zero; 490 m_parentPosition = Vector3.Zero;
479 } 491 }
480 } 492 }
@@ -693,10 +705,7 @@ namespace OpenSim.Region.Framework.Scenes
693 m_reprioritization_timer.AutoReset = false; 705 m_reprioritization_timer.AutoReset = false;
694 706
695 AdjustKnownSeeds(); 707 AdjustKnownSeeds();
696
697 // TODO: I think, this won't send anything, as we are still a child here...
698 Animator.TrySetMovementAnimation("STAND"); 708 Animator.TrySetMovementAnimation("STAND");
699
700 // we created a new ScenePresence (a new child agent) in a fresh region. 709 // we created a new ScenePresence (a new child agent) in a fresh region.
701 // Request info about all the (root) agents in this region 710 // Request info about all the (root) agents in this region
702 // Note: This won't send data *to* other clients in that region (children don't send) 711 // Note: This won't send data *to* other clients in that region (children don't send)
@@ -752,25 +761,47 @@ namespace OpenSim.Region.Framework.Scenes
752 Dir_Vectors[3] = -Vector3.UnitY; //RIGHT 761 Dir_Vectors[3] = -Vector3.UnitY; //RIGHT
753 Dir_Vectors[4] = Vector3.UnitZ; //UP 762 Dir_Vectors[4] = Vector3.UnitZ; //UP
754 Dir_Vectors[5] = -Vector3.UnitZ; //DOWN 763 Dir_Vectors[5] = -Vector3.UnitZ; //DOWN
755 Dir_Vectors[8] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge 764 Dir_Vectors[6] = new Vector3(0.5f, 0f, 0f); //FORWARD_NUDGE
756 Dir_Vectors[6] = Vector3.UnitX*2; //FORWARD 765 Dir_Vectors[7] = new Vector3(-0.5f, 0f, 0f); //BACK_NUDGE
757 Dir_Vectors[7] = -Vector3.UnitX; //BACK 766 Dir_Vectors[8] = new Vector3(0f, 0.5f, 0f); //LEFT_NUDGE
767 Dir_Vectors[9] = new Vector3(0f, -0.5f, 0f); //RIGHT_NUDGE
768 Dir_Vectors[10] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge
758 } 769 }
759 770
760 private Vector3[] GetWalkDirectionVectors() 771 private Vector3[] GetWalkDirectionVectors()
761 { 772 {
762 Vector3[] vector = new Vector3[9]; 773 Vector3[] vector = new Vector3[11];
763 vector[0] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD 774 vector[0] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD
764 vector[1] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK 775 vector[1] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK
765 vector[2] = Vector3.UnitY; //LEFT 776 vector[2] = Vector3.UnitY; //LEFT
766 vector[3] = -Vector3.UnitY; //RIGHT 777 vector[3] = -Vector3.UnitY; //RIGHT
767 vector[4] = new Vector3(m_CameraAtAxis.Z, 0f, m_CameraUpAxis.Z); //UP 778 vector[4] = new Vector3(m_CameraAtAxis.Z, 0f, m_CameraUpAxis.Z); //UP
768 vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN 779 vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN
769 vector[8] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_Nudge 780 vector[6] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD_NUDGE
770 vector[6] = (new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z) * 2); //FORWARD Nudge 781 vector[7] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK_NUDGE
771 vector[7] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK Nudge 782 vector[8] = Vector3.UnitY; //LEFT_NUDGE
783 vector[9] = -Vector3.UnitY; //RIGHT_NUDGE
784 vector[10] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_NUDGE
772 return vector; 785 return vector;
773 } 786 }
787
788 private bool[] GetDirectionIsNudge()
789 {
790 bool[] isNudge = new bool[11];
791 isNudge[0] = false; //FORWARD
792 isNudge[1] = false; //BACK
793 isNudge[2] = false; //LEFT
794 isNudge[3] = false; //RIGHT
795 isNudge[4] = false; //UP
796 isNudge[5] = false; //DOWN
797 isNudge[6] = true; //FORWARD_NUDGE
798 isNudge[7] = true; //BACK_NUDGE
799 isNudge[8] = true; //LEFT_NUDGE
800 isNudge[9] = true; //RIGHT_NUDGE
801 isNudge[10] = true; //DOWN_Nudge
802 return isNudge;
803 }
804
774 805
775 #endregion 806 #endregion
776 807
@@ -839,6 +870,22 @@ namespace OpenSim.Region.Framework.Scenes
839 { 870 {
840 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N); 871 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N);
841 pos.Y = crossedBorder.BorderLine.Z - 1; 872 pos.Y = crossedBorder.BorderLine.Z - 1;
873 }
874
875 //If they're TP'ing in or logging in, we haven't had time to add any known child regions yet.
876 //This has the unfortunate consequence that if somebody is TP'ing who is already a child agent,
877 //they'll bypass the landing point. But I can't think of any decent way of fixing this.
878 if (KnownChildRegionHandles.Count == 0)
879 {
880 ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y);
881 if (land != null)
882 {
883 //Don't restrict gods, estate managers, or land owners to the TP point. This behaviour mimics agni.
884 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero && m_userLevel < 200 && !m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid) && land.LandData.OwnerID != m_uuid)
885 {
886 pos = land.LandData.UserLocation;
887 }
888 }
842 } 889 }
843 890
844 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f) 891 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f)
@@ -973,9 +1020,10 @@ namespace OpenSim.Region.Framework.Scenes
973 public void Teleport(Vector3 pos) 1020 public void Teleport(Vector3 pos)
974 { 1021 {
975 bool isFlying = false; 1022 bool isFlying = false;
976 if (m_physicsActor != null)
977 isFlying = m_physicsActor.Flying;
978 1023
1024 if (m_physicsActor != null)
1025 isFlying = m_physicsActor.Flying;
1026
979 RemoveFromPhysicalScene(); 1027 RemoveFromPhysicalScene();
980 Velocity = Vector3.Zero; 1028 Velocity = Vector3.Zero;
981 AbsolutePosition = pos; 1029 AbsolutePosition = pos;
@@ -986,7 +1034,8 @@ namespace OpenSim.Region.Framework.Scenes
986 SetHeight(m_appearance.AvatarHeight); 1034 SetHeight(m_appearance.AvatarHeight);
987 } 1035 }
988 1036
989 SendTerseUpdateToAllClients(); 1037 SendTerseUpdateToAllClients();
1038
990 } 1039 }
991 1040
992 public void TeleportWithMomentum(Vector3 pos) 1041 public void TeleportWithMomentum(Vector3 pos)
@@ -1031,7 +1080,9 @@ namespace OpenSim.Region.Framework.Scenes
1031 { 1080 {
1032 AbsolutePosition = AbsolutePosition + new Vector3(0f, 0f, (1.56f / 6f)); 1081 AbsolutePosition = AbsolutePosition + new Vector3(0f, 0f, (1.56f / 6f));
1033 } 1082 }
1034 1083
1084 m_updateCount = UPDATE_COUNT; //KF: Trigger Anim updates to catch falling anim.
1085
1035 ControllingClient.SendAvatarTerseUpdate(new SendAvatarTerseData(m_rootRegionHandle, (ushort)(m_scene.TimeDilation * ushort.MaxValue), LocalId, 1086 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))); 1087 AbsolutePosition, Velocity, Vector3.Zero, m_bodyRot, new Vector4(0,0,1,AbsolutePosition.Z - 0.5f), m_uuid, null, GetUpdatePriority(ControllingClient)));
1037 } 1088 }
@@ -1216,6 +1267,7 @@ namespace OpenSim.Region.Framework.Scenes
1216 m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999902"); 1267 m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999902");
1217 1268
1218 m_pos = m_LastFinitePos; 1269 m_pos = m_LastFinitePos;
1270
1219 if (!m_pos.IsFinite()) 1271 if (!m_pos.IsFinite())
1220 { 1272 {
1221 m_pos.X = 127f; 1273 m_pos.X = 127f;
@@ -1282,7 +1334,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); 1334 m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(m_CameraCenter - posAdjusted), Vector3.Distance(m_CameraCenter, posAdjusted) + 0.3f, RayCastCameraCallback);
1283 } 1335 }
1284 } 1336 }
1285
1286 lock (scriptedcontrols) 1337 lock (scriptedcontrols)
1287 { 1338 {
1288 if (scriptedcontrols.Count > 0) 1339 if (scriptedcontrols.Count > 0)
@@ -1297,12 +1348,8 @@ namespace OpenSim.Region.Framework.Scenes
1297 1348
1298 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0) 1349 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0)
1299 { 1350 {
1300 // TODO: This doesn't prevent the user from walking yet. 1351 m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick.
1301 // Setting parent ID would fix this, if we knew what value 1352 Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED");
1302 // to use. Or we could add a m_isSitting variable.
1303 //Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED");
1304 SitGround = true;
1305
1306 } 1353 }
1307 1354
1308 // In the future, these values might need to go global. 1355 // In the future, these values might need to go global.
@@ -1352,6 +1399,11 @@ namespace OpenSim.Region.Framework.Scenes
1352 update_rotation = true; 1399 update_rotation = true;
1353 } 1400 }
1354 1401
1402 //guilty until proven innocent..
1403 bool Nudging = true;
1404 //Basically, if there is at least one non-nudge control then we don't need
1405 //to worry about stopping the avatar
1406
1355 if (m_parentID == 0) 1407 if (m_parentID == 0)
1356 { 1408 {
1357 bool bAllowUpdateMoveToPosition = false; 1409 bool bAllowUpdateMoveToPosition = false;
@@ -1366,9 +1418,12 @@ namespace OpenSim.Region.Framework.Scenes
1366 else 1418 else
1367 dirVectors = Dir_Vectors; 1419 dirVectors = Dir_Vectors;
1368 1420
1369 // The fact that m_movementflag is a byte needs to be fixed 1421 bool[] isNudge = GetDirectionIsNudge();
1370 // it really should be a uint 1422
1371 uint nudgehack = 250; 1423
1424
1425
1426
1372 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS) 1427 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS)
1373 { 1428 {
1374 if (((uint)flags & (uint)DCF) != 0) 1429 if (((uint)flags & (uint)DCF) != 0)
@@ -1378,40 +1433,28 @@ namespace OpenSim.Region.Framework.Scenes
1378 try 1433 try
1379 { 1434 {
1380 agent_control_v3 += dirVectors[i]; 1435 agent_control_v3 += dirVectors[i];
1381 //m_log.DebugFormat("[Motion]: {0}, {1}",i, dirVectors[i]); 1436 if (isNudge[i] == false)
1437 {
1438 Nudging = false;
1439 }
1382 } 1440 }
1383 catch (IndexOutOfRangeException) 1441 catch (IndexOutOfRangeException)
1384 { 1442 {
1385 // Why did I get this? 1443 // Why did I get this?
1386 } 1444 }
1387 1445
1388 if ((m_movementflag & (byte)(uint)DCF) == 0) 1446 if ((m_movementflag & (uint)DCF) == 0)
1389 { 1447 {
1390 if (DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
1391 {
1392 m_movementflag |= (byte)nudgehack;
1393 }
1394 m_movementflag += (byte)(uint)DCF; 1448 m_movementflag += (byte)(uint)DCF;
1395 update_movementflag = true; 1449 update_movementflag = true;
1396 } 1450 }
1397 } 1451 }
1398 else 1452 else
1399 { 1453 {
1400 if ((m_movementflag & (byte)(uint)DCF) != 0 || 1454 if ((m_movementflag & (uint)DCF) != 0)
1401 ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
1402 && ((m_movementflag & (byte)nudgehack) == nudgehack))
1403 ) // This or is for Nudge forward
1404 { 1455 {
1405 m_movementflag -= ((byte)(uint)DCF); 1456 m_movementflag -= (byte)(uint)DCF;
1406
1407 update_movementflag = true; 1457 update_movementflag = true;
1408 /*
1409 if ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
1410 && ((m_movementflag & (byte)nudgehack) == nudgehack))
1411 {
1412 m_log.Debug("Removed Hack flag");
1413 }
1414 */
1415 } 1458 }
1416 else 1459 else
1417 { 1460 {
@@ -1455,6 +1498,9 @@ namespace OpenSim.Region.Framework.Scenes
1455 // Ignore z component of vector 1498 // Ignore z component of vector
1456 Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f); 1499 Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f);
1457 LocalVectorToTarget2D.Normalize(); 1500 LocalVectorToTarget2D.Normalize();
1501
1502 //We're not nudging
1503 Nudging = false;
1458 agent_control_v3 += LocalVectorToTarget2D; 1504 agent_control_v3 += LocalVectorToTarget2D;
1459 1505
1460 // update avatar movement flags. the avatar coordinate system is as follows: 1506 // update avatar movement flags. the avatar coordinate system is as follows:
@@ -1543,13 +1589,13 @@ namespace OpenSim.Region.Framework.Scenes
1543 // m_log.DebugFormat( 1589 // m_log.DebugFormat(
1544 // "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3); 1590 // "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3);
1545 1591
1546 AddNewMovement(agent_control_v3, q); 1592 AddNewMovement(agent_control_v3, q, Nudging);
1547 1593
1548 1594
1549 } 1595 }
1550 } 1596 }
1551 1597
1552 if (update_movementflag && ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) == 0) && (m_parentID == 0) && !SitGround) 1598 if (update_movementflag)
1553 Animator.UpdateMovementAnimations(); 1599 Animator.UpdateMovementAnimations();
1554 1600
1555 m_scene.EventManager.TriggerOnClientMovement(this); 1601 m_scene.EventManager.TriggerOnClientMovement(this);
@@ -1564,7 +1610,6 @@ namespace OpenSim.Region.Framework.Scenes
1564 m_sitAtAutoTarget = false; 1610 m_sitAtAutoTarget = false;
1565 PrimitiveBaseShape proxy = PrimitiveBaseShape.Default; 1611 PrimitiveBaseShape proxy = PrimitiveBaseShape.Default;
1566 //proxy.PCode = (byte)PCode.ParticleSystem; 1612 //proxy.PCode = (byte)PCode.ParticleSystem;
1567
1568 proxyObjectGroup = new SceneObjectGroup(UUID, Pos, Rotation, proxy); 1613 proxyObjectGroup = new SceneObjectGroup(UUID, Pos, Rotation, proxy);
1569 proxyObjectGroup.AttachToScene(m_scene); 1614 proxyObjectGroup.AttachToScene(m_scene);
1570 1615
@@ -1606,7 +1651,7 @@ namespace OpenSim.Region.Framework.Scenes
1606 } 1651 }
1607 m_moveToPositionInProgress = true; 1652 m_moveToPositionInProgress = true;
1608 m_moveToPositionTarget = new Vector3(locx, locy, locz); 1653 m_moveToPositionTarget = new Vector3(locx, locy, locz);
1609 } 1654 }
1610 catch (Exception ex) 1655 catch (Exception ex)
1611 { 1656 {
1612 //Why did I get this error? 1657 //Why did I get this error?
@@ -1628,7 +1673,7 @@ namespace OpenSim.Region.Framework.Scenes
1628 Velocity = Vector3.Zero; 1673 Velocity = Vector3.Zero;
1629 SendFullUpdateToAllClients(); 1674 SendFullUpdateToAllClients();
1630 1675
1631 //HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); 1676 HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); //KF ??
1632 } 1677 }
1633 //ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false); 1678 //ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false);
1634 m_requestedSitTargetUUID = UUID.Zero; 1679 m_requestedSitTargetUUID = UUID.Zero;
@@ -1661,55 +1706,84 @@ namespace OpenSim.Region.Framework.Scenes
1661 /// </summary> 1706 /// </summary>
1662 public void StandUp() 1707 public void StandUp()
1663 { 1708 {
1664 if (SitGround)
1665 SitGround = false;
1666
1667 if (m_parentID != 0) 1709 if (m_parentID != 0)
1668 { 1710 {
1669 m_log.Debug("StandupCode Executed");
1670 SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID); 1711 SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID);
1671 if (part != null) 1712 if (part != null)
1672 { 1713 {
1714 part.TaskInventory.LockItemsForRead(true);
1673 TaskInventoryDictionary taskIDict = part.TaskInventory; 1715 TaskInventoryDictionary taskIDict = part.TaskInventory;
1674 if (taskIDict != null) 1716 if (taskIDict != null)
1675 { 1717 {
1676 lock (taskIDict) 1718 foreach (UUID taskID in taskIDict.Keys)
1677 { 1719 {
1678 foreach (UUID taskID in taskIDict.Keys) 1720 UnRegisterControlEventsToScript(LocalId, taskID);
1679 { 1721 taskIDict[taskID].PermsMask &= ~(
1680 UnRegisterControlEventsToScript(LocalId, taskID); 1722 2048 | //PERMISSION_CONTROL_CAMERA
1681 taskIDict[taskID].PermsMask &= ~( 1723 4); // PERMISSION_TAKE_CONTROLS
1682 2048 | //PERMISSION_CONTROL_CAMERA
1683 4); // PERMISSION_TAKE_CONTROLS
1684 }
1685 } 1724 }
1686
1687 } 1725 }
1726 part.TaskInventory.LockItemsForRead(false);
1688 // Reset sit target. 1727 // Reset sit target.
1689 if (part.GetAvatarOnSitTarget() == UUID) 1728 if (part.GetAvatarOnSitTarget() == UUID)
1690 part.SetAvatarOnSitTarget(UUID.Zero); 1729 part.SetAvatarOnSitTarget(UUID.Zero);
1691
1692 m_parentPosition = part.GetWorldPosition(); 1730 m_parentPosition = part.GetWorldPosition();
1693 ControllingClient.SendClearFollowCamProperties(part.ParentUUID); 1731 ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
1694 } 1732 }
1695 1733 // part.GetWorldRotation() is the rotation of the object being sat on
1696 if (m_physicsActor == null) 1734 // Rotation is the sittiing Av's rotation
1697 { 1735
1698 AddToPhysicalScene(false); 1736 Quaternion partRot;
1737// if (part.LinkNum == 1)
1738// { // Root prim of linkset
1739// partRot = part.ParentGroup.RootPart.RotationOffset;
1740// }
1741// else
1742// { // single or child prim
1743
1744// }
1745 if (part == null) //CW: Part may be gone. llDie() for example.
1746 {
1747 partRot = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
1748 }
1749 else
1750 {
1751 partRot = part.GetWorldRotation();
1699 } 1752 }
1700 1753
1701 m_pos += m_parentPosition + new Vector3(0.0f, 0.0f, 2.0f*m_sitAvatarHeight); 1754 Quaternion partIRot = Quaternion.Inverse(partRot);
1702 m_parentPosition = Vector3.Zero; 1755
1756 Quaternion avatarRot = Quaternion.Inverse(Quaternion.Inverse(Rotation) * partIRot); // world or. of the av
1757 Vector3 avStandUp = new Vector3(1.0f, 0f, 0f) * avatarRot; // 1M infront of av
1703 1758
1704 m_parentID = 0; 1759
1760 if (m_physicsActor == null)
1761 {
1762 AddToPhysicalScene(false);
1763 }
1764 //CW: If the part isn't null then we can set the current position
1765 if (part != null)
1766 {
1767 Vector3 avWorldStandUp = avStandUp + part.GetWorldPosition() + (m_pos * partRot); // + av sit offset!
1768 AbsolutePosition = avWorldStandUp; //KF: Fix stand up.
1769 part.IsOccupied = false;
1770 }
1771 else
1772 {
1773 //CW: Since the part doesn't exist, a coarse standup position isn't an issue
1774 AbsolutePosition = m_lastWorldPosition;
1775 }
1776
1777 m_parentPosition = Vector3.Zero;
1778 m_parentID = 0;
1705 SendFullUpdateToAllClients(); 1779 SendFullUpdateToAllClients();
1706 m_requestedSitTargetID = 0; 1780 m_requestedSitTargetID = 0;
1781
1707 if ((m_physicsActor != null) && (m_avHeight > 0)) 1782 if ((m_physicsActor != null) && (m_avHeight > 0))
1708 { 1783 {
1709 SetHeight(m_avHeight); 1784 SetHeight(m_avHeight);
1710 } 1785 }
1711 } 1786 }
1712
1713 Animator.TrySetMovementAnimation("STAND"); 1787 Animator.TrySetMovementAnimation("STAND");
1714 } 1788 }
1715 1789
@@ -1740,13 +1814,9 @@ namespace OpenSim.Region.Framework.Scenes
1740 Vector3 avSitOffSet = part.SitTargetPosition; 1814 Vector3 avSitOffSet = part.SitTargetPosition;
1741 Quaternion avSitOrientation = part.SitTargetOrientation; 1815 Quaternion avSitOrientation = part.SitTargetOrientation;
1742 UUID avOnTargetAlready = part.GetAvatarOnSitTarget(); 1816 UUID avOnTargetAlready = part.GetAvatarOnSitTarget();
1743 1817 bool SitTargetOccupied = (avOnTargetAlready != UUID.Zero);
1744 bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero)); 1818 bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored.
1745 bool SitTargetisSet = 1819 if (SitTargetisSet && !SitTargetOccupied)
1746 (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f && avSitOrientation.W == 1f &&
1747 avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f));
1748
1749 if (SitTargetisSet && SitTargetUnOccupied)
1750 { 1820 {
1751 //switch the target to this prim 1821 //switch the target to this prim
1752 return part; 1822 return part;
@@ -1760,84 +1830,153 @@ namespace OpenSim.Region.Framework.Scenes
1760 private void SendSitResponse(IClientAPI remoteClient, UUID targetID, Vector3 offset, Quaternion pSitOrientation) 1830 private void SendSitResponse(IClientAPI remoteClient, UUID targetID, Vector3 offset, Quaternion pSitOrientation)
1761 { 1831 {
1762 bool autopilot = true; 1832 bool autopilot = true;
1833 Vector3 autopilotTarget = new Vector3();
1834 Quaternion sitOrientation = Quaternion.Identity;
1763 Vector3 pos = new Vector3(); 1835 Vector3 pos = new Vector3();
1764 Quaternion sitOrientation = pSitOrientation;
1765 Vector3 cameraEyeOffset = Vector3.Zero; 1836 Vector3 cameraEyeOffset = Vector3.Zero;
1766 Vector3 cameraAtOffset = Vector3.Zero; 1837 Vector3 cameraAtOffset = Vector3.Zero;
1767 bool forceMouselook = false; 1838 bool forceMouselook = false;
1768 1839
1769 //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID); 1840 //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID);
1770 SceneObjectPart part = FindNextAvailableSitTarget(targetID); 1841 SceneObjectPart part = FindNextAvailableSitTarget(targetID);
1771 if (part != null) 1842 if (part == null) return;
1772 { 1843
1773 // TODO: determine position to sit at based on scene geometry; don't trust offset from client 1844 // TODO: determine position to sit at based on scene geometry; don't trust offset from client
1774 // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it 1845 // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it
1775 1846
1776 // Is a sit target available? 1847 // part is the prim to sit on
1777 Vector3 avSitOffSet = part.SitTargetPosition; 1848 // offset is the world-ref vector distance from that prim center to the click-spot
1778 Quaternion avSitOrientation = part.SitTargetOrientation; 1849 // UUID is the UUID of the Avatar doing the clicking
1779 UUID avOnTargetAlready = part.GetAvatarOnSitTarget(); 1850
1780 1851 m_avInitialPos = AbsolutePosition; // saved to calculate unscripted sit rotation
1781 bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero)); 1852
1782 bool SitTargetisSet = 1853 // Is a sit target available?
1783 (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f && 1854 Vector3 avSitOffSet = part.SitTargetPosition;
1784 ( 1855 Quaternion avSitOrientation = part.SitTargetOrientation;
1785 avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f && avSitOrientation.W == 1f // Valid Zero Rotation quaternion 1856
1786 || avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 1f && avSitOrientation.W == 0f // W-Z Mapping was invalid at one point 1857 bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored.
1787 || avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f && avSitOrientation.W == 0f // Invalid Quaternion 1858 // Quaternion partIRot = Quaternion.Inverse(part.GetWorldRotation());
1788 ) 1859 Quaternion partRot;
1789 )); 1860// if (part.LinkNum == 1)
1790 1861// { // Root prim of linkset
1791 if (SitTargetisSet && SitTargetUnOccupied) 1862// partRot = part.ParentGroup.RootPart.RotationOffset;
1792 { 1863// }
1793 part.SetAvatarOnSitTarget(UUID); 1864// else
1794 offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); 1865// { // single or child prim
1795 sitOrientation = avSitOrientation; 1866 partRot = part.GetWorldRotation();
1796 autopilot = false; 1867// }
1797 } 1868 Quaternion partIRot = Quaternion.Inverse(partRot);
1798 1869//Console.WriteLine("SendSitResponse offset=" + offset + " Occup=" + part.IsOccupied + " TargSet=" + SitTargetisSet);
1799 pos = part.AbsolutePosition + offset; 1870 // Sit analysis rewritten by KF 091125
1800 //if (Math.Abs(part.AbsolutePosition.Z - AbsolutePosition.Z) > 1) 1871 if (SitTargetisSet) // scipted sit
1801 //{ 1872 {
1802 // offset = pos; 1873 if (!part.IsOccupied)
1803 //autopilot = false; 1874 {
1804 //} 1875//Console.WriteLine("Scripted, unoccupied");
1805 if (m_physicsActor != null) 1876 part.SetAvatarOnSitTarget(UUID); // set that Av will be on it
1806 { 1877 offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); // change ofset to the scripted one
1807 // If we're not using the client autopilot, we're immediately warping the avatar to the location 1878 sitOrientation = avSitOrientation; // Change rotatione to the scripted one
1808 // We can remove the physicsActor until they stand up. 1879 autopilot = false; // Jump direct to scripted llSitPos()
1809 m_sitAvatarHeight = m_physicsActor.Size.Z; 1880 }
1810 1881 else
1811 if (autopilot) 1882 {
1812 { 1883//Console.WriteLine("Scripted, occupied");
1813 if (Util.GetDistanceTo(AbsolutePosition, pos) < 4.5) 1884 return;
1814 { 1885 }
1815 autopilot = false; 1886 }
1887 else // Not Scripted
1888 {
1889 if ( (Math.Abs(offset.X) > 0.5f) || (Math.Abs(offset.Y) > 0.5f) )
1890 {
1891 // large prim & offset, ignore if other Avs sitting
1892// offset.Z -= 0.05f;
1893 m_avUnscriptedSitPos = offset * partIRot; // (non-zero) sit where clicked
1894 autopilotTarget = part.AbsolutePosition + offset; // World location of clicked point
1895
1896//Console.WriteLine(" offset ={0}", offset);
1897//Console.WriteLine(" UnscriptedSitPos={0}", m_avUnscriptedSitPos);
1898//Console.WriteLine(" autopilotTarget={0}", autopilotTarget);
1899
1900 }
1901 else // small offset
1902 {
1903//Console.WriteLine("Small offset");
1904 if (!part.IsOccupied)
1905 {
1906 m_avUnscriptedSitPos = Vector3.Zero; // Zero = Sit on prim center
1907 autopilotTarget = part.AbsolutePosition;
1908//Console.WriteLine("UsSmall autopilotTarget={0}", autopilotTarget);
1909 }
1910 else return; // occupied small
1911 } // end large/small
1912 } // end Scripted/not
1913 cameraAtOffset = part.GetCameraAtOffset();
1914 cameraEyeOffset = part.GetCameraEyeOffset();
1915 forceMouselook = part.GetForceMouselook();
1916 if(cameraAtOffset == Vector3.Zero) cameraAtOffset = new Vector3(0f, 0f, 0.1f); //
1917 if(cameraEyeOffset == Vector3.Zero) cameraEyeOffset = new Vector3(0f, 0f, 0.1f); //
1816 1918
1817 RemoveFromPhysicalScene(); 1919 if (m_physicsActor != null)
1818 AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight); 1920 {
1819 } 1921 // If we're not using the client autopilot, we're immediately warping the avatar to the location
1820 } 1922 // We can remove the physicsActor until they stand up.
1821 else 1923 m_sitAvatarHeight = m_physicsActor.Size.Z;
1924 if (autopilot)
1925 { // its not a scripted sit
1926// if (Util.GetDistanceTo(AbsolutePosition, autopilotTarget) < 4.5)
1927 if( (Math.Abs(AbsolutePosition.X - autopilotTarget.X) < 2.0f) && (Math.Abs(AbsolutePosition.Y - autopilotTarget.Y) < 2.0f) )
1822 { 1928 {
1929 autopilot = false; // close enough
1930 m_lastWorldPosition = m_pos; /* CW - This give us a position to return the avatar to if the part is killed before standup.
1931 Not using the part's position because returning the AV to the last known standing
1932 position is likely to be more friendly, isn't it? */
1823 RemoveFromPhysicalScene(); 1933 RemoveFromPhysicalScene();
1824 } 1934 AbsolutePosition = autopilotTarget + new Vector3(0.0f, 0.0f, (m_sitAvatarHeight / 2.0f)); // Warp av to over sit target
1935 } // else the autopilot will get us close
1936 }
1937 else
1938 { // its a scripted sit
1939 m_lastWorldPosition = part.AbsolutePosition; /* CW - This give us a position to return the avatar to if the part is killed before standup.
1940 I *am* using the part's position this time because we have no real idea how far away
1941 the avatar is from the sit target. */
1942 RemoveFromPhysicalScene();
1825 } 1943 }
1826
1827 cameraAtOffset = part.GetCameraAtOffset();
1828 cameraEyeOffset = part.GetCameraEyeOffset();
1829 forceMouselook = part.GetForceMouselook();
1830 } 1944 }
1831 1945 else return; // physactor is null!
1832 ControllingClient.SendSitResponse(targetID, offset, sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook); 1946
1833 m_requestedSitTargetUUID = targetID; 1947 Vector3 offsetr; // = offset * partIRot;
1948 // KF: In a linkset, offsetr needs to be relative to the group root! 091208
1949 // offsetr = (part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) + (offset * partIRot);
1950 // if (part.LinkNum < 2) 091216 All this was necessary because of the GetWorldRotation error.
1951 // { // Single, or Root prim of linkset, target is ClickOffset * RootRot
1952 offsetr = offset * partIRot;
1953//
1954 // else
1955 // { // Child prim, offset is (ChildOffset * RootRot) + (ClickOffset * ChildRot)
1956 // offsetr = //(part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) +
1957 // (offset * partRot);
1958 // }
1959
1960//Console.WriteLine(" ");
1961//Console.WriteLine("link number ={0}", part.LinkNum);
1962//Console.WriteLine("Prim offset ={0}", part.OffsetPosition );
1963//Console.WriteLine("Root Rotate ={0}", part.ParentGroup.RootPart.RotationOffset);
1964//Console.WriteLine("Click offst ={0}", offset);
1965//Console.WriteLine("Prim Rotate ={0}", part.GetWorldRotation());
1966//Console.WriteLine("offsetr ={0}", offsetr);
1967//Console.WriteLine("Camera At ={0}", cameraAtOffset);
1968//Console.WriteLine("Camera Eye ={0}", cameraEyeOffset);
1969
1970 ControllingClient.SendSitResponse(part.UUID, offsetr, sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook);
1971 m_requestedSitTargetUUID = part.UUID; //KF: Correct autopilot target
1834 // This calls HandleAgentSit twice, once from here, and the client calls 1972 // This calls HandleAgentSit twice, once from here, and the client calls
1835 // HandleAgentSit itself after it gets to the location 1973 // HandleAgentSit itself after it gets to the location
1836 // It doesn't get to the location until we've moved them there though 1974 // It doesn't get to the location until we've moved them there though
1837 // which happens in HandleAgentSit :P 1975 // which happens in HandleAgentSit :P
1838 m_autopilotMoving = autopilot; 1976 m_autopilotMoving = autopilot;
1839 m_autoPilotTarget = pos; 1977 m_autoPilotTarget = autopilotTarget;
1840 m_sitAtAutoTarget = autopilot; 1978 m_sitAtAutoTarget = autopilot;
1979 m_initialSitTarget = autopilotTarget;
1841 if (!autopilot) 1980 if (!autopilot)
1842 HandleAgentSit(remoteClient, UUID); 1981 HandleAgentSit(remoteClient, UUID);
1843 } 1982 }
@@ -2132,31 +2271,66 @@ namespace OpenSim.Region.Framework.Scenes
2132 { 2271 {
2133 if (part != null) 2272 if (part != null)
2134 { 2273 {
2274//Console.WriteLine("Link #{0}, Rot {1}", part.LinkNum, part.GetWorldRotation());
2135 if (part.GetAvatarOnSitTarget() == UUID) 2275 if (part.GetAvatarOnSitTarget() == UUID)
2136 { 2276 {
2277//Console.WriteLine("Scripted Sit");
2278 // Scripted sit
2137 Vector3 sitTargetPos = part.SitTargetPosition; 2279 Vector3 sitTargetPos = part.SitTargetPosition;
2138 Quaternion sitTargetOrient = part.SitTargetOrientation; 2280 Quaternion sitTargetOrient = part.SitTargetOrientation;
2139
2140 //Quaternion vq = new Quaternion(sitTargetPos.X, sitTargetPos.Y+0.2f, sitTargetPos.Z+0.2f, 0);
2141 //Quaternion nq = new Quaternion(-sitTargetOrient.X, -sitTargetOrient.Y, -sitTargetOrient.Z, sitTargetOrient.w);
2142
2143 //Quaternion result = (sitTargetOrient * vq) * nq;
2144
2145 m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z); 2281 m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z);
2146 m_pos += SIT_TARGET_ADJUSTMENT; 2282 m_pos += SIT_TARGET_ADJUSTMENT;
2147 m_bodyRot = sitTargetOrient; 2283 m_bodyRot = sitTargetOrient;
2148 //Rotation = sitTargetOrient;
2149 m_parentPosition = part.AbsolutePosition; 2284 m_parentPosition = part.AbsolutePosition;
2150 2285 part.IsOccupied = true;
2151 //SendTerseUpdateToAllClients(); 2286Console.WriteLine("Scripted Sit ofset {0}", m_pos);
2152 } 2287 }
2153 else 2288 else
2154 { 2289 {
2155 m_pos -= part.AbsolutePosition; 2290 // if m_avUnscriptedSitPos is zero then Av sits above center
2291 // Else Av sits at m_avUnscriptedSitPos
2292
2293 // Non-scripted sit by Kitto Flora 21Nov09
2294 // Calculate angle of line from prim to Av
2295 Quaternion partIRot;
2296// if (part.LinkNum == 1)
2297// { // Root prim of linkset
2298// partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset);
2299// }
2300// else
2301// { // single or child prim
2302 partIRot = Quaternion.Inverse(part.GetWorldRotation());
2303// }
2304 Vector3 sitTargetPos= part.AbsolutePosition + m_avUnscriptedSitPos;
2305 float y_diff = (m_avInitialPos.Y - sitTargetPos.Y);
2306 float x_diff = ( m_avInitialPos.X - sitTargetPos.X);
2307 if(Math.Abs(x_diff) < 0.001f) x_diff = 0.001f; // avoid div by 0
2308 if(Math.Abs(y_diff) < 0.001f) y_diff = 0.001f; // avoid pol flip at 0
2309 float sit_angle = (float)Math.Atan2( (double)y_diff, (double)x_diff);
2310 // NOTE: when sitting m_ pos and m_bodyRot are *relative* to the prim location/rotation, not 'World'.
2311 // Av sits at world euler <0,0, z>, translated by part rotation
2312 m_bodyRot = partIRot * Quaternion.CreateFromEulers(0f, 0f, sit_angle); // sit at 0,0,inv-click
2313
2156 m_parentPosition = part.AbsolutePosition; 2314 m_parentPosition = part.AbsolutePosition;
2157 } 2315 part.IsOccupied = true;
2316 m_pos = new Vector3(0f, 0f, 0.05f) + // corrections to get Sit Animation
2317 (new Vector3(0.0f, 0f, 0.61f) * partIRot) + // located on center
2318 (new Vector3(0.34f, 0f, 0.0f) * m_bodyRot) +
2319 m_avUnscriptedSitPos; // adds click offset, if any
2320 //Set up raytrace to find top surface of prim
2321 Vector3 size = part.Scale;
2322 float mag = 2.0f; // 0.1f + (float)Math.Sqrt((size.X * size.X) + (size.Y * size.Y) + (size.Z * size.Z));
2323 Vector3 start = part.AbsolutePosition + new Vector3(0f, 0f, mag);
2324 Vector3 down = new Vector3(0f, 0f, -1f);
2325//Console.WriteLine("st={0} do={1} ma={2}", start, down, mag);
2326 m_scene.PhysicsScene.RaycastWorld(
2327 start, // Vector3 position,
2328 down, // Vector3 direction,
2329 mag, // float length,
2330 SitAltitudeCallback); // retMethod
2331 } // end scripted/not
2158 } 2332 }
2159 else 2333 else // no Av
2160 { 2334 {
2161 return; 2335 return;
2162 } 2336 }
@@ -2168,11 +2342,36 @@ namespace OpenSim.Region.Framework.Scenes
2168 2342
2169 Animator.TrySetMovementAnimation(sitAnimation); 2343 Animator.TrySetMovementAnimation(sitAnimation);
2170 SendFullUpdateToAllClients(); 2344 SendFullUpdateToAllClients();
2171 // This may seem stupid, but Our Full updates don't send avatar rotation :P
2172 // So we're also sending a terse update (which has avatar rotation)
2173 // [Update] We do now.
2174 //SendTerseUpdateToAllClients();
2175 } 2345 }
2346
2347 public void SitAltitudeCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 normal)
2348 {
2349 // KF: 091202 There appears to be a bug in Prim Edit Size - the process sometimes make a prim that RayTrace no longer
2350 // sees. Take/re-rez, or sim restart corrects the condition. Result of bug is incorrect sit height.
2351 if(hitYN)
2352 {
2353 // m_pos = Av offset from prim center to make look like on center
2354 // m_parentPosition = Actual center pos of prim
2355 // collisionPoint = spot on prim where we want to sit
2356 // collisionPoint.Z = global sit surface height
2357 SceneObjectPart part = m_scene.GetSceneObjectPart(localid);
2358 Quaternion partIRot;
2359// if (part.LinkNum == 1)
2360/// { // Root prim of linkset
2361// partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset);
2362// }
2363// else
2364// { // single or child prim
2365 partIRot = Quaternion.Inverse(part.GetWorldRotation());
2366// }
2367 float offZ = collisionPoint.Z - m_initialSitTarget.Z;
2368 Vector3 offset = new Vector3(0.0f, 0.0f, offZ) * partIRot; // Altitude correction
2369//Console.WriteLine("sitPoint={0}, offset={1}", sitPoint, offset);
2370 m_pos += offset;
2371// ControllingClient.SendClearFollowCamProperties(part.UUID);
2372
2373 }
2374 } // End SitAltitudeCallback KF.
2176 2375
2177 /// <summary> 2376 /// <summary>
2178 /// Event handler for the 'Always run' setting on the client 2377 /// Event handler for the 'Always run' setting on the client
@@ -2202,7 +2401,7 @@ namespace OpenSim.Region.Framework.Scenes
2202 /// </summary> 2401 /// </summary>
2203 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param> 2402 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param>
2204 /// <param name="rotation">The direction in which this avatar should now face. 2403 /// <param name="rotation">The direction in which this avatar should now face.
2205 public void AddNewMovement(Vector3 vec, Quaternion rotation) 2404 public void AddNewMovement(Vector3 vec, Quaternion rotation, bool Nudging)
2206 { 2405 {
2207 if (m_isChildAgent) 2406 if (m_isChildAgent)
2208 { 2407 {
@@ -2279,7 +2478,7 @@ namespace OpenSim.Region.Framework.Scenes
2279 2478
2280 // TODO: Add the force instead of only setting it to support multiple forces per frame? 2479 // TODO: Add the force instead of only setting it to support multiple forces per frame?
2281 m_forceToApply = direc; 2480 m_forceToApply = direc;
2282 2481 m_isNudging = Nudging;
2283 m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); 2482 m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
2284 } 2483 }
2285 2484
@@ -2294,7 +2493,7 @@ namespace OpenSim.Region.Framework.Scenes
2294 const float POSITION_TOLERANCE = 0.05f; 2493 const float POSITION_TOLERANCE = 0.05f;
2295 //const int TIME_MS_TOLERANCE = 3000; 2494 //const int TIME_MS_TOLERANCE = 3000;
2296 2495
2297 SendPrimUpdates(); 2496
2298 2497
2299 if (m_newCoarseLocations) 2498 if (m_newCoarseLocations)
2300 { 2499 {
@@ -2330,6 +2529,9 @@ namespace OpenSim.Region.Framework.Scenes
2330 CheckForBorderCrossing(); 2529 CheckForBorderCrossing();
2331 CheckForSignificantMovement(); // sends update to the modules. 2530 CheckForSignificantMovement(); // sends update to the modules.
2332 } 2531 }
2532
2533 //Sending prim updates AFTER the avatar terse updates are sent
2534 SendPrimUpdates();
2333 } 2535 }
2334 2536
2335 #endregion 2537 #endregion
@@ -3146,6 +3348,7 @@ namespace OpenSim.Region.Framework.Scenes
3146 m_callbackURI = cAgent.CallbackURI; 3348 m_callbackURI = cAgent.CallbackURI;
3147 3349
3148 m_pos = cAgent.Position; 3350 m_pos = cAgent.Position;
3351
3149 m_velocity = cAgent.Velocity; 3352 m_velocity = cAgent.Velocity;
3150 m_CameraCenter = cAgent.Center; 3353 m_CameraCenter = cAgent.Center;
3151 //m_avHeight = cAgent.Size.Z; 3354 //m_avHeight = cAgent.Size.Z;
@@ -3234,14 +3437,25 @@ namespace OpenSim.Region.Framework.Scenes
3234 { 3437 {
3235 if (m_forceToApply.HasValue) 3438 if (m_forceToApply.HasValue)
3236 { 3439 {
3237 Vector3 force = m_forceToApply.Value;
3238 3440
3441 Vector3 force = m_forceToApply.Value;
3239 m_updateflag = true; 3442 m_updateflag = true;
3240// movementvector = force;
3241 Velocity = force; 3443 Velocity = force;
3242 3444
3243 m_forceToApply = null; 3445 m_forceToApply = null;
3244 } 3446 }
3447 else
3448 {
3449 if (m_isNudging)
3450 {
3451 Vector3 force = Vector3.Zero;
3452
3453 m_updateflag = true;
3454 Velocity = force;
3455 m_isNudging = false;
3456 m_updateCount = UPDATE_COUNT; //KF: Update anims to pickup "STAND"
3457 }
3458 }
3245 } 3459 }
3246 3460
3247 public override void SetText(string text, Vector3 color, double alpha) 3461 public override void SetText(string text, Vector3 color, double alpha)
@@ -3292,18 +3506,29 @@ namespace OpenSim.Region.Framework.Scenes
3292 { 3506 {
3293 if (e == null) 3507 if (e == null)
3294 return; 3508 return;
3295 3509
3296 //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f)) 3510 // The Physics Scene will send (spam!) updates every 500 ms grep: m_physicsActor.SubscribeEvents(
3297 // The Physics Scene will send updates every 500 ms grep: m_physicsActor.SubscribeEvents(
3298 // as of this comment the interval is set in AddToPhysicalScene 3511 // as of this comment the interval is set in AddToPhysicalScene
3299 if (Animator!=null) 3512 if (Animator!=null)
3300 Animator.UpdateMovementAnimations(); 3513 {
3514 if (m_updateCount > 0) //KF: DO NOT call UpdateMovementAnimations outside of the m_updateCount wrapper,
3515 { // else its will lock out other animation changes, like ground sit.
3516 Animator.UpdateMovementAnimations();
3517 m_updateCount--;
3518 }
3519 }
3301 3520
3302 CollisionEventUpdate collisionData = (CollisionEventUpdate)e; 3521 CollisionEventUpdate collisionData = (CollisionEventUpdate)e;
3303 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList; 3522 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList;
3304 3523
3305 CollisionPlane = Vector4.UnitW; 3524 CollisionPlane = Vector4.UnitW;
3306 3525
3526 if (m_lastColCount != coldata.Count)
3527 {
3528 m_updateCount = UPDATE_COUNT;
3529 m_lastColCount = coldata.Count;
3530 }
3531
3307 if (coldata.Count != 0 && Animator != null) 3532 if (coldata.Count != 0 && Animator != null)
3308 { 3533 {
3309 switch (Animator.CurrentMovementAnimation) 3534 switch (Animator.CurrentMovementAnimation)
@@ -3910,5 +4135,16 @@ namespace OpenSim.Region.Framework.Scenes
3910 m_reprioritization_called = false; 4135 m_reprioritization_called = false;
3911 } 4136 }
3912 } 4137 }
4138
4139 private Vector3 Quat2Euler(Quaternion rot){
4140 float x = Utils.RAD_TO_DEG * (float)Math.Atan2((double)((2.0f * rot.X * rot.W) - (2.0f * rot.Y * rot.Z)) ,
4141 (double)(1 - (2.0f * rot.X * rot.X) - (2.0f * rot.Z * rot.Z)));
4142 float y = Utils.RAD_TO_DEG * (float)Math.Asin ((double)((2.0f * rot.X * rot.Y) + (2.0f * rot.Z * rot.W)));
4143 float z = Utils.RAD_TO_DEG * (float)Math.Atan2(((double)(2.0f * rot.Y * rot.W) - (2.0f * rot.X * rot.Z)) ,
4144 (double)(1 - (2.0f * rot.Y * rot.Y) - (2.0f * rot.Z * rot.Z)));
4145 return(new Vector3(x,y,z));
4146 }
4147
4148
3913 } 4149 }
3914} 4150}
diff --git a/OpenSim/Region/Framework/Scenes/SceneViewer.cs b/OpenSim/Region/Framework/Scenes/SceneViewer.cs
index c6cf4cc..4ba4fab 100644
--- a/OpenSim/Region/Framework/Scenes/SceneViewer.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneViewer.cs
@@ -75,7 +75,7 @@ namespace OpenSim.Region.Framework.Scenes
75 75
76 foreach (EntityBase e in m_presence.Scene.Entities) 76 foreach (EntityBase e in m_presence.Scene.Entities)
77 { 77 {
78 if (e is SceneObjectGroup) 78 if (e != null && e is SceneObjectGroup)
79 m_pendingObjects.Enqueue((SceneObjectGroup)e); 79 m_pendingObjects.Enqueue((SceneObjectGroup)e);
80 } 80 }
81 } 81 }