aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework')
-rw-r--r--OpenSim/Region/Framework/Interfaces/IRegionDataStore.cs2
-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
14 files changed, 1244 insertions, 621 deletions
diff --git a/OpenSim/Region/Framework/Interfaces/IRegionDataStore.cs b/OpenSim/Region/Framework/Interfaces/IRegionDataStore.cs
index 78bd622..7312799 100644
--- a/OpenSim/Region/Framework/Interfaces/IRegionDataStore.cs
+++ b/OpenSim/Region/Framework/Interfaces/IRegionDataStore.cs
@@ -103,6 +103,8 @@ namespace OpenSim.Region.Framework.Interfaces
103 103
104 void StoreRegionSettings(RegionSettings rs); 104 void StoreRegionSettings(RegionSettings rs);
105 RegionSettings LoadRegionSettings(UUID regionUUID); 105 RegionSettings LoadRegionSettings(UUID regionUUID);
106 RegionMeta7WindlightData LoadRegionWindlightSettings(UUID regionUUID);
107 void StoreRegionWindlightSettings(RegionMeta7WindlightData wl);
106 108
107 void Shutdown(); 109 void Shutdown();
108 } 110 }
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 4dd6f32..3e49691 100644
--- a/OpenSim/Region/Framework/Scenes/EventManager.cs
+++ b/OpenSim/Region/Framework/Scenes/EventManager.cs
@@ -197,7 +197,11 @@ namespace OpenSim.Region.Framework.Scenes
197 public event OnMakeChildAgentDelegate OnMakeChildAgent; 197 public event OnMakeChildAgentDelegate OnMakeChildAgent;
198 198
199 public delegate void OnMakeRootAgentDelegate(ScenePresence presence); 199 public delegate void OnMakeRootAgentDelegate(ScenePresence presence);
200 public delegate void OnSaveNewWindlightProfileDelegate();
201 public delegate void OnSendNewWindlightProfileTargetedDelegate(RegionMeta7WindlightData wl, UUID user);
200 public event OnMakeRootAgentDelegate OnMakeRootAgent; 202 public event OnMakeRootAgentDelegate OnMakeRootAgent;
203 public event OnSendNewWindlightProfileTargetedDelegate OnSendNewWindlightProfileTargeted;
204 public event OnSaveNewWindlightProfileDelegate OnSaveNewWindlightProfile;
201 205
202 public delegate void NewInventoryItemUploadComplete(UUID avatarID, UUID assetID, string name, int userlevel); 206 public delegate void NewInventoryItemUploadComplete(UUID avatarID, UUID assetID, string name, int userlevel);
203 207
@@ -415,6 +419,8 @@ namespace OpenSim.Region.Framework.Scenes
415 private IncomingInstantMessage handlerUnhandledInstantMessage = null; //OnUnhandledInstantMessage; 419 private IncomingInstantMessage handlerUnhandledInstantMessage = null; //OnUnhandledInstantMessage;
416 private ClientClosed handlerClientClosed = null; //OnClientClosed; 420 private ClientClosed handlerClientClosed = null; //OnClientClosed;
417 private OnMakeChildAgentDelegate handlerMakeChildAgent = null; //OnMakeChildAgent; 421 private OnMakeChildAgentDelegate handlerMakeChildAgent = null; //OnMakeChildAgent;
422 private OnSaveNewWindlightProfileDelegate handlerSaveNewWindlightProfile = null; //OnSaveNewWindlightProfile;
423 private OnSendNewWindlightProfileTargetedDelegate handlerSendNewWindlightProfileTargeted = null; //OnSendNewWindlightProfileTargeted;
418 private OnMakeRootAgentDelegate handlerMakeRootAgent = null; //OnMakeRootAgent; 424 private OnMakeRootAgentDelegate handlerMakeRootAgent = null; //OnMakeRootAgent;
419 private OnTerrainTickDelegate handlerTerrainTick = null; // OnTerainTick; 425 private OnTerrainTickDelegate handlerTerrainTick = null; // OnTerainTick;
420 private RegisterCapsEvent handlerRegisterCaps = null; // OnRegisterCaps; 426 private RegisterCapsEvent handlerRegisterCaps = null; // OnRegisterCaps;
@@ -779,6 +785,24 @@ namespace OpenSim.Region.Framework.Scenes
779 } 785 }
780 } 786 }
781 787
788 public void TriggerOnSendNewWindlightProfileTargeted(RegionMeta7WindlightData wl, UUID user)
789 {
790 handlerSendNewWindlightProfileTargeted = OnSendNewWindlightProfileTargeted;
791 if (handlerSendNewWindlightProfileTargeted != null)
792 {
793 handlerSendNewWindlightProfileTargeted(wl, user);
794 }
795 }
796
797 public void TriggerOnSaveNewWindlightProfile()
798 {
799 handlerSaveNewWindlightProfile = OnSaveNewWindlightProfile;
800 if (handlerSaveNewWindlightProfile != null)
801 {
802 handlerSaveNewWindlightProfile();
803 }
804 }
805
782 public void TriggerOnMakeRootAgent(ScenePresence presence) 806 public void TriggerOnMakeRootAgent(ScenePresence presence)
783 { 807 {
784 handlerMakeRootAgent = OnMakeRootAgent; 808 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 bc9301b..8ac4bc4 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 34d8b49..e63e8d9 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -98,6 +98,72 @@ namespace OpenSim.Region.Framework.Scenes
98 private bool m_hasGroupChanged = false; 98 private bool m_hasGroupChanged = false;
99 private long timeFirstChanged; 99 private long timeFirstChanged;
100 private long timeLastChanged; 100 private long timeLastChanged;
101 private System.Threading.ReaderWriterLockSlim m_partsLock = new System.Threading.ReaderWriterLockSlim();
102
103 public void lockPartsForRead(bool locked)
104 {
105 if (locked)
106 {
107 if (m_partsLock.RecursiveReadCount > 0)
108 {
109 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.");
110 m_partsLock.ExitReadLock();
111 }
112 if (m_partsLock.RecursiveWriteCount > 0)
113 {
114 m_log.Error("[SceneObjectGroup.m_parts] Recursive read lock requested. This should not happen and means something needs to be fixed.");
115 m_partsLock.ExitWriteLock();
116 }
117
118 while (!m_partsLock.TryEnterReadLock(60000))
119 {
120 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.");
121 if (m_partsLock.IsWriteLockHeld)
122 {
123 m_partsLock = new System.Threading.ReaderWriterLockSlim();
124 }
125 }
126 }
127 else
128 {
129 if (m_partsLock.RecursiveReadCount > 0)
130 {
131 m_partsLock.ExitReadLock();
132 }
133 }
134 }
135 public void lockPartsForWrite(bool locked)
136 {
137 if (locked)
138 {
139 if (m_partsLock.RecursiveReadCount > 0)
140 {
141 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.");
142 m_partsLock.ExitReadLock();
143 }
144 if (m_partsLock.RecursiveWriteCount > 0)
145 {
146 m_log.Error("[SceneObjectGroup.m_parts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
147 m_partsLock.ExitWriteLock();
148 }
149
150 while (!m_partsLock.TryEnterWriteLock(60000))
151 {
152 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.");
153 if (m_partsLock.IsWriteLockHeld)
154 {
155 m_partsLock = new System.Threading.ReaderWriterLockSlim();
156 }
157 }
158 }
159 else
160 {
161 if (m_partsLock.RecursiveWriteCount > 0)
162 {
163 m_partsLock.ExitWriteLock();
164 }
165 }
166 }
101 167
102 public bool HasGroupChanged 168 public bool HasGroupChanged
103 { 169 {
@@ -243,13 +309,16 @@ namespace OpenSim.Region.Framework.Scenes
243 set 309 set
244 { 310 {
245 m_regionHandle = value; 311 m_regionHandle = value;
246 lock (m_parts) 312 lockPartsForRead(true);
247 { 313 {
248 foreach (SceneObjectPart part in m_parts.Values) 314 foreach (SceneObjectPart part in m_parts.Values)
249 { 315 {
316
250 part.RegionHandle = m_regionHandle; 317 part.RegionHandle = m_regionHandle;
318
251 } 319 }
252 } 320 }
321 lockPartsForRead(false);
253 } 322 }
254 } 323 }
255 324
@@ -275,13 +344,16 @@ namespace OpenSim.Region.Framework.Scenes
275 m_scene.CrossPrimGroupIntoNewRegion(val, this, true); 344 m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
276 } 345 }
277 346
278 lock (m_parts) 347 lockPartsForRead(true);
279 { 348 {
280 foreach (SceneObjectPart part in m_parts.Values) 349 foreach (SceneObjectPart part in m_parts.Values)
281 { 350 {
351
282 part.GroupPosition = val; 352 part.GroupPosition = val;
353
283 } 354 }
284 } 355 }
356 lockPartsForRead(false);
285 357
286 //if (m_rootPart.PhysActor != null) 358 //if (m_rootPart.PhysActor != null)
287 //{ 359 //{
@@ -443,13 +515,16 @@ namespace OpenSim.Region.Framework.Scenes
443 515
444 public void SetFromItemID(UUID AssetId) 516 public void SetFromItemID(UUID AssetId)
445 { 517 {
446 lock (m_parts) 518 lockPartsForRead(true);
447 { 519 {
448 foreach (SceneObjectPart part in m_parts.Values) 520 foreach (SceneObjectPart part in m_parts.Values)
449 { 521 {
522
450 part.FromItemID = AssetId; 523 part.FromItemID = AssetId;
524
451 } 525 }
452 } 526 }
527 lockPartsForRead(false);
453 } 528 }
454 529
455 public UUID GetFromItemID() 530 public UUID GetFromItemID()
@@ -516,10 +591,11 @@ namespace OpenSim.Region.Framework.Scenes
516 Vector3 maxScale = Vector3.Zero; 591 Vector3 maxScale = Vector3.Zero;
517 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f); 592 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f);
518 593
519 lock (m_parts) 594 lockPartsForRead(true);
520 { 595 {
521 foreach (SceneObjectPart part in m_parts.Values) 596 foreach (SceneObjectPart part in m_parts.Values)
522 { 597 {
598
523 Vector3 partscale = part.Scale; 599 Vector3 partscale = part.Scale;
524 Vector3 partoffset = part.OffsetPosition; 600 Vector3 partoffset = part.OffsetPosition;
525 601
@@ -530,8 +606,11 @@ namespace OpenSim.Region.Framework.Scenes
530 maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X; 606 maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X;
531 maxScale.Y = (partscale.Y + partoffset.Y > maxScale.Y) ? partscale.Y + partoffset.Y : maxScale.Y; 607 maxScale.Y = (partscale.Y + partoffset.Y > maxScale.Y) ? partscale.Y + partoffset.Y : maxScale.Y;
532 maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z; 608 maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z;
609
533 } 610 }
534 } 611 }
612 lockPartsForRead(false);
613
535 finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X; 614 finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X;
536 finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y; 615 finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y;
537 finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z; 616 finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z;
@@ -547,10 +626,11 @@ namespace OpenSim.Region.Framework.Scenes
547 626
548 EntityIntersection result = new EntityIntersection(); 627 EntityIntersection result = new EntityIntersection();
549 628
550 lock (m_parts) 629 lockPartsForRead(true);
551 { 630 {
552 foreach (SceneObjectPart part in m_parts.Values) 631 foreach (SceneObjectPart part in m_parts.Values)
553 { 632 {
633
554 // Temporary commented to stop compiler warning 634 // Temporary commented to stop compiler warning
555 //Vector3 partPosition = 635 //Vector3 partPosition =
556 // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z); 636 // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z);
@@ -578,8 +658,10 @@ namespace OpenSim.Region.Framework.Scenes
578 result.distance = inter.distance; 658 result.distance = inter.distance;
579 } 659 }
580 } 660 }
661
581 } 662 }
582 } 663 }
664 lockPartsForRead(false);
583 return result; 665 return result;
584 } 666 }
585 667
@@ -592,10 +674,11 @@ namespace OpenSim.Region.Framework.Scenes
592 public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight) 674 public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight)
593 { 675 {
594 float maxX = -256f, maxY = -256f, maxZ = -256f, minX = 256f, minY = 256f, minZ = 256f; 676 float maxX = -256f, maxY = -256f, maxZ = -256f, minX = 256f, minY = 256f, minZ = 256f;
595 lock (m_parts) 677 lockPartsForRead(true);
596 { 678 {
597 foreach (SceneObjectPart part in m_parts.Values) 679 foreach (SceneObjectPart part in m_parts.Values)
598 { 680 {
681
599 Vector3 worldPos = part.GetWorldPosition(); 682 Vector3 worldPos = part.GetWorldPosition();
600 Vector3 offset = worldPos - AbsolutePosition; 683 Vector3 offset = worldPos - AbsolutePosition;
601 Quaternion worldRot; 684 Quaternion worldRot;
@@ -654,6 +737,8 @@ namespace OpenSim.Region.Framework.Scenes
654 backBottomRight.Y = orig.Y + (part.Scale.Y / 2); 737 backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
655 backBottomRight.Z = orig.Z - (part.Scale.Z / 2); 738 backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
656 739
740
741
657 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z); 742 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
658 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z); 743 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
659 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z); 744 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
@@ -825,6 +910,7 @@ namespace OpenSim.Region.Framework.Scenes
825 minZ = backBottomLeft.Z; 910 minZ = backBottomLeft.Z;
826 } 911 }
827 } 912 }
913 lockPartsForRead(false);
828 914
829 Vector3 boundingBox = new Vector3(maxX - minX, maxY - minY, maxZ - minZ); 915 Vector3 boundingBox = new Vector3(maxX - minX, maxY - minY, maxZ - minZ);
830 916
@@ -853,17 +939,20 @@ namespace OpenSim.Region.Framework.Scenes
853 Dictionary<UUID,string> states = new Dictionary<UUID,string>(); 939 Dictionary<UUID,string> states = new Dictionary<UUID,string>();
854 940
855 // Capture script state while holding the lock 941 // Capture script state while holding the lock
856 lock (m_parts) 942 lockPartsForRead(true);
857 { 943 {
858 foreach (SceneObjectPart part in m_parts.Values) 944 foreach (SceneObjectPart part in m_parts.Values)
859 { 945 {
946
860 Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates(); 947 Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates();
861 foreach (UUID itemid in pstates.Keys) 948 foreach (UUID itemid in pstates.Keys)
862 { 949 {
863 states.Add(itemid, pstates[itemid]); 950 states.Add(itemid, pstates[itemid]);
864 } 951 }
952
865 } 953 }
866 } 954 }
955 lockPartsForRead(false);
867 956
868 if (states.Count > 0) 957 if (states.Count > 0)
869 { 958 {
@@ -1025,13 +1114,16 @@ namespace OpenSim.Region.Framework.Scenes
1025 1114
1026 public override void UpdateMovement() 1115 public override void UpdateMovement()
1027 { 1116 {
1028 lock (m_parts) 1117 lockPartsForRead(true);
1029 { 1118 {
1030 foreach (SceneObjectPart part in m_parts.Values) 1119 foreach (SceneObjectPart part in m_parts.Values)
1031 { 1120 {
1121
1032 part.UpdateMovement(); 1122 part.UpdateMovement();
1123
1033 } 1124 }
1034 } 1125 }
1126 lockPartsForRead(false);
1035 } 1127 }
1036 1128
1037 public ushort GetTimeDilation() 1129 public ushort GetTimeDilation()
@@ -1075,7 +1167,7 @@ namespace OpenSim.Region.Framework.Scenes
1075 /// <param name="part"></param> 1167 /// <param name="part"></param>
1076 public void AddPart(SceneObjectPart part) 1168 public void AddPart(SceneObjectPart part)
1077 { 1169 {
1078 lock (m_parts) 1170 lockPartsForWrite(true);
1079 { 1171 {
1080 part.SetParent(this); 1172 part.SetParent(this);
1081 m_parts.Add(part.UUID, part); 1173 m_parts.Add(part.UUID, part);
@@ -1085,6 +1177,7 @@ namespace OpenSim.Region.Framework.Scenes
1085 if (part.LinkNum == 2 && RootPart != null) 1177 if (part.LinkNum == 2 && RootPart != null)
1086 RootPart.LinkNum = 1; 1178 RootPart.LinkNum = 1;
1087 } 1179 }
1180 lockPartsForWrite(false);
1088 } 1181 }
1089 1182
1090 /// <summary> 1183 /// <summary>
@@ -1092,28 +1185,33 @@ namespace OpenSim.Region.Framework.Scenes
1092 /// </summary> 1185 /// </summary>
1093 private void UpdateParentIDs() 1186 private void UpdateParentIDs()
1094 { 1187 {
1095 lock (m_parts) 1188 lockPartsForRead(true);
1096 { 1189 {
1097 foreach (SceneObjectPart part in m_parts.Values) 1190 foreach (SceneObjectPart part in m_parts.Values)
1098 { 1191 {
1192
1099 if (part.UUID != m_rootPart.UUID) 1193 if (part.UUID != m_rootPart.UUID)
1100 { 1194 {
1101 part.ParentID = m_rootPart.LocalId; 1195 part.ParentID = m_rootPart.LocalId;
1102 } 1196 }
1197
1103 } 1198 }
1104 } 1199 }
1200 lockPartsForRead(false);
1105 } 1201 }
1106 1202
1107 public void RegenerateFullIDs() 1203 public void RegenerateFullIDs()
1108 { 1204 {
1109 lock (m_parts) 1205 lockPartsForRead(true);
1110 { 1206 {
1111 foreach (SceneObjectPart part in m_parts.Values) 1207 foreach (SceneObjectPart part in m_parts.Values)
1112 { 1208 {
1209
1113 part.UUID = UUID.Random(); 1210 part.UUID = UUID.Random();
1114 1211
1115 } 1212 }
1116 } 1213 }
1214 lockPartsForRead(false);
1117 } 1215 }
1118 1216
1119 // helper provided for parts. 1217 // helper provided for parts.
@@ -1194,29 +1292,33 @@ namespace OpenSim.Region.Framework.Scenes
1194 1292
1195 DetachFromBackup(); 1293 DetachFromBackup();
1196 1294
1197 lock (m_parts) 1295 lockPartsForRead(true);
1296 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1297 lockPartsForRead(false);
1298
1299 foreach (SceneObjectPart part in values)
1198 { 1300 {
1199 foreach (SceneObjectPart part in m_parts.Values)
1200 {
1201// part.Inventory.RemoveScriptInstances(); 1301// part.Inventory.RemoveScriptInstances();
1202 1302
1203 ScenePresence[] avatars = Scene.GetScenePresences(); 1303 ScenePresence[] avatars = Scene.GetScenePresences();
1204 for (int i = 0; i < avatars.Length; i++) 1304 for (int i = 0; i < avatars.Length; i++)
1305 {
1306 if (avatars[i].ParentID == LocalId)
1205 { 1307 {
1206 if (avatars[i].ParentID == LocalId) 1308 avatars[i].StandUp();
1207 { 1309 }
1208 avatars[i].StandUp();
1209 }
1210 1310
1211 if (!silent) 1311 if (!silent)
1212 { 1312 {
1213 part.UpdateFlag = 0; 1313 part.UpdateFlag = 0;
1214 if (part == m_rootPart) 1314 if (part == m_rootPart)
1215 avatars[i].ControllingClient.SendKillObject(m_regionHandle, part.LocalId); 1315 avatars[i].ControllingClient.SendKillObject(m_regionHandle, part.LocalId);
1216 }
1217 } 1316 }
1218 } 1317 }
1318
1219 } 1319 }
1320
1321
1220 } 1322 }
1221 1323
1222 public void AddScriptLPS(int count) 1324 public void AddScriptLPS(int count)
@@ -1241,17 +1343,20 @@ namespace OpenSim.Region.Framework.Scenes
1241 1343
1242 scriptEvents aggregateScriptEvents=0; 1344 scriptEvents aggregateScriptEvents=0;
1243 1345
1244 lock (m_parts) 1346 lockPartsForRead(true);
1245 { 1347 {
1246 foreach (SceneObjectPart part in m_parts.Values) 1348 foreach (SceneObjectPart part in m_parts.Values)
1247 { 1349 {
1350
1248 if (part == null) 1351 if (part == null)
1249 continue; 1352 continue;
1250 if (part != RootPart) 1353 if (part != RootPart)
1251 part.ObjectFlags = objectflagupdate; 1354 part.ObjectFlags = objectflagupdate;
1252 aggregateScriptEvents |= part.AggregateScriptEvents; 1355 aggregateScriptEvents |= part.AggregateScriptEvents;
1356
1253 } 1357 }
1254 } 1358 }
1359 lockPartsForRead(false);
1255 1360
1256 m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0); 1361 m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0);
1257 m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0); 1362 m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0);
@@ -1284,42 +1389,52 @@ namespace OpenSim.Region.Framework.Scenes
1284 /// <param name="m_physicalPrim"></param> 1389 /// <param name="m_physicalPrim"></param>
1285 public void ApplyPhysics(bool m_physicalPrim) 1390 public void ApplyPhysics(bool m_physicalPrim)
1286 { 1391 {
1287 lock (m_parts) 1392 lockPartsForRead(true);
1393
1394 if (m_parts.Count > 1)
1288 { 1395 {
1289 if (m_parts.Count > 1) 1396 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1397 lockPartsForRead(false);
1398 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1399 foreach (SceneObjectPart part in values)
1290 { 1400 {
1291 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim); 1401
1292 foreach (SceneObjectPart part in m_parts.Values) 1402 if (part.LocalId != m_rootPart.LocalId)
1293 { 1403 {
1294 if (part.LocalId != m_rootPart.LocalId) 1404 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
1295 {
1296 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
1297 }
1298 } 1405 }
1299 1406
1300 // Hack to get the physics scene geometries in the right spot
1301 ResetChildPrimPhysicsPositions();
1302 }
1303 else
1304 {
1305 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1306 } 1407 }
1408 // Hack to get the physics scene geometries in the right spot
1409 ResetChildPrimPhysicsPositions();
1410 }
1411 else
1412 {
1413 lockPartsForRead(false);
1414 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1307 } 1415 }
1308 } 1416 }
1309 1417
1310 public void SetOwnerId(UUID userId) 1418 public void SetOwnerId(UUID userId)
1311 { 1419 {
1312 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); 1420 ForEachPart(delegate(SceneObjectPart part)
1421 {
1422
1423 part.OwnerID = userId;
1424
1425 });
1313 } 1426 }
1314 1427
1315 public void ForEachPart(Action<SceneObjectPart> whatToDo) 1428 public void ForEachPart(Action<SceneObjectPart> whatToDo)
1316 { 1429 {
1317 lock (m_parts) 1430 lockPartsForRead(true);
1431 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1432 lockPartsForRead(false);
1433 foreach (SceneObjectPart part in values)
1318 { 1434 {
1319 foreach (SceneObjectPart part in m_parts.Values) 1435
1320 { 1436 whatToDo(part);
1321 whatToDo(part); 1437
1322 }
1323 } 1438 }
1324 } 1439 }
1325 1440
@@ -1418,14 +1533,17 @@ namespace OpenSim.Region.Framework.Scenes
1418 { 1533 {
1419 SendPartFullUpdate(remoteClient, RootPart, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID)); 1534 SendPartFullUpdate(remoteClient, RootPart, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID));
1420 1535
1421 lock (m_parts) 1536 lockPartsForRead(true);
1422 { 1537 {
1423 foreach (SceneObjectPart part in m_parts.Values) 1538 foreach (SceneObjectPart part in m_parts.Values)
1424 { 1539 {
1540
1425 if (part != RootPart) 1541 if (part != RootPart)
1426 SendPartFullUpdate(remoteClient, part, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID)); 1542 SendPartFullUpdate(remoteClient, part, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID));
1543
1427 } 1544 }
1428 } 1545 }
1546 lockPartsForRead(false);
1429 } 1547 }
1430 1548
1431 /// <summary> 1549 /// <summary>
@@ -1520,10 +1638,11 @@ namespace OpenSim.Region.Framework.Scenes
1520 1638
1521 List<SceneObjectPart> partList; 1639 List<SceneObjectPart> partList;
1522 1640
1523 lock (m_parts) 1641 lockPartsForRead(true);
1524 { 1642
1525 partList = new List<SceneObjectPart>(m_parts.Values); 1643 partList = new List<SceneObjectPart>(m_parts.Values);
1526 } 1644
1645 lockPartsForRead(false);
1527 1646
1528 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) 1647 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1529 { 1648 {
@@ -1772,6 +1891,7 @@ namespace OpenSim.Region.Framework.Scenes
1772 } 1891 }
1773 } 1892 }
1774 } 1893 }
1894
1775 public void stopLookAt() 1895 public void stopLookAt()
1776 { 1896 {
1777 SceneObjectPart rootpart = m_rootPart; 1897 SceneObjectPart rootpart = m_rootPart;
@@ -1846,10 +1966,11 @@ namespace OpenSim.Region.Framework.Scenes
1846 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 1966 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
1847 newPart.SetParent(this); 1967 newPart.SetParent(this);
1848 1968
1849 lock (m_parts) 1969 lockPartsForWrite(true);
1850 { 1970 {
1851 m_parts.Add(newPart.UUID, newPart); 1971 m_parts.Add(newPart.UUID, newPart);
1852 } 1972 }
1973 lockPartsForWrite(false);
1853 1974
1854 SetPartAsNonRoot(newPart); 1975 SetPartAsNonRoot(newPart);
1855 1976
@@ -1912,7 +2033,7 @@ namespace OpenSim.Region.Framework.Scenes
1912 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0) 2033 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
1913 // return; 2034 // return;
1914 2035
1915 lock (m_parts) 2036 lockPartsForRead(true);
1916 { 2037 {
1917 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0); 2038 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0);
1918 2039
@@ -1930,34 +2051,43 @@ namespace OpenSim.Region.Framework.Scenes
1930 2051
1931 foreach (SceneObjectPart part in m_parts.Values) 2052 foreach (SceneObjectPart part in m_parts.Values)
1932 { 2053 {
2054
1933 part.SendScheduledUpdates(); 2055 part.SendScheduledUpdates();
2056
1934 } 2057 }
1935 } 2058 }
2059 lockPartsForRead(false);
1936 } 2060 }
1937 2061
1938 public void ScheduleFullUpdateToAvatar(ScenePresence presence) 2062 public void ScheduleFullUpdateToAvatar(ScenePresence presence)
1939 { 2063 {
1940 RootPart.AddFullUpdateToAvatar(presence); 2064 RootPart.AddFullUpdateToAvatar(presence);
1941 2065
1942 lock (m_parts) 2066 lockPartsForRead(true);
1943 { 2067 {
1944 foreach (SceneObjectPart part in m_parts.Values) 2068 foreach (SceneObjectPart part in m_parts.Values)
1945 { 2069 {
2070
1946 if (part != RootPart) 2071 if (part != RootPart)
1947 part.AddFullUpdateToAvatar(presence); 2072 part.AddFullUpdateToAvatar(presence);
2073
1948 } 2074 }
1949 } 2075 }
2076 lockPartsForRead(false);
1950 } 2077 }
1951 2078
1952 public void ScheduleTerseUpdateToAvatar(ScenePresence presence) 2079 public void ScheduleTerseUpdateToAvatar(ScenePresence presence)
1953 { 2080 {
1954 lock (m_parts) 2081 lockPartsForRead(true);
1955 { 2082 {
1956 foreach (SceneObjectPart part in m_parts.Values) 2083 foreach (SceneObjectPart part in m_parts.Values)
1957 { 2084 {
2085
1958 part.AddTerseUpdateToAvatar(presence); 2086 part.AddTerseUpdateToAvatar(presence);
2087
1959 } 2088 }
1960 } 2089 }
2090 lockPartsForRead(false);
1961 } 2091 }
1962 2092
1963 /// <summary> 2093 /// <summary>
@@ -1968,14 +2098,17 @@ namespace OpenSim.Region.Framework.Scenes
1968 checkAtTargets(); 2098 checkAtTargets();
1969 RootPart.ScheduleFullUpdate(); 2099 RootPart.ScheduleFullUpdate();
1970 2100
1971 lock (m_parts) 2101 lockPartsForRead(true);
1972 { 2102 {
1973 foreach (SceneObjectPart part in m_parts.Values) 2103 foreach (SceneObjectPart part in m_parts.Values)
1974 { 2104 {
2105
1975 if (part != RootPart) 2106 if (part != RootPart)
1976 part.ScheduleFullUpdate(); 2107 part.ScheduleFullUpdate();
2108
1977 } 2109 }
1978 } 2110 }
2111 lockPartsForRead(false);
1979 } 2112 }
1980 2113
1981 /// <summary> 2114 /// <summary>
@@ -1983,13 +2116,16 @@ namespace OpenSim.Region.Framework.Scenes
1983 /// </summary> 2116 /// </summary>
1984 public void ScheduleGroupForTerseUpdate() 2117 public void ScheduleGroupForTerseUpdate()
1985 { 2118 {
1986 lock (m_parts) 2119 lockPartsForRead(true);
1987 { 2120 {
1988 foreach (SceneObjectPart part in m_parts.Values) 2121 foreach (SceneObjectPart part in m_parts.Values)
1989 { 2122 {
2123
1990 part.ScheduleTerseUpdate(); 2124 part.ScheduleTerseUpdate();
2125
1991 } 2126 }
1992 } 2127 }
2128 lockPartsForRead(false);
1993 } 2129 }
1994 2130
1995 /// <summary> 2131 /// <summary>
@@ -2002,14 +2138,17 @@ namespace OpenSim.Region.Framework.Scenes
2002 2138
2003 RootPart.SendFullUpdateToAllClients(); 2139 RootPart.SendFullUpdateToAllClients();
2004 2140
2005 lock (m_parts) 2141 lockPartsForRead(true);
2006 { 2142 {
2007 foreach (SceneObjectPart part in m_parts.Values) 2143 foreach (SceneObjectPart part in m_parts.Values)
2008 { 2144 {
2145
2009 if (part != RootPart) 2146 if (part != RootPart)
2010 part.SendFullUpdateToAllClients(); 2147 part.SendFullUpdateToAllClients();
2148
2011 } 2149 }
2012 } 2150 }
2151 lockPartsForRead(false);
2013 } 2152 }
2014 2153
2015 /// <summary> 2154 /// <summary>
@@ -2040,14 +2179,15 @@ namespace OpenSim.Region.Framework.Scenes
2040 { 2179 {
2041 if (IsDeleted) 2180 if (IsDeleted)
2042 return; 2181 return;
2043 2182
2044 lock (m_parts) 2183 lockPartsForRead(true);
2045 { 2184 {
2046 foreach (SceneObjectPart part in m_parts.Values) 2185 foreach (SceneObjectPart part in m_parts.Values)
2047 { 2186 {
2048 part.SendTerseUpdateToAllClients(); 2187 part.SendTerseUpdateToAllClients();
2049 } 2188 }
2050 } 2189 }
2190 lockPartsForRead(false);
2051 } 2191 }
2052 2192
2053 #endregion 2193 #endregion
@@ -2061,16 +2201,18 @@ namespace OpenSim.Region.Framework.Scenes
2061 /// <returns>null if no child part with that linknum or child part</returns> 2201 /// <returns>null if no child part with that linknum or child part</returns>
2062 public SceneObjectPart GetLinkNumPart(int linknum) 2202 public SceneObjectPart GetLinkNumPart(int linknum)
2063 { 2203 {
2064 lock (m_parts) 2204 lockPartsForRead(true);
2065 { 2205 {
2066 foreach (SceneObjectPart part in m_parts.Values) 2206 foreach (SceneObjectPart part in m_parts.Values)
2067 { 2207 {
2068 if (part.LinkNum == linknum) 2208 if (part.LinkNum == linknum)
2069 { 2209 {
2210 lockPartsForRead(false);
2070 return part; 2211 return part;
2071 } 2212 }
2072 } 2213 }
2073 } 2214 }
2215 lockPartsForRead(false);
2074 2216
2075 return null; 2217 return null;
2076 } 2218 }
@@ -2098,17 +2240,19 @@ namespace OpenSim.Region.Framework.Scenes
2098 public SceneObjectPart GetChildPart(uint localID) 2240 public SceneObjectPart GetChildPart(uint localID)
2099 { 2241 {
2100 //m_log.DebugFormat("Entered looking for {0}", localID); 2242 //m_log.DebugFormat("Entered looking for {0}", localID);
2101 lock (m_parts) 2243 lockPartsForRead(true);
2102 { 2244 {
2103 foreach (SceneObjectPart part in m_parts.Values) 2245 foreach (SceneObjectPart part in m_parts.Values)
2104 { 2246 {
2105 //m_log.DebugFormat("Found {0}", part.LocalId); 2247 //m_log.DebugFormat("Found {0}", part.LocalId);
2106 if (part.LocalId == localID) 2248 if (part.LocalId == localID)
2107 { 2249 {
2250 lockPartsForRead(false);
2108 return part; 2251 return part;
2109 } 2252 }
2110 } 2253 }
2111 } 2254 }
2255 lockPartsForRead(false);
2112 2256
2113 return null; 2257 return null;
2114 } 2258 }
@@ -2138,17 +2282,19 @@ namespace OpenSim.Region.Framework.Scenes
2138 public bool HasChildPrim(uint localID) 2282 public bool HasChildPrim(uint localID)
2139 { 2283 {
2140 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID); 2284 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID);
2141 lock (m_parts) 2285 lockPartsForRead(true);
2142 { 2286 {
2143 foreach (SceneObjectPart part in m_parts.Values) 2287 foreach (SceneObjectPart part in m_parts.Values)
2144 { 2288 {
2145 //m_log.DebugFormat("Found {0}", part.LocalId); 2289 //m_log.DebugFormat("Found {0}", part.LocalId);
2146 if (part.LocalId == localID) 2290 if (part.LocalId == localID)
2147 { 2291 {
2292 lockPartsForRead(false);
2148 return true; 2293 return true;
2149 } 2294 }
2150 } 2295 }
2151 } 2296 }
2297 lockPartsForRead(false);
2152 2298
2153 return false; 2299 return false;
2154 } 2300 }
@@ -2198,53 +2344,57 @@ namespace OpenSim.Region.Framework.Scenes
2198 if (m_rootPart.LinkNum == 0) 2344 if (m_rootPart.LinkNum == 0)
2199 m_rootPart.LinkNum = 1; 2345 m_rootPart.LinkNum = 1;
2200 2346
2201 lock (m_parts) 2347 lockPartsForWrite(true);
2202 { 2348
2203 m_parts.Add(linkPart.UUID, linkPart); 2349 m_parts.Add(linkPart.UUID, linkPart);
2204 2350
2205 // Insert in terms of link numbers, the new links 2351 lockPartsForWrite(false);
2206 // before the current ones (with the exception of 2352
2207 // the root prim. Shuffle the old ones up 2353 // Insert in terms of link numbers, the new links
2208 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts) 2354 // before the current ones (with the exception of
2355 // the root prim. Shuffle the old ones up
2356 lockPartsForRead(true);
2357 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts)
2358 {
2359 if (kvp.Value.LinkNum != 1)
2209 { 2360 {
2210 if (kvp.Value.LinkNum != 1) 2361 // Don't update root prim link number
2211 { 2362 kvp.Value.LinkNum += objectGroup.PrimCount;
2212 // Don't update root prim link number
2213 kvp.Value.LinkNum += objectGroup.PrimCount;
2214 }
2215 } 2363 }
2364 }
2365 lockPartsForRead(false);
2216 2366
2217 linkPart.LinkNum = 2; 2367 linkPart.LinkNum = 2;
2218 2368
2219 linkPart.SetParent(this); 2369 linkPart.SetParent(this);
2220 linkPart.AddFlag(PrimFlags.CreateSelected); 2370 linkPart.AddFlag(PrimFlags.CreateSelected);
2221 2371
2222 //if (linkPart.PhysActor != null) 2372 //if (linkPart.PhysActor != null)
2223 //{ 2373 //{
2224 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); 2374 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
2225 2375
2226 //linkPart.PhysActor = null; 2376 //linkPart.PhysActor = null;
2227 //} 2377 //}
2228 2378
2229 //TODO: rest of parts 2379 //TODO: rest of parts
2230 int linkNum = 3; 2380 int linkNum = 3;
2231 foreach (SceneObjectPart part in objectGroup.Children.Values) 2381 foreach (SceneObjectPart part in objectGroup.Children.Values)
2382 {
2383 if (part.UUID != objectGroup.m_rootPart.UUID)
2232 { 2384 {
2233 if (part.UUID != objectGroup.m_rootPart.UUID) 2385 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2234 {
2235 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2236 }
2237 part.ClearUndoState();
2238 } 2386 }
2387 part.ClearUndoState();
2239 } 2388 }
2240 2389
2241 m_scene.UnlinkSceneObject(objectGroup.UUID, true); 2390 m_scene.UnlinkSceneObject(objectGroup.UUID, true);
2242 objectGroup.m_isDeleted = true; 2391 objectGroup.m_isDeleted = true;
2392
2393 objectGroup.lockPartsForWrite(true);
2243 2394
2244 lock (objectGroup.m_parts) 2395 objectGroup.m_parts.Clear();
2245 { 2396
2246 objectGroup.m_parts.Clear(); 2397 objectGroup.lockPartsForWrite(false);
2247 }
2248 2398
2249 // Can't do this yet since backup still makes use of the root part without any synchronization 2399 // Can't do this yet since backup still makes use of the root part without any synchronization
2250// objectGroup.m_rootPart = null; 2400// objectGroup.m_rootPart = null;
@@ -2303,11 +2453,12 @@ namespace OpenSim.Region.Framework.Scenes
2303 Quaternion worldRot = linkPart.GetWorldRotation(); 2453 Quaternion worldRot = linkPart.GetWorldRotation();
2304 2454
2305 // Remove the part from this object 2455 // Remove the part from this object
2306 lock (m_parts) 2456 lockPartsForWrite(true);
2307 { 2457 {
2308 m_parts.Remove(linkPart.UUID); 2458 m_parts.Remove(linkPart.UUID);
2309 } 2459 }
2310 2460 lockPartsForWrite(false);
2461 lockPartsForRead(true);
2311 if (m_parts.Count == 1 && RootPart != null) //Single prim is left 2462 if (m_parts.Count == 1 && RootPart != null) //Single prim is left
2312 RootPart.LinkNum = 0; 2463 RootPart.LinkNum = 0;
2313 else 2464 else
@@ -2318,6 +2469,7 @@ namespace OpenSim.Region.Framework.Scenes
2318 p.LinkNum--; 2469 p.LinkNum--;
2319 } 2470 }
2320 } 2471 }
2472 lockPartsForRead(false);
2321 2473
2322 linkPart.ParentID = 0; 2474 linkPart.ParentID = 0;
2323 linkPart.LinkNum = 0; 2475 linkPart.LinkNum = 0;
@@ -2635,9 +2787,12 @@ namespace OpenSim.Region.Framework.Scenes
2635 2787
2636 if (selectionPart != null) 2788 if (selectionPart != null)
2637 { 2789 {
2638 lock (m_parts) 2790 lockPartsForRead(true);
2791 List<SceneObjectPart> parts = new List<SceneObjectPart>(m_parts.Values);
2792 lockPartsForRead(false);
2793 foreach (SceneObjectPart part in parts)
2639 { 2794 {
2640 foreach (SceneObjectPart part in m_parts.Values) 2795 if (part.Scale.X > 10.0 || part.Scale.Y > 10.0 || part.Scale.Z > 10.0)
2641 { 2796 {
2642 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax || 2797 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax ||
2643 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax || 2798 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax ||
@@ -2647,12 +2802,13 @@ namespace OpenSim.Region.Framework.Scenes
2647 break; 2802 break;
2648 } 2803 }
2649 } 2804 }
2805 }
2650 2806
2651 foreach (SceneObjectPart part in m_parts.Values) 2807 foreach (SceneObjectPart part in parts)
2652 { 2808 {
2653 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect); 2809 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
2654 }
2655 } 2810 }
2811
2656 } 2812 }
2657 } 2813 }
2658 2814
@@ -2738,11 +2894,9 @@ namespace OpenSim.Region.Framework.Scenes
2738 scale.Y = m_scene.m_maxNonphys; 2894 scale.Y = m_scene.m_maxNonphys;
2739 if (scale.Z > m_scene.m_maxNonphys) 2895 if (scale.Z > m_scene.m_maxNonphys)
2740 scale.Z = m_scene.m_maxNonphys; 2896 scale.Z = m_scene.m_maxNonphys;
2741
2742 SceneObjectPart part = GetChildPart(localID); 2897 SceneObjectPart part = GetChildPart(localID);
2743 if (part != null) 2898 if (part != null)
2744 { 2899 {
2745 part.Resize(scale);
2746 if (part.PhysActor != null) 2900 if (part.PhysActor != null)
2747 { 2901 {
2748 if (part.PhysActor.IsPhysical) 2902 if (part.PhysActor.IsPhysical)
@@ -2757,7 +2911,7 @@ namespace OpenSim.Region.Framework.Scenes
2757 part.PhysActor.Size = scale; 2911 part.PhysActor.Size = scale;
2758 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); 2912 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
2759 } 2913 }
2760 //if (part.UUID != m_rootPart.UUID) 2914 part.Resize(scale);
2761 2915
2762 HasGroupChanged = true; 2916 HasGroupChanged = true;
2763 ScheduleGroupForFullUpdate(); 2917 ScheduleGroupForFullUpdate();
@@ -2798,77 +2952,76 @@ namespace OpenSim.Region.Framework.Scenes
2798 float y = (scale.Y / part.Scale.Y); 2952 float y = (scale.Y / part.Scale.Y);
2799 float z = (scale.Z / part.Scale.Z); 2953 float z = (scale.Z / part.Scale.Z);
2800 2954
2801 lock (m_parts) 2955 lockPartsForRead(true);
2956 if (x > 1.0f || y > 1.0f || z > 1.0f)
2802 { 2957 {
2803 if (x > 1.0f || y > 1.0f || z > 1.0f) 2958 foreach (SceneObjectPart obPart in m_parts.Values)
2804 { 2959 {
2805 foreach (SceneObjectPart obPart in m_parts.Values) 2960 if (obPart.UUID != m_rootPart.UUID)
2806 { 2961 {
2807 if (obPart.UUID != m_rootPart.UUID) 2962 Vector3 oldSize = new Vector3(obPart.Scale);
2808 {
2809 Vector3 oldSize = new Vector3(obPart.Scale);
2810 2963
2811 float f = 1.0f; 2964 float f = 1.0f;
2812 float a = 1.0f; 2965 float a = 1.0f;
2813 2966
2814 if (part.PhysActor != null && part.PhysActor.IsPhysical) 2967 if (part.PhysActor != null && part.PhysActor.IsPhysical)
2968 {
2969 if (oldSize.X*x > m_scene.m_maxPhys)
2815 { 2970 {
2816 if (oldSize.X*x > m_scene.m_maxPhys) 2971 f = m_scene.m_maxPhys / oldSize.X;
2817 { 2972 a = f / x;
2818 f = m_scene.m_maxPhys / oldSize.X; 2973 x *= a;
2819 a = f / x; 2974 y *= a;
2820 x *= a; 2975 z *= a;
2821 y *= a;
2822 z *= a;
2823 }
2824 if (oldSize.Y*y > m_scene.m_maxPhys)
2825 {
2826 f = m_scene.m_maxPhys / oldSize.Y;
2827 a = f / y;
2828 x *= a;
2829 y *= a;
2830 z *= a;
2831 }
2832 if (oldSize.Z*z > m_scene.m_maxPhys)
2833 {
2834 f = m_scene.m_maxPhys / oldSize.Z;
2835 a = f / z;
2836 x *= a;
2837 y *= a;
2838 z *= a;
2839 }
2840 } 2976 }
2841 else 2977 if (oldSize.Y*y > m_scene.m_maxPhys)
2978 {
2979 f = m_scene.m_maxPhys / oldSize.Y;
2980 a = f / y;
2981 x *= a;
2982 y *= a;
2983 z *= a;
2984 }
2985 if (oldSize.Z*z > m_scene.m_maxPhys)
2986 {
2987 f = m_scene.m_maxPhys / oldSize.Z;
2988 a = f / z;
2989 x *= a;
2990 y *= a;
2991 z *= a;
2992 }
2993 }
2994 else
2995 {
2996 if (oldSize.X*x > m_scene.m_maxNonphys)
2997 {
2998 f = m_scene.m_maxNonphys / oldSize.X;
2999 a = f / x;
3000 x *= a;
3001 y *= a;
3002 z *= a;
3003 }
3004 if (oldSize.Y*y > m_scene.m_maxNonphys)
2842 { 3005 {
2843 if (oldSize.X*x > m_scene.m_maxNonphys) 3006 f = m_scene.m_maxNonphys / oldSize.Y;
2844 { 3007 a = f / y;
2845 f = m_scene.m_maxNonphys / oldSize.X; 3008 x *= a;
2846 a = f / x; 3009 y *= a;
2847 x *= a; 3010 z *= a;
2848 y *= a; 3011 }
2849 z *= a; 3012 if (oldSize.Z*z > m_scene.m_maxNonphys)
2850 } 3013 {
2851 if (oldSize.Y*y > m_scene.m_maxNonphys) 3014 f = m_scene.m_maxNonphys / oldSize.Z;
2852 { 3015 a = f / z;
2853 f = m_scene.m_maxNonphys / oldSize.Y; 3016 x *= a;
2854 a = f / y; 3017 y *= a;
2855 x *= a; 3018 z *= a;
2856 y *= a;
2857 z *= a;
2858 }
2859 if (oldSize.Z*z > m_scene.m_maxNonphys)
2860 {
2861 f = m_scene.m_maxNonphys / oldSize.Z;
2862 a = f / z;
2863 x *= a;
2864 y *= a;
2865 z *= a;
2866 }
2867 } 3019 }
2868 } 3020 }
2869 } 3021 }
2870 } 3022 }
2871 } 3023 }
3024 lockPartsForRead(false);
2872 3025
2873 Vector3 prevScale = part.Scale; 3026 Vector3 prevScale = part.Scale;
2874 prevScale.X *= x; 3027 prevScale.X *= x;
@@ -2876,7 +3029,7 @@ namespace OpenSim.Region.Framework.Scenes
2876 prevScale.Z *= z; 3029 prevScale.Z *= z;
2877 part.Resize(prevScale); 3030 part.Resize(prevScale);
2878 3031
2879 lock (m_parts) 3032 lockPartsForRead(true);
2880 { 3033 {
2881 foreach (SceneObjectPart obPart in m_parts.Values) 3034 foreach (SceneObjectPart obPart in m_parts.Values)
2882 { 3035 {
@@ -2895,6 +3048,7 @@ namespace OpenSim.Region.Framework.Scenes
2895 } 3048 }
2896 } 3049 }
2897 } 3050 }
3051 lockPartsForRead(false);
2898 3052
2899 if (part.PhysActor != null) 3053 if (part.PhysActor != null)
2900 { 3054 {
@@ -2975,7 +3129,7 @@ namespace OpenSim.Region.Framework.Scenes
2975 axDiff *= Quaternion.Inverse(partRotation); 3129 axDiff *= Quaternion.Inverse(partRotation);
2976 diff = axDiff; 3130 diff = axDiff;
2977 3131
2978 lock (m_parts) 3132 lockPartsForRead(true);
2979 { 3133 {
2980 foreach (SceneObjectPart obPart in m_parts.Values) 3134 foreach (SceneObjectPart obPart in m_parts.Values)
2981 { 3135 {
@@ -2985,6 +3139,7 @@ namespace OpenSim.Region.Framework.Scenes
2985 } 3139 }
2986 } 3140 }
2987 } 3141 }
3142 lockPartsForRead(false);
2988 3143
2989 AbsolutePosition = newPos; 3144 AbsolutePosition = newPos;
2990 3145
@@ -3102,7 +3257,7 @@ namespace OpenSim.Region.Framework.Scenes
3102 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); 3257 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
3103 } 3258 }
3104 3259
3105 lock (m_parts) 3260 lockPartsForRead(true);
3106 { 3261 {
3107 foreach (SceneObjectPart prim in m_parts.Values) 3262 foreach (SceneObjectPart prim in m_parts.Values)
3108 { 3263 {
@@ -3120,6 +3275,7 @@ namespace OpenSim.Region.Framework.Scenes
3120 } 3275 }
3121 } 3276 }
3122 } 3277 }
3278 lockPartsForRead(false);
3123 3279
3124 m_rootPart.ScheduleTerseUpdate(); 3280 m_rootPart.ScheduleTerseUpdate();
3125 } 3281 }
@@ -3218,7 +3374,7 @@ namespace OpenSim.Region.Framework.Scenes
3218 if (atTargets.Count > 0) 3374 if (atTargets.Count > 0)
3219 { 3375 {
3220 uint[] localids = new uint[0]; 3376 uint[] localids = new uint[0];
3221 lock (m_parts) 3377 lockPartsForRead(true);
3222 { 3378 {
3223 localids = new uint[m_parts.Count]; 3379 localids = new uint[m_parts.Count];
3224 int cntr = 0; 3380 int cntr = 0;
@@ -3228,6 +3384,7 @@ namespace OpenSim.Region.Framework.Scenes
3228 cntr++; 3384 cntr++;
3229 } 3385 }
3230 } 3386 }
3387 lockPartsForRead(false);
3231 3388
3232 for (int ctr = 0; ctr < localids.Length; ctr++) 3389 for (int ctr = 0; ctr < localids.Length; ctr++)
3233 { 3390 {
@@ -3246,7 +3403,7 @@ namespace OpenSim.Region.Framework.Scenes
3246 { 3403 {
3247 //trigger not_at_target 3404 //trigger not_at_target
3248 uint[] localids = new uint[0]; 3405 uint[] localids = new uint[0];
3249 lock (m_parts) 3406 lockPartsForRead(true);
3250 { 3407 {
3251 localids = new uint[m_parts.Count]; 3408 localids = new uint[m_parts.Count];
3252 int cntr = 0; 3409 int cntr = 0;
@@ -3256,7 +3413,8 @@ namespace OpenSim.Region.Framework.Scenes
3256 cntr++; 3413 cntr++;
3257 } 3414 }
3258 } 3415 }
3259 3416 lockPartsForRead(false);
3417
3260 for (int ctr = 0; ctr < localids.Length; ctr++) 3418 for (int ctr = 0; ctr < localids.Length; ctr++)
3261 { 3419 {
3262 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]); 3420 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]);
@@ -3269,19 +3427,20 @@ namespace OpenSim.Region.Framework.Scenes
3269 public float GetMass() 3427 public float GetMass()
3270 { 3428 {
3271 float retmass = 0f; 3429 float retmass = 0f;
3272 lock (m_parts) 3430 lockPartsForRead(true);
3273 { 3431 {
3274 foreach (SceneObjectPart part in m_parts.Values) 3432 foreach (SceneObjectPart part in m_parts.Values)
3275 { 3433 {
3276 retmass += part.GetMass(); 3434 retmass += part.GetMass();
3277 } 3435 }
3278 } 3436 }
3437 lockPartsForRead(false);
3279 return retmass; 3438 return retmass;
3280 } 3439 }
3281 3440
3282 public void CheckSculptAndLoad() 3441 public void CheckSculptAndLoad()
3283 { 3442 {
3284 lock (m_parts) 3443 lockPartsForRead(true);
3285 { 3444 {
3286 if (!IsDeleted) 3445 if (!IsDeleted)
3287 { 3446 {
@@ -3306,6 +3465,7 @@ namespace OpenSim.Region.Framework.Scenes
3306 } 3465 }
3307 } 3466 }
3308 } 3467 }
3468 lockPartsForRead(false);
3309 } 3469 }
3310 3470
3311 protected void AssetReceived(string id, Object sender, AssetBase asset) 3471 protected void AssetReceived(string id, Object sender, AssetBase asset)
@@ -3326,7 +3486,7 @@ namespace OpenSim.Region.Framework.Scenes
3326 /// <param name="client"></param> 3486 /// <param name="client"></param>
3327 public void SetGroup(UUID GroupID, IClientAPI client) 3487 public void SetGroup(UUID GroupID, IClientAPI client)
3328 { 3488 {
3329 lock (m_parts) 3489 lockPartsForRead(true);
3330 { 3490 {
3331 foreach (SceneObjectPart part in m_parts.Values) 3491 foreach (SceneObjectPart part in m_parts.Values)
3332 { 3492 {
@@ -3336,7 +3496,7 @@ namespace OpenSim.Region.Framework.Scenes
3336 3496
3337 HasGroupChanged = true; 3497 HasGroupChanged = true;
3338 } 3498 }
3339 3499 lockPartsForRead(false);
3340 ScheduleGroupForFullUpdate(); 3500 ScheduleGroupForFullUpdate();
3341 } 3501 }
3342 3502
@@ -3355,11 +3515,12 @@ namespace OpenSim.Region.Framework.Scenes
3355 3515
3356 public void SetAttachmentPoint(byte point) 3516 public void SetAttachmentPoint(byte point)
3357 { 3517 {
3358 lock (m_parts) 3518 lockPartsForRead(true);
3359 { 3519 {
3360 foreach (SceneObjectPart part in m_parts.Values) 3520 foreach (SceneObjectPart part in m_parts.Values)
3361 part.SetAttachmentPoint(point); 3521 part.SetAttachmentPoint(point);
3362 } 3522 }
3523 lockPartsForRead(false);
3363 } 3524 }
3364 3525
3365 #region ISceneObject 3526 #region ISceneObject
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 73f79b3..7906138 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;