aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework/Scenes')
-rw-r--r--OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs29
-rw-r--r--OpenSim/Region/Framework/Scenes/EntityManager.cs79
-rw-r--r--OpenSim/Region/Framework/Scenes/EventManager.cs24
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs8
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs44
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs47
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs36
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs24
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs519
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs83
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs380
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs579
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs11
13 files changed, 1242 insertions, 621 deletions
diff --git a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
index fd526eb..e98f0e7 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
@@ -454,4 +455,4 @@ namespace OpenSim.Region.Framework.Scenes.Animation
454 m_scenePresence = null; 455 m_scenePresence = null;
455 } 456 }
456 } 457 }
457} \ No newline at end of file 458}
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/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs
index 399379e..8f0b866 100644
--- a/OpenSim/Region/Framework/Scenes/EventManager.cs
+++ b/OpenSim/Region/Framework/Scenes/EventManager.cs
@@ -205,7 +205,11 @@ namespace OpenSim.Region.Framework.Scenes
205 public event OnMakeChildAgentDelegate OnMakeChildAgent; 205 public event OnMakeChildAgentDelegate OnMakeChildAgent;
206 206
207 public delegate void OnMakeRootAgentDelegate(ScenePresence presence); 207 public delegate void OnMakeRootAgentDelegate(ScenePresence presence);
208 public delegate void OnSaveNewWindlightProfileDelegate();
209 public delegate void OnSendNewWindlightProfileTargetedDelegate(RegionMeta7WindlightData wl, UUID user);
208 public event OnMakeRootAgentDelegate OnMakeRootAgent; 210 public event OnMakeRootAgentDelegate OnMakeRootAgent;
211 public event OnSendNewWindlightProfileTargetedDelegate OnSendNewWindlightProfileTargeted;
212 public event OnSaveNewWindlightProfileDelegate OnSaveNewWindlightProfile;
209 213
210 public delegate void NewInventoryItemUploadComplete(UUID avatarID, UUID assetID, string name, int userlevel); 214 public delegate void NewInventoryItemUploadComplete(UUID avatarID, UUID assetID, string name, int userlevel);
211 215
@@ -425,6 +429,8 @@ namespace OpenSim.Region.Framework.Scenes
425 private IncomingInstantMessage handlerUnhandledInstantMessage = null; //OnUnhandledInstantMessage; 429 private IncomingInstantMessage handlerUnhandledInstantMessage = null; //OnUnhandledInstantMessage;
426 private ClientClosed handlerClientClosed = null; //OnClientClosed; 430 private ClientClosed handlerClientClosed = null; //OnClientClosed;
427 private OnMakeChildAgentDelegate handlerMakeChildAgent = null; //OnMakeChildAgent; 431 private OnMakeChildAgentDelegate handlerMakeChildAgent = null; //OnMakeChildAgent;
432 private OnSaveNewWindlightProfileDelegate handlerSaveNewWindlightProfile = null; //OnSaveNewWindlightProfile;
433 private OnSendNewWindlightProfileTargetedDelegate handlerSendNewWindlightProfileTargeted = null; //OnSendNewWindlightProfileTargeted;
428 private OnMakeRootAgentDelegate handlerMakeRootAgent = null; //OnMakeRootAgent; 434 private OnMakeRootAgentDelegate handlerMakeRootAgent = null; //OnMakeRootAgent;
429 private OnTerrainTickDelegate handlerTerrainTick = null; // OnTerainTick; 435 private OnTerrainTickDelegate handlerTerrainTick = null; // OnTerainTick;
430 private RegisterCapsEvent handlerRegisterCaps = null; // OnRegisterCaps; 436 private RegisterCapsEvent handlerRegisterCaps = null; // OnRegisterCaps;
@@ -789,6 +795,24 @@ namespace OpenSim.Region.Framework.Scenes
789 } 795 }
790 } 796 }
791 797
798 public void TriggerOnSendNewWindlightProfileTargeted(RegionMeta7WindlightData wl, UUID user)
799 {
800 handlerSendNewWindlightProfileTargeted = OnSendNewWindlightProfileTargeted;
801 if (handlerSendNewWindlightProfileTargeted != null)
802 {
803 handlerSendNewWindlightProfileTargeted(wl, user);
804 }
805 }
806
807 public void TriggerOnSaveNewWindlightProfile()
808 {
809 handlerSaveNewWindlightProfile = OnSaveNewWindlightProfile;
810 if (handlerSaveNewWindlightProfile != null)
811 {
812 handlerSaveNewWindlightProfile();
813 }
814 }
815
792 public void TriggerOnMakeRootAgent(ScenePresence presence) 816 public void TriggerOnMakeRootAgent(ScenePresence presence)
793 { 817 {
794 handlerMakeRootAgent = OnMakeRootAgent; 818 handlerMakeRootAgent = OnMakeRootAgent;
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index 3044017..18ec25f 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -846,8 +846,12 @@ namespace OpenSim.Region.Framework.Scenes
846 public void RemoveTaskInventory(IClientAPI remoteClient, UUID itemID, uint localID) 846 public void RemoveTaskInventory(IClientAPI remoteClient, UUID itemID, uint localID)
847 { 847 {
848 SceneObjectPart part = GetSceneObjectPart(localID); 848 SceneObjectPart part = GetSceneObjectPart(localID);
849 SceneObjectGroup group = part.ParentGroup; 849 SceneObjectGroup group = null;
850 if (group != null) 850 if (part != null)
851 {
852 group = part.ParentGroup;
853 }
854 if (part != null && group != null)
851 { 855 {
852 TaskInventoryItem item = group.GetInventoryItem(localID, itemID); 856 TaskInventoryItem item = group.GetInventoryItem(localID, itemID);
853 if (item == null) 857 if (item == null)
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 234554e..db21bf9 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -539,6 +539,8 @@ namespace OpenSim.Region.Framework.Scenes
539 539
540 // Load region settings 540 // Load region settings
541 m_regInfo.RegionSettings = m_storageManager.DataStore.LoadRegionSettings(m_regInfo.RegionID); 541 m_regInfo.RegionSettings = m_storageManager.DataStore.LoadRegionSettings(m_regInfo.RegionID);
542 m_regInfo.WindlightSettings = m_storageManager.DataStore.LoadRegionWindlightSettings(m_regInfo.RegionID);
543
542 if (m_storageManager.EstateDataStore != null) 544 if (m_storageManager.EstateDataStore != null)
543 { 545 {
544 m_regInfo.EstateSettings = m_storageManager.EstateDataStore.LoadEstateSettings(m_regInfo.RegionID); 546 m_regInfo.EstateSettings = m_storageManager.EstateDataStore.LoadEstateSettings(m_regInfo.RegionID);
@@ -886,6 +888,15 @@ namespace OpenSim.Region.Framework.Scenes
886 /// <param name="seconds">float indicating duration before restart.</param> 888 /// <param name="seconds">float indicating duration before restart.</param>
887 public virtual void Restart(float seconds) 889 public virtual void Restart(float seconds)
888 { 890 {
891 Restart(seconds, true);
892 }
893
894 /// <summary>
895 /// Given float seconds, this will restart the region. showDialog will optionally alert the users.
896 /// </summary>
897 /// <param name="seconds">float indicating duration before restart.</param>
898 public virtual void Restart(float seconds, bool showDialog)
899 {
889 // notifications are done in 15 second increments 900 // notifications are done in 15 second increments
890 // so .. if the number of seconds is less then 15 seconds, it's not really a restart request 901 // so .. if the number of seconds is less then 15 seconds, it's not really a restart request
891 // It's a 'Cancel restart' request. 902 // It's a 'Cancel restart' request.
@@ -906,8 +917,11 @@ namespace OpenSim.Region.Framework.Scenes
906 m_restartTimer.Elapsed += new ElapsedEventHandler(RestartTimer_Elapsed); 917 m_restartTimer.Elapsed += new ElapsedEventHandler(RestartTimer_Elapsed);
907 m_log.Info("[REGION]: Restarting Region in " + (seconds / 60) + " minutes"); 918 m_log.Info("[REGION]: Restarting Region in " + (seconds / 60) + " minutes");
908 m_restartTimer.Start(); 919 m_restartTimer.Start();
909 m_dialogModule.SendNotificationToUsersInRegion( 920 if (showDialog)
921 {
922 m_dialogModule.SendNotificationToUsersInRegion(
910 UUID.Random(), String.Empty, RegionInfo.RegionName + String.Format(": Restarting in {0} Minutes", (int)(seconds / 60.0))); 923 UUID.Random(), String.Empty, RegionInfo.RegionName + String.Format(": Restarting in {0} Minutes", (int)(seconds / 60.0)));
924 }
911 } 925 }
912 } 926 }
913 927
@@ -1189,16 +1203,16 @@ namespace OpenSim.Region.Framework.Scenes
1189 // Check if any objects have reached their targets 1203 // Check if any objects have reached their targets
1190 CheckAtTargets(); 1204 CheckAtTargets();
1191 1205
1192 // Update SceneObjectGroups that have scheduled themselves for updates
1193 // Objects queue their updates onto all scene presences
1194 if (m_frame % m_update_objects == 0)
1195 m_sceneGraph.UpdateObjectGroups();
1196
1197 // Run through all ScenePresences looking for updates 1206 // Run through all ScenePresences looking for updates
1198 // Presence updates and queued object updates for each presence are sent to clients 1207 // Presence updates and queued object updates for each presence are sent to clients
1199 if (m_frame % m_update_presences == 0) 1208 if (m_frame % m_update_presences == 0)
1200 m_sceneGraph.UpdatePresences(); 1209 m_sceneGraph.UpdatePresences();
1201 1210
1211 // Update SceneObjectGroups that have scheduled themselves for updates
1212 // Objects queue their updates onto all scene presences
1213 if (m_frame % m_update_objects == 0)
1214 m_sceneGraph.UpdateObjectGroups();
1215
1202 int tmpPhysicsMS2 = Util.EnvironmentTickCount(); 1216 int tmpPhysicsMS2 = Util.EnvironmentTickCount();
1203 if ((m_frame % m_update_physics == 0) && m_physics_enabled) 1217 if ((m_frame % m_update_physics == 0) && m_physics_enabled)
1204 m_sceneGraph.UpdatePreparePhysics(); 1218 m_sceneGraph.UpdatePreparePhysics();
@@ -1509,6 +1523,19 @@ namespace OpenSim.Region.Framework.Scenes
1509 public void SaveTerrain() 1523 public void SaveTerrain()
1510 { 1524 {
1511 m_storageManager.DataStore.StoreTerrain(Heightmap.GetDoubles(), RegionInfo.RegionID); 1525 m_storageManager.DataStore.StoreTerrain(Heightmap.GetDoubles(), RegionInfo.RegionID);
1526 }
1527
1528 public void StoreWindlightProfile(RegionMeta7WindlightData wl)
1529 {
1530 m_regInfo.WindlightSettings = wl;
1531 m_storageManager.DataStore.StoreRegionWindlightSettings(wl);
1532 m_eventManager.TriggerOnSaveNewWindlightProfile();
1533 }
1534
1535 public void LoadWindlightProfile()
1536 {
1537 m_regInfo.WindlightSettings = m_storageManager.DataStore.LoadRegionWindlightSettings(RegionInfo.RegionID);
1538 m_eventManager.TriggerOnSaveNewWindlightProfile();
1512 } 1539 }
1513 1540
1514 /// <summary> 1541 /// <summary>
@@ -3391,6 +3418,9 @@ namespace OpenSim.Region.Framework.Scenes
3391 3418
3392 CapsModule.AddCapsHandler(agent.AgentID); 3419 CapsModule.AddCapsHandler(agent.AgentID);
3393 3420
3421 if ((teleportFlags & ((uint)TeleportFlags.ViaLandmark | (uint)TeleportFlags.ViaLocation | (uint)TeleportFlags.ViaLandmark | (uint)TeleportFlags.Default)) != 0)
3422 System.Threading.Thread.Sleep(2000);
3423
3394 if (!agent.child) 3424 if (!agent.child)
3395 { 3425 {
3396 if (TestBorderCross(agent.startpos,Cardinals.E)) 3426 if (TestBorderCross(agent.startpos,Cardinals.E))
@@ -3449,6 +3479,7 @@ namespace OpenSim.Region.Framework.Scenes
3449 } 3479 }
3450 } 3480 }
3451 // Honor parcel landing type and position. 3481 // Honor parcel landing type and position.
3482 /*
3452 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y); 3483 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3453 if (land != null) 3484 if (land != null)
3454 { 3485 {
@@ -3457,6 +3488,7 @@ namespace OpenSim.Region.Framework.Scenes
3457 agent.startpos = land.LandData.UserLocation; 3488 agent.startpos = land.LandData.UserLocation;
3458 } 3489 }
3459 } 3490 }
3491 */// This is now handled properly in ScenePresence.MakeRootAgent
3460 } 3492 }
3461 3493
3462 m_authenticateHandler.AddNewCircuit(agent.circuitcode, agent); 3494 m_authenticateHandler.AddNewCircuit(agent.circuitcode, agent);
diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
index 6164368..6a3c386 100644
--- a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
@@ -699,17 +699,42 @@ namespace OpenSim.Region.Framework.Scenes
699 { 699 {
700 m_log.DebugFormat( 700 m_log.DebugFormat(
701 "[SCENE COMMUNICATION SERVICE]: RequestTeleportToLocation {0} within {1}", 701 "[SCENE COMMUNICATION SERVICE]: RequestTeleportToLocation {0} within {1}",
702 position, m_regionInfo.RegionName); 702 position, m_regionInfo.RegionName);
703 703
704 // Teleport within the same region 704 // Teleport within the same region
705 if (IsOutsideRegion(avatar.Scene, position) || position.Z < 0) 705 if (IsOutsideRegion(avatar.Scene, position) || position.Z < 0)
706 { 706 {
707 Vector3 emergencyPos = new Vector3(128, 128, 128); 707 Vector3 emergencyPos = new Vector3(128, 128, 128);
708 708
709 m_log.WarnFormat( 709 m_log.WarnFormat(
710 "[SCENE COMMUNICATION SERVICE]: RequestTeleportToLocation() was given an illegal position of {0} for avatar {1}, {2}. Substituting {3}", 710 "[SCENE COMMUNICATION SERVICE]: RequestTeleportToLocation() was given an illegal position of {0} for avatar {1}, {2}. Substituting {3}",
711 position, avatar.Name, avatar.UUID, emergencyPos); 711 position, avatar.Name, avatar.UUID, emergencyPos);
712 position = emergencyPos; 712 position = emergencyPos;
713 }
714
715 Vector3 currentPos = avatar.AbsolutePosition;
716 ILandObject srcLand = m_scene.LandChannel.GetLandObject(currentPos.X, currentPos.Y);
717 ILandObject destLand = m_scene.LandChannel.GetLandObject(position.X, position.Y);
718 if (srcLand != null && destLand != null && (teleportFlags & (uint)TeleportFlags.ViaLure) == 0 && (teleportFlags & (uint)TeleportFlags.ViaGodlikeLure) == 0)
719 {
720 if (srcLand.LandData.LocalID == destLand.LandData.LocalID)
721 {
722 //TPing within the same parcel. If the landing point is restricted, block the TP.
723 //Don't restrict gods, estate managers, or land owners to the TP point. This behaviour mimics agni.
724 if (destLand.LandData.LandingType == (byte)1 && destLand.LandData.UserLocation != Vector3.Zero && avatar.GodLevel < 200 && !m_scene.RegionInfo.EstateSettings.IsEstateManager(avatar.UUID) && destLand.LandData.OwnerID != avatar.UUID)
725 {
726 avatar.ControllingClient.SendAgentAlertMessage("Can't TP to the destination; landing point set.", false);
727 position = currentPos;
728 }
729 }
730 else
731 {
732 //Tping to a different parcel. Respect the landing point on the destination parcel.
733 if (destLand.LandData.LandingType == (byte)1 && destLand.LandData.UserLocation != Vector3.Zero && avatar.GodLevel < 200 && !m_scene.RegionInfo.EstateSettings.IsEstateManager(avatar.UUID) && destLand.LandData.OwnerID != avatar.UUID)
734 {
735 position = destLand.LandData.UserLocation;
736 }
737 }
713 } 738 }
714 739
715 // TODO: Get proper AVG Height 740 // TODO: Get proper AVG Height
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index f74fd5d..34a92fe 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -222,6 +222,30 @@ namespace OpenSim.Region.Framework.Scenes
222 protected internal bool AddRestoredSceneObject( 222 protected internal bool AddRestoredSceneObject(
223 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted) 223 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted)
224 { 224 {
225 // KF: Check for out-of-region, move inside and make static.
226 Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X,
227 sceneObject.RootPart.GroupPosition.Y,
228 sceneObject.RootPart.GroupPosition.Z);
229 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 ||
230 npos.X > Constants.RegionSize ||
231 npos.Y > Constants.RegionSize))
232 {
233 if (npos.X < 0.0) npos.X = 1.0f;
234 if (npos.Y < 0.0) npos.Y = 1.0f;
235 if (npos.Z < 0.0) npos.Z = 0.0f;
236 if (npos.X > Constants.RegionSize) npos.X = Constants.RegionSize - 1.0f;
237 if (npos.Y > Constants.RegionSize) npos.Y = Constants.RegionSize - 1.0f;
238
239 foreach (SceneObjectPart part in sceneObject.Children.Values)
240 {
241 part.GroupPosition = npos;
242 }
243 sceneObject.RootPart.Velocity = Vector3.Zero;
244 sceneObject.RootPart.AngularVelocity = Vector3.Zero;
245 sceneObject.RootPart.Acceleration = Vector3.Zero;
246 sceneObject.RootPart.Velocity = Vector3.Zero;
247 }
248
225 if (!alreadyPersisted) 249 if (!alreadyPersisted)
226 { 250 {
227 sceneObject.ForceInventoryPersistence(); 251 sceneObject.ForceInventoryPersistence();
@@ -542,6 +566,18 @@ namespace OpenSim.Region.Framework.Scenes
542 if (group.GetFromItemID() == itemID) 566 if (group.GetFromItemID() == itemID)
543 { 567 {
544 m_parentScene.SendAttachEvent(group.LocalId, itemID, UUID.Zero); 568 m_parentScene.SendAttachEvent(group.LocalId, itemID, UUID.Zero);
569 bool hasScripts = false;
570 foreach (SceneObjectPart part in group.Children.Values)
571 {
572 if (part.Inventory.ContainsScripts())
573 {
574 hasScripts = true;
575 break;
576 }
577 }
578
579 if (hasScripts) // Allow the object to execute the attach(NULL_KEY) event
580 System.Threading.Thread.Sleep(100);
545 group.DetachToInventoryPrep(); 581 group.DetachToInventoryPrep();
546 m_log.Debug("[DETACH]: Saving attachpoint: " + 582 m_log.Debug("[DETACH]: Saving attachpoint: " +
547 ((uint)group.GetAttachmentPoint()).ToString()); 583 ((uint)group.GetAttachmentPoint()).ToString());
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
index 5a06bdb..65ce13a 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
@@ -75,14 +75,16 @@ namespace OpenSim.Region.Framework.Scenes
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 public void RemoveScriptInstances() 77 public void RemoveScriptInstances()
78 { 78 {
79 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)
80 { 84 {
81 foreach (SceneObjectPart part in m_parts.Values) 85 part.Inventory.RemoveScriptInstances();
82 {
83 part.Inventory.RemoveScriptInstances();
84 }
85 } 86 }
87
86 } 88 }
87 89
88 /// <summary> 90 /// <summary>
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index ec41ac7..768ceb5 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -106,6 +106,72 @@ namespace OpenSim.Region.Framework.Scenes
106 private bool m_hasGroupChanged = false; 106 private bool m_hasGroupChanged = false;
107 private long timeFirstChanged; 107 private long timeFirstChanged;
108 private long timeLastChanged; 108 private long timeLastChanged;
109 private System.Threading.ReaderWriterLockSlim m_partsLock = new System.Threading.ReaderWriterLockSlim();
110
111 public void lockPartsForRead(bool locked)
112 {
113 if (locked)
114 {
115 if (m_partsLock.RecursiveReadCount > 0)
116 {
117 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.");
118 m_partsLock.ExitReadLock();
119 }
120 if (m_partsLock.RecursiveWriteCount > 0)
121 {
122 m_log.Error("[SceneObjectGroup.m_parts] Recursive read lock requested. This should not happen and means something needs to be fixed.");
123 m_partsLock.ExitWriteLock();
124 }
125
126 while (!m_partsLock.TryEnterReadLock(60000))
127 {
128 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.");
129 if (m_partsLock.IsWriteLockHeld)
130 {
131 m_partsLock = new System.Threading.ReaderWriterLockSlim();
132 }
133 }
134 }
135 else
136 {
137 if (m_partsLock.RecursiveReadCount > 0)
138 {
139 m_partsLock.ExitReadLock();
140 }
141 }
142 }
143 public void lockPartsForWrite(bool locked)
144 {
145 if (locked)
146 {
147 if (m_partsLock.RecursiveReadCount > 0)
148 {
149 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.");
150 m_partsLock.ExitReadLock();
151 }
152 if (m_partsLock.RecursiveWriteCount > 0)
153 {
154 m_log.Error("[SceneObjectGroup.m_parts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
155 m_partsLock.ExitWriteLock();
156 }
157
158 while (!m_partsLock.TryEnterWriteLock(60000))
159 {
160 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.");
161 if (m_partsLock.IsWriteLockHeld)
162 {
163 m_partsLock = new System.Threading.ReaderWriterLockSlim();
164 }
165 }
166 }
167 else
168 {
169 if (m_partsLock.RecursiveWriteCount > 0)
170 {
171 m_partsLock.ExitWriteLock();
172 }
173 }
174 }
109 175
110 public bool HasGroupChanged 176 public bool HasGroupChanged
111 { 177 {
@@ -255,13 +321,16 @@ namespace OpenSim.Region.Framework.Scenes
255 set 321 set
256 { 322 {
257 m_regionHandle = value; 323 m_regionHandle = value;
258 lock (m_parts) 324 lockPartsForRead(true);
259 { 325 {
260 foreach (SceneObjectPart part in m_parts.Values) 326 foreach (SceneObjectPart part in m_parts.Values)
261 { 327 {
328
262 part.RegionHandle = m_regionHandle; 329 part.RegionHandle = m_regionHandle;
330
263 } 331 }
264 } 332 }
333 lockPartsForRead(false);
265 } 334 }
266 } 335 }
267 336
@@ -287,13 +356,16 @@ namespace OpenSim.Region.Framework.Scenes
287 m_scene.CrossPrimGroupIntoNewRegion(val, this, true); 356 m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
288 } 357 }
289 358
290 lock (m_parts) 359 lockPartsForRead(true);
291 { 360 {
292 foreach (SceneObjectPart part in m_parts.Values) 361 foreach (SceneObjectPart part in m_parts.Values)
293 { 362 {
363
294 part.GroupPosition = val; 364 part.GroupPosition = val;
365
295 } 366 }
296 } 367 }
368 lockPartsForRead(false);
297 369
298 //if (m_rootPart.PhysActor != null) 370 //if (m_rootPart.PhysActor != null)
299 //{ 371 //{
@@ -455,13 +527,16 @@ namespace OpenSim.Region.Framework.Scenes
455 527
456 public void SetFromItemID(UUID AssetId) 528 public void SetFromItemID(UUID AssetId)
457 { 529 {
458 lock (m_parts) 530 lockPartsForRead(true);
459 { 531 {
460 foreach (SceneObjectPart part in m_parts.Values) 532 foreach (SceneObjectPart part in m_parts.Values)
461 { 533 {
534
462 part.FromItemID = AssetId; 535 part.FromItemID = AssetId;
536
463 } 537 }
464 } 538 }
539 lockPartsForRead(false);
465 } 540 }
466 541
467 public UUID GetFromItemID() 542 public UUID GetFromItemID()
@@ -528,10 +603,11 @@ namespace OpenSim.Region.Framework.Scenes
528 Vector3 maxScale = Vector3.Zero; 603 Vector3 maxScale = Vector3.Zero;
529 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f); 604 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f);
530 605
531 lock (m_parts) 606 lockPartsForRead(true);
532 { 607 {
533 foreach (SceneObjectPart part in m_parts.Values) 608 foreach (SceneObjectPart part in m_parts.Values)
534 { 609 {
610
535 Vector3 partscale = part.Scale; 611 Vector3 partscale = part.Scale;
536 Vector3 partoffset = part.OffsetPosition; 612 Vector3 partoffset = part.OffsetPosition;
537 613
@@ -542,8 +618,11 @@ namespace OpenSim.Region.Framework.Scenes
542 maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X; 618 maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X;
543 maxScale.Y = (partscale.Y + partoffset.Y > maxScale.Y) ? partscale.Y + partoffset.Y : maxScale.Y; 619 maxScale.Y = (partscale.Y + partoffset.Y > maxScale.Y) ? partscale.Y + partoffset.Y : maxScale.Y;
544 maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z; 620 maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z;
621
545 } 622 }
546 } 623 }
624 lockPartsForRead(false);
625
547 finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X; 626 finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X;
548 finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y; 627 finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y;
549 finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z; 628 finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z;
@@ -559,10 +638,11 @@ namespace OpenSim.Region.Framework.Scenes
559 638
560 EntityIntersection result = new EntityIntersection(); 639 EntityIntersection result = new EntityIntersection();
561 640
562 lock (m_parts) 641 lockPartsForRead(true);
563 { 642 {
564 foreach (SceneObjectPart part in m_parts.Values) 643 foreach (SceneObjectPart part in m_parts.Values)
565 { 644 {
645
566 // Temporary commented to stop compiler warning 646 // Temporary commented to stop compiler warning
567 //Vector3 partPosition = 647 //Vector3 partPosition =
568 // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z); 648 // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z);
@@ -590,8 +670,10 @@ namespace OpenSim.Region.Framework.Scenes
590 result.distance = inter.distance; 670 result.distance = inter.distance;
591 } 671 }
592 } 672 }
673
593 } 674 }
594 } 675 }
676 lockPartsForRead(false);
595 return result; 677 return result;
596 } 678 }
597 679
@@ -604,10 +686,11 @@ namespace OpenSim.Region.Framework.Scenes
604 public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight) 686 public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight)
605 { 687 {
606 float maxX = -256f, maxY = -256f, maxZ = -256f, minX = 256f, minY = 256f, minZ = 256f; 688 float maxX = -256f, maxY = -256f, maxZ = -256f, minX = 256f, minY = 256f, minZ = 256f;
607 lock (m_parts) 689 lockPartsForRead(true);
608 { 690 {
609 foreach (SceneObjectPart part in m_parts.Values) 691 foreach (SceneObjectPart part in m_parts.Values)
610 { 692 {
693
611 Vector3 worldPos = part.GetWorldPosition(); 694 Vector3 worldPos = part.GetWorldPosition();
612 Vector3 offset = worldPos - AbsolutePosition; 695 Vector3 offset = worldPos - AbsolutePosition;
613 Quaternion worldRot; 696 Quaternion worldRot;
@@ -666,6 +749,8 @@ namespace OpenSim.Region.Framework.Scenes
666 backBottomRight.Y = orig.Y + (part.Scale.Y / 2); 749 backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
667 backBottomRight.Z = orig.Z - (part.Scale.Z / 2); 750 backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
668 751
752
753
669 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z); 754 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
670 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z); 755 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
671 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z); 756 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
@@ -837,6 +922,7 @@ namespace OpenSim.Region.Framework.Scenes
837 minZ = backBottomLeft.Z; 922 minZ = backBottomLeft.Z;
838 } 923 }
839 } 924 }
925 lockPartsForRead(false);
840 926
841 Vector3 boundingBox = new Vector3(maxX - minX, maxY - minY, maxZ - minZ); 927 Vector3 boundingBox = new Vector3(maxX - minX, maxY - minY, maxZ - minZ);
842 928
@@ -865,17 +951,20 @@ namespace OpenSim.Region.Framework.Scenes
865 Dictionary<UUID,string> states = new Dictionary<UUID,string>(); 951 Dictionary<UUID,string> states = new Dictionary<UUID,string>();
866 952
867 // Capture script state while holding the lock 953 // Capture script state while holding the lock
868 lock (m_parts) 954 lockPartsForRead(true);
869 { 955 {
870 foreach (SceneObjectPart part in m_parts.Values) 956 foreach (SceneObjectPart part in m_parts.Values)
871 { 957 {
958
872 Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates(); 959 Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates();
873 foreach (UUID itemid in pstates.Keys) 960 foreach (UUID itemid in pstates.Keys)
874 { 961 {
875 states.Add(itemid, pstates[itemid]); 962 states.Add(itemid, pstates[itemid]);
876 } 963 }
964
877 } 965 }
878 } 966 }
967 lockPartsForRead(false);
879 968
880 if (states.Count > 0) 969 if (states.Count > 0)
881 { 970 {
@@ -1037,13 +1126,16 @@ namespace OpenSim.Region.Framework.Scenes
1037 1126
1038 public override void UpdateMovement() 1127 public override void UpdateMovement()
1039 { 1128 {
1040 lock (m_parts) 1129 lockPartsForRead(true);
1041 { 1130 {
1042 foreach (SceneObjectPart part in m_parts.Values) 1131 foreach (SceneObjectPart part in m_parts.Values)
1043 { 1132 {
1133
1044 part.UpdateMovement(); 1134 part.UpdateMovement();
1135
1045 } 1136 }
1046 } 1137 }
1138 lockPartsForRead(false);
1047 } 1139 }
1048 1140
1049 public ushort GetTimeDilation() 1141 public ushort GetTimeDilation()
@@ -1087,7 +1179,7 @@ namespace OpenSim.Region.Framework.Scenes
1087 /// <param name="part"></param> 1179 /// <param name="part"></param>
1088 public void AddPart(SceneObjectPart part) 1180 public void AddPart(SceneObjectPart part)
1089 { 1181 {
1090 lock (m_parts) 1182 lockPartsForWrite(true);
1091 { 1183 {
1092 part.SetParent(this); 1184 part.SetParent(this);
1093 m_parts.Add(part.UUID, part); 1185 m_parts.Add(part.UUID, part);
@@ -1097,6 +1189,7 @@ namespace OpenSim.Region.Framework.Scenes
1097 if (part.LinkNum == 2 && RootPart != null) 1189 if (part.LinkNum == 2 && RootPart != null)
1098 RootPart.LinkNum = 1; 1190 RootPart.LinkNum = 1;
1099 } 1191 }
1192 lockPartsForWrite(false);
1100 } 1193 }
1101 1194
1102 /// <summary> 1195 /// <summary>
@@ -1104,28 +1197,33 @@ namespace OpenSim.Region.Framework.Scenes
1104 /// </summary> 1197 /// </summary>
1105 private void UpdateParentIDs() 1198 private void UpdateParentIDs()
1106 { 1199 {
1107 lock (m_parts) 1200 lockPartsForRead(true);
1108 { 1201 {
1109 foreach (SceneObjectPart part in m_parts.Values) 1202 foreach (SceneObjectPart part in m_parts.Values)
1110 { 1203 {
1204
1111 if (part.UUID != m_rootPart.UUID) 1205 if (part.UUID != m_rootPart.UUID)
1112 { 1206 {
1113 part.ParentID = m_rootPart.LocalId; 1207 part.ParentID = m_rootPart.LocalId;
1114 } 1208 }
1209
1115 } 1210 }
1116 } 1211 }
1212 lockPartsForRead(false);
1117 } 1213 }
1118 1214
1119 public void RegenerateFullIDs() 1215 public void RegenerateFullIDs()
1120 { 1216 {
1121 lock (m_parts) 1217 lockPartsForRead(true);
1122 { 1218 {
1123 foreach (SceneObjectPart part in m_parts.Values) 1219 foreach (SceneObjectPart part in m_parts.Values)
1124 { 1220 {
1221
1125 part.UUID = UUID.Random(); 1222 part.UUID = UUID.Random();
1126 1223
1127 } 1224 }
1128 } 1225 }
1226 lockPartsForRead(false);
1129 } 1227 }
1130 1228
1131 // helper provided for parts. 1229 // helper provided for parts.
@@ -1206,29 +1304,33 @@ namespace OpenSim.Region.Framework.Scenes
1206 1304
1207 DetachFromBackup(); 1305 DetachFromBackup();
1208 1306
1209 lock (m_parts) 1307 lockPartsForRead(true);
1308 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1309 lockPartsForRead(false);
1310
1311 foreach (SceneObjectPart part in values)
1210 { 1312 {
1211 foreach (SceneObjectPart part in m_parts.Values)
1212 {
1213// part.Inventory.RemoveScriptInstances(); 1313// part.Inventory.RemoveScriptInstances();
1214 1314
1215 ScenePresence[] avatars = Scene.GetScenePresences(); 1315 ScenePresence[] avatars = Scene.GetScenePresences();
1216 for (int i = 0; i < avatars.Length; i++) 1316 for (int i = 0; i < avatars.Length; i++)
1317 {
1318 if (avatars[i].ParentID == LocalId)
1217 { 1319 {
1218 if (avatars[i].ParentID == LocalId) 1320 avatars[i].StandUp();
1219 { 1321 }
1220 avatars[i].StandUp();
1221 }
1222 1322
1223 if (!silent) 1323 if (!silent)
1224 { 1324 {
1225 part.UpdateFlag = 0; 1325 part.UpdateFlag = 0;
1226 if (part == m_rootPart) 1326 if (part == m_rootPart)
1227 avatars[i].ControllingClient.SendKillObject(m_regionHandle, part.LocalId); 1327 avatars[i].ControllingClient.SendKillObject(m_regionHandle, part.LocalId);
1228 }
1229 } 1328 }
1230 } 1329 }
1330
1231 } 1331 }
1332
1333
1232 } 1334 }
1233 1335
1234 public void AddScriptLPS(int count) 1336 public void AddScriptLPS(int count)
@@ -1253,17 +1355,20 @@ namespace OpenSim.Region.Framework.Scenes
1253 1355
1254 scriptEvents aggregateScriptEvents=0; 1356 scriptEvents aggregateScriptEvents=0;
1255 1357
1256 lock (m_parts) 1358 lockPartsForRead(true);
1257 { 1359 {
1258 foreach (SceneObjectPart part in m_parts.Values) 1360 foreach (SceneObjectPart part in m_parts.Values)
1259 { 1361 {
1362
1260 if (part == null) 1363 if (part == null)
1261 continue; 1364 continue;
1262 if (part != RootPart) 1365 if (part != RootPart)
1263 part.ObjectFlags = objectflagupdate; 1366 part.ObjectFlags = objectflagupdate;
1264 aggregateScriptEvents |= part.AggregateScriptEvents; 1367 aggregateScriptEvents |= part.AggregateScriptEvents;
1368
1265 } 1369 }
1266 } 1370 }
1371 lockPartsForRead(false);
1267 1372
1268 m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0); 1373 m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0);
1269 m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0); 1374 m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0);
@@ -1305,42 +1410,52 @@ namespace OpenSim.Region.Framework.Scenes
1305 /// <param name="m_physicalPrim"></param> 1410 /// <param name="m_physicalPrim"></param>
1306 public void ApplyPhysics(bool m_physicalPrim) 1411 public void ApplyPhysics(bool m_physicalPrim)
1307 { 1412 {
1308 lock (m_parts) 1413 lockPartsForRead(true);
1414
1415 if (m_parts.Count > 1)
1309 { 1416 {
1310 if (m_parts.Count > 1) 1417 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1418 lockPartsForRead(false);
1419 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1420 foreach (SceneObjectPart part in values)
1311 { 1421 {
1312 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim); 1422
1313 foreach (SceneObjectPart part in m_parts.Values) 1423 if (part.LocalId != m_rootPart.LocalId)
1314 { 1424 {
1315 if (part.LocalId != m_rootPart.LocalId) 1425 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
1316 {
1317 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
1318 }
1319 } 1426 }
1320 1427
1321 // Hack to get the physics scene geometries in the right spot
1322 ResetChildPrimPhysicsPositions();
1323 }
1324 else
1325 {
1326 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1327 } 1428 }
1429 // Hack to get the physics scene geometries in the right spot
1430 ResetChildPrimPhysicsPositions();
1431 }
1432 else
1433 {
1434 lockPartsForRead(false);
1435 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1328 } 1436 }
1329 } 1437 }
1330 1438
1331 public void SetOwnerId(UUID userId) 1439 public void SetOwnerId(UUID userId)
1332 { 1440 {
1333 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); 1441 ForEachPart(delegate(SceneObjectPart part)
1442 {
1443
1444 part.OwnerID = userId;
1445
1446 });
1334 } 1447 }
1335 1448
1336 public void ForEachPart(Action<SceneObjectPart> whatToDo) 1449 public void ForEachPart(Action<SceneObjectPart> whatToDo)
1337 { 1450 {
1338 lock (m_parts) 1451 lockPartsForRead(true);
1452 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1453 lockPartsForRead(false);
1454 foreach (SceneObjectPart part in values)
1339 { 1455 {
1340 foreach (SceneObjectPart part in m_parts.Values) 1456
1341 { 1457 whatToDo(part);
1342 whatToDo(part); 1458
1343 }
1344 } 1459 }
1345 } 1460 }
1346 1461
@@ -1439,14 +1554,17 @@ namespace OpenSim.Region.Framework.Scenes
1439 { 1554 {
1440 SendPartFullUpdate(remoteClient, RootPart, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID)); 1555 SendPartFullUpdate(remoteClient, RootPart, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID));
1441 1556
1442 lock (m_parts) 1557 lockPartsForRead(true);
1443 { 1558 {
1444 foreach (SceneObjectPart part in m_parts.Values) 1559 foreach (SceneObjectPart part in m_parts.Values)
1445 { 1560 {
1561
1446 if (part != RootPart) 1562 if (part != RootPart)
1447 SendPartFullUpdate(remoteClient, part, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID)); 1563 SendPartFullUpdate(remoteClient, part, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID));
1564
1448 } 1565 }
1449 } 1566 }
1567 lockPartsForRead(false);
1450 } 1568 }
1451 1569
1452 /// <summary> 1570 /// <summary>
@@ -1541,10 +1659,11 @@ namespace OpenSim.Region.Framework.Scenes
1541 1659
1542 List<SceneObjectPart> partList; 1660 List<SceneObjectPart> partList;
1543 1661
1544 lock (m_parts) 1662 lockPartsForRead(true);
1545 { 1663
1546 partList = new List<SceneObjectPart>(m_parts.Values); 1664 partList = new List<SceneObjectPart>(m_parts.Values);
1547 } 1665
1666 lockPartsForRead(false);
1548 1667
1549 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) 1668 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1550 { 1669 {
@@ -1793,6 +1912,7 @@ namespace OpenSim.Region.Framework.Scenes
1793 } 1912 }
1794 } 1913 }
1795 } 1914 }
1915
1796 public void stopLookAt() 1916 public void stopLookAt()
1797 { 1917 {
1798 SceneObjectPart rootpart = m_rootPart; 1918 SceneObjectPart rootpart = m_rootPart;
@@ -1867,10 +1987,11 @@ namespace OpenSim.Region.Framework.Scenes
1867 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 1987 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
1868 newPart.SetParent(this); 1988 newPart.SetParent(this);
1869 1989
1870 lock (m_parts) 1990 lockPartsForWrite(true);
1871 { 1991 {
1872 m_parts.Add(newPart.UUID, newPart); 1992 m_parts.Add(newPart.UUID, newPart);
1873 } 1993 }
1994 lockPartsForWrite(false);
1874 1995
1875 SetPartAsNonRoot(newPart); 1996 SetPartAsNonRoot(newPart);
1876 1997
@@ -1933,7 +2054,7 @@ namespace OpenSim.Region.Framework.Scenes
1933 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0) 2054 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
1934 // return; 2055 // return;
1935 2056
1936 lock (m_parts) 2057 lockPartsForRead(true);
1937 { 2058 {
1938 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0); 2059 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0);
1939 2060
@@ -1951,34 +2072,43 @@ namespace OpenSim.Region.Framework.Scenes
1951 2072
1952 foreach (SceneObjectPart part in m_parts.Values) 2073 foreach (SceneObjectPart part in m_parts.Values)
1953 { 2074 {
2075
1954 part.SendScheduledUpdates(); 2076 part.SendScheduledUpdates();
2077
1955 } 2078 }
1956 } 2079 }
2080 lockPartsForRead(false);
1957 } 2081 }
1958 2082
1959 public void ScheduleFullUpdateToAvatar(ScenePresence presence) 2083 public void ScheduleFullUpdateToAvatar(ScenePresence presence)
1960 { 2084 {
1961 RootPart.AddFullUpdateToAvatar(presence); 2085 RootPart.AddFullUpdateToAvatar(presence);
1962 2086
1963 lock (m_parts) 2087 lockPartsForRead(true);
1964 { 2088 {
1965 foreach (SceneObjectPart part in m_parts.Values) 2089 foreach (SceneObjectPart part in m_parts.Values)
1966 { 2090 {
2091
1967 if (part != RootPart) 2092 if (part != RootPart)
1968 part.AddFullUpdateToAvatar(presence); 2093 part.AddFullUpdateToAvatar(presence);
2094
1969 } 2095 }
1970 } 2096 }
2097 lockPartsForRead(false);
1971 } 2098 }
1972 2099
1973 public void ScheduleTerseUpdateToAvatar(ScenePresence presence) 2100 public void ScheduleTerseUpdateToAvatar(ScenePresence presence)
1974 { 2101 {
1975 lock (m_parts) 2102 lockPartsForRead(true);
1976 { 2103 {
1977 foreach (SceneObjectPart part in m_parts.Values) 2104 foreach (SceneObjectPart part in m_parts.Values)
1978 { 2105 {
2106
1979 part.AddTerseUpdateToAvatar(presence); 2107 part.AddTerseUpdateToAvatar(presence);
2108
1980 } 2109 }
1981 } 2110 }
2111 lockPartsForRead(false);
1982 } 2112 }
1983 2113
1984 /// <summary> 2114 /// <summary>
@@ -1989,14 +2119,17 @@ namespace OpenSim.Region.Framework.Scenes
1989 checkAtTargets(); 2119 checkAtTargets();
1990 RootPart.ScheduleFullUpdate(); 2120 RootPart.ScheduleFullUpdate();
1991 2121
1992 lock (m_parts) 2122 lockPartsForRead(true);
1993 { 2123 {
1994 foreach (SceneObjectPart part in m_parts.Values) 2124 foreach (SceneObjectPart part in m_parts.Values)
1995 { 2125 {
2126
1996 if (part != RootPart) 2127 if (part != RootPart)
1997 part.ScheduleFullUpdate(); 2128 part.ScheduleFullUpdate();
2129
1998 } 2130 }
1999 } 2131 }
2132 lockPartsForRead(false);
2000 } 2133 }
2001 2134
2002 /// <summary> 2135 /// <summary>
@@ -2004,13 +2137,16 @@ namespace OpenSim.Region.Framework.Scenes
2004 /// </summary> 2137 /// </summary>
2005 public void ScheduleGroupForTerseUpdate() 2138 public void ScheduleGroupForTerseUpdate()
2006 { 2139 {
2007 lock (m_parts) 2140 lockPartsForRead(true);
2008 { 2141 {
2009 foreach (SceneObjectPart part in m_parts.Values) 2142 foreach (SceneObjectPart part in m_parts.Values)
2010 { 2143 {
2144
2011 part.ScheduleTerseUpdate(); 2145 part.ScheduleTerseUpdate();
2146
2012 } 2147 }
2013 } 2148 }
2149 lockPartsForRead(false);
2014 } 2150 }
2015 2151
2016 /// <summary> 2152 /// <summary>
@@ -2023,14 +2159,17 @@ namespace OpenSim.Region.Framework.Scenes
2023 2159
2024 RootPart.SendFullUpdateToAllClients(); 2160 RootPart.SendFullUpdateToAllClients();
2025 2161
2026 lock (m_parts) 2162 lockPartsForRead(true);
2027 { 2163 {
2028 foreach (SceneObjectPart part in m_parts.Values) 2164 foreach (SceneObjectPart part in m_parts.Values)
2029 { 2165 {
2166
2030 if (part != RootPart) 2167 if (part != RootPart)
2031 part.SendFullUpdateToAllClients(); 2168 part.SendFullUpdateToAllClients();
2169
2032 } 2170 }
2033 } 2171 }
2172 lockPartsForRead(false);
2034 } 2173 }
2035 2174
2036 /// <summary> 2175 /// <summary>
@@ -2061,14 +2200,15 @@ namespace OpenSim.Region.Framework.Scenes
2061 { 2200 {
2062 if (IsDeleted) 2201 if (IsDeleted)
2063 return; 2202 return;
2064 2203
2065 lock (m_parts) 2204 lockPartsForRead(true);
2066 { 2205 {
2067 foreach (SceneObjectPart part in m_parts.Values) 2206 foreach (SceneObjectPart part in m_parts.Values)
2068 { 2207 {
2069 part.SendTerseUpdateToAllClients(); 2208 part.SendTerseUpdateToAllClients();
2070 } 2209 }
2071 } 2210 }
2211 lockPartsForRead(false);
2072 } 2212 }
2073 2213
2074 #endregion 2214 #endregion
@@ -2082,16 +2222,18 @@ namespace OpenSim.Region.Framework.Scenes
2082 /// <returns>null if no child part with that linknum or child part</returns> 2222 /// <returns>null if no child part with that linknum or child part</returns>
2083 public SceneObjectPart GetLinkNumPart(int linknum) 2223 public SceneObjectPart GetLinkNumPart(int linknum)
2084 { 2224 {
2085 lock (m_parts) 2225 lockPartsForRead(true);
2086 { 2226 {
2087 foreach (SceneObjectPart part in m_parts.Values) 2227 foreach (SceneObjectPart part in m_parts.Values)
2088 { 2228 {
2089 if (part.LinkNum == linknum) 2229 if (part.LinkNum == linknum)
2090 { 2230 {
2231 lockPartsForRead(false);
2091 return part; 2232 return part;
2092 } 2233 }
2093 } 2234 }
2094 } 2235 }
2236 lockPartsForRead(false);
2095 2237
2096 return null; 2238 return null;
2097 } 2239 }
@@ -2119,17 +2261,19 @@ namespace OpenSim.Region.Framework.Scenes
2119 public SceneObjectPart GetChildPart(uint localID) 2261 public SceneObjectPart GetChildPart(uint localID)
2120 { 2262 {
2121 //m_log.DebugFormat("Entered looking for {0}", localID); 2263 //m_log.DebugFormat("Entered looking for {0}", localID);
2122 lock (m_parts) 2264 lockPartsForRead(true);
2123 { 2265 {
2124 foreach (SceneObjectPart part in m_parts.Values) 2266 foreach (SceneObjectPart part in m_parts.Values)
2125 { 2267 {
2126 //m_log.DebugFormat("Found {0}", part.LocalId); 2268 //m_log.DebugFormat("Found {0}", part.LocalId);
2127 if (part.LocalId == localID) 2269 if (part.LocalId == localID)
2128 { 2270 {
2271 lockPartsForRead(false);
2129 return part; 2272 return part;
2130 } 2273 }
2131 } 2274 }
2132 } 2275 }
2276 lockPartsForRead(false);
2133 2277
2134 return null; 2278 return null;
2135 } 2279 }
@@ -2159,17 +2303,19 @@ namespace OpenSim.Region.Framework.Scenes
2159 public bool HasChildPrim(uint localID) 2303 public bool HasChildPrim(uint localID)
2160 { 2304 {
2161 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID); 2305 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID);
2162 lock (m_parts) 2306 lockPartsForRead(true);
2163 { 2307 {
2164 foreach (SceneObjectPart part in m_parts.Values) 2308 foreach (SceneObjectPart part in m_parts.Values)
2165 { 2309 {
2166 //m_log.DebugFormat("Found {0}", part.LocalId); 2310 //m_log.DebugFormat("Found {0}", part.LocalId);
2167 if (part.LocalId == localID) 2311 if (part.LocalId == localID)
2168 { 2312 {
2313 lockPartsForRead(false);
2169 return true; 2314 return true;
2170 } 2315 }
2171 } 2316 }
2172 } 2317 }
2318 lockPartsForRead(false);
2173 2319
2174 return false; 2320 return false;
2175 } 2321 }
@@ -2219,53 +2365,57 @@ namespace OpenSim.Region.Framework.Scenes
2219 if (m_rootPart.LinkNum == 0) 2365 if (m_rootPart.LinkNum == 0)
2220 m_rootPart.LinkNum = 1; 2366 m_rootPart.LinkNum = 1;
2221 2367
2222 lock (m_parts) 2368 lockPartsForWrite(true);
2223 { 2369
2224 m_parts.Add(linkPart.UUID, linkPart); 2370 m_parts.Add(linkPart.UUID, linkPart);
2225 2371
2226 // Insert in terms of link numbers, the new links 2372 lockPartsForWrite(false);
2227 // before the current ones (with the exception of 2373
2228 // the root prim. Shuffle the old ones up 2374 // Insert in terms of link numbers, the new links
2229 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts) 2375 // before the current ones (with the exception of
2376 // the root prim. Shuffle the old ones up
2377 lockPartsForRead(true);
2378 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts)
2379 {
2380 if (kvp.Value.LinkNum != 1)
2230 { 2381 {
2231 if (kvp.Value.LinkNum != 1) 2382 // Don't update root prim link number
2232 { 2383 kvp.Value.LinkNum += objectGroup.PrimCount;
2233 // Don't update root prim link number
2234 kvp.Value.LinkNum += objectGroup.PrimCount;
2235 }
2236 } 2384 }
2385 }
2386 lockPartsForRead(false);
2237 2387
2238 linkPart.LinkNum = 2; 2388 linkPart.LinkNum = 2;
2239 2389
2240 linkPart.SetParent(this); 2390 linkPart.SetParent(this);
2241 linkPart.AddFlag(PrimFlags.CreateSelected); 2391 linkPart.AddFlag(PrimFlags.CreateSelected);
2242 2392
2243 //if (linkPart.PhysActor != null) 2393 //if (linkPart.PhysActor != null)
2244 //{ 2394 //{
2245 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); 2395 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
2246 2396
2247 //linkPart.PhysActor = null; 2397 //linkPart.PhysActor = null;
2248 //} 2398 //}
2249 2399
2250 //TODO: rest of parts 2400 //TODO: rest of parts
2251 int linkNum = 3; 2401 int linkNum = 3;
2252 foreach (SceneObjectPart part in objectGroup.Children.Values) 2402 foreach (SceneObjectPart part in objectGroup.Children.Values)
2403 {
2404 if (part.UUID != objectGroup.m_rootPart.UUID)
2253 { 2405 {
2254 if (part.UUID != objectGroup.m_rootPart.UUID) 2406 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2255 {
2256 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2257 }
2258 part.ClearUndoState();
2259 } 2407 }
2408 part.ClearUndoState();
2260 } 2409 }
2261 2410
2262 m_scene.UnlinkSceneObject(objectGroup.UUID, true); 2411 m_scene.UnlinkSceneObject(objectGroup.UUID, true);
2263 objectGroup.m_isDeleted = true; 2412 objectGroup.m_isDeleted = true;
2413
2414 objectGroup.lockPartsForWrite(true);
2264 2415
2265 lock (objectGroup.m_parts) 2416 objectGroup.m_parts.Clear();
2266 { 2417
2267 objectGroup.m_parts.Clear(); 2418 objectGroup.lockPartsForWrite(false);
2268 }
2269 2419
2270 // Can't do this yet since backup still makes use of the root part without any synchronization 2420 // Can't do this yet since backup still makes use of the root part without any synchronization
2271// objectGroup.m_rootPart = null; 2421// objectGroup.m_rootPart = null;
@@ -2324,11 +2474,12 @@ namespace OpenSim.Region.Framework.Scenes
2324 Quaternion worldRot = linkPart.GetWorldRotation(); 2474 Quaternion worldRot = linkPart.GetWorldRotation();
2325 2475
2326 // Remove the part from this object 2476 // Remove the part from this object
2327 lock (m_parts) 2477 lockPartsForWrite(true);
2328 { 2478 {
2329 m_parts.Remove(linkPart.UUID); 2479 m_parts.Remove(linkPart.UUID);
2330 } 2480 }
2331 2481 lockPartsForWrite(false);
2482 lockPartsForRead(true);
2332 if (m_parts.Count == 1 && RootPart != null) //Single prim is left 2483 if (m_parts.Count == 1 && RootPart != null) //Single prim is left
2333 RootPart.LinkNum = 0; 2484 RootPart.LinkNum = 0;
2334 else 2485 else
@@ -2339,6 +2490,7 @@ namespace OpenSim.Region.Framework.Scenes
2339 p.LinkNum--; 2490 p.LinkNum--;
2340 } 2491 }
2341 } 2492 }
2493 lockPartsForRead(false);
2342 2494
2343 linkPart.ParentID = 0; 2495 linkPart.ParentID = 0;
2344 linkPart.LinkNum = 0; 2496 linkPart.LinkNum = 0;
@@ -2656,9 +2808,12 @@ namespace OpenSim.Region.Framework.Scenes
2656 2808
2657 if (selectionPart != null) 2809 if (selectionPart != null)
2658 { 2810 {
2659 lock (m_parts) 2811 lockPartsForRead(true);
2812 List<SceneObjectPart> parts = new List<SceneObjectPart>(m_parts.Values);
2813 lockPartsForRead(false);
2814 foreach (SceneObjectPart part in parts)
2660 { 2815 {
2661 foreach (SceneObjectPart part in m_parts.Values) 2816 if (part.Scale.X > 10.0 || part.Scale.Y > 10.0 || part.Scale.Z > 10.0)
2662 { 2817 {
2663 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax || 2818 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax ||
2664 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax || 2819 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax ||
@@ -2668,12 +2823,13 @@ namespace OpenSim.Region.Framework.Scenes
2668 break; 2823 break;
2669 } 2824 }
2670 } 2825 }
2826 }
2671 2827
2672 foreach (SceneObjectPart part in m_parts.Values) 2828 foreach (SceneObjectPart part in parts)
2673 { 2829 {
2674 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect); 2830 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
2675 }
2676 } 2831 }
2832
2677 } 2833 }
2678 } 2834 }
2679 2835
@@ -2759,11 +2915,9 @@ namespace OpenSim.Region.Framework.Scenes
2759 scale.Y = m_scene.m_maxNonphys; 2915 scale.Y = m_scene.m_maxNonphys;
2760 if (scale.Z > m_scene.m_maxNonphys) 2916 if (scale.Z > m_scene.m_maxNonphys)
2761 scale.Z = m_scene.m_maxNonphys; 2917 scale.Z = m_scene.m_maxNonphys;
2762
2763 SceneObjectPart part = GetChildPart(localID); 2918 SceneObjectPart part = GetChildPart(localID);
2764 if (part != null) 2919 if (part != null)
2765 { 2920 {
2766 part.Resize(scale);
2767 if (part.PhysActor != null) 2921 if (part.PhysActor != null)
2768 { 2922 {
2769 if (part.PhysActor.IsPhysical) 2923 if (part.PhysActor.IsPhysical)
@@ -2778,7 +2932,7 @@ namespace OpenSim.Region.Framework.Scenes
2778 part.PhysActor.Size = scale; 2932 part.PhysActor.Size = scale;
2779 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); 2933 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
2780 } 2934 }
2781 //if (part.UUID != m_rootPart.UUID) 2935 part.Resize(scale);
2782 2936
2783 HasGroupChanged = true; 2937 HasGroupChanged = true;
2784 ScheduleGroupForFullUpdate(); 2938 ScheduleGroupForFullUpdate();
@@ -2819,77 +2973,76 @@ namespace OpenSim.Region.Framework.Scenes
2819 float y = (scale.Y / part.Scale.Y); 2973 float y = (scale.Y / part.Scale.Y);
2820 float z = (scale.Z / part.Scale.Z); 2974 float z = (scale.Z / part.Scale.Z);
2821 2975
2822 lock (m_parts) 2976 lockPartsForRead(true);
2977 if (x > 1.0f || y > 1.0f || z > 1.0f)
2823 { 2978 {
2824 if (x > 1.0f || y > 1.0f || z > 1.0f) 2979 foreach (SceneObjectPart obPart in m_parts.Values)
2825 { 2980 {
2826 foreach (SceneObjectPart obPart in m_parts.Values) 2981 if (obPart.UUID != m_rootPart.UUID)
2827 { 2982 {
2828 if (obPart.UUID != m_rootPart.UUID) 2983 Vector3 oldSize = new Vector3(obPart.Scale);
2829 {
2830 Vector3 oldSize = new Vector3(obPart.Scale);
2831 2984
2832 float f = 1.0f; 2985 float f = 1.0f;
2833 float a = 1.0f; 2986 float a = 1.0f;
2834 2987
2835 if (part.PhysActor != null && part.PhysActor.IsPhysical) 2988 if (part.PhysActor != null && part.PhysActor.IsPhysical)
2989 {
2990 if (oldSize.X*x > m_scene.m_maxPhys)
2836 { 2991 {
2837 if (oldSize.X*x > m_scene.m_maxPhys) 2992 f = m_scene.m_maxPhys / oldSize.X;
2838 { 2993 a = f / x;
2839 f = m_scene.m_maxPhys / oldSize.X; 2994 x *= a;
2840 a = f / x; 2995 y *= a;
2841 x *= a; 2996 z *= a;
2842 y *= a;
2843 z *= a;
2844 }
2845 if (oldSize.Y*y > m_scene.m_maxPhys)
2846 {
2847 f = m_scene.m_maxPhys / oldSize.Y;
2848 a = f / y;
2849 x *= a;
2850 y *= a;
2851 z *= a;
2852 }
2853 if (oldSize.Z*z > m_scene.m_maxPhys)
2854 {
2855 f = m_scene.m_maxPhys / oldSize.Z;
2856 a = f / z;
2857 x *= a;
2858 y *= a;
2859 z *= a;
2860 }
2861 } 2997 }
2862 else 2998 if (oldSize.Y*y > m_scene.m_maxPhys)
2999 {
3000 f = m_scene.m_maxPhys / oldSize.Y;
3001 a = f / y;
3002 x *= a;
3003 y *= a;
3004 z *= a;
3005 }
3006 if (oldSize.Z*z > m_scene.m_maxPhys)
3007 {
3008 f = m_scene.m_maxPhys / oldSize.Z;
3009 a = f / z;
3010 x *= a;
3011 y *= a;
3012 z *= a;
3013 }
3014 }
3015 else
3016 {
3017 if (oldSize.X*x > m_scene.m_maxNonphys)
3018 {
3019 f = m_scene.m_maxNonphys / oldSize.X;
3020 a = f / x;
3021 x *= a;
3022 y *= a;
3023 z *= a;
3024 }
3025 if (oldSize.Y*y > m_scene.m_maxNonphys)
3026 {
3027 f = m_scene.m_maxNonphys / oldSize.Y;
3028 a = f / y;
3029 x *= a;
3030 y *= a;
3031 z *= a;
3032 }
3033 if (oldSize.Z*z > m_scene.m_maxNonphys)
2863 { 3034 {
2864 if (oldSize.X*x > m_scene.m_maxNonphys) 3035 f = m_scene.m_maxNonphys / oldSize.Z;
2865 { 3036 a = f / z;
2866 f = m_scene.m_maxNonphys / oldSize.X; 3037 x *= a;
2867 a = f / x; 3038 y *= a;
2868 x *= a; 3039 z *= a;
2869 y *= a;
2870 z *= a;
2871 }
2872 if (oldSize.Y*y > m_scene.m_maxNonphys)
2873 {
2874 f = m_scene.m_maxNonphys / oldSize.Y;
2875 a = f / y;
2876 x *= a;
2877 y *= a;
2878 z *= a;
2879 }
2880 if (oldSize.Z*z > m_scene.m_maxNonphys)
2881 {
2882 f = m_scene.m_maxNonphys / oldSize.Z;
2883 a = f / z;
2884 x *= a;
2885 y *= a;
2886 z *= a;
2887 }
2888 } 3040 }
2889 } 3041 }
2890 } 3042 }
2891 } 3043 }
2892 } 3044 }
3045 lockPartsForRead(false);
2893 3046
2894 Vector3 prevScale = part.Scale; 3047 Vector3 prevScale = part.Scale;
2895 prevScale.X *= x; 3048 prevScale.X *= x;
@@ -2897,7 +3050,7 @@ namespace OpenSim.Region.Framework.Scenes
2897 prevScale.Z *= z; 3050 prevScale.Z *= z;
2898 part.Resize(prevScale); 3051 part.Resize(prevScale);
2899 3052
2900 lock (m_parts) 3053 lockPartsForRead(true);
2901 { 3054 {
2902 foreach (SceneObjectPart obPart in m_parts.Values) 3055 foreach (SceneObjectPart obPart in m_parts.Values)
2903 { 3056 {
@@ -2916,6 +3069,7 @@ namespace OpenSim.Region.Framework.Scenes
2916 } 3069 }
2917 } 3070 }
2918 } 3071 }
3072 lockPartsForRead(false);
2919 3073
2920 if (part.PhysActor != null) 3074 if (part.PhysActor != null)
2921 { 3075 {
@@ -2996,7 +3150,7 @@ namespace OpenSim.Region.Framework.Scenes
2996 axDiff *= Quaternion.Inverse(partRotation); 3150 axDiff *= Quaternion.Inverse(partRotation);
2997 diff = axDiff; 3151 diff = axDiff;
2998 3152
2999 lock (m_parts) 3153 lockPartsForRead(true);
3000 { 3154 {
3001 foreach (SceneObjectPart obPart in m_parts.Values) 3155 foreach (SceneObjectPart obPart in m_parts.Values)
3002 { 3156 {
@@ -3006,6 +3160,7 @@ namespace OpenSim.Region.Framework.Scenes
3006 } 3160 }
3007 } 3161 }
3008 } 3162 }
3163 lockPartsForRead(false);
3009 3164
3010 AbsolutePosition = newPos; 3165 AbsolutePosition = newPos;
3011 3166
@@ -3123,7 +3278,7 @@ namespace OpenSim.Region.Framework.Scenes
3123 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); 3278 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
3124 } 3279 }
3125 3280
3126 lock (m_parts) 3281 lockPartsForRead(true);
3127 { 3282 {
3128 foreach (SceneObjectPart prim in m_parts.Values) 3283 foreach (SceneObjectPart prim in m_parts.Values)
3129 { 3284 {
@@ -3141,6 +3296,7 @@ namespace OpenSim.Region.Framework.Scenes
3141 } 3296 }
3142 } 3297 }
3143 } 3298 }
3299 lockPartsForRead(false);
3144 3300
3145 m_rootPart.ScheduleTerseUpdate(); 3301 m_rootPart.ScheduleTerseUpdate();
3146 } 3302 }
@@ -3263,7 +3419,7 @@ namespace OpenSim.Region.Framework.Scenes
3263 if (atTargets.Count > 0) 3419 if (atTargets.Count > 0)
3264 { 3420 {
3265 uint[] localids = new uint[0]; 3421 uint[] localids = new uint[0];
3266 lock (m_parts) 3422 lockPartsForRead(true);
3267 { 3423 {
3268 localids = new uint[m_parts.Count]; 3424 localids = new uint[m_parts.Count];
3269 int cntr = 0; 3425 int cntr = 0;
@@ -3273,6 +3429,7 @@ namespace OpenSim.Region.Framework.Scenes
3273 cntr++; 3429 cntr++;
3274 } 3430 }
3275 } 3431 }
3432 lockPartsForRead(false);
3276 3433
3277 for (int ctr = 0; ctr < localids.Length; ctr++) 3434 for (int ctr = 0; ctr < localids.Length; ctr++)
3278 { 3435 {
@@ -3291,7 +3448,7 @@ namespace OpenSim.Region.Framework.Scenes
3291 { 3448 {
3292 //trigger not_at_target 3449 //trigger not_at_target
3293 uint[] localids = new uint[0]; 3450 uint[] localids = new uint[0];
3294 lock (m_parts) 3451 lockPartsForRead(true);
3295 { 3452 {
3296 localids = new uint[m_parts.Count]; 3453 localids = new uint[m_parts.Count];
3297 int cntr = 0; 3454 int cntr = 0;
@@ -3301,7 +3458,8 @@ namespace OpenSim.Region.Framework.Scenes
3301 cntr++; 3458 cntr++;
3302 } 3459 }
3303 } 3460 }
3304 3461 lockPartsForRead(false);
3462
3305 for (int ctr = 0; ctr < localids.Length; ctr++) 3463 for (int ctr = 0; ctr < localids.Length; ctr++)
3306 { 3464 {
3307 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]); 3465 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]);
@@ -3393,19 +3551,20 @@ namespace OpenSim.Region.Framework.Scenes
3393 public float GetMass() 3551 public float GetMass()
3394 { 3552 {
3395 float retmass = 0f; 3553 float retmass = 0f;
3396 lock (m_parts) 3554 lockPartsForRead(true);
3397 { 3555 {
3398 foreach (SceneObjectPart part in m_parts.Values) 3556 foreach (SceneObjectPart part in m_parts.Values)
3399 { 3557 {
3400 retmass += part.GetMass(); 3558 retmass += part.GetMass();
3401 } 3559 }
3402 } 3560 }
3561 lockPartsForRead(false);
3403 return retmass; 3562 return retmass;
3404 } 3563 }
3405 3564
3406 public void CheckSculptAndLoad() 3565 public void CheckSculptAndLoad()
3407 { 3566 {
3408 lock (m_parts) 3567 lockPartsForRead(true);
3409 { 3568 {
3410 if (!IsDeleted) 3569 if (!IsDeleted)
3411 { 3570 {
@@ -3430,6 +3589,7 @@ namespace OpenSim.Region.Framework.Scenes
3430 } 3589 }
3431 } 3590 }
3432 } 3591 }
3592 lockPartsForRead(false);
3433 } 3593 }
3434 3594
3435 protected void AssetReceived(string id, Object sender, AssetBase asset) 3595 protected void AssetReceived(string id, Object sender, AssetBase asset)
@@ -3450,7 +3610,7 @@ namespace OpenSim.Region.Framework.Scenes
3450 /// <param name="client"></param> 3610 /// <param name="client"></param>
3451 public void SetGroup(UUID GroupID, IClientAPI client) 3611 public void SetGroup(UUID GroupID, IClientAPI client)
3452 { 3612 {
3453 lock (m_parts) 3613 lockPartsForRead(true);
3454 { 3614 {
3455 foreach (SceneObjectPart part in m_parts.Values) 3615 foreach (SceneObjectPart part in m_parts.Values)
3456 { 3616 {
@@ -3460,7 +3620,7 @@ namespace OpenSim.Region.Framework.Scenes
3460 3620
3461 HasGroupChanged = true; 3621 HasGroupChanged = true;
3462 } 3622 }
3463 3623 lockPartsForRead(false);
3464 ScheduleGroupForFullUpdate(); 3624 ScheduleGroupForFullUpdate();
3465 } 3625 }
3466 3626
@@ -3479,11 +3639,12 @@ namespace OpenSim.Region.Framework.Scenes
3479 3639
3480 public void SetAttachmentPoint(byte point) 3640 public void SetAttachmentPoint(byte point)
3481 { 3641 {
3482 lock (m_parts) 3642 lockPartsForRead(true);
3483 { 3643 {
3484 foreach (SceneObjectPart part in m_parts.Values) 3644 foreach (SceneObjectPart part in m_parts.Values)
3485 part.SetAttachmentPoint(point); 3645 part.SetAttachmentPoint(point);
3486 } 3646 }
3647 lockPartsForRead(false);
3487 } 3648 }
3488 3649
3489 #region ISceneObject 3650 #region ISceneObject
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 56b2f13..a7c14cf 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -224,6 +224,7 @@ namespace OpenSim.Region.Framework.Scenes
224 private Quaternion m_sitTargetOrientation = Quaternion.Identity; 224 private Quaternion m_sitTargetOrientation = Quaternion.Identity;
225 private Vector3 m_sitTargetPosition; 225 private Vector3 m_sitTargetPosition;
226 private string m_sitAnimation = "SIT"; 226 private string m_sitAnimation = "SIT";
227 private bool m_occupied; // KF if any av is sitting on this prim
227 private string m_text = String.Empty; 228 private string m_text = String.Empty;
228 private string m_touchName = String.Empty; 229 private string m_touchName = String.Empty;
229 private readonly UndoStack<UndoState> m_undo = new UndoStack<UndoState>(5); 230 private readonly UndoStack<UndoState> m_undo = new UndoStack<UndoState>(5);
@@ -401,12 +402,16 @@ namespace OpenSim.Region.Framework.Scenes
401 } 402 }
402 403
403 /// <value> 404 /// <value>
404 /// Access should be via Inventory directly - this property temporarily remains for xml serialization purposes 405 /// Get the inventory list
405 /// </value> 406 /// </value>
406 public TaskInventoryDictionary TaskInventory 407 public TaskInventoryDictionary TaskInventory
407 { 408 {
408 get { return m_inventory.Items; } 409 get {
409 set { m_inventory.Items = value; } 410 return m_inventory.Items;
411 }
412 set {
413 m_inventory.Items = value;
414 }
410 } 415 }
411 416
412 public uint ObjectFlags 417 public uint ObjectFlags
@@ -550,7 +555,6 @@ namespace OpenSim.Region.Framework.Scenes
550 StoreUndoState(); 555 StoreUndoState();
551 556
552 m_groupPosition = value; 557 m_groupPosition = value;
553
554 PhysicsActor actor = PhysActor; 558 PhysicsActor actor = PhysActor;
555 if (actor != null) 559 if (actor != null)
556 { 560 {
@@ -860,7 +864,8 @@ namespace OpenSim.Region.Framework.Scenes
860 if (IsAttachment) 864 if (IsAttachment)
861 return GroupPosition; 865 return GroupPosition;
862 866
863 return m_offsetPosition + m_groupPosition; } 867// return m_offsetPosition + m_groupPosition; }
868 return m_groupPosition + (m_offsetPosition * ParentGroup.RootPart.RotationOffset) ; } //KF: Rotation was ignored!
864 } 869 }
865 870
866 public SceneObjectGroup ParentGroup 871 public SceneObjectGroup ParentGroup
@@ -1012,6 +1017,13 @@ namespace OpenSim.Region.Framework.Scenes
1012 get { return _flags; } 1017 get { return _flags; }
1013 set { _flags = value; } 1018 set { _flags = value; }
1014 } 1019 }
1020
1021 [XmlIgnore]
1022 public bool IsOccupied // KF If an av is sittingon this prim
1023 {
1024 get { return m_occupied; }
1025 set { m_occupied = value; }
1026 }
1015 1027
1016 [XmlIgnore] 1028 [XmlIgnore]
1017 public UUID SitTargetAvatar 1029 public UUID SitTargetAvatar
@@ -1087,14 +1099,6 @@ namespace OpenSim.Region.Framework.Scenes
1087 } 1099 }
1088 } 1100 }
1089 1101
1090 /// <summary>
1091 /// Clear all pending updates of parts to clients
1092 /// </summary>
1093 private void ClearUpdateSchedule()
1094 {
1095 m_updateFlag = 0;
1096 }
1097
1098 private void SendObjectPropertiesToClient(UUID AgentID) 1102 private void SendObjectPropertiesToClient(UUID AgentID)
1099 { 1103 {
1100 ScenePresence[] avatars = m_parentGroup.Scene.GetScenePresences(); 1104 ScenePresence[] avatars = m_parentGroup.Scene.GetScenePresences();
@@ -1773,12 +1777,17 @@ namespace OpenSim.Region.Framework.Scenes
1773 public Vector3 GetWorldPosition() 1777 public Vector3 GetWorldPosition()
1774 { 1778 {
1775 Quaternion parentRot = ParentGroup.RootPart.RotationOffset; 1779 Quaternion parentRot = ParentGroup.RootPart.RotationOffset;
1776
1777 Vector3 axPos = OffsetPosition; 1780 Vector3 axPos = OffsetPosition;
1778
1779 axPos *= parentRot; 1781 axPos *= parentRot;
1780 Vector3 translationOffsetPosition = axPos; 1782 Vector3 translationOffsetPosition = axPos;
1781 return GroupPosition + translationOffsetPosition; 1783 if(_parentID == 0)
1784 {
1785 return GroupPosition;
1786 }
1787 else
1788 {
1789 return ParentGroup.AbsolutePosition + translationOffsetPosition; //KF: Fix child prim position
1790 }
1782 } 1791 }
1783 1792
1784 /// <summary> 1793 /// <summary>
@@ -1789,7 +1798,7 @@ namespace OpenSim.Region.Framework.Scenes
1789 { 1798 {
1790 Quaternion newRot; 1799 Quaternion newRot;
1791 1800
1792 if (this.LinkNum == 0) 1801 if (this.LinkNum < 2) //KF Single or root prim
1793 { 1802 {
1794 newRot = RotationOffset; 1803 newRot = RotationOffset;
1795 } 1804 }
@@ -2446,17 +2455,18 @@ namespace OpenSim.Region.Framework.Scenes
2446 //Trys to fetch sound id from prim's inventory. 2455 //Trys to fetch sound id from prim's inventory.
2447 //Prim's inventory doesn't support non script items yet 2456 //Prim's inventory doesn't support non script items yet
2448 2457
2449 lock (TaskInventory) 2458 TaskInventory.LockItemsForRead(true);
2459
2460 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2450 { 2461 {
2451 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 2462 if (item.Value.Name == sound)
2452 { 2463 {
2453 if (item.Value.Name == sound) 2464 soundID = item.Value.ItemID;
2454 { 2465 break;
2455 soundID = item.Value.ItemID;
2456 break;
2457 }
2458 } 2466 }
2459 } 2467 }
2468
2469 TaskInventory.LockItemsForRead(false);
2460 } 2470 }
2461 2471
2462 List<ScenePresence> avatarts = m_parentGroup.Scene.GetAvatars(); 2472 List<ScenePresence> avatarts = m_parentGroup.Scene.GetAvatars();
@@ -2731,8 +2741,8 @@ namespace OpenSim.Region.Framework.Scenes
2731 { 2741 {
2732 const float ROTATION_TOLERANCE = 0.01f; 2742 const float ROTATION_TOLERANCE = 0.01f;
2733 const float VELOCITY_TOLERANCE = 0.001f; 2743 const float VELOCITY_TOLERANCE = 0.001f;
2734 const float POSITION_TOLERANCE = 0.05f; 2744 const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary
2735 const int TIME_MS_TOLERANCE = 3000; 2745 const int TIME_MS_TOLERANCE = 200; //llSetPos has a 200ms delay. This should NOT be 3 seconds.
2736 2746
2737 if (m_updateFlag == 1) 2747 if (m_updateFlag == 1)
2738 { 2748 {
@@ -2746,7 +2756,7 @@ namespace OpenSim.Region.Framework.Scenes
2746 Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE) 2756 Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE)
2747 { 2757 {
2748 AddTerseUpdateToAllAvatars(); 2758 AddTerseUpdateToAllAvatars();
2749 ClearUpdateSchedule(); 2759
2750 2760
2751 // This causes the Scene to 'poll' physical objects every couple of frames 2761 // This causes the Scene to 'poll' physical objects every couple of frames
2752 // bad, so it's been replaced by an event driven method. 2762 // bad, so it's been replaced by an event driven method.
@@ -2764,16 +2774,18 @@ namespace OpenSim.Region.Framework.Scenes
2764 m_lastAngularVelocity = AngularVelocity; 2774 m_lastAngularVelocity = AngularVelocity;
2765 m_lastTerseSent = Environment.TickCount; 2775 m_lastTerseSent = Environment.TickCount;
2766 } 2776 }
2777 //Moved this outside of the if clause so updates don't get blocked.. *sigh*
2778 m_updateFlag = 0; //Why were we calling a function to do this? Inefficient! *screams*
2767 } 2779 }
2768 else 2780 else
2769 { 2781 {
2770 if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes 2782 if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes
2771 { 2783 {
2772 AddFullUpdateToAllAvatars(); 2784 AddFullUpdateToAllAvatars();
2773 ClearUpdateSchedule(); 2785 m_updateFlag = 0; //Same here
2774 } 2786 }
2775 } 2787 }
2776 ClearUpdateSchedule(); 2788 m_updateFlag = 0;
2777 } 2789 }
2778 2790
2779 /// <summary> 2791 /// <summary>
@@ -2800,17 +2812,16 @@ namespace OpenSim.Region.Framework.Scenes
2800 if (!UUID.TryParse(sound, out soundID)) 2812 if (!UUID.TryParse(sound, out soundID))
2801 { 2813 {
2802 // search sound file from inventory 2814 // search sound file from inventory
2803 lock (TaskInventory) 2815 TaskInventory.LockItemsForRead(true);
2816 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2804 { 2817 {
2805 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 2818 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound)
2806 { 2819 {
2807 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound) 2820 soundID = item.Value.ItemID;
2808 { 2821 break;
2809 soundID = item.Value.ItemID;
2810 break;
2811 }
2812 } 2822 }
2813 } 2823 }
2824 TaskInventory.LockItemsForRead(false);
2814 } 2825 }
2815 2826
2816 if (soundID == UUID.Zero) 2827 if (soundID == UUID.Zero)
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index eb7f5ff..c3c6342 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
@@ -82,7 +82,9 @@ namespace OpenSim.Region.Framework.Scenes
82 /// </value> 82 /// </value>
83 protected internal TaskInventoryDictionary Items 83 protected internal TaskInventoryDictionary Items
84 { 84 {
85 get { return m_items; } 85 get {
86 return m_items;
87 }
86 set 88 set
87 { 89 {
88 m_items = value; 90 m_items = value;
@@ -118,22 +120,25 @@ namespace OpenSim.Region.Framework.Scenes
118 /// <param name="linkNum">Link number for the part</param> 120 /// <param name="linkNum">Link number for the part</param>
119 public void ResetInventoryIDs() 121 public void ResetInventoryIDs()
120 { 122 {
121 lock (Items) 123 m_items.LockItemsForWrite(true);
124
125 if (0 == Items.Count)
122 { 126 {
123 if (0 == Items.Count) 127 m_items.LockItemsForWrite(false);
124 return; 128 return;
129 }
125 130
126 HasInventoryChanged = true; 131 HasInventoryChanged = true;
127 m_part.ParentGroup.HasGroupChanged = true; 132 m_part.ParentGroup.HasGroupChanged = true;
128 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values); 133 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
129 Items.Clear(); 134 Items.Clear();
130 135
131 foreach (TaskInventoryItem item in items) 136 foreach (TaskInventoryItem item in items)
132 { 137 {
133 item.ResetIDs(m_part.UUID); 138 item.ResetIDs(m_part.UUID);
134 Items.Add(item.ItemID, item); 139 Items.Add(item.ItemID, item);
135 }
136 } 140 }
141 m_items.LockItemsForWrite(false);
137 } 142 }
138 143
139 /// <summary> 144 /// <summary>
@@ -142,25 +147,25 @@ namespace OpenSim.Region.Framework.Scenes
142 /// <param name="ownerId"></param> 147 /// <param name="ownerId"></param>
143 public void ChangeInventoryOwner(UUID ownerId) 148 public void ChangeInventoryOwner(UUID ownerId)
144 { 149 {
145 lock (Items) 150 m_items.LockItemsForWrite(true);
151 if (0 == Items.Count)
146 { 152 {
147 if (0 == Items.Count) 153 m_items.LockItemsForWrite(false);
148 { 154 return;
149 return; 155 }
150 }
151 156
152 HasInventoryChanged = true; 157 HasInventoryChanged = true;
153 m_part.ParentGroup.HasGroupChanged = true; 158 m_part.ParentGroup.HasGroupChanged = true;
154 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values); 159 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
155 foreach (TaskInventoryItem item in items) 160 foreach (TaskInventoryItem item in items)
161 {
162 if (ownerId != item.OwnerID)
156 { 163 {
157 if (ownerId != item.OwnerID) 164 item.LastOwnerID = item.OwnerID;
158 { 165 item.OwnerID = ownerId;
159 item.LastOwnerID = item.OwnerID;
160 item.OwnerID = ownerId;
161 }
162 } 166 }
163 } 167 }
168 m_items.LockItemsForWrite(false);
164 } 169 }
165 170
166 /// <summary> 171 /// <summary>
@@ -169,24 +174,24 @@ namespace OpenSim.Region.Framework.Scenes
169 /// <param name="groupID"></param> 174 /// <param name="groupID"></param>
170 public void ChangeInventoryGroup(UUID groupID) 175 public void ChangeInventoryGroup(UUID groupID)
171 { 176 {
172 lock (Items) 177 m_items.LockItemsForWrite(true);
178 if (0 == Items.Count)
173 { 179 {
174 if (0 == Items.Count) 180 m_items.LockItemsForWrite(false);
175 { 181 return;
176 return; 182 }
177 }
178 183
179 HasInventoryChanged = true; 184 HasInventoryChanged = true;
180 m_part.ParentGroup.HasGroupChanged = true; 185 m_part.ParentGroup.HasGroupChanged = true;
181 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values); 186 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
182 foreach (TaskInventoryItem item in items) 187 foreach (TaskInventoryItem item in items)
188 {
189 if (groupID != item.GroupID)
183 { 190 {
184 if (groupID != item.GroupID) 191 item.GroupID = groupID;
185 {
186 item.GroupID = groupID;
187 }
188 } 192 }
189 } 193 }
194 m_items.LockItemsForWrite(false);
190 } 195 }
191 196
192 /// <summary> 197 /// <summary>
@@ -194,14 +199,14 @@ namespace OpenSim.Region.Framework.Scenes
194 /// </summary> 199 /// </summary>
195 public void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource) 200 public void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource)
196 { 201 {
197 lock (m_items) 202 Items.LockItemsForRead(true);
203 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
204 Items.LockItemsForRead(false);
205 foreach (TaskInventoryItem item in items)
198 { 206 {
199 foreach (TaskInventoryItem item in Items.Values) 207 if ((int)InventoryType.LSL == item.InvType)
200 { 208 {
201 if ((int)InventoryType.LSL == item.InvType) 209 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource);
202 {
203 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource);
204 }
205 } 210 }
206 } 211 }
207 } 212 }
@@ -232,17 +237,20 @@ namespace OpenSim.Region.Framework.Scenes
232 /// </summary> 237 /// </summary>
233 public void RemoveScriptInstances() 238 public void RemoveScriptInstances()
234 { 239 {
235 lock (Items) 240 Items.LockItemsForRead(true);
241 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
242 Items.LockItemsForRead(false);
243
244 foreach (TaskInventoryItem item in items)
236 { 245 {
237 foreach (TaskInventoryItem item in Items.Values) 246 if ((int)InventoryType.LSL == item.InvType)
238 { 247 {
239 if ((int)InventoryType.LSL == item.InvType) 248 RemoveScriptInstance(item.ItemID);
240 { 249 m_part.RemoveScriptEvents(item.ItemID);
241 RemoveScriptInstance(item.ItemID);
242 m_part.RemoveScriptEvents(item.ItemID);
243 }
244 } 250 }
245 } 251 }
252
253
246 } 254 }
247 255
248 /// <summary> 256 /// <summary>
@@ -267,8 +275,10 @@ namespace OpenSim.Region.Framework.Scenes
267 if (stateSource == 1 && // Prim crossing 275 if (stateSource == 1 && // Prim crossing
268 m_part.ParentGroup.Scene.m_trustBinaries) 276 m_part.ParentGroup.Scene.m_trustBinaries)
269 { 277 {
278 m_items.LockItemsForWrite(true);
270 m_items[item.ItemID].PermsMask = 0; 279 m_items[item.ItemID].PermsMask = 0;
271 m_items[item.ItemID].PermsGranter = UUID.Zero; 280 m_items[item.ItemID].PermsGranter = UUID.Zero;
281 m_items.LockItemsForWrite(false);
272 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 282 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
273 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource); 283 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource);
274 m_part.ParentGroup.AddActiveScriptCount(1); 284 m_part.ParentGroup.AddActiveScriptCount(1);
@@ -290,8 +300,10 @@ namespace OpenSim.Region.Framework.Scenes
290 { 300 {
291 if (m_part.ParentGroup.m_savedScriptState != null) 301 if (m_part.ParentGroup.m_savedScriptState != null)
292 RestoreSavedScriptState(item.OldItemID, item.ItemID); 302 RestoreSavedScriptState(item.OldItemID, item.ItemID);
303 m_items.LockItemsForWrite(true);
293 m_items[item.ItemID].PermsMask = 0; 304 m_items[item.ItemID].PermsMask = 0;
294 m_items[item.ItemID].PermsGranter = UUID.Zero; 305 m_items[item.ItemID].PermsGranter = UUID.Zero;
306 m_items.LockItemsForWrite(false);
295 string script = Utils.BytesToString(asset.Data); 307 string script = Utils.BytesToString(asset.Data);
296 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 308 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
297 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource); 309 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource);
@@ -367,14 +379,17 @@ namespace OpenSim.Region.Framework.Scenes
367 /// </param> 379 /// </param>
368 public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource) 380 public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
369 { 381 {
370 lock (m_items) 382 m_items.LockItemsForRead(true);
383 if (m_items.ContainsKey(itemId))
371 { 384 {
372 if (m_items.ContainsKey(itemId)) 385 if (m_items.ContainsKey(itemId))
373 { 386 {
387 m_items.LockItemsForRead(false);
374 CreateScriptInstance(m_items[itemId], startParam, postOnRez, engine, stateSource); 388 CreateScriptInstance(m_items[itemId], startParam, postOnRez, engine, stateSource);
375 } 389 }
376 else 390 else
377 { 391 {
392 m_items.LockItemsForRead(false);
378 m_log.ErrorFormat( 393 m_log.ErrorFormat(
379 "[PRIM INVENTORY]: " + 394 "[PRIM INVENTORY]: " +
380 "Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}", 395 "Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}",
@@ -382,6 +397,15 @@ namespace OpenSim.Region.Framework.Scenes
382 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 397 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
383 } 398 }
384 } 399 }
400 else
401 {
402 m_items.LockItemsForRead(false);
403 m_log.ErrorFormat(
404 "[PRIM INVENTORY]: " +
405 "Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2}",
406 itemId, m_part.Name, m_part.UUID);
407 }
408
385 } 409 }
386 410
387 /// <summary> 411 /// <summary>
@@ -413,11 +437,16 @@ namespace OpenSim.Region.Framework.Scenes
413 /// <returns></returns> 437 /// <returns></returns>
414 private bool InventoryContainsName(string name) 438 private bool InventoryContainsName(string name)
415 { 439 {
416 foreach (TaskInventoryItem item in Items.Values) 440 m_items.LockItemsForRead(true);
441 foreach (TaskInventoryItem item in m_items.Values)
417 { 442 {
418 if (item.Name == name) 443 if (item.Name == name)
444 {
445 m_items.LockItemsForRead(false);
419 return true; 446 return true;
447 }
420 } 448 }
449 m_items.LockItemsForRead(false);
421 return false; 450 return false;
422 } 451 }
423 452
@@ -459,7 +488,9 @@ namespace OpenSim.Region.Framework.Scenes
459 /// <param name="item"></param> 488 /// <param name="item"></param>
460 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop) 489 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop)
461 { 490 {
491 m_items.LockItemsForRead(true);
462 List<TaskInventoryItem> il = new List<TaskInventoryItem>(m_items.Values); 492 List<TaskInventoryItem> il = new List<TaskInventoryItem>(m_items.Values);
493 m_items.LockItemsForRead(false);
463 foreach (TaskInventoryItem i in il) 494 foreach (TaskInventoryItem i in il)
464 { 495 {
465 if (i.Name == item.Name) 496 if (i.Name == item.Name)
@@ -496,15 +527,14 @@ namespace OpenSim.Region.Framework.Scenes
496 item.ParentPartID = m_part.UUID; 527 item.ParentPartID = m_part.UUID;
497 item.Name = name; 528 item.Name = name;
498 529
499 lock (m_items) 530 m_items.LockItemsForWrite(true);
500 { 531 m_items.Add(item.ItemID, item);
501 m_items.Add(item.ItemID, item); 532 m_items.LockItemsForWrite(false);
502
503 if (allowedDrop) 533 if (allowedDrop)
504 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP); 534 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP);
505 else 535 else
506 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 536 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
507 } 537
508 538
509 m_inventorySerial++; 539 m_inventorySerial++;
510 //m_inventorySerial += 2; 540 //m_inventorySerial += 2;
@@ -521,14 +551,13 @@ namespace OpenSim.Region.Framework.Scenes
521 /// <param name="items"></param> 551 /// <param name="items"></param>
522 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items) 552 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items)
523 { 553 {
524 lock (m_items) 554 m_items.LockItemsForWrite(true);
555 foreach (TaskInventoryItem item in items)
525 { 556 {
526 foreach (TaskInventoryItem item in items) 557 m_items.Add(item.ItemID, item);
527 { 558 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
528 m_items.Add(item.ItemID, item);
529 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
530 }
531 } 559 }
560 m_items.LockItemsForWrite(false);
532 561
533 m_inventorySerial++; 562 m_inventorySerial++;
534 } 563 }
@@ -541,8 +570,9 @@ namespace OpenSim.Region.Framework.Scenes
541 public TaskInventoryItem GetInventoryItem(UUID itemId) 570 public TaskInventoryItem GetInventoryItem(UUID itemId)
542 { 571 {
543 TaskInventoryItem item; 572 TaskInventoryItem item;
573 m_items.LockItemsForRead(true);
544 m_items.TryGetValue(itemId, out item); 574 m_items.TryGetValue(itemId, out item);
545 575 m_items.LockItemsForRead(false);
546 return item; 576 return item;
547 } 577 }
548 578
@@ -554,46 +584,46 @@ namespace OpenSim.Region.Framework.Scenes
554 /// <returns>false if the item did not exist, true if the update occurred successfully</returns> 584 /// <returns>false if the item did not exist, true if the update occurred successfully</returns>
555 public bool UpdateInventoryItem(TaskInventoryItem item) 585 public bool UpdateInventoryItem(TaskInventoryItem item)
556 { 586 {
557 lock (m_items) 587 m_items.LockItemsForWrite(true);
588
589 if (m_items.ContainsKey(item.ItemID))
558 { 590 {
559 if (m_items.ContainsKey(item.ItemID)) 591 item.ParentID = m_part.UUID;
592 item.ParentPartID = m_part.UUID;
593 item.Flags = m_items[item.ItemID].Flags;
594 if (item.AssetID == UUID.Zero)
560 { 595 {
561 item.ParentID = m_part.UUID; 596 item.AssetID = m_items[item.ItemID].AssetID;
562 item.ParentPartID = m_part.UUID; 597 }
563 item.Flags = m_items[item.ItemID].Flags; 598 else if ((InventoryType)item.Type == InventoryType.Notecard)
564 if (item.AssetID == UUID.Zero) 599 {
565 { 600 ScenePresence presence = m_part.ParentGroup.Scene.GetScenePresence(item.OwnerID);
566 item.AssetID = m_items[item.ItemID].AssetID;
567 }
568 else if ((InventoryType)item.Type == InventoryType.Notecard)
569 {
570 ScenePresence presence = m_part.ParentGroup.Scene.GetScenePresence(item.OwnerID);
571 601
572 if (presence != null) 602 if (presence != null)
573 { 603 {
574 presence.ControllingClient.SendAgentAlertMessage( 604 presence.ControllingClient.SendAgentAlertMessage(
575 "Notecard saved", false); 605 "Notecard saved", false);
576 }
577 } 606 }
607 }
578 608
579 m_items[item.ItemID] = item; 609 m_items[item.ItemID] = item;
580 m_inventorySerial++; 610 m_inventorySerial++;
581 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 611 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
582
583 HasInventoryChanged = true;
584 m_part.ParentGroup.HasGroupChanged = true;
585 612
586 return true; 613 HasInventoryChanged = true;
587 } 614 m_part.ParentGroup.HasGroupChanged = true;
588 else 615 m_items.LockItemsForWrite(false);
589 { 616 return true;
590 m_log.ErrorFormat( 617 }
591 "[PRIM INVENTORY]: " + 618 else
592 "Tried to retrieve item ID {0} from prim {1}, {2} at {3} in {4} but the item does not exist in this inventory", 619 {
593 item.ItemID, m_part.Name, m_part.UUID, 620 m_log.ErrorFormat(
594 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 621 "[PRIM INVENTORY]: " +
595 } 622 "Tried to retrieve item ID {0} from prim {1}, {2} at {3} in {4} but the item does not exist in this inventory",
623 item.ItemID, m_part.Name, m_part.UUID,
624 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
596 } 625 }
626 m_items.LockItemsForWrite(false);
597 627
598 return false; 628 return false;
599 } 629 }
@@ -606,52 +636,54 @@ namespace OpenSim.Region.Framework.Scenes
606 /// in this prim's inventory.</returns> 636 /// in this prim's inventory.</returns>
607 public int RemoveInventoryItem(UUID itemID) 637 public int RemoveInventoryItem(UUID itemID)
608 { 638 {
609 lock (m_items) 639 m_items.LockItemsForRead(true);
640
641 if (m_items.ContainsKey(itemID))
610 { 642 {
611 if (m_items.ContainsKey(itemID)) 643 int type = m_items[itemID].InvType;
644 m_items.LockItemsForRead(false);
645 if (type == 10) // Script
612 { 646 {
613 int type = m_items[itemID].InvType; 647 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID);
614 if (type == 10) // Script 648 }
615 { 649 m_items.LockItemsForWrite(true);
616 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID); 650 m_items.Remove(itemID);
617 } 651 m_items.LockItemsForWrite(false);
618 m_items.Remove(itemID); 652 m_inventorySerial++;
619 m_inventorySerial++; 653 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
620 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
621
622 HasInventoryChanged = true;
623 m_part.ParentGroup.HasGroupChanged = true;
624 654
625 int scriptcount = 0; 655 HasInventoryChanged = true;
626 lock (m_items) 656 m_part.ParentGroup.HasGroupChanged = true;
627 {
628 foreach (TaskInventoryItem item in m_items.Values)
629 {
630 if (item.Type == 10)
631 {
632 scriptcount++;
633 }
634 }
635 }
636 657
637 if (scriptcount <= 0) 658 int scriptcount = 0;
659 m_items.LockItemsForRead(true);
660 foreach (TaskInventoryItem item in m_items.Values)
661 {
662 if (item.Type == 10)
638 { 663 {
639 m_part.RemFlag(PrimFlags.Scripted); 664 scriptcount++;
640 } 665 }
641
642 m_part.ScheduleFullUpdate();
643
644 return type;
645 } 666 }
646 else 667 m_items.LockItemsForRead(false);
668
669
670 if (scriptcount <= 0)
647 { 671 {
648 m_log.ErrorFormat( 672 m_part.RemFlag(PrimFlags.Scripted);
649 "[PRIM INVENTORY]: " +
650 "Tried to remove item ID {0} from prim {1}, {2} at {3} in {4} but the item does not exist in this inventory",
651 itemID, m_part.Name, m_part.UUID,
652 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
653 } 673 }
674
675 m_part.ScheduleFullUpdate();
676
677 return type;
678 }
679 else
680 {
681 m_log.ErrorFormat(
682 "[PRIM INVENTORY]: " +
683 "Tried to remove item ID {0} from prim {1}, {2} but the item does not exist in this inventory",
684 itemID, m_part.Name, m_part.UUID);
654 } 685 }
686 m_items.LockItemsForWrite(false);
655 687
656 return -1; 688 return -1;
657 } 689 }
@@ -704,52 +736,53 @@ namespace OpenSim.Region.Framework.Scenes
704 // isn't available (such as drag from prim inventory to agent inventory) 736 // isn't available (such as drag from prim inventory to agent inventory)
705 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero); 737 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero);
706 738
707 lock (m_items) 739 m_items.LockItemsForRead(true);
740
741 foreach (TaskInventoryItem item in m_items.Values)
708 { 742 {
709 foreach (TaskInventoryItem item in m_items.Values) 743 UUID ownerID = item.OwnerID;
710 { 744 uint everyoneMask = 0;
711 UUID ownerID = item.OwnerID; 745 uint baseMask = item.BasePermissions;
712 uint everyoneMask = 0; 746 uint ownerMask = item.CurrentPermissions;
713 uint baseMask = item.BasePermissions;
714 uint ownerMask = item.CurrentPermissions;
715 747
716 invString.AddItemStart(); 748 invString.AddItemStart();
717 invString.AddNameValueLine("item_id", item.ItemID.ToString()); 749 invString.AddNameValueLine("item_id", item.ItemID.ToString());
718 invString.AddNameValueLine("parent_id", m_part.UUID.ToString()); 750 invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
719 751
720 invString.AddPermissionsStart(); 752 invString.AddPermissionsStart();
721 753
722 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask)); 754 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask));
723 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask)); 755 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask));
724 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(0)); 756 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(0));
725 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask)); 757 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask));
726 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions)); 758 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
727 759
728 invString.AddNameValueLine("creator_id", item.CreatorID.ToString()); 760 invString.AddNameValueLine("creator_id", item.CreatorID.ToString());
729 invString.AddNameValueLine("owner_id", ownerID.ToString()); 761 invString.AddNameValueLine("owner_id", ownerID.ToString());
730 762
731 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString()); 763 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString());
732 764
733 invString.AddNameValueLine("group_id", item.GroupID.ToString()); 765 invString.AddNameValueLine("group_id", item.GroupID.ToString());
734 invString.AddSectionEnd(); 766 invString.AddSectionEnd();
735 767
736 invString.AddNameValueLine("asset_id", item.AssetID.ToString()); 768 invString.AddNameValueLine("asset_id", item.AssetID.ToString());
737 invString.AddNameValueLine("type", TaskInventoryItem.Types[item.Type]); 769 invString.AddNameValueLine("type", TaskInventoryItem.Types[item.Type]);
738 invString.AddNameValueLine("inv_type", TaskInventoryItem.InvTypes[item.InvType]); 770 invString.AddNameValueLine("inv_type", TaskInventoryItem.InvTypes[item.InvType]);
739 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags)); 771 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags));
740 772
741 invString.AddSaleStart(); 773 invString.AddSaleStart();
742 invString.AddNameValueLine("sale_type", "not"); 774 invString.AddNameValueLine("sale_type", "not");
743 invString.AddNameValueLine("sale_price", "0"); 775 invString.AddNameValueLine("sale_price", "0");
744 invString.AddSectionEnd(); 776 invString.AddSectionEnd();
745 777
746 invString.AddNameValueLine("name", item.Name + "|"); 778 invString.AddNameValueLine("name", item.Name + "|");
747 invString.AddNameValueLine("desc", item.Description + "|"); 779 invString.AddNameValueLine("desc", item.Description + "|");
748 780
749 invString.AddNameValueLine("creation_date", item.CreationDate.ToString()); 781 invString.AddNameValueLine("creation_date", item.CreationDate.ToString());
750 invString.AddSectionEnd(); 782 invString.AddSectionEnd();
751 }
752 } 783 }
784 int count = m_items.Count;
785 m_items.LockItemsForRead(false);
753 786
754 fileData = Utils.StringToBytes(invString.BuildString); 787 fileData = Utils.StringToBytes(invString.BuildString);
755 788
@@ -770,10 +803,9 @@ namespace OpenSim.Region.Framework.Scenes
770 { 803 {
771 if (HasInventoryChanged) 804 if (HasInventoryChanged)
772 { 805 {
773 lock (Items) 806 Items.LockItemsForRead(true);
774 { 807 datastore.StorePrimInventory(m_part.UUID, Items.Values);
775 datastore.StorePrimInventory(m_part.UUID, Items.Values); 808 Items.LockItemsForRead(false);
776 }
777 809
778 HasInventoryChanged = false; 810 HasInventoryChanged = false;
779 } 811 }
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 8545425..f36c1a9 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
@@ -113,8 +115,11 @@ namespace OpenSim.Region.Framework.Scenes
113 public Vector3 lastKnownAllowedPosition; 115 public Vector3 lastKnownAllowedPosition;
114 public bool sentMessageAboutRestrictedParcelFlyingDown; 116 public bool sentMessageAboutRestrictedParcelFlyingDown;
115 public Vector4 CollisionPlane = Vector4.UnitW; 117 public Vector4 CollisionPlane = Vector4.UnitW;
116 118
117 private Vector3 m_lastPosition; 119 private Vector3 m_avInitialPos; // used to calculate unscripted sit rotation
120 private Vector3 m_avUnscriptedSitPos; // for non-scripted prims
121 private Vector3 m_lastPosition;
122 private Vector3 m_lastWorldPosition;
118 private Quaternion m_lastRotation; 123 private Quaternion m_lastRotation;
119 private Vector3 m_lastVelocity; 124 private Vector3 m_lastVelocity;
120 //private int m_lastTerseSent; 125 //private int m_lastTerseSent;
@@ -124,7 +129,6 @@ namespace OpenSim.Region.Framework.Scenes
124 private Vector3? m_forceToApply; 129 private Vector3? m_forceToApply;
125 private uint m_requestedSitTargetID; 130 private uint m_requestedSitTargetID;
126 private UUID m_requestedSitTargetUUID; 131 private UUID m_requestedSitTargetUUID;
127 public bool SitGround = false;
128 132
129 private SendCourseLocationsMethod m_sendCourseLocationsMethod; 133 private SendCourseLocationsMethod m_sendCourseLocationsMethod;
130 134
@@ -146,7 +150,6 @@ namespace OpenSim.Region.Framework.Scenes
146 private int m_perfMonMS; 150 private int m_perfMonMS;
147 151
148 private bool m_setAlwaysRun; 152 private bool m_setAlwaysRun;
149
150 private bool m_forceFly; 153 private bool m_forceFly;
151 private bool m_flyDisabled; 154 private bool m_flyDisabled;
152 155
@@ -170,7 +173,8 @@ namespace OpenSim.Region.Framework.Scenes
170 protected RegionInfo m_regionInfo; 173 protected RegionInfo m_regionInfo;
171 protected ulong crossingFromRegion; 174 protected ulong crossingFromRegion;
172 175
173 private readonly Vector3[] Dir_Vectors = new Vector3[9]; 176 private readonly Vector3[] Dir_Vectors = new Vector3[11];
177 private bool m_isNudging = false;
174 178
175 // Position of agent's camera in world (region cordinates) 179 // Position of agent's camera in world (region cordinates)
176 protected Vector3 m_CameraCenter; 180 protected Vector3 m_CameraCenter;
@@ -195,6 +199,7 @@ namespace OpenSim.Region.Framework.Scenes
195 private bool m_autopilotMoving; 199 private bool m_autopilotMoving;
196 private Vector3 m_autoPilotTarget; 200 private Vector3 m_autoPilotTarget;
197 private bool m_sitAtAutoTarget; 201 private bool m_sitAtAutoTarget;
202 private Vector3 m_initialSitTarget; //KF: First estimate of where to sit
198 203
199 private string m_nextSitAnimation = String.Empty; 204 private string m_nextSitAnimation = String.Empty;
200 205
@@ -205,6 +210,9 @@ namespace OpenSim.Region.Framework.Scenes
205 private bool m_followCamAuto; 210 private bool m_followCamAuto;
206 211
207 private int m_movementUpdateCount; 212 private int m_movementUpdateCount;
213 private int m_lastColCount = -1; //KF: Look for Collision chnages
214 private int m_updateCount = 0; //KF: Update Anims for a while
215 private static readonly int UPDATE_COUNT = 10; // how many frames to update for
208 216
209 private const int NumMovementsBetweenRayCast = 5; 217 private const int NumMovementsBetweenRayCast = 5;
210 218
@@ -235,7 +243,9 @@ namespace OpenSim.Region.Framework.Scenes
235 DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS, 243 DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS,
236 DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG, 244 DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG,
237 DIR_CONTROL_FLAG_FORWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS, 245 DIR_CONTROL_FLAG_FORWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS,
238 DIR_CONTROL_FLAG_BACKWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG, 246 DIR_CONTROL_FLAG_BACK_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG,
247 DIR_CONTROL_FLAG_LEFT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS,
248 DIR_CONTROL_FLAG_RIGHT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG,
239 DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG 249 DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG
240 } 250 }
241 251
@@ -661,10 +671,7 @@ namespace OpenSim.Region.Framework.Scenes
661 671
662 672
663 AdjustKnownSeeds(); 673 AdjustKnownSeeds();
664
665 // TODO: I think, this won't send anything, as we are still a child here...
666 Animator.TrySetMovementAnimation("STAND"); 674 Animator.TrySetMovementAnimation("STAND");
667
668 // we created a new ScenePresence (a new child agent) in a fresh region. 675 // we created a new ScenePresence (a new child agent) in a fresh region.
669 // Request info about all the (root) agents in this region 676 // Request info about all the (root) agents in this region
670 // Note: This won't send data *to* other clients in that region (children don't send) 677 // Note: This won't send data *to* other clients in that region (children don't send)
@@ -720,25 +727,47 @@ namespace OpenSim.Region.Framework.Scenes
720 Dir_Vectors[3] = -Vector3.UnitY; //RIGHT 727 Dir_Vectors[3] = -Vector3.UnitY; //RIGHT
721 Dir_Vectors[4] = Vector3.UnitZ; //UP 728 Dir_Vectors[4] = Vector3.UnitZ; //UP
722 Dir_Vectors[5] = -Vector3.UnitZ; //DOWN 729 Dir_Vectors[5] = -Vector3.UnitZ; //DOWN
723 Dir_Vectors[8] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge 730 Dir_Vectors[6] = new Vector3(0.5f, 0f, 0f); //FORWARD_NUDGE
724 Dir_Vectors[6] = Vector3.UnitX*2; //FORWARD 731 Dir_Vectors[7] = new Vector3(-0.5f, 0f, 0f); //BACK_NUDGE
725 Dir_Vectors[7] = -Vector3.UnitX; //BACK 732 Dir_Vectors[8] = new Vector3(0f, 0.5f, 0f); //LEFT_NUDGE
733 Dir_Vectors[9] = new Vector3(0f, -0.5f, 0f); //RIGHT_NUDGE
734 Dir_Vectors[10] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge
726 } 735 }
727 736
728 private Vector3[] GetWalkDirectionVectors() 737 private Vector3[] GetWalkDirectionVectors()
729 { 738 {
730 Vector3[] vector = new Vector3[9]; 739 Vector3[] vector = new Vector3[11];
731 vector[0] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD 740 vector[0] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD
732 vector[1] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK 741 vector[1] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK
733 vector[2] = Vector3.UnitY; //LEFT 742 vector[2] = Vector3.UnitY; //LEFT
734 vector[3] = -Vector3.UnitY; //RIGHT 743 vector[3] = -Vector3.UnitY; //RIGHT
735 vector[4] = new Vector3(m_CameraAtAxis.Z, 0f, m_CameraUpAxis.Z); //UP 744 vector[4] = new Vector3(m_CameraAtAxis.Z, 0f, m_CameraUpAxis.Z); //UP
736 vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN 745 vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN
737 vector[8] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_Nudge 746 vector[6] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD_NUDGE
738 vector[6] = (new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z) * 2); //FORWARD Nudge 747 vector[7] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK_NUDGE
739 vector[7] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK Nudge 748 vector[8] = Vector3.UnitY; //LEFT_NUDGE
749 vector[9] = -Vector3.UnitY; //RIGHT_NUDGE
750 vector[10] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_NUDGE
740 return vector; 751 return vector;
741 } 752 }
753
754 private bool[] GetDirectionIsNudge()
755 {
756 bool[] isNudge = new bool[11];
757 isNudge[0] = false; //FORWARD
758 isNudge[1] = false; //BACK
759 isNudge[2] = false; //LEFT
760 isNudge[3] = false; //RIGHT
761 isNudge[4] = false; //UP
762 isNudge[5] = false; //DOWN
763 isNudge[6] = true; //FORWARD_NUDGE
764 isNudge[7] = true; //BACK_NUDGE
765 isNudge[8] = true; //LEFT_NUDGE
766 isNudge[9] = true; //RIGHT_NUDGE
767 isNudge[10] = true; //DOWN_Nudge
768 return isNudge;
769 }
770
742 771
743 #endregion 772 #endregion
744 773
@@ -807,9 +836,24 @@ namespace OpenSim.Region.Framework.Scenes
807 { 836 {
808 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N); 837 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N);
809 pos.Y = crossedBorder.BorderLine.Z - 1; 838 pos.Y = crossedBorder.BorderLine.Z - 1;
839 }
840
841 //If they're TP'ing in or logging in, we haven't had time to add any known child regions yet.
842 //This has the unfortunate consequence that if somebody is TP'ing who is already a child agent,
843 //they'll bypass the landing point. But I can't think of any decent way of fixing this.
844 if (KnownChildRegionHandles.Count == 0)
845 {
846 ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y);
847 if (land != null)
848 {
849 //Don't restrict gods, estate managers, or land owners to the TP point. This behaviour mimics agni.
850 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero && m_godlevel < 200 && !m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid) && land.LandData.OwnerID != m_uuid)
851 {
852 pos = land.LandData.UserLocation;
853 }
854 }
810 } 855 }
811 856
812
813 if (pos.X < 0 || pos.Y < 0 || pos.Z < 0) 857 if (pos.X < 0 || pos.Y < 0 || pos.Z < 0)
814 { 858 {
815 Vector3 emergencyPos = new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 128); 859 Vector3 emergencyPos = new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 128);
@@ -944,9 +988,10 @@ namespace OpenSim.Region.Framework.Scenes
944 public void Teleport(Vector3 pos) 988 public void Teleport(Vector3 pos)
945 { 989 {
946 bool isFlying = false; 990 bool isFlying = false;
947 if (m_physicsActor != null)
948 isFlying = m_physicsActor.Flying;
949 991
992 if (m_physicsActor != null)
993 isFlying = m_physicsActor.Flying;
994
950 RemoveFromPhysicalScene(); 995 RemoveFromPhysicalScene();
951 Velocity = Vector3.Zero; 996 Velocity = Vector3.Zero;
952 AbsolutePosition = pos; 997 AbsolutePosition = pos;
@@ -957,7 +1002,8 @@ namespace OpenSim.Region.Framework.Scenes
957 SetHeight(m_appearance.AvatarHeight); 1002 SetHeight(m_appearance.AvatarHeight);
958 } 1003 }
959 1004
960 SendTerseUpdateToAllClients(); 1005 SendTerseUpdateToAllClients();
1006
961 } 1007 }
962 1008
963 public void TeleportWithMomentum(Vector3 pos) 1009 public void TeleportWithMomentum(Vector3 pos)
@@ -1002,7 +1048,9 @@ namespace OpenSim.Region.Framework.Scenes
1002 { 1048 {
1003 AbsolutePosition = AbsolutePosition + new Vector3(0f, 0f, (1.56f / 6f)); 1049 AbsolutePosition = AbsolutePosition + new Vector3(0f, 0f, (1.56f / 6f));
1004 } 1050 }
1005 1051
1052 m_updateCount = UPDATE_COUNT; //KF: Trigger Anim updates to catch falling anim.
1053
1006 ControllingClient.SendAvatarTerseUpdate(new SendAvatarTerseData(m_rootRegionHandle, (ushort)(m_scene.TimeDilation * ushort.MaxValue), LocalId, 1054 ControllingClient.SendAvatarTerseUpdate(new SendAvatarTerseData(m_rootRegionHandle, (ushort)(m_scene.TimeDilation * ushort.MaxValue), LocalId,
1007 AbsolutePosition, Velocity, Vector3.Zero, m_bodyRot, new Vector4(0,0,1,AbsolutePosition.Z - 0.5f), m_uuid, null, GetUpdatePriority(ControllingClient))); 1055 AbsolutePosition, Velocity, Vector3.Zero, m_bodyRot, new Vector4(0,0,1,AbsolutePosition.Z - 0.5f), m_uuid, null, GetUpdatePriority(ControllingClient)));
1008 } 1056 }
@@ -1237,7 +1285,6 @@ namespace OpenSim.Region.Framework.Scenes
1237 m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(m_CameraCenter - posAdjusted), Vector3.Distance(m_CameraCenter, posAdjusted) + 0.3f, RayCastCameraCallback); 1285 m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(m_CameraCenter - posAdjusted), Vector3.Distance(m_CameraCenter, posAdjusted) + 0.3f, RayCastCameraCallback);
1238 } 1286 }
1239 } 1287 }
1240
1241 lock (scriptedcontrols) 1288 lock (scriptedcontrols)
1242 { 1289 {
1243 if (scriptedcontrols.Count > 0) 1290 if (scriptedcontrols.Count > 0)
@@ -1252,12 +1299,8 @@ namespace OpenSim.Region.Framework.Scenes
1252 1299
1253 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0) 1300 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0)
1254 { 1301 {
1255 // TODO: This doesn't prevent the user from walking yet. 1302 m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick.
1256 // Setting parent ID would fix this, if we knew what value 1303 Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED");
1257 // to use. Or we could add a m_isSitting variable.
1258 //Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED");
1259 SitGround = true;
1260
1261 } 1304 }
1262 1305
1263 // In the future, these values might need to go global. 1306 // In the future, these values might need to go global.
@@ -1301,6 +1344,11 @@ namespace OpenSim.Region.Framework.Scenes
1301 update_rotation = true; 1344 update_rotation = true;
1302 } 1345 }
1303 1346
1347 //guilty until proven innocent..
1348 bool Nudging = true;
1349 //Basically, if there is at least one non-nudge control then we don't need
1350 //to worry about stopping the avatar
1351
1304 if (m_parentID == 0) 1352 if (m_parentID == 0)
1305 { 1353 {
1306 bool bAllowUpdateMoveToPosition = false; 1354 bool bAllowUpdateMoveToPosition = false;
@@ -1315,9 +1363,12 @@ namespace OpenSim.Region.Framework.Scenes
1315 else 1363 else
1316 dirVectors = Dir_Vectors; 1364 dirVectors = Dir_Vectors;
1317 1365
1318 // The fact that m_movementflag is a byte needs to be fixed 1366 bool[] isNudge = GetDirectionIsNudge();
1319 // it really should be a uint 1367
1320 uint nudgehack = 250; 1368
1369
1370
1371
1321 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS) 1372 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS)
1322 { 1373 {
1323 if (((uint)flags & (uint)DCF) != 0) 1374 if (((uint)flags & (uint)DCF) != 0)
@@ -1327,40 +1378,28 @@ namespace OpenSim.Region.Framework.Scenes
1327 try 1378 try
1328 { 1379 {
1329 agent_control_v3 += dirVectors[i]; 1380 agent_control_v3 += dirVectors[i];
1330 //m_log.DebugFormat("[Motion]: {0}, {1}",i, dirVectors[i]); 1381 if (isNudge[i] == false)
1382 {
1383 Nudging = false;
1384 }
1331 } 1385 }
1332 catch (IndexOutOfRangeException) 1386 catch (IndexOutOfRangeException)
1333 { 1387 {
1334 // Why did I get this? 1388 // Why did I get this?
1335 } 1389 }
1336 1390
1337 if ((m_movementflag & (byte)(uint)DCF) == 0) 1391 if ((m_movementflag & (uint)DCF) == 0)
1338 { 1392 {
1339 if (DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
1340 {
1341 m_movementflag |= (byte)nudgehack;
1342 }
1343 m_movementflag += (byte)(uint)DCF; 1393 m_movementflag += (byte)(uint)DCF;
1344 update_movementflag = true; 1394 update_movementflag = true;
1345 } 1395 }
1346 } 1396 }
1347 else 1397 else
1348 { 1398 {
1349 if ((m_movementflag & (byte)(uint)DCF) != 0 || 1399 if ((m_movementflag & (uint)DCF) != 0)
1350 ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
1351 && ((m_movementflag & (byte)nudgehack) == nudgehack))
1352 ) // This or is for Nudge forward
1353 { 1400 {
1354 m_movementflag -= ((byte)(uint)DCF); 1401 m_movementflag -= (byte)(uint)DCF;
1355
1356 update_movementflag = true; 1402 update_movementflag = true;
1357 /*
1358 if ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
1359 && ((m_movementflag & (byte)nudgehack) == nudgehack))
1360 {
1361 m_log.Debug("Removed Hack flag");
1362 }
1363 */
1364 } 1403 }
1365 else 1404 else
1366 { 1405 {
@@ -1404,6 +1443,9 @@ namespace OpenSim.Region.Framework.Scenes
1404 // Ignore z component of vector 1443 // Ignore z component of vector
1405 Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f); 1444 Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f);
1406 LocalVectorToTarget2D.Normalize(); 1445 LocalVectorToTarget2D.Normalize();
1446
1447 //We're not nudging
1448 Nudging = false;
1407 agent_control_v3 += LocalVectorToTarget2D; 1449 agent_control_v3 += LocalVectorToTarget2D;
1408 1450
1409 // update avatar movement flags. the avatar coordinate system is as follows: 1451 // update avatar movement flags. the avatar coordinate system is as follows:
@@ -1492,13 +1534,13 @@ namespace OpenSim.Region.Framework.Scenes
1492 // m_log.DebugFormat( 1534 // m_log.DebugFormat(
1493 // "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3); 1535 // "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3);
1494 1536
1495 AddNewMovement(agent_control_v3, q); 1537 AddNewMovement(agent_control_v3, q, Nudging);
1496 1538
1497 1539
1498 } 1540 }
1499 } 1541 }
1500 1542
1501 if (update_movementflag && ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) == 0) && (m_parentID == 0) && !SitGround) 1543 if (update_movementflag)
1502 Animator.UpdateMovementAnimations(); 1544 Animator.UpdateMovementAnimations();
1503 1545
1504 m_scene.EventManager.TriggerOnClientMovement(this); 1546 m_scene.EventManager.TriggerOnClientMovement(this);
@@ -1513,7 +1555,6 @@ namespace OpenSim.Region.Framework.Scenes
1513 m_sitAtAutoTarget = false; 1555 m_sitAtAutoTarget = false;
1514 PrimitiveBaseShape proxy = PrimitiveBaseShape.Default; 1556 PrimitiveBaseShape proxy = PrimitiveBaseShape.Default;
1515 //proxy.PCode = (byte)PCode.ParticleSystem; 1557 //proxy.PCode = (byte)PCode.ParticleSystem;
1516
1517 proxyObjectGroup = new SceneObjectGroup(UUID, Pos, Rotation, proxy); 1558 proxyObjectGroup = new SceneObjectGroup(UUID, Pos, Rotation, proxy);
1518 proxyObjectGroup.AttachToScene(m_scene); 1559 proxyObjectGroup.AttachToScene(m_scene);
1519 1560
@@ -1555,7 +1596,7 @@ namespace OpenSim.Region.Framework.Scenes
1555 } 1596 }
1556 m_moveToPositionInProgress = true; 1597 m_moveToPositionInProgress = true;
1557 m_moveToPositionTarget = new Vector3(locx, locy, locz); 1598 m_moveToPositionTarget = new Vector3(locx, locy, locz);
1558 } 1599 }
1559 catch (Exception ex) 1600 catch (Exception ex)
1560 { 1601 {
1561 //Why did I get this error? 1602 //Why did I get this error?
@@ -1577,7 +1618,7 @@ namespace OpenSim.Region.Framework.Scenes
1577 Velocity = Vector3.Zero; 1618 Velocity = Vector3.Zero;
1578 SendFullUpdateToAllClients(); 1619 SendFullUpdateToAllClients();
1579 1620
1580 //HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); 1621 HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); //KF ??
1581 } 1622 }
1582 //ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false); 1623 //ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false);
1583 m_requestedSitTargetUUID = UUID.Zero; 1624 m_requestedSitTargetUUID = UUID.Zero;
@@ -1610,55 +1651,84 @@ namespace OpenSim.Region.Framework.Scenes
1610 /// </summary> 1651 /// </summary>
1611 public void StandUp() 1652 public void StandUp()
1612 { 1653 {
1613 if (SitGround)
1614 SitGround = false;
1615
1616 if (m_parentID != 0) 1654 if (m_parentID != 0)
1617 { 1655 {
1618 m_log.Debug("StandupCode Executed");
1619 SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID); 1656 SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID);
1620 if (part != null) 1657 if (part != null)
1621 { 1658 {
1659 part.TaskInventory.LockItemsForRead(true);
1622 TaskInventoryDictionary taskIDict = part.TaskInventory; 1660 TaskInventoryDictionary taskIDict = part.TaskInventory;
1623 if (taskIDict != null) 1661 if (taskIDict != null)
1624 { 1662 {
1625 lock (taskIDict) 1663 foreach (UUID taskID in taskIDict.Keys)
1626 { 1664 {
1627 foreach (UUID taskID in taskIDict.Keys) 1665 UnRegisterControlEventsToScript(LocalId, taskID);
1628 { 1666 taskIDict[taskID].PermsMask &= ~(
1629 UnRegisterControlEventsToScript(LocalId, taskID); 1667 2048 | //PERMISSION_CONTROL_CAMERA
1630 taskIDict[taskID].PermsMask &= ~( 1668 4); // PERMISSION_TAKE_CONTROLS
1631 2048 | //PERMISSION_CONTROL_CAMERA
1632 4); // PERMISSION_TAKE_CONTROLS
1633 }
1634 } 1669 }
1635
1636 } 1670 }
1671 part.TaskInventory.LockItemsForRead(false);
1637 // Reset sit target. 1672 // Reset sit target.
1638 if (part.GetAvatarOnSitTarget() == UUID) 1673 if (part.GetAvatarOnSitTarget() == UUID)
1639 part.SetAvatarOnSitTarget(UUID.Zero); 1674 part.SetAvatarOnSitTarget(UUID.Zero);
1640
1641 m_parentPosition = part.GetWorldPosition(); 1675 m_parentPosition = part.GetWorldPosition();
1642 ControllingClient.SendClearFollowCamProperties(part.ParentUUID); 1676 ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
1643 } 1677 }
1644 1678 // part.GetWorldRotation() is the rotation of the object being sat on
1645 if (m_physicsActor == null) 1679 // Rotation is the sittiing Av's rotation
1646 { 1680
1647 AddToPhysicalScene(false); 1681 Quaternion partRot;
1682// if (part.LinkNum == 1)
1683// { // Root prim of linkset
1684// partRot = part.ParentGroup.RootPart.RotationOffset;
1685// }
1686// else
1687// { // single or child prim
1688
1689// }
1690 if (part == null) //CW: Part may be gone. llDie() for example.
1691 {
1692 partRot = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
1693 }
1694 else
1695 {
1696 partRot = part.GetWorldRotation();
1697 }
1698
1699 Quaternion partIRot = Quaternion.Inverse(partRot);
1700
1701 Quaternion avatarRot = Quaternion.Inverse(Quaternion.Inverse(Rotation) * partIRot); // world or. of the av
1702 Vector3 avStandUp = new Vector3(1.0f, 0f, 0f) * avatarRot; // 1M infront of av
1703
1704
1705 if (m_physicsActor == null)
1706 {
1707 AddToPhysicalScene(false);
1708 }
1709 //CW: If the part isn't null then we can set the current position
1710 if (part != null)
1711 {
1712 Vector3 avWorldStandUp = avStandUp + part.GetWorldPosition() + (m_pos * partRot); // + av sit offset!
1713 AbsolutePosition = avWorldStandUp; //KF: Fix stand up.
1714 part.IsOccupied = false;
1715 }
1716 else
1717 {
1718 //CW: Since the part doesn't exist, a coarse standup position isn't an issue
1719 AbsolutePosition = m_lastWorldPosition;
1648 } 1720 }
1649 1721
1650 m_pos += m_parentPosition + new Vector3(0.0f, 0.0f, 2.0f*m_sitAvatarHeight); 1722 m_parentPosition = Vector3.Zero;
1651 m_parentPosition = Vector3.Zero; 1723 m_parentID = 0;
1652
1653 m_parentID = 0;
1654 SendFullUpdateToAllClients(); 1724 SendFullUpdateToAllClients();
1655 m_requestedSitTargetID = 0; 1725 m_requestedSitTargetID = 0;
1726
1656 if ((m_physicsActor != null) && (m_avHeight > 0)) 1727 if ((m_physicsActor != null) && (m_avHeight > 0))
1657 { 1728 {
1658 SetHeight(m_avHeight); 1729 SetHeight(m_avHeight);
1659 } 1730 }
1660 } 1731 }
1661
1662 Animator.TrySetMovementAnimation("STAND"); 1732 Animator.TrySetMovementAnimation("STAND");
1663 } 1733 }
1664 1734
@@ -1689,13 +1759,9 @@ namespace OpenSim.Region.Framework.Scenes
1689 Vector3 avSitOffSet = part.SitTargetPosition; 1759 Vector3 avSitOffSet = part.SitTargetPosition;
1690 Quaternion avSitOrientation = part.SitTargetOrientation; 1760 Quaternion avSitOrientation = part.SitTargetOrientation;
1691 UUID avOnTargetAlready = part.GetAvatarOnSitTarget(); 1761 UUID avOnTargetAlready = part.GetAvatarOnSitTarget();
1692 1762 bool SitTargetOccupied = (avOnTargetAlready != UUID.Zero);
1693 bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero)); 1763 bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored.
1694 bool SitTargetisSet = 1764 if (SitTargetisSet && !SitTargetOccupied)
1695 (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f && avSitOrientation.W == 1f &&
1696 avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f));
1697
1698 if (SitTargetisSet && SitTargetUnOccupied)
1699 { 1765 {
1700 //switch the target to this prim 1766 //switch the target to this prim
1701 return part; 1767 return part;
@@ -1709,84 +1775,152 @@ namespace OpenSim.Region.Framework.Scenes
1709 private void SendSitResponse(IClientAPI remoteClient, UUID targetID, Vector3 offset, Quaternion pSitOrientation) 1775 private void SendSitResponse(IClientAPI remoteClient, UUID targetID, Vector3 offset, Quaternion pSitOrientation)
1710 { 1776 {
1711 bool autopilot = true; 1777 bool autopilot = true;
1778 Vector3 autopilotTarget = new Vector3();
1779 Quaternion sitOrientation = Quaternion.Identity;
1712 Vector3 pos = new Vector3(); 1780 Vector3 pos = new Vector3();
1713 Quaternion sitOrientation = pSitOrientation;
1714 Vector3 cameraEyeOffset = Vector3.Zero; 1781 Vector3 cameraEyeOffset = Vector3.Zero;
1715 Vector3 cameraAtOffset = Vector3.Zero; 1782 Vector3 cameraAtOffset = Vector3.Zero;
1716 bool forceMouselook = false; 1783 bool forceMouselook = false;
1717 1784
1718 //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID); 1785 //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID);
1719 SceneObjectPart part = FindNextAvailableSitTarget(targetID); 1786 SceneObjectPart part = FindNextAvailableSitTarget(targetID);
1720 if (part != null) 1787 if (part == null) return;
1721 { 1788
1722 // TODO: determine position to sit at based on scene geometry; don't trust offset from client 1789 // TODO: determine position to sit at based on scene geometry; don't trust offset from client
1723 // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it 1790 // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it
1724 1791
1725 // Is a sit target available? 1792 // part is the prim to sit on
1726 Vector3 avSitOffSet = part.SitTargetPosition; 1793 // offset is the world-ref vector distance from that prim center to the click-spot
1727 Quaternion avSitOrientation = part.SitTargetOrientation; 1794 // UUID is the UUID of the Avatar doing the clicking
1728 UUID avOnTargetAlready = part.GetAvatarOnSitTarget(); 1795
1729 1796 m_avInitialPos = AbsolutePosition; // saved to calculate unscripted sit rotation
1730 bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero)); 1797
1731 bool SitTargetisSet = 1798 // Is a sit target available?
1732 (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f && 1799 Vector3 avSitOffSet = part.SitTargetPosition;
1733 ( 1800 Quaternion avSitOrientation = part.SitTargetOrientation;
1734 avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f && avSitOrientation.W == 1f // Valid Zero Rotation quaternion 1801
1735 || avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 1f && avSitOrientation.W == 0f // W-Z Mapping was invalid at one point 1802 bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored.
1736 || avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f && avSitOrientation.W == 0f // Invalid Quaternion 1803 // Quaternion partIRot = Quaternion.Inverse(part.GetWorldRotation());
1737 ) 1804 Quaternion partRot;
1738 )); 1805// if (part.LinkNum == 1)
1739 1806// { // Root prim of linkset
1740 if (SitTargetisSet && SitTargetUnOccupied) 1807// partRot = part.ParentGroup.RootPart.RotationOffset;
1741 { 1808// }
1742 part.SetAvatarOnSitTarget(UUID); 1809// else
1743 offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); 1810// { // single or child prim
1744 sitOrientation = avSitOrientation; 1811 partRot = part.GetWorldRotation();
1745 autopilot = false; 1812// }
1746 } 1813 Quaternion partIRot = Quaternion.Inverse(partRot);
1747 1814//Console.WriteLine("SendSitResponse offset=" + offset + " Occup=" + part.IsOccupied + " TargSet=" + SitTargetisSet);
1748 pos = part.AbsolutePosition + offset; 1815 // Sit analysis rewritten by KF 091125
1749 //if (Math.Abs(part.AbsolutePosition.Z - AbsolutePosition.Z) > 1) 1816 if (SitTargetisSet) // scipted sit
1750 //{ 1817 {
1751 // offset = pos; 1818 if (!part.IsOccupied)
1752 //autopilot = false; 1819 {
1753 //} 1820//Console.WriteLine("Scripted, unoccupied");
1754 if (m_physicsActor != null) 1821 part.SetAvatarOnSitTarget(UUID); // set that Av will be on it
1755 { 1822 offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); // change ofset to the scripted one
1756 // If we're not using the client autopilot, we're immediately warping the avatar to the location 1823 sitOrientation = avSitOrientation; // Change rotatione to the scripted one
1757 // We can remove the physicsActor until they stand up. 1824 autopilot = false; // Jump direct to scripted llSitPos()
1758 m_sitAvatarHeight = m_physicsActor.Size.Z; 1825 }
1759 1826 else
1760 if (autopilot) 1827 {
1761 { 1828//Console.WriteLine("Scripted, occupied");
1762 if (Util.GetDistanceTo(AbsolutePosition, pos) < 4.5) 1829 return;
1763 { 1830 }
1764 autopilot = false; 1831 }
1832 else // Not Scripted
1833 {
1834 if ( (Math.Abs(offset.X) > 0.5f) || (Math.Abs(offset.Y) > 0.5f) )
1835 {
1836 // large prim & offset, ignore if other Avs sitting
1837// offset.Z -= 0.05f;
1838 m_avUnscriptedSitPos = offset * partIRot; // (non-zero) sit where clicked
1839 autopilotTarget = part.AbsolutePosition + offset; // World location of clicked point
1840
1841//Console.WriteLine(" offset ={0}", offset);
1842//Console.WriteLine(" UnscriptedSitPos={0}", m_avUnscriptedSitPos);
1843//Console.WriteLine(" autopilotTarget={0}", autopilotTarget);
1844
1845 }
1846 else // small offset
1847 {
1848//Console.WriteLine("Small offset");
1849 if (!part.IsOccupied)
1850 {
1851 m_avUnscriptedSitPos = Vector3.Zero; // Zero = Sit on prim center
1852 autopilotTarget = part.AbsolutePosition;
1853 }
1854 else return; // occupied small
1855 } // end large/small
1856 } // end Scripted/not
1857 cameraAtOffset = part.GetCameraAtOffset();
1858 cameraEyeOffset = part.GetCameraEyeOffset();
1859 forceMouselook = part.GetForceMouselook();
1860 if(cameraAtOffset == Vector3.Zero) cameraAtOffset = new Vector3(0f, 0f, 0.1f); //
1861 if(cameraEyeOffset == Vector3.Zero) cameraEyeOffset = new Vector3(0f, 0f, 0.1f); //
1765 1862
1766 RemoveFromPhysicalScene(); 1863 if (m_physicsActor != null)
1767 AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight); 1864 {
1768 } 1865 // If we're not using the client autopilot, we're immediately warping the avatar to the location
1769 } 1866 // We can remove the physicsActor until they stand up.
1770 else 1867 m_sitAvatarHeight = m_physicsActor.Size.Z;
1868 if (autopilot)
1869 { // its not a scripted sit
1870// if (Util.GetDistanceTo(AbsolutePosition, autopilotTarget) < 4.5)
1871 if( (Math.Abs(AbsolutePosition.X - autopilotTarget.X) < 2.0f) && (Math.Abs(AbsolutePosition.Y - autopilotTarget.Y) < 2.0f) )
1771 { 1872 {
1873 autopilot = false; // close enough
1874 m_lastWorldPosition = m_pos; /* CW - This give us a position to return the avatar to if the part is killed before standup.
1875 Not using the part's position because returning the AV to the last known standing
1876 position is likely to be more friendly, isn't it? */
1772 RemoveFromPhysicalScene(); 1877 RemoveFromPhysicalScene();
1773 } 1878 AbsolutePosition = autopilotTarget + new Vector3(0.0f, 0.0f, (m_sitAvatarHeight / 2.0f)); // Warp av to over sit target
1879 } // else the autopilot will get us close
1880 }
1881 else
1882 { // its a scripted sit
1883 m_lastWorldPosition = part.AbsolutePosition; /* CW - This give us a position to return the avatar to if the part is killed before standup.
1884 I *am* using the part's position this time because we have no real idea how far away
1885 the avatar is from the sit target. */
1886 RemoveFromPhysicalScene();
1774 } 1887 }
1775
1776 cameraAtOffset = part.GetCameraAtOffset();
1777 cameraEyeOffset = part.GetCameraEyeOffset();
1778 forceMouselook = part.GetForceMouselook();
1779 } 1888 }
1780 1889 else return; // physactor is null!
1781 ControllingClient.SendSitResponse(targetID, offset, sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook); 1890
1782 m_requestedSitTargetUUID = targetID; 1891 Vector3 offsetr; // = offset * partIRot;
1892 // KF: In a linkset, offsetr needs to be relative to the group root! 091208
1893 // offsetr = (part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) + (offset * partIRot);
1894 // if (part.LinkNum < 2) 091216 All this was necessary because of the GetWorldRotation error.
1895 // { // Single, or Root prim of linkset, target is ClickOffset * RootRot
1896 offsetr = offset * partIRot;
1897//
1898 // else
1899 // { // Child prim, offset is (ChildOffset * RootRot) + (ClickOffset * ChildRot)
1900 // offsetr = //(part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) +
1901 // (offset * partRot);
1902 // }
1903
1904//Console.WriteLine(" ");
1905//Console.WriteLine("link number ={0}", part.LinkNum);
1906//Console.WriteLine("Prim offset ={0}", part.OffsetPosition );
1907//Console.WriteLine("Root Rotate ={0}", part.ParentGroup.RootPart.RotationOffset);
1908//Console.WriteLine("Click offst ={0}", offset);
1909//Console.WriteLine("Prim Rotate ={0}", part.GetWorldRotation());
1910//Console.WriteLine("offsetr ={0}", offsetr);
1911//Console.WriteLine("Camera At ={0}", cameraAtOffset);
1912//Console.WriteLine("Camera Eye ={0}", cameraEyeOffset);
1913
1914 ControllingClient.SendSitResponse(part.UUID, offsetr, sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook);
1915 m_requestedSitTargetUUID = part.UUID; //KF: Correct autopilot target
1783 // This calls HandleAgentSit twice, once from here, and the client calls 1916 // This calls HandleAgentSit twice, once from here, and the client calls
1784 // HandleAgentSit itself after it gets to the location 1917 // HandleAgentSit itself after it gets to the location
1785 // It doesn't get to the location until we've moved them there though 1918 // It doesn't get to the location until we've moved them there though
1786 // which happens in HandleAgentSit :P 1919 // which happens in HandleAgentSit :P
1787 m_autopilotMoving = autopilot; 1920 m_autopilotMoving = autopilot;
1788 m_autoPilotTarget = pos; 1921 m_autoPilotTarget = autopilotTarget;
1789 m_sitAtAutoTarget = autopilot; 1922 m_sitAtAutoTarget = autopilot;
1923 m_initialSitTarget = autopilotTarget;
1790 if (!autopilot) 1924 if (!autopilot)
1791 HandleAgentSit(remoteClient, UUID); 1925 HandleAgentSit(remoteClient, UUID);
1792 } 1926 }
@@ -2081,31 +2215,65 @@ namespace OpenSim.Region.Framework.Scenes
2081 { 2215 {
2082 if (part != null) 2216 if (part != null)
2083 { 2217 {
2218//Console.WriteLine("Link #{0}, Rot {1}", part.LinkNum, part.GetWorldRotation());
2084 if (part.GetAvatarOnSitTarget() == UUID) 2219 if (part.GetAvatarOnSitTarget() == UUID)
2085 { 2220 {
2221//Console.WriteLine("Scripted Sit");
2222 // Scripted sit
2086 Vector3 sitTargetPos = part.SitTargetPosition; 2223 Vector3 sitTargetPos = part.SitTargetPosition;
2087 Quaternion sitTargetOrient = part.SitTargetOrientation; 2224 Quaternion sitTargetOrient = part.SitTargetOrientation;
2088
2089 //Quaternion vq = new Quaternion(sitTargetPos.X, sitTargetPos.Y+0.2f, sitTargetPos.Z+0.2f, 0);
2090 //Quaternion nq = new Quaternion(-sitTargetOrient.X, -sitTargetOrient.Y, -sitTargetOrient.Z, sitTargetOrient.w);
2091
2092 //Quaternion result = (sitTargetOrient * vq) * nq;
2093
2094 m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z); 2225 m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z);
2095 m_pos += SIT_TARGET_ADJUSTMENT; 2226 m_pos += SIT_TARGET_ADJUSTMENT;
2096 m_bodyRot = sitTargetOrient; 2227 m_bodyRot = sitTargetOrient;
2097 //Rotation = sitTargetOrient;
2098 m_parentPosition = part.AbsolutePosition; 2228 m_parentPosition = part.AbsolutePosition;
2099 2229 part.IsOccupied = true;
2100 //SendTerseUpdateToAllClients();
2101 } 2230 }
2102 else 2231 else
2103 { 2232 {
2104 m_pos -= part.AbsolutePosition; 2233 // if m_avUnscriptedSitPos is zero then Av sits above center
2234 // Else Av sits at m_avUnscriptedSitPos
2235
2236 // Non-scripted sit by Kitto Flora 21Nov09
2237 // Calculate angle of line from prim to Av
2238 Quaternion partIRot;
2239// if (part.LinkNum == 1)
2240// { // Root prim of linkset
2241// partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset);
2242// }
2243// else
2244// { // single or child prim
2245 partIRot = Quaternion.Inverse(part.GetWorldRotation());
2246// }
2247 Vector3 sitTargetPos= part.AbsolutePosition + m_avUnscriptedSitPos;
2248 float y_diff = (m_avInitialPos.Y - sitTargetPos.Y);
2249 float x_diff = ( m_avInitialPos.X - sitTargetPos.X);
2250 if(Math.Abs(x_diff) < 0.001f) x_diff = 0.001f; // avoid div by 0
2251 if(Math.Abs(y_diff) < 0.001f) y_diff = 0.001f; // avoid pol flip at 0
2252 float sit_angle = (float)Math.Atan2( (double)y_diff, (double)x_diff);
2253 // NOTE: when sitting m_ pos and m_bodyRot are *relative* to the prim location/rotation, not 'World'.
2254 // Av sits at world euler <0,0, z>, translated by part rotation
2255 m_bodyRot = partIRot * Quaternion.CreateFromEulers(0f, 0f, sit_angle); // sit at 0,0,inv-click
2256
2105 m_parentPosition = part.AbsolutePosition; 2257 m_parentPosition = part.AbsolutePosition;
2106 } 2258 part.IsOccupied = true;
2107 } 2259 m_pos = new Vector3(0f, 0f, 0.05f) + // corrections to get Sit Animation
2108 else 2260 (new Vector3(0.0f, 0f, 0.61f) * partIRot) + // located on center
2261 (new Vector3(0.34f, 0f, 0.0f) * m_bodyRot) +
2262 m_avUnscriptedSitPos; // adds click offset, if any
2263 //Set up raytrace to find top surface of prim
2264 Vector3 size = part.Scale;
2265 float mag = 2.0f; // 0.1f + (float)Math.Sqrt((size.X * size.X) + (size.Y * size.Y) + (size.Z * size.Z));
2266 Vector3 start = part.AbsolutePosition + new Vector3(0f, 0f, mag);
2267 Vector3 down = new Vector3(0f, 0f, -1f);
2268//Console.WriteLine("st={0} do={1} ma={2}", start, down, mag);
2269 m_scene.PhysicsScene.RaycastWorld(
2270 start, // Vector3 position,
2271 down, // Vector3 direction,
2272 mag, // float length,
2273 SitAltitudeCallback); // retMethod
2274 } // end scripted/not
2275 }
2276 else // no Av
2109 { 2277 {
2110 return; 2278 return;
2111 } 2279 }
@@ -2117,11 +2285,36 @@ namespace OpenSim.Region.Framework.Scenes
2117 2285
2118 Animator.TrySetMovementAnimation(sitAnimation); 2286 Animator.TrySetMovementAnimation(sitAnimation);
2119 SendFullUpdateToAllClients(); 2287 SendFullUpdateToAllClients();
2120 // This may seem stupid, but Our Full updates don't send avatar rotation :P
2121 // So we're also sending a terse update (which has avatar rotation)
2122 // [Update] We do now.
2123 //SendTerseUpdateToAllClients();
2124 } 2288 }
2289
2290 public void SitAltitudeCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 normal)
2291 {
2292 // KF: 091202 There appears to be a bug in Prim Edit Size - the process sometimes make a prim that RayTrace no longer
2293 // sees. Take/re-rez, or sim restart corrects the condition. Result of bug is incorrect sit height.
2294 if(hitYN)
2295 {
2296 // m_pos = Av offset from prim center to make look like on center
2297 // m_parentPosition = Actual center pos of prim
2298 // collisionPoint = spot on prim where we want to sit
2299 // collisionPoint.Z = global sit surface height
2300 SceneObjectPart part = m_scene.GetSceneObjectPart(localid);
2301 Quaternion partIRot;
2302// if (part.LinkNum == 1)
2303/// { // Root prim of linkset
2304// partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset);
2305// }
2306// else
2307// { // single or child prim
2308 partIRot = Quaternion.Inverse(part.GetWorldRotation());
2309// }
2310 float offZ = collisionPoint.Z - m_initialSitTarget.Z;
2311 Vector3 offset = new Vector3(0.0f, 0.0f, offZ) * partIRot; // Altitude correction
2312//Console.WriteLine("sitPoint={0}, offset={1}", sitPoint, offset);
2313 m_pos += offset;
2314// ControllingClient.SendClearFollowCamProperties(part.UUID);
2315
2316 }
2317 } // End SitAltitudeCallback KF.
2125 2318
2126 /// <summary> 2319 /// <summary>
2127 /// Event handler for the 'Always run' setting on the client 2320 /// Event handler for the 'Always run' setting on the client
@@ -2151,7 +2344,7 @@ namespace OpenSim.Region.Framework.Scenes
2151 /// </summary> 2344 /// </summary>
2152 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param> 2345 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param>
2153 /// <param name="rotation">The direction in which this avatar should now face. 2346 /// <param name="rotation">The direction in which this avatar should now face.
2154 public void AddNewMovement(Vector3 vec, Quaternion rotation) 2347 public void AddNewMovement(Vector3 vec, Quaternion rotation, bool Nudging)
2155 { 2348 {
2156 if (m_isChildAgent) 2349 if (m_isChildAgent)
2157 { 2350 {
@@ -2225,7 +2418,7 @@ namespace OpenSim.Region.Framework.Scenes
2225 2418
2226 // TODO: Add the force instead of only setting it to support multiple forces per frame? 2419 // TODO: Add the force instead of only setting it to support multiple forces per frame?
2227 m_forceToApply = direc; 2420 m_forceToApply = direc;
2228 2421 m_isNudging = Nudging;
2229 m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); 2422 m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
2230 } 2423 }
2231 2424
@@ -2240,7 +2433,7 @@ namespace OpenSim.Region.Framework.Scenes
2240 const float POSITION_TOLERANCE = 0.05f; 2433 const float POSITION_TOLERANCE = 0.05f;
2241 //const int TIME_MS_TOLERANCE = 3000; 2434 //const int TIME_MS_TOLERANCE = 3000;
2242 2435
2243 SendPrimUpdates(); 2436
2244 2437
2245 if (m_newCoarseLocations) 2438 if (m_newCoarseLocations)
2246 { 2439 {
@@ -2276,6 +2469,9 @@ namespace OpenSim.Region.Framework.Scenes
2276 CheckForBorderCrossing(); 2469 CheckForBorderCrossing();
2277 CheckForSignificantMovement(); // sends update to the modules. 2470 CheckForSignificantMovement(); // sends update to the modules.
2278 } 2471 }
2472
2473 //Sending prim updates AFTER the avatar terse updates are sent
2474 SendPrimUpdates();
2279 } 2475 }
2280 2476
2281 #endregion 2477 #endregion
@@ -3129,14 +3325,25 @@ namespace OpenSim.Region.Framework.Scenes
3129 { 3325 {
3130 if (m_forceToApply.HasValue) 3326 if (m_forceToApply.HasValue)
3131 { 3327 {
3132 Vector3 force = m_forceToApply.Value;
3133 3328
3329 Vector3 force = m_forceToApply.Value;
3134 m_updateflag = true; 3330 m_updateflag = true;
3135// movementvector = force;
3136 Velocity = force; 3331 Velocity = force;
3137 3332
3138 m_forceToApply = null; 3333 m_forceToApply = null;
3139 } 3334 }
3335 else
3336 {
3337 if (m_isNudging)
3338 {
3339 Vector3 force = Vector3.Zero;
3340
3341 m_updateflag = true;
3342 Velocity = force;
3343 m_isNudging = false;
3344 m_updateCount = UPDATE_COUNT; //KF: Update anims to pickup "STAND"
3345 }
3346 }
3140 } 3347 }
3141 3348
3142 public override void SetText(string text, Vector3 color, double alpha) 3349 public override void SetText(string text, Vector3 color, double alpha)
@@ -3188,18 +3395,29 @@ namespace OpenSim.Region.Framework.Scenes
3188 { 3395 {
3189 if (e == null) 3396 if (e == null)
3190 return; 3397 return;
3191 3398
3192 //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f)) 3399 // The Physics Scene will send (spam!) updates every 500 ms grep: m_physicsActor.SubscribeEvents(
3193 // The Physics Scene will send updates every 500 ms grep: m_physicsActor.SubscribeEvents(
3194 // as of this comment the interval is set in AddToPhysicalScene 3400 // as of this comment the interval is set in AddToPhysicalScene
3195 if (Animator!=null) 3401 if (Animator!=null)
3196 Animator.UpdateMovementAnimations(); 3402 {
3403 if (m_updateCount > 0) //KF: DO NOT call UpdateMovementAnimations outside of the m_updateCount wrapper,
3404 { // else its will lock out other animation changes, like ground sit.
3405 Animator.UpdateMovementAnimations();
3406 m_updateCount--;
3407 }
3408 }
3197 3409
3198 CollisionEventUpdate collisionData = (CollisionEventUpdate)e; 3410 CollisionEventUpdate collisionData = (CollisionEventUpdate)e;
3199 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList; 3411 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList;
3200 3412
3201 CollisionPlane = Vector4.UnitW; 3413 CollisionPlane = Vector4.UnitW;
3202 3414
3415 if (m_lastColCount != coldata.Count)
3416 {
3417 m_updateCount = UPDATE_COUNT;
3418 m_lastColCount = coldata.Count;
3419 }
3420
3203 if (coldata.Count != 0 && Animator != null) 3421 if (coldata.Count != 0 && Animator != null)
3204 { 3422 {
3205 switch (Animator.CurrentMovementAnimation) 3423 switch (Animator.CurrentMovementAnimation)
@@ -3847,5 +4065,16 @@ namespace OpenSim.Region.Framework.Scenes
3847 m_reprioritization_called = false; 4065 m_reprioritization_called = false;
3848 } 4066 }
3849 } 4067 }
4068
4069 private Vector3 Quat2Euler(Quaternion rot){
4070 float x = Utils.RAD_TO_DEG * (float)Math.Atan2((double)((2.0f * rot.X * rot.W) - (2.0f * rot.Y * rot.Z)) ,
4071 (double)(1 - (2.0f * rot.X * rot.X) - (2.0f * rot.Z * rot.Z)));
4072 float y = Utils.RAD_TO_DEG * (float)Math.Asin ((double)((2.0f * rot.X * rot.Y) + (2.0f * rot.Z * rot.W)));
4073 float z = Utils.RAD_TO_DEG * (float)Math.Atan2(((double)(2.0f * rot.Y * rot.W) - (2.0f * rot.X * rot.Z)) ,
4074 (double)(1 - (2.0f * rot.Y * rot.Y) - (2.0f * rot.Z * rot.Z)));
4075 return(new Vector3(x,y,z));
4076 }
4077
4078
3850 } 4079 }
3851} \ No newline at end of file 4080}
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs
index 8a27b7b..5abbb82 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs
@@ -101,7 +101,16 @@ namespace OpenSim.Region.Framework.Scenes.Tests
101 { 101 {
102 throw new NotImplementedException(); 102 throw new NotImplementedException();
103 } 103 }
104 104 public RegionMeta7WindlightData LoadRegionWindlightSettings(UUID regionUUID)
105 {
106 //This connector doesn't support the windlight module yet
107 //Return default LL windlight settings
108 return new RegionMeta7WindlightData();
109 }
110 public void StoreRegionWindlightSettings(RegionMeta7WindlightData wl)
111 {
112 //This connector doesn't support the windlight module yet
113 }
105 public RegionSettings LoadRegionSettings(UUID regionUUID) 114 public RegionSettings LoadRegionSettings(UUID regionUUID)
106 { 115 {
107 return null; 116 return null;