aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework/Scenes')
-rw-r--r--OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs23
-rw-r--r--OpenSim/Region/Framework/Scenes/EntityManager.cs79
-rw-r--r--OpenSim/Region/Framework/Scenes/EventManager.cs12
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs8
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs41
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs557
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs98
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs380
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs404
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs11
10 files changed, 1070 insertions, 543 deletions
diff --git a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
index a459ffa..50624a1 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, UUID.Zero)) 131 anim, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, UUID.Zero))
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
@@ -156,10 +161,10 @@ namespace OpenSim.Region.Framework.Scenes.Animation
156 Vector3 left = Vector3.Transform(Vector3.UnitY, rotMatrix); 161 Vector3 left = Vector3.Transform(Vector3.UnitY, rotMatrix);
157 162
158 // Check control flags 163 // Check control flags
159 bool heldForward = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_AT_POS; 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);
160 bool heldBack = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG; 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);
161 bool heldLeft = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS; 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);
162 bool heldRight = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG; 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);
163 //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;
164 //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;
165 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;
@@ -312,7 +317,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
312 public void UpdateMovementAnimations() 317 public void UpdateMovementAnimations()
313 { 318 {
314 m_movementAnimation = GetMovementAnimation(); 319 m_movementAnimation = GetMovementAnimation();
315 320//Console.WriteLine("UMA got {0}", m_movementAnimation);
316 if (m_movementAnimation == "PREJUMP" && !m_scenePresence.Scene.m_usePreJump) 321 if (m_movementAnimation == "PREJUMP" && !m_scenePresence.Scene.m_usePreJump)
317 { 322 {
318 // This was the previous behavior before PREJUMP 323 // This was the previous behavior before PREJUMP
@@ -450,4 +455,4 @@ namespace OpenSim.Region.Framework.Scenes.Animation
450 m_scenePresence = null; 455 m_scenePresence = null;
451 } 456 }
452 } 457 }
453} \ 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 753344d..a86e263 100644
--- a/OpenSim/Region/Framework/Scenes/EventManager.cs
+++ b/OpenSim/Region/Framework/Scenes/EventManager.cs
@@ -193,7 +193,9 @@ namespace OpenSim.Region.Framework.Scenes
193 public event OnMakeChildAgentDelegate OnMakeChildAgent; 193 public event OnMakeChildAgentDelegate OnMakeChildAgent;
194 194
195 public delegate void OnMakeRootAgentDelegate(ScenePresence presence); 195 public delegate void OnMakeRootAgentDelegate(ScenePresence presence);
196 public delegate void OnSaveNewWindlightProfileDelegate();
196 public event OnMakeRootAgentDelegate OnMakeRootAgent; 197 public event OnMakeRootAgentDelegate OnMakeRootAgent;
198 public event OnSaveNewWindlightProfileDelegate OnSaveNewWindlightProfile;
197 199
198 public delegate void NewInventoryItemUploadComplete(UUID avatarID, UUID assetID, string name, int userlevel); 200 public delegate void NewInventoryItemUploadComplete(UUID avatarID, UUID assetID, string name, int userlevel);
199 201
@@ -411,6 +413,7 @@ namespace OpenSim.Region.Framework.Scenes
411 private IncomingInstantMessage handlerUnhandledInstantMessage = null; //OnUnhandledInstantMessage; 413 private IncomingInstantMessage handlerUnhandledInstantMessage = null; //OnUnhandledInstantMessage;
412 private ClientClosed handlerClientClosed = null; //OnClientClosed; 414 private ClientClosed handlerClientClosed = null; //OnClientClosed;
413 private OnMakeChildAgentDelegate handlerMakeChildAgent = null; //OnMakeChildAgent; 415 private OnMakeChildAgentDelegate handlerMakeChildAgent = null; //OnMakeChildAgent;
416 private OnSaveNewWindlightProfileDelegate handlerSaveNewWindlightProfile = null; //OnSaveNewWindlightProfile;
414 private OnMakeRootAgentDelegate handlerMakeRootAgent = null; //OnMakeRootAgent; 417 private OnMakeRootAgentDelegate handlerMakeRootAgent = null; //OnMakeRootAgent;
415 private OnTerrainTickDelegate handlerTerrainTick = null; // OnTerainTick; 418 private OnTerrainTickDelegate handlerTerrainTick = null; // OnTerainTick;
416 private RegisterCapsEvent handlerRegisterCaps = null; // OnRegisterCaps; 419 private RegisterCapsEvent handlerRegisterCaps = null; // OnRegisterCaps;
@@ -772,6 +775,15 @@ namespace OpenSim.Region.Framework.Scenes
772 } 775 }
773 } 776 }
774 777
778 public void TriggerOnSaveNewWindlightProfile()
779 {
780 handlerSaveNewWindlightProfile = OnSaveNewWindlightProfile;
781 if (handlerSaveNewWindlightProfile != null)
782 {
783 handlerSaveNewWindlightProfile();
784 }
785 }
786
775 public void TriggerOnMakeRootAgent(ScenePresence presence) 787 public void TriggerOnMakeRootAgent(ScenePresence presence)
776 { 788 {
777 handlerMakeRootAgent = OnMakeRootAgent; 789 handlerMakeRootAgent = OnMakeRootAgent;
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index 0b0c205..7ca779a 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -840,8 +840,12 @@ namespace OpenSim.Region.Framework.Scenes
840 public void RemoveTaskInventory(IClientAPI remoteClient, UUID itemID, uint localID) 840 public void RemoveTaskInventory(IClientAPI remoteClient, UUID itemID, uint localID)
841 { 841 {
842 SceneObjectPart part = GetSceneObjectPart(localID); 842 SceneObjectPart part = GetSceneObjectPart(localID);
843 SceneObjectGroup group = part.ParentGroup; 843 SceneObjectGroup group = null;
844 if (group != null) 844 if (part != null)
845 {
846 group = part.ParentGroup;
847 }
848 if (part != null && group != null)
845 { 849 {
846 TaskInventoryItem item = group.GetInventoryItem(localID, itemID); 850 TaskInventoryItem item = group.GetInventoryItem(localID, itemID);
847 if (item == null) 851 if (item == null)
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index a22fb5f..1b275b0 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);
@@ -881,6 +883,15 @@ namespace OpenSim.Region.Framework.Scenes
881 /// <param name="seconds">float indicating duration before restart.</param> 883 /// <param name="seconds">float indicating duration before restart.</param>
882 public virtual void Restart(float seconds) 884 public virtual void Restart(float seconds)
883 { 885 {
886 Restart(seconds, true);
887 }
888
889 /// <summary>
890 /// Given float seconds, this will restart the region. showDialog will optionally alert the users.
891 /// </summary>
892 /// <param name="seconds">float indicating duration before restart.</param>
893 public virtual void Restart(float seconds, bool showDialog)
894 {
884 // notifications are done in 15 second increments 895 // notifications are done in 15 second increments
885 // so .. if the number of seconds is less then 15 seconds, it's not really a restart request 896 // so .. if the number of seconds is less then 15 seconds, it's not really a restart request
886 // It's a 'Cancel restart' request. 897 // It's a 'Cancel restart' request.
@@ -901,8 +912,11 @@ namespace OpenSim.Region.Framework.Scenes
901 m_restartTimer.Elapsed += new ElapsedEventHandler(RestartTimer_Elapsed); 912 m_restartTimer.Elapsed += new ElapsedEventHandler(RestartTimer_Elapsed);
902 m_log.Info("[REGION]: Restarting Region in " + (seconds / 60) + " minutes"); 913 m_log.Info("[REGION]: Restarting Region in " + (seconds / 60) + " minutes");
903 m_restartTimer.Start(); 914 m_restartTimer.Start();
904 m_dialogModule.SendNotificationToUsersInRegion( 915 if (showDialog)
905 UUID.Random(), String.Empty, RegionInfo.RegionName + ": Restarting in 2 Minutes"); 916 {
917 m_dialogModule.SendNotificationToUsersInRegion(
918 UUID.Random(), String.Empty, RegionInfo.RegionName + ": Restarting in " + (seconds / 60).ToString() + " Minutes");
919 }
906 } 920 }
907 } 921 }
908 922
@@ -1173,16 +1187,16 @@ namespace OpenSim.Region.Framework.Scenes
1173 // Check if any objects have reached their targets 1187 // Check if any objects have reached their targets
1174 CheckAtTargets(); 1188 CheckAtTargets();
1175 1189
1176 // Update SceneObjectGroups that have scheduled themselves for updates
1177 // Objects queue their updates onto all scene presences
1178 if (m_frame % m_update_objects == 0)
1179 m_sceneGraph.UpdateObjectGroups();
1180
1181 // Run through all ScenePresences looking for updates 1190 // Run through all ScenePresences looking for updates
1182 // Presence updates and queued object updates for each presence are sent to clients 1191 // Presence updates and queued object updates for each presence are sent to clients
1183 if (m_frame % m_update_presences == 0) 1192 if (m_frame % m_update_presences == 0)
1184 m_sceneGraph.UpdatePresences(); 1193 m_sceneGraph.UpdatePresences();
1185 1194
1195 // Update SceneObjectGroups that have scheduled themselves for updates
1196 // Objects queue their updates onto all scene presences
1197 if (m_frame % m_update_objects == 0)
1198 m_sceneGraph.UpdateObjectGroups();
1199
1186 int tmpPhysicsMS2 = Util.EnvironmentTickCount(); 1200 int tmpPhysicsMS2 = Util.EnvironmentTickCount();
1187 if ((m_frame % m_update_physics == 0) && m_physics_enabled) 1201 if ((m_frame % m_update_physics == 0) && m_physics_enabled)
1188 m_sceneGraph.UpdatePreparePhysics(); 1202 m_sceneGraph.UpdatePreparePhysics();
@@ -1490,6 +1504,19 @@ namespace OpenSim.Region.Framework.Scenes
1490 { 1504 {
1491 m_storageManager.DataStore.StoreTerrain(Heightmap.GetDoubles(), RegionInfo.RegionID); 1505 m_storageManager.DataStore.StoreTerrain(Heightmap.GetDoubles(), RegionInfo.RegionID);
1492 } 1506 }
1507
1508 public void StoreWindlightProfile(RegionMeta7WindlightData wl)
1509 {
1510 m_regInfo.WindlightSettings = wl;
1511 m_storageManager.DataStore.StoreRegionWindlightSettings(wl);
1512 m_eventManager.TriggerOnSaveNewWindlightProfile();
1513 }
1514
1515 public void LoadWindlightProfile()
1516 {
1517 m_regInfo.WindlightSettings = m_storageManager.DataStore.LoadRegionWindlightSettings(RegionInfo.RegionID);
1518 m_eventManager.TriggerOnSaveNewWindlightProfile();
1519 }
1493 1520
1494 /// <summary> 1521 /// <summary>
1495 /// Loads the World heightmap 1522 /// Loads the World heightmap
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index cb87212..eacd219 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 //{
@@ -432,13 +504,16 @@ namespace OpenSim.Region.Framework.Scenes
432 504
433 public void SetFromItemID(UUID AssetId) 505 public void SetFromItemID(UUID AssetId)
434 { 506 {
435 lock (m_parts) 507 lockPartsForRead(true);
436 { 508 {
437 foreach (SceneObjectPart part in m_parts.Values) 509 foreach (SceneObjectPart part in m_parts.Values)
438 { 510 {
511
439 part.FromItemID = AssetId; 512 part.FromItemID = AssetId;
513
440 } 514 }
441 } 515 }
516 lockPartsForRead(false);
442 } 517 }
443 518
444 public UUID GetFromItemID() 519 public UUID GetFromItemID()
@@ -505,10 +580,11 @@ namespace OpenSim.Region.Framework.Scenes
505 Vector3 maxScale = Vector3.Zero; 580 Vector3 maxScale = Vector3.Zero;
506 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f); 581 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f);
507 582
508 lock (m_parts) 583 lockPartsForRead(true);
509 { 584 {
510 foreach (SceneObjectPart part in m_parts.Values) 585 foreach (SceneObjectPart part in m_parts.Values)
511 { 586 {
587
512 Vector3 partscale = part.Scale; 588 Vector3 partscale = part.Scale;
513 Vector3 partoffset = part.OffsetPosition; 589 Vector3 partoffset = part.OffsetPosition;
514 590
@@ -519,8 +595,11 @@ namespace OpenSim.Region.Framework.Scenes
519 maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X; 595 maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X;
520 maxScale.Y = (partscale.Y + partoffset.Y > maxScale.Y) ? partscale.Y + partoffset.Y : maxScale.Y; 596 maxScale.Y = (partscale.Y + partoffset.Y > maxScale.Y) ? partscale.Y + partoffset.Y : maxScale.Y;
521 maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z; 597 maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z;
598
522 } 599 }
523 } 600 }
601 lockPartsForRead(false);
602
524 finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X; 603 finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X;
525 finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y; 604 finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y;
526 finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z; 605 finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z;
@@ -536,10 +615,11 @@ namespace OpenSim.Region.Framework.Scenes
536 615
537 EntityIntersection result = new EntityIntersection(); 616 EntityIntersection result = new EntityIntersection();
538 617
539 lock (m_parts) 618 lockPartsForRead(true);
540 { 619 {
541 foreach (SceneObjectPart part in m_parts.Values) 620 foreach (SceneObjectPart part in m_parts.Values)
542 { 621 {
622
543 // Temporary commented to stop compiler warning 623 // Temporary commented to stop compiler warning
544 //Vector3 partPosition = 624 //Vector3 partPosition =
545 // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z); 625 // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z);
@@ -567,8 +647,10 @@ namespace OpenSim.Region.Framework.Scenes
567 result.distance = inter.distance; 647 result.distance = inter.distance;
568 } 648 }
569 } 649 }
650
570 } 651 }
571 } 652 }
653 lockPartsForRead(false);
572 return result; 654 return result;
573 } 655 }
574 656
@@ -581,10 +663,11 @@ namespace OpenSim.Region.Framework.Scenes
581 public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight) 663 public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight)
582 { 664 {
583 float maxX = -256f, maxY = -256f, maxZ = -256f, minX = 256f, minY = 256f, minZ = 256f; 665 float maxX = -256f, maxY = -256f, maxZ = -256f, minX = 256f, minY = 256f, minZ = 256f;
584 lock (m_parts) 666 lockPartsForRead(true);
585 { 667 {
586 foreach (SceneObjectPart part in m_parts.Values) 668 foreach (SceneObjectPart part in m_parts.Values)
587 { 669 {
670
588 Vector3 worldPos = part.GetWorldPosition(); 671 Vector3 worldPos = part.GetWorldPosition();
589 Vector3 offset = worldPos - AbsolutePosition; 672 Vector3 offset = worldPos - AbsolutePosition;
590 Quaternion worldRot; 673 Quaternion worldRot;
@@ -643,6 +726,8 @@ namespace OpenSim.Region.Framework.Scenes
643 backBottomRight.Y = orig.Y + (part.Scale.Y / 2); 726 backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
644 backBottomRight.Z = orig.Z - (part.Scale.Z / 2); 727 backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
645 728
729
730
646 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z); 731 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
647 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z); 732 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
648 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z); 733 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
@@ -814,6 +899,7 @@ namespace OpenSim.Region.Framework.Scenes
814 minZ = backBottomLeft.Z; 899 minZ = backBottomLeft.Z;
815 } 900 }
816 } 901 }
902 lockPartsForRead(false);
817 903
818 Vector3 boundingBox = new Vector3(maxX - minX, maxY - minY, maxZ - minZ); 904 Vector3 boundingBox = new Vector3(maxX - minX, maxY - minY, maxZ - minZ);
819 905
@@ -842,17 +928,20 @@ namespace OpenSim.Region.Framework.Scenes
842 Dictionary<UUID,string> states = new Dictionary<UUID,string>(); 928 Dictionary<UUID,string> states = new Dictionary<UUID,string>();
843 929
844 // Capture script state while holding the lock 930 // Capture script state while holding the lock
845 lock (m_parts) 931 lockPartsForRead(true);
846 { 932 {
847 foreach (SceneObjectPart part in m_parts.Values) 933 foreach (SceneObjectPart part in m_parts.Values)
848 { 934 {
935
849 Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates(); 936 Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates();
850 foreach (UUID itemid in pstates.Keys) 937 foreach (UUID itemid in pstates.Keys)
851 { 938 {
852 states.Add(itemid, pstates[itemid]); 939 states.Add(itemid, pstates[itemid]);
853 } 940 }
941
854 } 942 }
855 } 943 }
944 lockPartsForRead(false);
856 945
857 if (states.Count > 0) 946 if (states.Count > 0)
858 { 947 {
@@ -1014,13 +1103,16 @@ namespace OpenSim.Region.Framework.Scenes
1014 1103
1015 public override void UpdateMovement() 1104 public override void UpdateMovement()
1016 { 1105 {
1017 lock (m_parts) 1106 lockPartsForRead(true);
1018 { 1107 {
1019 foreach (SceneObjectPart part in m_parts.Values) 1108 foreach (SceneObjectPart part in m_parts.Values)
1020 { 1109 {
1110
1021 part.UpdateMovement(); 1111 part.UpdateMovement();
1112
1022 } 1113 }
1023 } 1114 }
1115 lockPartsForRead(false);
1024 } 1116 }
1025 1117
1026 public ushort GetTimeDilation() 1118 public ushort GetTimeDilation()
@@ -1064,7 +1156,7 @@ namespace OpenSim.Region.Framework.Scenes
1064 /// <param name="part"></param> 1156 /// <param name="part"></param>
1065 public void AddPart(SceneObjectPart part) 1157 public void AddPart(SceneObjectPart part)
1066 { 1158 {
1067 lock (m_parts) 1159 lockPartsForWrite(true);
1068 { 1160 {
1069 part.SetParent(this); 1161 part.SetParent(this);
1070 m_parts.Add(part.UUID, part); 1162 m_parts.Add(part.UUID, part);
@@ -1074,6 +1166,7 @@ namespace OpenSim.Region.Framework.Scenes
1074 if (part.LinkNum == 2 && RootPart != null) 1166 if (part.LinkNum == 2 && RootPart != null)
1075 RootPart.LinkNum = 1; 1167 RootPart.LinkNum = 1;
1076 } 1168 }
1169 lockPartsForWrite(false);
1077 } 1170 }
1078 1171
1079 /// <summary> 1172 /// <summary>
@@ -1081,28 +1174,33 @@ namespace OpenSim.Region.Framework.Scenes
1081 /// </summary> 1174 /// </summary>
1082 private void UpdateParentIDs() 1175 private void UpdateParentIDs()
1083 { 1176 {
1084 lock (m_parts) 1177 lockPartsForRead(true);
1085 { 1178 {
1086 foreach (SceneObjectPart part in m_parts.Values) 1179 foreach (SceneObjectPart part in m_parts.Values)
1087 { 1180 {
1181
1088 if (part.UUID != m_rootPart.UUID) 1182 if (part.UUID != m_rootPart.UUID)
1089 { 1183 {
1090 part.ParentID = m_rootPart.LocalId; 1184 part.ParentID = m_rootPart.LocalId;
1091 } 1185 }
1186
1092 } 1187 }
1093 } 1188 }
1189 lockPartsForRead(false);
1094 } 1190 }
1095 1191
1096 public void RegenerateFullIDs() 1192 public void RegenerateFullIDs()
1097 { 1193 {
1098 lock (m_parts) 1194 lockPartsForRead(true);
1099 { 1195 {
1100 foreach (SceneObjectPart part in m_parts.Values) 1196 foreach (SceneObjectPart part in m_parts.Values)
1101 { 1197 {
1198
1102 part.UUID = UUID.Random(); 1199 part.UUID = UUID.Random();
1103 1200
1104 } 1201 }
1105 } 1202 }
1203 lockPartsForRead(false);
1106 } 1204 }
1107 1205
1108 // helper provided for parts. 1206 // helper provided for parts.
@@ -1183,29 +1281,33 @@ namespace OpenSim.Region.Framework.Scenes
1183 1281
1184 DetachFromBackup(); 1282 DetachFromBackup();
1185 1283
1186 lock (m_parts) 1284 lockPartsForRead(true);
1285 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1286 lockPartsForRead(false);
1287
1288 foreach (SceneObjectPart part in values)
1187 { 1289 {
1188 foreach (SceneObjectPart part in m_parts.Values)
1189 {
1190// part.Inventory.RemoveScriptInstances(); 1290// part.Inventory.RemoveScriptInstances();
1191 1291
1192 ScenePresence[] avatars = Scene.GetScenePresences(); 1292 ScenePresence[] avatars = Scene.GetScenePresences();
1193 for (int i = 0; i < avatars.Length; i++) 1293 for (int i = 0; i < avatars.Length; i++)
1294 {
1295 if (avatars[i].ParentID == LocalId)
1194 { 1296 {
1195 if (avatars[i].ParentID == LocalId) 1297 avatars[i].StandUp();
1196 { 1298 }
1197 avatars[i].StandUp();
1198 }
1199 1299
1200 if (!silent) 1300 if (!silent)
1201 { 1301 {
1202 part.UpdateFlag = 0; 1302 part.UpdateFlag = 0;
1203 if (part == m_rootPart) 1303 if (part == m_rootPart)
1204 avatars[i].ControllingClient.SendKillObject(m_regionHandle, part.LocalId); 1304 avatars[i].ControllingClient.SendKillObject(m_regionHandle, part.LocalId);
1205 }
1206 } 1305 }
1207 } 1306 }
1307
1208 } 1308 }
1309
1310
1209 } 1311 }
1210 1312
1211 public void AddScriptLPS(int count) 1313 public void AddScriptLPS(int count)
@@ -1230,17 +1332,20 @@ namespace OpenSim.Region.Framework.Scenes
1230 1332
1231 scriptEvents aggregateScriptEvents=0; 1333 scriptEvents aggregateScriptEvents=0;
1232 1334
1233 lock (m_parts) 1335 lockPartsForRead(true);
1234 { 1336 {
1235 foreach (SceneObjectPart part in m_parts.Values) 1337 foreach (SceneObjectPart part in m_parts.Values)
1236 { 1338 {
1339
1237 if (part == null) 1340 if (part == null)
1238 continue; 1341 continue;
1239 if (part != RootPart) 1342 if (part != RootPart)
1240 part.ObjectFlags = objectflagupdate; 1343 part.ObjectFlags = objectflagupdate;
1241 aggregateScriptEvents |= part.AggregateScriptEvents; 1344 aggregateScriptEvents |= part.AggregateScriptEvents;
1345
1242 } 1346 }
1243 } 1347 }
1348 lockPartsForRead(false);
1244 1349
1245 m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0); 1350 m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0);
1246 m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0); 1351 m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0);
@@ -1273,42 +1378,52 @@ namespace OpenSim.Region.Framework.Scenes
1273 /// <param name="m_physicalPrim"></param> 1378 /// <param name="m_physicalPrim"></param>
1274 public void ApplyPhysics(bool m_physicalPrim) 1379 public void ApplyPhysics(bool m_physicalPrim)
1275 { 1380 {
1276 lock (m_parts) 1381 lockPartsForRead(true);
1382
1383 if (m_parts.Count > 1)
1277 { 1384 {
1278 if (m_parts.Count > 1) 1385 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1386 lockPartsForRead(false);
1387 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1388 foreach (SceneObjectPart part in values)
1279 { 1389 {
1280 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim); 1390
1281 foreach (SceneObjectPart part in m_parts.Values) 1391 if (part.LocalId != m_rootPart.LocalId)
1282 { 1392 {
1283 if (part.LocalId != m_rootPart.LocalId) 1393 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
1284 {
1285 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
1286 }
1287 } 1394 }
1288 1395
1289 // Hack to get the physics scene geometries in the right spot
1290 ResetChildPrimPhysicsPositions();
1291 }
1292 else
1293 {
1294 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1295 } 1396 }
1397 // Hack to get the physics scene geometries in the right spot
1398 ResetChildPrimPhysicsPositions();
1399 }
1400 else
1401 {
1402 lockPartsForRead(false);
1403 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1296 } 1404 }
1297 } 1405 }
1298 1406
1299 public void SetOwnerId(UUID userId) 1407 public void SetOwnerId(UUID userId)
1300 { 1408 {
1301 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); 1409 ForEachPart(delegate(SceneObjectPart part)
1410 {
1411
1412 part.OwnerID = userId;
1413
1414 });
1302 } 1415 }
1303 1416
1304 public void ForEachPart(Action<SceneObjectPart> whatToDo) 1417 public void ForEachPart(Action<SceneObjectPart> whatToDo)
1305 { 1418 {
1306 lock (m_parts) 1419 lockPartsForRead(true);
1420 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1421 lockPartsForRead(false);
1422 foreach (SceneObjectPart part in values)
1307 { 1423 {
1308 foreach (SceneObjectPart part in m_parts.Values) 1424
1309 { 1425 whatToDo(part);
1310 whatToDo(part); 1426
1311 }
1312 } 1427 }
1313 } 1428 }
1314 1429
@@ -1407,14 +1522,17 @@ namespace OpenSim.Region.Framework.Scenes
1407 { 1522 {
1408 SendPartFullUpdate(remoteClient, RootPart, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID)); 1523 SendPartFullUpdate(remoteClient, RootPart, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID));
1409 1524
1410 lock (m_parts) 1525 lockPartsForRead(true);
1411 { 1526 {
1412 foreach (SceneObjectPart part in m_parts.Values) 1527 foreach (SceneObjectPart part in m_parts.Values)
1413 { 1528 {
1529
1414 if (part != RootPart) 1530 if (part != RootPart)
1415 SendPartFullUpdate(remoteClient, part, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID)); 1531 SendPartFullUpdate(remoteClient, part, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID));
1532
1416 } 1533 }
1417 } 1534 }
1535 lockPartsForRead(false);
1418 } 1536 }
1419 1537
1420 /// <summary> 1538 /// <summary>
@@ -1509,10 +1627,11 @@ namespace OpenSim.Region.Framework.Scenes
1509 1627
1510 List<SceneObjectPart> partList; 1628 List<SceneObjectPart> partList;
1511 1629
1512 lock (m_parts) 1630 lockPartsForRead(true);
1513 { 1631
1514 partList = new List<SceneObjectPart>(m_parts.Values); 1632 partList = new List<SceneObjectPart>(m_parts.Values);
1515 } 1633
1634 lockPartsForRead(false);
1516 1635
1517 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) 1636 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1518 { 1637 {
@@ -1735,6 +1854,45 @@ namespace OpenSim.Region.Framework.Scenes
1735 } 1854 }
1736 } 1855 }
1737 1856
1857 public void rotLookAt(Quaternion target, float strength, float damping)
1858 {
1859 SceneObjectPart rootpart = m_rootPart;
1860 if (rootpart != null)
1861 {
1862 if (IsAttachment)
1863 {
1864 /*
1865 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
1866 if (avatar != null)
1867 {
1868 Rotate the Av?
1869 } */
1870 }
1871 else
1872 {
1873 if (rootpart.PhysActor != null)
1874 {
1875 rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W);
1876 rootpart.PhysActor.APIDStrength = strength;
1877 rootpart.PhysActor.APIDDamping = damping;
1878 rootpart.PhysActor.APIDActive = true;
1879 }
1880 }
1881 }
1882 }
1883 public void stopLookAt()
1884 {
1885 SceneObjectPart rootpart = m_rootPart;
1886 if (rootpart != null)
1887 {
1888 if (rootpart.PhysActor != null)
1889 {
1890 rootpart.PhysActor.APIDActive = false;
1891 }
1892 }
1893
1894 }
1895
1738 /// <summary> 1896 /// <summary>
1739 /// Uses a PID to attempt to clamp the object on the Z axis at the given height over tau seconds. 1897 /// Uses a PID to attempt to clamp the object on the Z axis at the given height over tau seconds.
1740 /// </summary> 1898 /// </summary>
@@ -1796,10 +1954,11 @@ namespace OpenSim.Region.Framework.Scenes
1796 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 1954 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
1797 newPart.SetParent(this); 1955 newPart.SetParent(this);
1798 1956
1799 lock (m_parts) 1957 lockPartsForWrite(true);
1800 { 1958 {
1801 m_parts.Add(newPart.UUID, newPart); 1959 m_parts.Add(newPart.UUID, newPart);
1802 } 1960 }
1961 lockPartsForWrite(false);
1803 1962
1804 SetPartAsNonRoot(newPart); 1963 SetPartAsNonRoot(newPart);
1805 1964
@@ -1862,7 +2021,7 @@ namespace OpenSim.Region.Framework.Scenes
1862 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0) 2021 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
1863 // return; 2022 // return;
1864 2023
1865 lock (m_parts) 2024 lockPartsForRead(true);
1866 { 2025 {
1867 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0); 2026 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0);
1868 2027
@@ -1880,34 +2039,43 @@ namespace OpenSim.Region.Framework.Scenes
1880 2039
1881 foreach (SceneObjectPart part in m_parts.Values) 2040 foreach (SceneObjectPart part in m_parts.Values)
1882 { 2041 {
2042
1883 part.SendScheduledUpdates(); 2043 part.SendScheduledUpdates();
2044
1884 } 2045 }
1885 } 2046 }
2047 lockPartsForRead(false);
1886 } 2048 }
1887 2049
1888 public void ScheduleFullUpdateToAvatar(ScenePresence presence) 2050 public void ScheduleFullUpdateToAvatar(ScenePresence presence)
1889 { 2051 {
1890 RootPart.AddFullUpdateToAvatar(presence); 2052 RootPart.AddFullUpdateToAvatar(presence);
1891 2053
1892 lock (m_parts) 2054 lockPartsForRead(true);
1893 { 2055 {
1894 foreach (SceneObjectPart part in m_parts.Values) 2056 foreach (SceneObjectPart part in m_parts.Values)
1895 { 2057 {
2058
1896 if (part != RootPart) 2059 if (part != RootPart)
1897 part.AddFullUpdateToAvatar(presence); 2060 part.AddFullUpdateToAvatar(presence);
2061
1898 } 2062 }
1899 } 2063 }
2064 lockPartsForRead(false);
1900 } 2065 }
1901 2066
1902 public void ScheduleTerseUpdateToAvatar(ScenePresence presence) 2067 public void ScheduleTerseUpdateToAvatar(ScenePresence presence)
1903 { 2068 {
1904 lock (m_parts) 2069 lockPartsForRead(true);
1905 { 2070 {
1906 foreach (SceneObjectPart part in m_parts.Values) 2071 foreach (SceneObjectPart part in m_parts.Values)
1907 { 2072 {
2073
1908 part.AddTerseUpdateToAvatar(presence); 2074 part.AddTerseUpdateToAvatar(presence);
2075
1909 } 2076 }
1910 } 2077 }
2078 lockPartsForRead(false);
1911 } 2079 }
1912 2080
1913 /// <summary> 2081 /// <summary>
@@ -1918,14 +2086,17 @@ namespace OpenSim.Region.Framework.Scenes
1918 checkAtTargets(); 2086 checkAtTargets();
1919 RootPart.ScheduleFullUpdate(); 2087 RootPart.ScheduleFullUpdate();
1920 2088
1921 lock (m_parts) 2089 lockPartsForRead(true);
1922 { 2090 {
1923 foreach (SceneObjectPart part in m_parts.Values) 2091 foreach (SceneObjectPart part in m_parts.Values)
1924 { 2092 {
2093
1925 if (part != RootPart) 2094 if (part != RootPart)
1926 part.ScheduleFullUpdate(); 2095 part.ScheduleFullUpdate();
2096
1927 } 2097 }
1928 } 2098 }
2099 lockPartsForRead(false);
1929 } 2100 }
1930 2101
1931 /// <summary> 2102 /// <summary>
@@ -1933,13 +2104,16 @@ namespace OpenSim.Region.Framework.Scenes
1933 /// </summary> 2104 /// </summary>
1934 public void ScheduleGroupForTerseUpdate() 2105 public void ScheduleGroupForTerseUpdate()
1935 { 2106 {
1936 lock (m_parts) 2107 lockPartsForRead(true);
1937 { 2108 {
1938 foreach (SceneObjectPart part in m_parts.Values) 2109 foreach (SceneObjectPart part in m_parts.Values)
1939 { 2110 {
2111
1940 part.ScheduleTerseUpdate(); 2112 part.ScheduleTerseUpdate();
2113
1941 } 2114 }
1942 } 2115 }
2116 lockPartsForRead(false);
1943 } 2117 }
1944 2118
1945 /// <summary> 2119 /// <summary>
@@ -1952,14 +2126,17 @@ namespace OpenSim.Region.Framework.Scenes
1952 2126
1953 RootPart.SendFullUpdateToAllClients(); 2127 RootPart.SendFullUpdateToAllClients();
1954 2128
1955 lock (m_parts) 2129 lockPartsForRead(true);
1956 { 2130 {
1957 foreach (SceneObjectPart part in m_parts.Values) 2131 foreach (SceneObjectPart part in m_parts.Values)
1958 { 2132 {
2133
1959 if (part != RootPart) 2134 if (part != RootPart)
1960 part.SendFullUpdateToAllClients(); 2135 part.SendFullUpdateToAllClients();
2136
1961 } 2137 }
1962 } 2138 }
2139 lockPartsForRead(false);
1963 } 2140 }
1964 2141
1965 /// <summary> 2142 /// <summary>
@@ -1990,14 +2167,15 @@ namespace OpenSim.Region.Framework.Scenes
1990 { 2167 {
1991 if (IsDeleted) 2168 if (IsDeleted)
1992 return; 2169 return;
1993 2170
1994 lock (m_parts) 2171 lockPartsForRead(true);
1995 { 2172 {
1996 foreach (SceneObjectPart part in m_parts.Values) 2173 foreach (SceneObjectPart part in m_parts.Values)
1997 { 2174 {
1998 part.SendTerseUpdateToAllClients(); 2175 part.SendTerseUpdateToAllClients();
1999 } 2176 }
2000 } 2177 }
2178 lockPartsForRead(false);
2001 } 2179 }
2002 2180
2003 #endregion 2181 #endregion
@@ -2011,16 +2189,18 @@ namespace OpenSim.Region.Framework.Scenes
2011 /// <returns>null if no child part with that linknum or child part</returns> 2189 /// <returns>null if no child part with that linknum or child part</returns>
2012 public SceneObjectPart GetLinkNumPart(int linknum) 2190 public SceneObjectPart GetLinkNumPart(int linknum)
2013 { 2191 {
2014 lock (m_parts) 2192 lockPartsForRead(true);
2015 { 2193 {
2016 foreach (SceneObjectPart part in m_parts.Values) 2194 foreach (SceneObjectPart part in m_parts.Values)
2017 { 2195 {
2018 if (part.LinkNum == linknum) 2196 if (part.LinkNum == linknum)
2019 { 2197 {
2198 lockPartsForRead(false);
2020 return part; 2199 return part;
2021 } 2200 }
2022 } 2201 }
2023 } 2202 }
2203 lockPartsForRead(false);
2024 2204
2025 return null; 2205 return null;
2026 } 2206 }
@@ -2048,17 +2228,19 @@ namespace OpenSim.Region.Framework.Scenes
2048 public SceneObjectPart GetChildPart(uint localID) 2228 public SceneObjectPart GetChildPart(uint localID)
2049 { 2229 {
2050 //m_log.DebugFormat("Entered looking for {0}", localID); 2230 //m_log.DebugFormat("Entered looking for {0}", localID);
2051 lock (m_parts) 2231 lockPartsForRead(true);
2052 { 2232 {
2053 foreach (SceneObjectPart part in m_parts.Values) 2233 foreach (SceneObjectPart part in m_parts.Values)
2054 { 2234 {
2055 //m_log.DebugFormat("Found {0}", part.LocalId); 2235 //m_log.DebugFormat("Found {0}", part.LocalId);
2056 if (part.LocalId == localID) 2236 if (part.LocalId == localID)
2057 { 2237 {
2238 lockPartsForRead(false);
2058 return part; 2239 return part;
2059 } 2240 }
2060 } 2241 }
2061 } 2242 }
2243 lockPartsForRead(false);
2062 2244
2063 return null; 2245 return null;
2064 } 2246 }
@@ -2088,17 +2270,19 @@ namespace OpenSim.Region.Framework.Scenes
2088 public bool HasChildPrim(uint localID) 2270 public bool HasChildPrim(uint localID)
2089 { 2271 {
2090 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID); 2272 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID);
2091 lock (m_parts) 2273 lockPartsForRead(true);
2092 { 2274 {
2093 foreach (SceneObjectPart part in m_parts.Values) 2275 foreach (SceneObjectPart part in m_parts.Values)
2094 { 2276 {
2095 //m_log.DebugFormat("Found {0}", part.LocalId); 2277 //m_log.DebugFormat("Found {0}", part.LocalId);
2096 if (part.LocalId == localID) 2278 if (part.LocalId == localID)
2097 { 2279 {
2280 lockPartsForRead(false);
2098 return true; 2281 return true;
2099 } 2282 }
2100 } 2283 }
2101 } 2284 }
2285 lockPartsForRead(false);
2102 2286
2103 return false; 2287 return false;
2104 } 2288 }
@@ -2148,53 +2332,57 @@ namespace OpenSim.Region.Framework.Scenes
2148 if (m_rootPart.LinkNum == 0) 2332 if (m_rootPart.LinkNum == 0)
2149 m_rootPart.LinkNum = 1; 2333 m_rootPart.LinkNum = 1;
2150 2334
2151 lock (m_parts) 2335 lockPartsForWrite(true);
2152 { 2336
2153 m_parts.Add(linkPart.UUID, linkPart); 2337 m_parts.Add(linkPart.UUID, linkPart);
2338
2339 lockPartsForWrite(false);
2154 2340
2155 // Insert in terms of link numbers, the new links 2341 // Insert in terms of link numbers, the new links
2156 // before the current ones (with the exception of 2342 // before the current ones (with the exception of
2157 // the root prim. Shuffle the old ones up 2343 // the root prim. Shuffle the old ones up
2158 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts) 2344 lockPartsForRead(true);
2345 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts)
2346 {
2347 if (kvp.Value.LinkNum != 1)
2159 { 2348 {
2160 if (kvp.Value.LinkNum != 1) 2349 // Don't update root prim link number
2161 { 2350 kvp.Value.LinkNum += objectGroup.PrimCount;
2162 // Don't update root prim link number
2163 kvp.Value.LinkNum += objectGroup.PrimCount;
2164 }
2165 } 2351 }
2352 }
2353 lockPartsForRead(false);
2166 2354
2167 linkPart.LinkNum = 2; 2355 linkPart.LinkNum = 2;
2168 2356
2169 linkPart.SetParent(this); 2357 linkPart.SetParent(this);
2170 linkPart.AddFlag(PrimFlags.CreateSelected); 2358 linkPart.AddFlag(PrimFlags.CreateSelected);
2171 2359
2172 //if (linkPart.PhysActor != null) 2360 //if (linkPart.PhysActor != null)
2173 //{ 2361 //{
2174 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); 2362 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
2175 2363
2176 //linkPart.PhysActor = null; 2364 //linkPart.PhysActor = null;
2177 //} 2365 //}
2178 2366
2179 //TODO: rest of parts 2367 //TODO: rest of parts
2180 int linkNum = 3; 2368 int linkNum = 3;
2181 foreach (SceneObjectPart part in objectGroup.Children.Values) 2369 foreach (SceneObjectPart part in objectGroup.Children.Values)
2370 {
2371 if (part.UUID != objectGroup.m_rootPart.UUID)
2182 { 2372 {
2183 if (part.UUID != objectGroup.m_rootPart.UUID) 2373 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2184 {
2185 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2186 }
2187 part.ClearUndoState();
2188 } 2374 }
2375 part.ClearUndoState();
2189 } 2376 }
2190 2377
2191 m_scene.UnlinkSceneObject(objectGroup.UUID, true); 2378 m_scene.UnlinkSceneObject(objectGroup.UUID, true);
2192 objectGroup.m_isDeleted = true; 2379 objectGroup.m_isDeleted = true;
2380
2381 objectGroup.lockPartsForWrite(true);
2193 2382
2194 lock (objectGroup.m_parts) 2383 objectGroup.m_parts.Clear();
2195 { 2384
2196 objectGroup.m_parts.Clear(); 2385 objectGroup.lockPartsForWrite(false);
2197 }
2198 2386
2199 // Can't do this yet since backup still makes use of the root part without any synchronization 2387 // Can't do this yet since backup still makes use of the root part without any synchronization
2200// objectGroup.m_rootPart = null; 2388// objectGroup.m_rootPart = null;
@@ -2253,11 +2441,12 @@ namespace OpenSim.Region.Framework.Scenes
2253 Quaternion worldRot = linkPart.GetWorldRotation(); 2441 Quaternion worldRot = linkPart.GetWorldRotation();
2254 2442
2255 // Remove the part from this object 2443 // Remove the part from this object
2256 lock (m_parts) 2444 lockPartsForWrite(true);
2257 { 2445 {
2258 m_parts.Remove(linkPart.UUID); 2446 m_parts.Remove(linkPart.UUID);
2259 } 2447 }
2260 2448 lockPartsForWrite(false);
2449 lockPartsForRead(true);
2261 if (m_parts.Count == 1 && RootPart != null) //Single prim is left 2450 if (m_parts.Count == 1 && RootPart != null) //Single prim is left
2262 RootPart.LinkNum = 0; 2451 RootPart.LinkNum = 0;
2263 else 2452 else
@@ -2268,6 +2457,7 @@ namespace OpenSim.Region.Framework.Scenes
2268 p.LinkNum--; 2457 p.LinkNum--;
2269 } 2458 }
2270 } 2459 }
2460 lockPartsForRead(false);
2271 2461
2272 linkPart.ParentID = 0; 2462 linkPart.ParentID = 0;
2273 linkPart.LinkNum = 0; 2463 linkPart.LinkNum = 0;
@@ -2585,9 +2775,12 @@ namespace OpenSim.Region.Framework.Scenes
2585 2775
2586 if (selectionPart != null) 2776 if (selectionPart != null)
2587 { 2777 {
2588 lock (m_parts) 2778 lockPartsForRead(true);
2779 List<SceneObjectPart> parts = new List<SceneObjectPart>(m_parts.Values);
2780 lockPartsForRead(false);
2781 foreach (SceneObjectPart part in parts)
2589 { 2782 {
2590 foreach (SceneObjectPart part in m_parts.Values) 2783 if (part.Scale.X > 10.0 || part.Scale.Y > 10.0 || part.Scale.Z > 10.0)
2591 { 2784 {
2592 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax || 2785 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax ||
2593 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax || 2786 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax ||
@@ -2597,12 +2790,13 @@ namespace OpenSim.Region.Framework.Scenes
2597 break; 2790 break;
2598 } 2791 }
2599 } 2792 }
2793 }
2600 2794
2601 foreach (SceneObjectPart part in m_parts.Values) 2795 foreach (SceneObjectPart part in parts)
2602 { 2796 {
2603 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect); 2797 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
2604 }
2605 } 2798 }
2799
2606 } 2800 }
2607 } 2801 }
2608 2802
@@ -2688,11 +2882,9 @@ namespace OpenSim.Region.Framework.Scenes
2688 scale.Y = m_scene.m_maxNonphys; 2882 scale.Y = m_scene.m_maxNonphys;
2689 if (scale.Z > m_scene.m_maxNonphys) 2883 if (scale.Z > m_scene.m_maxNonphys)
2690 scale.Z = m_scene.m_maxNonphys; 2884 scale.Z = m_scene.m_maxNonphys;
2691
2692 SceneObjectPart part = GetChildPart(localID); 2885 SceneObjectPart part = GetChildPart(localID);
2693 if (part != null) 2886 if (part != null)
2694 { 2887 {
2695 part.Resize(scale);
2696 if (part.PhysActor != null) 2888 if (part.PhysActor != null)
2697 { 2889 {
2698 if (part.PhysActor.IsPhysical) 2890 if (part.PhysActor.IsPhysical)
@@ -2707,7 +2899,7 @@ namespace OpenSim.Region.Framework.Scenes
2707 part.PhysActor.Size = scale; 2899 part.PhysActor.Size = scale;
2708 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); 2900 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
2709 } 2901 }
2710 //if (part.UUID != m_rootPart.UUID) 2902 part.Resize(scale);
2711 2903
2712 HasGroupChanged = true; 2904 HasGroupChanged = true;
2713 ScheduleGroupForFullUpdate(); 2905 ScheduleGroupForFullUpdate();
@@ -2748,77 +2940,76 @@ namespace OpenSim.Region.Framework.Scenes
2748 float y = (scale.Y / part.Scale.Y); 2940 float y = (scale.Y / part.Scale.Y);
2749 float z = (scale.Z / part.Scale.Z); 2941 float z = (scale.Z / part.Scale.Z);
2750 2942
2751 lock (m_parts) 2943 lockPartsForRead(true);
2944 if (x > 1.0f || y > 1.0f || z > 1.0f)
2752 { 2945 {
2753 if (x > 1.0f || y > 1.0f || z > 1.0f) 2946 foreach (SceneObjectPart obPart in m_parts.Values)
2754 { 2947 {
2755 foreach (SceneObjectPart obPart in m_parts.Values) 2948 if (obPart.UUID != m_rootPart.UUID)
2756 { 2949 {
2757 if (obPart.UUID != m_rootPart.UUID) 2950 Vector3 oldSize = new Vector3(obPart.Scale);
2758 {
2759 Vector3 oldSize = new Vector3(obPart.Scale);
2760 2951
2761 float f = 1.0f; 2952 float f = 1.0f;
2762 float a = 1.0f; 2953 float a = 1.0f;
2763 2954
2764 if (part.PhysActor != null && part.PhysActor.IsPhysical) 2955 if (part.PhysActor != null && part.PhysActor.IsPhysical)
2956 {
2957 if (oldSize.X*x > m_scene.m_maxPhys)
2765 { 2958 {
2766 if (oldSize.X*x > m_scene.m_maxPhys) 2959 f = m_scene.m_maxPhys / oldSize.X;
2767 { 2960 a = f / x;
2768 f = m_scene.m_maxPhys / oldSize.X; 2961 x *= a;
2769 a = f / x; 2962 y *= a;
2770 x *= a; 2963 z *= a;
2771 y *= a;
2772 z *= a;
2773 }
2774 if (oldSize.Y*y > m_scene.m_maxPhys)
2775 {
2776 f = m_scene.m_maxPhys / oldSize.Y;
2777 a = f / y;
2778 x *= a;
2779 y *= a;
2780 z *= a;
2781 }
2782 if (oldSize.Z*z > m_scene.m_maxPhys)
2783 {
2784 f = m_scene.m_maxPhys / oldSize.Z;
2785 a = f / z;
2786 x *= a;
2787 y *= a;
2788 z *= a;
2789 }
2790 } 2964 }
2791 else 2965 if (oldSize.Y*y > m_scene.m_maxPhys)
2966 {
2967 f = m_scene.m_maxPhys / oldSize.Y;
2968 a = f / y;
2969 x *= a;
2970 y *= a;
2971 z *= a;
2972 }
2973 if (oldSize.Z*z > m_scene.m_maxPhys)
2974 {
2975 f = m_scene.m_maxPhys / oldSize.Z;
2976 a = f / z;
2977 x *= a;
2978 y *= a;
2979 z *= a;
2980 }
2981 }
2982 else
2983 {
2984 if (oldSize.X*x > m_scene.m_maxNonphys)
2985 {
2986 f = m_scene.m_maxNonphys / oldSize.X;
2987 a = f / x;
2988 x *= a;
2989 y *= a;
2990 z *= a;
2991 }
2992 if (oldSize.Y*y > m_scene.m_maxNonphys)
2993 {
2994 f = m_scene.m_maxNonphys / oldSize.Y;
2995 a = f / y;
2996 x *= a;
2997 y *= a;
2998 z *= a;
2999 }
3000 if (oldSize.Z*z > m_scene.m_maxNonphys)
2792 { 3001 {
2793 if (oldSize.X*x > m_scene.m_maxNonphys) 3002 f = m_scene.m_maxNonphys / oldSize.Z;
2794 { 3003 a = f / z;
2795 f = m_scene.m_maxNonphys / oldSize.X; 3004 x *= a;
2796 a = f / x; 3005 y *= a;
2797 x *= a; 3006 z *= a;
2798 y *= a;
2799 z *= a;
2800 }
2801 if (oldSize.Y*y > m_scene.m_maxNonphys)
2802 {
2803 f = m_scene.m_maxNonphys / oldSize.Y;
2804 a = f / y;
2805 x *= a;
2806 y *= a;
2807 z *= a;
2808 }
2809 if (oldSize.Z*z > m_scene.m_maxNonphys)
2810 {
2811 f = m_scene.m_maxNonphys / oldSize.Z;
2812 a = f / z;
2813 x *= a;
2814 y *= a;
2815 z *= a;
2816 }
2817 } 3007 }
2818 } 3008 }
2819 } 3009 }
2820 } 3010 }
2821 } 3011 }
3012 lockPartsForRead(false);
2822 3013
2823 Vector3 prevScale = part.Scale; 3014 Vector3 prevScale = part.Scale;
2824 prevScale.X *= x; 3015 prevScale.X *= x;
@@ -2826,7 +3017,7 @@ namespace OpenSim.Region.Framework.Scenes
2826 prevScale.Z *= z; 3017 prevScale.Z *= z;
2827 part.Resize(prevScale); 3018 part.Resize(prevScale);
2828 3019
2829 lock (m_parts) 3020 lockPartsForRead(true);
2830 { 3021 {
2831 foreach (SceneObjectPart obPart in m_parts.Values) 3022 foreach (SceneObjectPart obPart in m_parts.Values)
2832 { 3023 {
@@ -2845,6 +3036,7 @@ namespace OpenSim.Region.Framework.Scenes
2845 } 3036 }
2846 } 3037 }
2847 } 3038 }
3039 lockPartsForRead(false);
2848 3040
2849 if (part.PhysActor != null) 3041 if (part.PhysActor != null)
2850 { 3042 {
@@ -2925,7 +3117,7 @@ namespace OpenSim.Region.Framework.Scenes
2925 axDiff *= Quaternion.Inverse(partRotation); 3117 axDiff *= Quaternion.Inverse(partRotation);
2926 diff = axDiff; 3118 diff = axDiff;
2927 3119
2928 lock (m_parts) 3120 lockPartsForRead(true);
2929 { 3121 {
2930 foreach (SceneObjectPart obPart in m_parts.Values) 3122 foreach (SceneObjectPart obPart in m_parts.Values)
2931 { 3123 {
@@ -2935,6 +3127,7 @@ namespace OpenSim.Region.Framework.Scenes
2935 } 3127 }
2936 } 3128 }
2937 } 3129 }
3130 lockPartsForRead(false);
2938 3131
2939 AbsolutePosition = newPos; 3132 AbsolutePosition = newPos;
2940 3133
@@ -3052,7 +3245,7 @@ namespace OpenSim.Region.Framework.Scenes
3052 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); 3245 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
3053 } 3246 }
3054 3247
3055 lock (m_parts) 3248 lockPartsForRead(true);
3056 { 3249 {
3057 foreach (SceneObjectPart prim in m_parts.Values) 3250 foreach (SceneObjectPart prim in m_parts.Values)
3058 { 3251 {
@@ -3070,6 +3263,7 @@ namespace OpenSim.Region.Framework.Scenes
3070 } 3263 }
3071 } 3264 }
3072 } 3265 }
3266 lockPartsForRead(false);
3073 3267
3074 m_rootPart.ScheduleTerseUpdate(); 3268 m_rootPart.ScheduleTerseUpdate();
3075 } 3269 }
@@ -3168,7 +3362,7 @@ namespace OpenSim.Region.Framework.Scenes
3168 if (atTargets.Count > 0) 3362 if (atTargets.Count > 0)
3169 { 3363 {
3170 uint[] localids = new uint[0]; 3364 uint[] localids = new uint[0];
3171 lock (m_parts) 3365 lockPartsForRead(true);
3172 { 3366 {
3173 localids = new uint[m_parts.Count]; 3367 localids = new uint[m_parts.Count];
3174 int cntr = 0; 3368 int cntr = 0;
@@ -3178,6 +3372,7 @@ namespace OpenSim.Region.Framework.Scenes
3178 cntr++; 3372 cntr++;
3179 } 3373 }
3180 } 3374 }
3375 lockPartsForRead(false);
3181 3376
3182 for (int ctr = 0; ctr < localids.Length; ctr++) 3377 for (int ctr = 0; ctr < localids.Length; ctr++)
3183 { 3378 {
@@ -3196,7 +3391,7 @@ namespace OpenSim.Region.Framework.Scenes
3196 { 3391 {
3197 //trigger not_at_target 3392 //trigger not_at_target
3198 uint[] localids = new uint[0]; 3393 uint[] localids = new uint[0];
3199 lock (m_parts) 3394 lockPartsForRead(true);
3200 { 3395 {
3201 localids = new uint[m_parts.Count]; 3396 localids = new uint[m_parts.Count];
3202 int cntr = 0; 3397 int cntr = 0;
@@ -3206,7 +3401,8 @@ namespace OpenSim.Region.Framework.Scenes
3206 cntr++; 3401 cntr++;
3207 } 3402 }
3208 } 3403 }
3209 3404 lockPartsForRead(false);
3405
3210 for (int ctr = 0; ctr < localids.Length; ctr++) 3406 for (int ctr = 0; ctr < localids.Length; ctr++)
3211 { 3407 {
3212 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]); 3408 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]);
@@ -3219,19 +3415,20 @@ namespace OpenSim.Region.Framework.Scenes
3219 public float GetMass() 3415 public float GetMass()
3220 { 3416 {
3221 float retmass = 0f; 3417 float retmass = 0f;
3222 lock (m_parts) 3418 lockPartsForRead(true);
3223 { 3419 {
3224 foreach (SceneObjectPart part in m_parts.Values) 3420 foreach (SceneObjectPart part in m_parts.Values)
3225 { 3421 {
3226 retmass += part.GetMass(); 3422 retmass += part.GetMass();
3227 } 3423 }
3228 } 3424 }
3425 lockPartsForRead(false);
3229 return retmass; 3426 return retmass;
3230 } 3427 }
3231 3428
3232 public void CheckSculptAndLoad() 3429 public void CheckSculptAndLoad()
3233 { 3430 {
3234 lock (m_parts) 3431 lockPartsForRead(true);
3235 { 3432 {
3236 if (!IsDeleted) 3433 if (!IsDeleted)
3237 { 3434 {
@@ -3256,6 +3453,7 @@ namespace OpenSim.Region.Framework.Scenes
3256 } 3453 }
3257 } 3454 }
3258 } 3455 }
3456 lockPartsForRead(false);
3259 } 3457 }
3260 3458
3261 protected void AssetReceived(string id, Object sender, AssetBase asset) 3459 protected void AssetReceived(string id, Object sender, AssetBase asset)
@@ -3276,7 +3474,7 @@ namespace OpenSim.Region.Framework.Scenes
3276 /// <param name="client"></param> 3474 /// <param name="client"></param>
3277 public void SetGroup(UUID GroupID, IClientAPI client) 3475 public void SetGroup(UUID GroupID, IClientAPI client)
3278 { 3476 {
3279 lock (m_parts) 3477 lockPartsForRead(true);
3280 { 3478 {
3281 foreach (SceneObjectPart part in m_parts.Values) 3479 foreach (SceneObjectPart part in m_parts.Values)
3282 { 3480 {
@@ -3286,7 +3484,7 @@ namespace OpenSim.Region.Framework.Scenes
3286 3484
3287 HasGroupChanged = true; 3485 HasGroupChanged = true;
3288 } 3486 }
3289 3487 lockPartsForRead(false);
3290 ScheduleGroupForFullUpdate(); 3488 ScheduleGroupForFullUpdate();
3291 } 3489 }
3292 3490
@@ -3305,11 +3503,12 @@ namespace OpenSim.Region.Framework.Scenes
3305 3503
3306 public void SetAttachmentPoint(byte point) 3504 public void SetAttachmentPoint(byte point)
3307 { 3505 {
3308 lock (m_parts) 3506 lockPartsForRead(true);
3309 { 3507 {
3310 foreach (SceneObjectPart part in m_parts.Values) 3508 foreach (SceneObjectPart part in m_parts.Values)
3311 part.SetAttachmentPoint(point); 3509 part.SetAttachmentPoint(point);
3312 } 3510 }
3511 lockPartsForRead(false);
3313 } 3512 }
3314 3513
3315 #region ISceneObject 3514 #region ISceneObject
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index b6916f2..a23c11e 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -212,6 +212,7 @@ namespace OpenSim.Region.Framework.Scenes
212 private Quaternion m_sitTargetOrientation = Quaternion.Identity; 212 private Quaternion m_sitTargetOrientation = Quaternion.Identity;
213 private Vector3 m_sitTargetPosition; 213 private Vector3 m_sitTargetPosition;
214 private string m_sitAnimation = "SIT"; 214 private string m_sitAnimation = "SIT";
215 private bool m_occupied; // KF if any av is sitting on this prim
215 private string m_text = String.Empty; 216 private string m_text = String.Empty;
216 private string m_touchName = String.Empty; 217 private string m_touchName = String.Empty;
217 private readonly UndoStack<UndoState> m_undo = new UndoStack<UndoState>(5); 218 private readonly UndoStack<UndoState> m_undo = new UndoStack<UndoState>(5);
@@ -389,12 +390,16 @@ namespace OpenSim.Region.Framework.Scenes
389 } 390 }
390 391
391 /// <value> 392 /// <value>
392 /// Access should be via Inventory directly - this property temporarily remains for xml serialization purposes 393 /// Get the inventory list
393 /// </value> 394 /// </value>
394 public TaskInventoryDictionary TaskInventory 395 public TaskInventoryDictionary TaskInventory
395 { 396 {
396 get { return m_inventory.Items; } 397 get {
397 set { m_inventory.Items = value; } 398 return m_inventory.Items;
399 }
400 set {
401 m_inventory.Items = value;
402 }
398 } 403 }
399 404
400 public uint ObjectFlags 405 public uint ObjectFlags
@@ -508,9 +513,16 @@ namespace OpenSim.Region.Framework.Scenes
508 { 513 {
509 // If this is a linkset, we don't want the physics engine mucking up our group position here. 514 // If this is a linkset, we don't want the physics engine mucking up our group position here.
510 PhysicsActor actor = PhysActor; 515 PhysicsActor actor = PhysActor;
511 if (actor != null && _parentID == 0) 516 if (actor != null)
512 { 517 {
513 m_groupPosition = actor.Position; 518 if (_parentID == 0)
519 {
520 m_groupPosition = actor.Position;
521 }
522 else
523 {
524 m_groupPosition = ParentGroup.AbsolutePosition; // KF+Casper Update Child prims too!
525 }
514 } 526 }
515 527
516 if (IsAttachment) 528 if (IsAttachment)
@@ -837,7 +849,8 @@ namespace OpenSim.Region.Framework.Scenes
837 if (IsAttachment) 849 if (IsAttachment)
838 return GroupPosition; 850 return GroupPosition;
839 851
840 return m_offsetPosition + m_groupPosition; } 852// return m_offsetPosition + m_groupPosition; }
853 return m_groupPosition + (m_offsetPosition * ParentGroup.RootPart.RotationOffset) ; } //KF: Rotation was ignored!
841 } 854 }
842 855
843 public SceneObjectGroup ParentGroup 856 public SceneObjectGroup ParentGroup
@@ -989,6 +1002,13 @@ namespace OpenSim.Region.Framework.Scenes
989 get { return _flags; } 1002 get { return _flags; }
990 set { _flags = value; } 1003 set { _flags = value; }
991 } 1004 }
1005
1006 [XmlIgnore]
1007 public bool IsOccupied // KF If an av is sittingon this prim
1008 {
1009 get { return m_occupied; }
1010 set { m_occupied = value; }
1011 }
992 1012
993 [XmlIgnore] 1013 [XmlIgnore]
994 public UUID SitTargetAvatar 1014 public UUID SitTargetAvatar
@@ -1064,14 +1084,6 @@ namespace OpenSim.Region.Framework.Scenes
1064 } 1084 }
1065 } 1085 }
1066 1086
1067 /// <summary>
1068 /// Clear all pending updates of parts to clients
1069 /// </summary>
1070 private void ClearUpdateSchedule()
1071 {
1072 m_updateFlag = 0;
1073 }
1074
1075 private void SendObjectPropertiesToClient(UUID AgentID) 1087 private void SendObjectPropertiesToClient(UUID AgentID)
1076 { 1088 {
1077 ScenePresence[] avatars = m_parentGroup.Scene.GetScenePresences(); 1089 ScenePresence[] avatars = m_parentGroup.Scene.GetScenePresences();
@@ -1739,9 +1751,13 @@ namespace OpenSim.Region.Framework.Scenes
1739 Quaternion parentRot = ParentGroup.RootPart.RotationOffset; 1751 Quaternion parentRot = ParentGroup.RootPart.RotationOffset;
1740 1752
1741 Vector3 axPos = OffsetPosition; 1753 Vector3 axPos = OffsetPosition;
1742
1743 axPos *= parentRot; 1754 axPos *= parentRot;
1744 Vector3 translationOffsetPosition = axPos; 1755 Vector3 translationOffsetPosition = axPos;
1756
1757 int tx = (int)GroupPosition.X;
1758 int ty = (int)GroupPosition.Y;
1759 int tz = (int)GroupPosition.Z;
1760
1745 return GroupPosition + translationOffsetPosition; 1761 return GroupPosition + translationOffsetPosition;
1746 } 1762 }
1747 1763
@@ -2109,17 +2125,18 @@ namespace OpenSim.Region.Framework.Scenes
2109 //Trys to fetch sound id from prim's inventory. 2125 //Trys to fetch sound id from prim's inventory.
2110 //Prim's inventory doesn't support non script items yet 2126 //Prim's inventory doesn't support non script items yet
2111 2127
2112 lock (TaskInventory) 2128 TaskInventory.LockItemsForRead(true);
2129
2130 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2113 { 2131 {
2114 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 2132 if (item.Value.Name == sound)
2115 { 2133 {
2116 if (item.Value.Name == sound) 2134 soundID = item.Value.ItemID;
2117 { 2135 break;
2118 soundID = item.Value.ItemID;
2119 break;
2120 }
2121 } 2136 }
2122 } 2137 }
2138
2139 TaskInventory.LockItemsForRead(false);
2123 } 2140 }
2124 2141
2125 List<ScenePresence> avatarts = m_parentGroup.Scene.GetAvatars(); 2142 List<ScenePresence> avatarts = m_parentGroup.Scene.GetAvatars();
@@ -2185,6 +2202,11 @@ namespace OpenSim.Region.Framework.Scenes
2185 ParentGroup.HasGroupChanged = true; 2202 ParentGroup.HasGroupChanged = true;
2186 ScheduleFullUpdate(); 2203 ScheduleFullUpdate();
2187 } 2204 }
2205
2206 public void RotLookAt(Quaternion target, float strength, float damping)
2207 {
2208 m_parentGroup.rotLookAt(target, strength, damping);
2209 }
2188 2210
2189 /// <summary> 2211 /// <summary>
2190 /// Schedules this prim for a full update 2212 /// Schedules this prim for a full update
@@ -2389,8 +2411,8 @@ namespace OpenSim.Region.Framework.Scenes
2389 { 2411 {
2390 const float ROTATION_TOLERANCE = 0.01f; 2412 const float ROTATION_TOLERANCE = 0.01f;
2391 const float VELOCITY_TOLERANCE = 0.001f; 2413 const float VELOCITY_TOLERANCE = 0.001f;
2392 const float POSITION_TOLERANCE = 0.05f; 2414 const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary
2393 const int TIME_MS_TOLERANCE = 3000; 2415 const int TIME_MS_TOLERANCE = 200; //llSetPos has a 200ms delay. This should NOT be 3 seconds.
2394 2416
2395 if (m_updateFlag == 1) 2417 if (m_updateFlag == 1)
2396 { 2418 {
@@ -2404,7 +2426,7 @@ namespace OpenSim.Region.Framework.Scenes
2404 Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE) 2426 Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE)
2405 { 2427 {
2406 AddTerseUpdateToAllAvatars(); 2428 AddTerseUpdateToAllAvatars();
2407 ClearUpdateSchedule(); 2429
2408 2430
2409 // This causes the Scene to 'poll' physical objects every couple of frames 2431 // This causes the Scene to 'poll' physical objects every couple of frames
2410 // bad, so it's been replaced by an event driven method. 2432 // bad, so it's been replaced by an event driven method.
@@ -2422,16 +2444,18 @@ namespace OpenSim.Region.Framework.Scenes
2422 m_lastAngularVelocity = AngularVelocity; 2444 m_lastAngularVelocity = AngularVelocity;
2423 m_lastTerseSent = Environment.TickCount; 2445 m_lastTerseSent = Environment.TickCount;
2424 } 2446 }
2447 //Moved this outside of the if clause so updates don't get blocked.. *sigh*
2448 m_updateFlag = 0; //Why were we calling a function to do this? Inefficient! *screams*
2425 } 2449 }
2426 else 2450 else
2427 { 2451 {
2428 if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes 2452 if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes
2429 { 2453 {
2430 AddFullUpdateToAllAvatars(); 2454 AddFullUpdateToAllAvatars();
2431 ClearUpdateSchedule(); 2455 m_updateFlag = 0; //Same here
2432 } 2456 }
2433 } 2457 }
2434 ClearUpdateSchedule(); 2458 m_updateFlag = 0;
2435 } 2459 }
2436 2460
2437 /// <summary> 2461 /// <summary>
@@ -2458,17 +2482,16 @@ namespace OpenSim.Region.Framework.Scenes
2458 if (!UUID.TryParse(sound, out soundID)) 2482 if (!UUID.TryParse(sound, out soundID))
2459 { 2483 {
2460 // search sound file from inventory 2484 // search sound file from inventory
2461 lock (TaskInventory) 2485 TaskInventory.LockItemsForRead(true);
2486 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2462 { 2487 {
2463 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 2488 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound)
2464 { 2489 {
2465 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound) 2490 soundID = item.Value.ItemID;
2466 { 2491 break;
2467 soundID = item.Value.ItemID;
2468 break;
2469 }
2470 } 2492 }
2471 } 2493 }
2494 TaskInventory.LockItemsForRead(false);
2472 } 2495 }
2473 2496
2474 if (soundID == UUID.Zero) 2497 if (soundID == UUID.Zero)
@@ -2684,6 +2707,13 @@ namespace OpenSim.Region.Framework.Scenes
2684 SetText(text); 2707 SetText(text);
2685 } 2708 }
2686 2709
2710 public void StopLookAt()
2711 {
2712 m_parentGroup.stopLookAt();
2713
2714 m_parentGroup.ScheduleGroupForTerseUpdate();
2715 }
2716
2687 public void StopMoveToTarget() 2717 public void StopMoveToTarget()
2688 { 2718 {
2689 m_parentGroup.stopMoveToTarget(); 2719 m_parentGroup.stopMoveToTarget();
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index 22eedba..b57d912 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
@@ -80,7 +80,9 @@ namespace OpenSim.Region.Framework.Scenes
80 /// </value> 80 /// </value>
81 protected internal TaskInventoryDictionary Items 81 protected internal TaskInventoryDictionary Items
82 { 82 {
83 get { return m_items; } 83 get {
84 return m_items;
85 }
84 set 86 set
85 { 87 {
86 m_items = value; 88 m_items = value;
@@ -116,22 +118,25 @@ namespace OpenSim.Region.Framework.Scenes
116 /// <param name="linkNum">Link number for the part</param> 118 /// <param name="linkNum">Link number for the part</param>
117 public void ResetInventoryIDs() 119 public void ResetInventoryIDs()
118 { 120 {
119 lock (Items) 121 m_items.LockItemsForWrite(true);
122
123 if (0 == Items.Count)
120 { 124 {
121 if (0 == Items.Count) 125 m_items.LockItemsForWrite(false);
122 return; 126 return;
127 }
123 128
124 HasInventoryChanged = true; 129 HasInventoryChanged = true;
125 m_part.ParentGroup.HasGroupChanged = true; 130 m_part.ParentGroup.HasGroupChanged = true;
126 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values); 131 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
127 Items.Clear(); 132 Items.Clear();
128 133
129 foreach (TaskInventoryItem item in items) 134 foreach (TaskInventoryItem item in items)
130 { 135 {
131 item.ResetIDs(m_part.UUID); 136 item.ResetIDs(m_part.UUID);
132 Items.Add(item.ItemID, item); 137 Items.Add(item.ItemID, item);
133 }
134 } 138 }
139 m_items.LockItemsForWrite(false);
135 } 140 }
136 141
137 /// <summary> 142 /// <summary>
@@ -140,25 +145,25 @@ namespace OpenSim.Region.Framework.Scenes
140 /// <param name="ownerId"></param> 145 /// <param name="ownerId"></param>
141 public void ChangeInventoryOwner(UUID ownerId) 146 public void ChangeInventoryOwner(UUID ownerId)
142 { 147 {
143 lock (Items) 148 m_items.LockItemsForWrite(true);
149 if (0 == Items.Count)
144 { 150 {
145 if (0 == Items.Count) 151 m_items.LockItemsForWrite(false);
146 { 152 return;
147 return; 153 }
148 }
149 154
150 HasInventoryChanged = true; 155 HasInventoryChanged = true;
151 m_part.ParentGroup.HasGroupChanged = true; 156 m_part.ParentGroup.HasGroupChanged = true;
152 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values); 157 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
153 foreach (TaskInventoryItem item in items) 158 foreach (TaskInventoryItem item in items)
159 {
160 if (ownerId != item.OwnerID)
154 { 161 {
155 if (ownerId != item.OwnerID) 162 item.LastOwnerID = item.OwnerID;
156 { 163 item.OwnerID = ownerId;
157 item.LastOwnerID = item.OwnerID;
158 item.OwnerID = ownerId;
159 }
160 } 164 }
161 } 165 }
166 m_items.LockItemsForWrite(false);
162 } 167 }
163 168
164 /// <summary> 169 /// <summary>
@@ -167,24 +172,24 @@ namespace OpenSim.Region.Framework.Scenes
167 /// <param name="groupID"></param> 172 /// <param name="groupID"></param>
168 public void ChangeInventoryGroup(UUID groupID) 173 public void ChangeInventoryGroup(UUID groupID)
169 { 174 {
170 lock (Items) 175 m_items.LockItemsForWrite(true);
176 if (0 == Items.Count)
171 { 177 {
172 if (0 == Items.Count) 178 m_items.LockItemsForWrite(false);
173 { 179 return;
174 return; 180 }
175 }
176 181
177 HasInventoryChanged = true; 182 HasInventoryChanged = true;
178 m_part.ParentGroup.HasGroupChanged = true; 183 m_part.ParentGroup.HasGroupChanged = true;
179 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values); 184 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
180 foreach (TaskInventoryItem item in items) 185 foreach (TaskInventoryItem item in items)
186 {
187 if (groupID != item.GroupID)
181 { 188 {
182 if (groupID != item.GroupID) 189 item.GroupID = groupID;
183 {
184 item.GroupID = groupID;
185 }
186 } 190 }
187 } 191 }
192 m_items.LockItemsForWrite(false);
188 } 193 }
189 194
190 /// <summary> 195 /// <summary>
@@ -192,14 +197,14 @@ namespace OpenSim.Region.Framework.Scenes
192 /// </summary> 197 /// </summary>
193 public void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource) 198 public void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource)
194 { 199 {
195 lock (m_items) 200 Items.LockItemsForRead(true);
201 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
202 Items.LockItemsForRead(false);
203 foreach (TaskInventoryItem item in items)
196 { 204 {
197 foreach (TaskInventoryItem item in Items.Values) 205 if ((int)InventoryType.LSL == item.InvType)
198 { 206 {
199 if ((int)InventoryType.LSL == item.InvType) 207 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource);
200 {
201 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource);
202 }
203 } 208 }
204 } 209 }
205 } 210 }
@@ -209,17 +214,20 @@ namespace OpenSim.Region.Framework.Scenes
209 /// </summary> 214 /// </summary>
210 public void RemoveScriptInstances() 215 public void RemoveScriptInstances()
211 { 216 {
212 lock (Items) 217 Items.LockItemsForRead(true);
218 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
219 Items.LockItemsForRead(false);
220
221 foreach (TaskInventoryItem item in items)
213 { 222 {
214 foreach (TaskInventoryItem item in Items.Values) 223 if ((int)InventoryType.LSL == item.InvType)
215 { 224 {
216 if ((int)InventoryType.LSL == item.InvType) 225 RemoveScriptInstance(item.ItemID);
217 { 226 m_part.RemoveScriptEvents(item.ItemID);
218 RemoveScriptInstance(item.ItemID);
219 m_part.RemoveScriptEvents(item.ItemID);
220 }
221 } 227 }
222 } 228 }
229
230
223 } 231 }
224 232
225 /// <summary> 233 /// <summary>
@@ -244,8 +252,10 @@ namespace OpenSim.Region.Framework.Scenes
244 if (stateSource == 1 && // Prim crossing 252 if (stateSource == 1 && // Prim crossing
245 m_part.ParentGroup.Scene.m_trustBinaries) 253 m_part.ParentGroup.Scene.m_trustBinaries)
246 { 254 {
255 m_items.LockItemsForWrite(true);
247 m_items[item.ItemID].PermsMask = 0; 256 m_items[item.ItemID].PermsMask = 0;
248 m_items[item.ItemID].PermsGranter = UUID.Zero; 257 m_items[item.ItemID].PermsGranter = UUID.Zero;
258 m_items.LockItemsForWrite(false);
249 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 259 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
250 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource); 260 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource);
251 m_part.ParentGroup.AddActiveScriptCount(1); 261 m_part.ParentGroup.AddActiveScriptCount(1);
@@ -267,8 +277,10 @@ namespace OpenSim.Region.Framework.Scenes
267 { 277 {
268 if (m_part.ParentGroup.m_savedScriptState != null) 278 if (m_part.ParentGroup.m_savedScriptState != null)
269 RestoreSavedScriptState(item.OldItemID, item.ItemID); 279 RestoreSavedScriptState(item.OldItemID, item.ItemID);
280 m_items.LockItemsForWrite(true);
270 m_items[item.ItemID].PermsMask = 0; 281 m_items[item.ItemID].PermsMask = 0;
271 m_items[item.ItemID].PermsGranter = UUID.Zero; 282 m_items[item.ItemID].PermsGranter = UUID.Zero;
283 m_items.LockItemsForWrite(false);
272 string script = Utils.BytesToString(asset.Data); 284 string script = Utils.BytesToString(asset.Data);
273 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 285 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
274 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource); 286 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource);
@@ -303,14 +315,17 @@ namespace OpenSim.Region.Framework.Scenes
303 /// </param> 315 /// </param>
304 public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource) 316 public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
305 { 317 {
306 lock (m_items) 318 m_items.LockItemsForRead(true);
319 if (m_items.ContainsKey(itemId))
307 { 320 {
308 if (m_items.ContainsKey(itemId)) 321 if (m_items.ContainsKey(itemId))
309 { 322 {
323 m_items.LockItemsForRead(false);
310 CreateScriptInstance(m_items[itemId], startParam, postOnRez, engine, stateSource); 324 CreateScriptInstance(m_items[itemId], startParam, postOnRez, engine, stateSource);
311 } 325 }
312 else 326 else
313 { 327 {
328 m_items.LockItemsForRead(false);
314 m_log.ErrorFormat( 329 m_log.ErrorFormat(
315 "[PRIM INVENTORY]: " + 330 "[PRIM INVENTORY]: " +
316 "Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}", 331 "Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}",
@@ -318,6 +333,15 @@ namespace OpenSim.Region.Framework.Scenes
318 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 333 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
319 } 334 }
320 } 335 }
336 else
337 {
338 m_items.LockItemsForRead(false);
339 m_log.ErrorFormat(
340 "[PRIM INVENTORY]: " +
341 "Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2}",
342 itemId, m_part.Name, m_part.UUID);
343 }
344
321 } 345 }
322 346
323 /// <summary> 347 /// <summary>
@@ -349,11 +373,16 @@ namespace OpenSim.Region.Framework.Scenes
349 /// <returns></returns> 373 /// <returns></returns>
350 private bool InventoryContainsName(string name) 374 private bool InventoryContainsName(string name)
351 { 375 {
352 foreach (TaskInventoryItem item in Items.Values) 376 m_items.LockItemsForRead(true);
377 foreach (TaskInventoryItem item in m_items.Values)
353 { 378 {
354 if (item.Name == name) 379 if (item.Name == name)
380 {
381 m_items.LockItemsForRead(false);
355 return true; 382 return true;
383 }
356 } 384 }
385 m_items.LockItemsForRead(false);
357 return false; 386 return false;
358 } 387 }
359 388
@@ -395,7 +424,9 @@ namespace OpenSim.Region.Framework.Scenes
395 /// <param name="item"></param> 424 /// <param name="item"></param>
396 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop) 425 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop)
397 { 426 {
427 m_items.LockItemsForRead(true);
398 List<TaskInventoryItem> il = new List<TaskInventoryItem>(m_items.Values); 428 List<TaskInventoryItem> il = new List<TaskInventoryItem>(m_items.Values);
429 m_items.LockItemsForRead(false);
399 foreach (TaskInventoryItem i in il) 430 foreach (TaskInventoryItem i in il)
400 { 431 {
401 if (i.Name == item.Name) 432 if (i.Name == item.Name)
@@ -432,15 +463,14 @@ namespace OpenSim.Region.Framework.Scenes
432 item.ParentPartID = m_part.UUID; 463 item.ParentPartID = m_part.UUID;
433 item.Name = name; 464 item.Name = name;
434 465
435 lock (m_items) 466 m_items.LockItemsForWrite(true);
436 { 467 m_items.Add(item.ItemID, item);
437 m_items.Add(item.ItemID, item); 468 m_items.LockItemsForWrite(false);
438
439 if (allowedDrop) 469 if (allowedDrop)
440 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP); 470 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP);
441 else 471 else
442 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 472 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
443 } 473
444 474
445 m_inventorySerial++; 475 m_inventorySerial++;
446 //m_inventorySerial += 2; 476 //m_inventorySerial += 2;
@@ -457,14 +487,13 @@ namespace OpenSim.Region.Framework.Scenes
457 /// <param name="items"></param> 487 /// <param name="items"></param>
458 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items) 488 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items)
459 { 489 {
460 lock (m_items) 490 m_items.LockItemsForWrite(true);
491 foreach (TaskInventoryItem item in items)
461 { 492 {
462 foreach (TaskInventoryItem item in items) 493 m_items.Add(item.ItemID, item);
463 { 494 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
464 m_items.Add(item.ItemID, item);
465 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
466 }
467 } 495 }
496 m_items.LockItemsForWrite(false);
468 497
469 m_inventorySerial++; 498 m_inventorySerial++;
470 } 499 }
@@ -477,8 +506,9 @@ namespace OpenSim.Region.Framework.Scenes
477 public TaskInventoryItem GetInventoryItem(UUID itemId) 506 public TaskInventoryItem GetInventoryItem(UUID itemId)
478 { 507 {
479 TaskInventoryItem item; 508 TaskInventoryItem item;
509 m_items.LockItemsForRead(true);
480 m_items.TryGetValue(itemId, out item); 510 m_items.TryGetValue(itemId, out item);
481 511 m_items.LockItemsForRead(false);
482 return item; 512 return item;
483 } 513 }
484 514
@@ -490,46 +520,46 @@ namespace OpenSim.Region.Framework.Scenes
490 /// <returns>false if the item did not exist, true if the update occurred successfully</returns> 520 /// <returns>false if the item did not exist, true if the update occurred successfully</returns>
491 public bool UpdateInventoryItem(TaskInventoryItem item) 521 public bool UpdateInventoryItem(TaskInventoryItem item)
492 { 522 {
493 lock (m_items) 523 m_items.LockItemsForWrite(true);
524
525 if (m_items.ContainsKey(item.ItemID))
494 { 526 {
495 if (m_items.ContainsKey(item.ItemID)) 527 item.ParentID = m_part.UUID;
528 item.ParentPartID = m_part.UUID;
529 item.Flags = m_items[item.ItemID].Flags;
530 if (item.AssetID == UUID.Zero)
496 { 531 {
497 item.ParentID = m_part.UUID; 532 item.AssetID = m_items[item.ItemID].AssetID;
498 item.ParentPartID = m_part.UUID; 533 }
499 item.Flags = m_items[item.ItemID].Flags; 534 else if ((InventoryType)item.Type == InventoryType.Notecard)
500 if (item.AssetID == UUID.Zero) 535 {
501 { 536 ScenePresence presence = m_part.ParentGroup.Scene.GetScenePresence(item.OwnerID);
502 item.AssetID = m_items[item.ItemID].AssetID;
503 }
504 else if ((InventoryType)item.Type == InventoryType.Notecard)
505 {
506 ScenePresence presence = m_part.ParentGroup.Scene.GetScenePresence(item.OwnerID);
507 537
508 if (presence != null) 538 if (presence != null)
509 { 539 {
510 presence.ControllingClient.SendAgentAlertMessage( 540 presence.ControllingClient.SendAgentAlertMessage(
511 "Notecard saved", false); 541 "Notecard saved", false);
512 }
513 } 542 }
543 }
514 544
515 m_items[item.ItemID] = item; 545 m_items[item.ItemID] = item;
516 m_inventorySerial++; 546 m_inventorySerial++;
517 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 547 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
518
519 HasInventoryChanged = true;
520 m_part.ParentGroup.HasGroupChanged = true;
521 548
522 return true; 549 HasInventoryChanged = true;
523 } 550 m_part.ParentGroup.HasGroupChanged = true;
524 else 551 m_items.LockItemsForWrite(false);
525 { 552 return true;
526 m_log.ErrorFormat( 553 }
527 "[PRIM INVENTORY]: " + 554 else
528 "Tried to retrieve item ID {0} from prim {1}, {2} at {3} in {4} but the item does not exist in this inventory", 555 {
529 item.ItemID, m_part.Name, m_part.UUID, 556 m_log.ErrorFormat(
530 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 557 "[PRIM INVENTORY]: " +
531 } 558 "Tried to retrieve item ID {0} from prim {1}, {2} at {3} in {4} but the item does not exist in this inventory",
559 item.ItemID, m_part.Name, m_part.UUID,
560 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
532 } 561 }
562 m_items.LockItemsForWrite(false);
533 563
534 return false; 564 return false;
535 } 565 }
@@ -542,52 +572,54 @@ namespace OpenSim.Region.Framework.Scenes
542 /// in this prim's inventory.</returns> 572 /// in this prim's inventory.</returns>
543 public int RemoveInventoryItem(UUID itemID) 573 public int RemoveInventoryItem(UUID itemID)
544 { 574 {
545 lock (m_items) 575 m_items.LockItemsForRead(true);
576
577 if (m_items.ContainsKey(itemID))
546 { 578 {
547 if (m_items.ContainsKey(itemID)) 579 int type = m_items[itemID].InvType;
580 m_items.LockItemsForRead(false);
581 if (type == 10) // Script
548 { 582 {
549 int type = m_items[itemID].InvType; 583 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID);
550 if (type == 10) // Script 584 }
551 { 585 m_items.LockItemsForWrite(true);
552 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID); 586 m_items.Remove(itemID);
553 } 587 m_items.LockItemsForWrite(false);
554 m_items.Remove(itemID); 588 m_inventorySerial++;
555 m_inventorySerial++; 589 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
556 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
557
558 HasInventoryChanged = true;
559 m_part.ParentGroup.HasGroupChanged = true;
560 590
561 int scriptcount = 0; 591 HasInventoryChanged = true;
562 lock (m_items) 592 m_part.ParentGroup.HasGroupChanged = true;
563 {
564 foreach (TaskInventoryItem item in m_items.Values)
565 {
566 if (item.Type == 10)
567 {
568 scriptcount++;
569 }
570 }
571 }
572 593
573 if (scriptcount <= 0) 594 int scriptcount = 0;
595 m_items.LockItemsForRead(true);
596 foreach (TaskInventoryItem item in m_items.Values)
597 {
598 if (item.Type == 10)
574 { 599 {
575 m_part.RemFlag(PrimFlags.Scripted); 600 scriptcount++;
576 } 601 }
577
578 m_part.ScheduleFullUpdate();
579
580 return type;
581 } 602 }
582 else 603 m_items.LockItemsForRead(false);
604
605
606 if (scriptcount <= 0)
583 { 607 {
584 m_log.ErrorFormat( 608 m_part.RemFlag(PrimFlags.Scripted);
585 "[PRIM INVENTORY]: " +
586 "Tried to remove item ID {0} from prim {1}, {2} at {3} in {4} but the item does not exist in this inventory",
587 itemID, m_part.Name, m_part.UUID,
588 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
589 } 609 }
610
611 m_part.ScheduleFullUpdate();
612
613 return type;
614 }
615 else
616 {
617 m_log.ErrorFormat(
618 "[PRIM INVENTORY]: " +
619 "Tried to remove item ID {0} from prim {1}, {2} but the item does not exist in this inventory",
620 itemID, m_part.Name, m_part.UUID);
590 } 621 }
622 m_items.LockItemsForWrite(false);
591 623
592 return -1; 624 return -1;
593 } 625 }
@@ -640,52 +672,53 @@ namespace OpenSim.Region.Framework.Scenes
640 // isn't available (such as drag from prim inventory to agent inventory) 672 // isn't available (such as drag from prim inventory to agent inventory)
641 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero); 673 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero);
642 674
643 lock (m_items) 675 m_items.LockItemsForRead(true);
676
677 foreach (TaskInventoryItem item in m_items.Values)
644 { 678 {
645 foreach (TaskInventoryItem item in m_items.Values) 679 UUID ownerID = item.OwnerID;
646 { 680 uint everyoneMask = 0;
647 UUID ownerID = item.OwnerID; 681 uint baseMask = item.BasePermissions;
648 uint everyoneMask = 0; 682 uint ownerMask = item.CurrentPermissions;
649 uint baseMask = item.BasePermissions;
650 uint ownerMask = item.CurrentPermissions;
651 683
652 invString.AddItemStart(); 684 invString.AddItemStart();
653 invString.AddNameValueLine("item_id", item.ItemID.ToString()); 685 invString.AddNameValueLine("item_id", item.ItemID.ToString());
654 invString.AddNameValueLine("parent_id", m_part.UUID.ToString()); 686 invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
655 687
656 invString.AddPermissionsStart(); 688 invString.AddPermissionsStart();
657 689
658 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask)); 690 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask));
659 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask)); 691 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask));
660 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(0)); 692 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(0));
661 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask)); 693 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask));
662 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions)); 694 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
663 695
664 invString.AddNameValueLine("creator_id", item.CreatorID.ToString()); 696 invString.AddNameValueLine("creator_id", item.CreatorID.ToString());
665 invString.AddNameValueLine("owner_id", ownerID.ToString()); 697 invString.AddNameValueLine("owner_id", ownerID.ToString());
666 698
667 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString()); 699 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString());
668 700
669 invString.AddNameValueLine("group_id", item.GroupID.ToString()); 701 invString.AddNameValueLine("group_id", item.GroupID.ToString());
670 invString.AddSectionEnd(); 702 invString.AddSectionEnd();
671 703
672 invString.AddNameValueLine("asset_id", item.AssetID.ToString()); 704 invString.AddNameValueLine("asset_id", item.AssetID.ToString());
673 invString.AddNameValueLine("type", TaskInventoryItem.Types[item.Type]); 705 invString.AddNameValueLine("type", TaskInventoryItem.Types[item.Type]);
674 invString.AddNameValueLine("inv_type", TaskInventoryItem.InvTypes[item.InvType]); 706 invString.AddNameValueLine("inv_type", TaskInventoryItem.InvTypes[item.InvType]);
675 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags)); 707 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags));
676 708
677 invString.AddSaleStart(); 709 invString.AddSaleStart();
678 invString.AddNameValueLine("sale_type", "not"); 710 invString.AddNameValueLine("sale_type", "not");
679 invString.AddNameValueLine("sale_price", "0"); 711 invString.AddNameValueLine("sale_price", "0");
680 invString.AddSectionEnd(); 712 invString.AddSectionEnd();
681 713
682 invString.AddNameValueLine("name", item.Name + "|"); 714 invString.AddNameValueLine("name", item.Name + "|");
683 invString.AddNameValueLine("desc", item.Description + "|"); 715 invString.AddNameValueLine("desc", item.Description + "|");
684 716
685 invString.AddNameValueLine("creation_date", item.CreationDate.ToString()); 717 invString.AddNameValueLine("creation_date", item.CreationDate.ToString());
686 invString.AddSectionEnd(); 718 invString.AddSectionEnd();
687 }
688 } 719 }
720 int count = m_items.Count;
721 m_items.LockItemsForRead(false);
689 722
690 fileData = Utils.StringToBytes(invString.BuildString); 723 fileData = Utils.StringToBytes(invString.BuildString);
691 724
@@ -706,10 +739,9 @@ namespace OpenSim.Region.Framework.Scenes
706 { 739 {
707 if (HasInventoryChanged) 740 if (HasInventoryChanged)
708 { 741 {
709 lock (Items) 742 Items.LockItemsForRead(true);
710 { 743 datastore.StorePrimInventory(m_part.UUID, Items.Values);
711 datastore.StorePrimInventory(m_part.UUID, Items.Values); 744 Items.LockItemsForRead(false);
712 }
713 745
714 HasInventoryChanged = false; 746 HasInventoryChanged = false;
715 } 747 }
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 24840d4..fbc4ed5 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,7 +115,9 @@ 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
119 private Vector3 m_avInitialPos; // used to calculate unscripted sit rotation
120 private Vector3 m_avUnscriptedSitPos; // for non-scripted prims
117 private Vector3 m_lastPosition; 121 private Vector3 m_lastPosition;
118 private Quaternion m_lastRotation; 122 private Quaternion m_lastRotation;
119 private Vector3 m_lastVelocity; 123 private Vector3 m_lastVelocity;
@@ -144,7 +148,6 @@ namespace OpenSim.Region.Framework.Scenes
144 private int m_perfMonMS; 148 private int m_perfMonMS;
145 149
146 private bool m_setAlwaysRun; 150 private bool m_setAlwaysRun;
147
148 private bool m_forceFly; 151 private bool m_forceFly;
149 private bool m_flyDisabled; 152 private bool m_flyDisabled;
150 153
@@ -168,7 +171,8 @@ namespace OpenSim.Region.Framework.Scenes
168 protected RegionInfo m_regionInfo; 171 protected RegionInfo m_regionInfo;
169 protected ulong crossingFromRegion; 172 protected ulong crossingFromRegion;
170 173
171 private readonly Vector3[] Dir_Vectors = new Vector3[6]; 174 private readonly Vector3[] Dir_Vectors = new Vector3[11];
175 private bool m_isNudging = false;
172 176
173 // Position of agent's camera in world (region cordinates) 177 // Position of agent's camera in world (region cordinates)
174 protected Vector3 m_CameraCenter; 178 protected Vector3 m_CameraCenter;
@@ -193,6 +197,7 @@ namespace OpenSim.Region.Framework.Scenes
193 private bool m_autopilotMoving; 197 private bool m_autopilotMoving;
194 private Vector3 m_autoPilotTarget; 198 private Vector3 m_autoPilotTarget;
195 private bool m_sitAtAutoTarget; 199 private bool m_sitAtAutoTarget;
200 private Vector3 m_initialSitTarget; //KF: First estimate of where to sit
196 201
197 private string m_nextSitAnimation = String.Empty; 202 private string m_nextSitAnimation = String.Empty;
198 203
@@ -203,6 +208,9 @@ namespace OpenSim.Region.Framework.Scenes
203 private bool m_followCamAuto; 208 private bool m_followCamAuto;
204 209
205 private int m_movementUpdateCount; 210 private int m_movementUpdateCount;
211 private int m_lastColCount = -1; //KF: Look for Collision chnages
212 private int m_updateCount = 0; //KF: Update Anims for a while
213 private static readonly int UPDATE_COUNT = 10; // how many frames to update for
206 214
207 private const int NumMovementsBetweenRayCast = 5; 215 private const int NumMovementsBetweenRayCast = 5;
208 216
@@ -232,6 +240,10 @@ namespace OpenSim.Region.Framework.Scenes
232 DIR_CONTROL_FLAG_RIGHT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG, 240 DIR_CONTROL_FLAG_RIGHT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG,
233 DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS, 241 DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS,
234 DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG, 242 DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG,
243 DIR_CONTROL_FLAG_FORWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS,
244 DIR_CONTROL_FLAG_BACK_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG,
245 DIR_CONTROL_FLAG_LEFT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS,
246 DIR_CONTROL_FLAG_RIGHT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG,
235 DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG 247 DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG
236 } 248 }
237 249
@@ -658,9 +670,7 @@ namespace OpenSim.Region.Framework.Scenes
658 670
659 AdjustKnownSeeds(); 671 AdjustKnownSeeds();
660 672
661 // TODO: I think, this won't send anything, as we are still a child here... 673 Animator.TrySetMovementAnimation("STAND");
662 Animator.TrySetMovementAnimation("STAND");
663
664 // we created a new ScenePresence (a new child agent) in a fresh region. 674 // we created a new ScenePresence (a new child agent) in a fresh region.
665 // Request info about all the (root) agents in this region 675 // Request info about all the (root) agents in this region
666 // Note: This won't send data *to* other clients in that region (children don't send) 676 // Note: This won't send data *to* other clients in that region (children don't send)
@@ -716,21 +726,47 @@ namespace OpenSim.Region.Framework.Scenes
716 Dir_Vectors[3] = -Vector3.UnitY; //RIGHT 726 Dir_Vectors[3] = -Vector3.UnitY; //RIGHT
717 Dir_Vectors[4] = Vector3.UnitZ; //UP 727 Dir_Vectors[4] = Vector3.UnitZ; //UP
718 Dir_Vectors[5] = -Vector3.UnitZ; //DOWN 728 Dir_Vectors[5] = -Vector3.UnitZ; //DOWN
719 Dir_Vectors[5] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge 729 Dir_Vectors[6] = new Vector3(0.5f, 0f, 0f); //FORWARD_NUDGE
730 Dir_Vectors[7] = new Vector3(-0.5f, 0f, 0f); //BACK_NUDGE
731 Dir_Vectors[8] = new Vector3(0f, 0.5f, 0f); //LEFT_NUDGE
732 Dir_Vectors[9] = new Vector3(0f, -0.5f, 0f); //RIGHT_NUDGE
733 Dir_Vectors[10] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge
720 } 734 }
721 735
722 private Vector3[] GetWalkDirectionVectors() 736 private Vector3[] GetWalkDirectionVectors()
723 { 737 {
724 Vector3[] vector = new Vector3[6]; 738 Vector3[] vector = new Vector3[11];
725 vector[0] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD 739 vector[0] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD
726 vector[1] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK 740 vector[1] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK
727 vector[2] = Vector3.UnitY; //LEFT 741 vector[2] = Vector3.UnitY; //LEFT
728 vector[3] = -Vector3.UnitY; //RIGHT 742 vector[3] = -Vector3.UnitY; //RIGHT
729 vector[4] = new Vector3(m_CameraAtAxis.Z, 0f, m_CameraUpAxis.Z); //UP 743 vector[4] = new Vector3(m_CameraAtAxis.Z, 0f, m_CameraUpAxis.Z); //UP
730 vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN 744 vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN
731 vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_Nudge 745 vector[6] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD_NUDGE
746 vector[7] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK_NUDGE
747 vector[8] = Vector3.UnitY; //LEFT_NUDGE
748 vector[9] = -Vector3.UnitY; //RIGHT_NUDGE
749 vector[10] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_NUDGE
732 return vector; 750 return vector;
733 } 751 }
752
753 private bool[] GetDirectionIsNudge()
754 {
755 bool[] isNudge = new bool[11];
756 isNudge[0] = false; //FORWARD
757 isNudge[1] = false; //BACK
758 isNudge[2] = false; //LEFT
759 isNudge[3] = false; //RIGHT
760 isNudge[4] = false; //UP
761 isNudge[5] = false; //DOWN
762 isNudge[6] = true; //FORWARD_NUDGE
763 isNudge[7] = true; //BACK_NUDGE
764 isNudge[8] = true; //LEFT_NUDGE
765 isNudge[9] = true; //RIGHT_NUDGE
766 isNudge[10] = true; //DOWN_Nudge
767 return isNudge;
768 }
769
734 770
735 #endregion 771 #endregion
736 772
@@ -994,7 +1030,9 @@ namespace OpenSim.Region.Framework.Scenes
994 { 1030 {
995 AbsolutePosition = AbsolutePosition + new Vector3(0f, 0f, (1.56f / 6f)); 1031 AbsolutePosition = AbsolutePosition + new Vector3(0f, 0f, (1.56f / 6f));
996 } 1032 }
997 1033
1034 m_updateCount = UPDATE_COUNT; //KF: Trigger Anim updates to catch falling anim.
1035
998 ControllingClient.SendAvatarTerseUpdate(new SendAvatarTerseData(m_rootRegionHandle, (ushort)(m_scene.TimeDilation * ushort.MaxValue), LocalId, 1036 ControllingClient.SendAvatarTerseUpdate(new SendAvatarTerseData(m_rootRegionHandle, (ushort)(m_scene.TimeDilation * ushort.MaxValue), LocalId,
999 AbsolutePosition, Velocity, Vector3.Zero, m_bodyRot, new Vector4(0,0,1,AbsolutePosition.Z - 0.5f), m_uuid, null, GetUpdatePriority(ControllingClient))); 1037 AbsolutePosition, Velocity, Vector3.Zero, m_bodyRot, new Vector4(0,0,1,AbsolutePosition.Z - 0.5f), m_uuid, null, GetUpdatePriority(ControllingClient)));
1000 } 1038 }
@@ -1229,7 +1267,6 @@ namespace OpenSim.Region.Framework.Scenes
1229 m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(m_CameraCenter - posAdjusted), Vector3.Distance(m_CameraCenter, posAdjusted) + 0.3f, RayCastCameraCallback); 1267 m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(m_CameraCenter - posAdjusted), Vector3.Distance(m_CameraCenter, posAdjusted) + 0.3f, RayCastCameraCallback);
1230 } 1268 }
1231 } 1269 }
1232
1233 lock (scriptedcontrols) 1270 lock (scriptedcontrols)
1234 { 1271 {
1235 if (scriptedcontrols.Count > 0) 1272 if (scriptedcontrols.Count > 0)
@@ -1244,9 +1281,7 @@ namespace OpenSim.Region.Framework.Scenes
1244 1281
1245 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0) 1282 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0)
1246 { 1283 {
1247 // TODO: This doesn't prevent the user from walking yet. 1284 m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick.
1248 // Setting parent ID would fix this, if we knew what value
1249 // to use. Or we could add a m_isSitting variable.
1250 Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED"); 1285 Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED");
1251 } 1286 }
1252 1287
@@ -1261,7 +1296,6 @@ namespace OpenSim.Region.Framework.Scenes
1261 { 1296 {
1262 return; 1297 return;
1263 } 1298 }
1264
1265 if (m_allowMovement) 1299 if (m_allowMovement)
1266 { 1300 {
1267 int i = 0; 1301 int i = 0;
@@ -1289,6 +1323,11 @@ namespace OpenSim.Region.Framework.Scenes
1289 update_rotation = true; 1323 update_rotation = true;
1290 } 1324 }
1291 1325
1326 //guilty until proven innocent..
1327 bool Nudging = true;
1328 //Basically, if there is at least one non-nudge control then we don't need
1329 //to worry about stopping the avatar
1330
1292 if (m_parentID == 0) 1331 if (m_parentID == 0)
1293 { 1332 {
1294 bool bAllowUpdateMoveToPosition = false; 1333 bool bAllowUpdateMoveToPosition = false;
@@ -1303,6 +1342,12 @@ namespace OpenSim.Region.Framework.Scenes
1303 else 1342 else
1304 dirVectors = Dir_Vectors; 1343 dirVectors = Dir_Vectors;
1305 1344
1345 bool[] isNudge = GetDirectionIsNudge();
1346
1347
1348
1349
1350
1306 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS) 1351 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS)
1307 { 1352 {
1308 if (((uint)flags & (uint)DCF) != 0) 1353 if (((uint)flags & (uint)DCF) != 0)
@@ -1312,6 +1357,10 @@ namespace OpenSim.Region.Framework.Scenes
1312 try 1357 try
1313 { 1358 {
1314 agent_control_v3 += dirVectors[i]; 1359 agent_control_v3 += dirVectors[i];
1360 if (isNudge[i] == false)
1361 {
1362 Nudging = false;
1363 }
1315 } 1364 }
1316 catch (IndexOutOfRangeException) 1365 catch (IndexOutOfRangeException)
1317 { 1366 {
@@ -1373,6 +1422,9 @@ namespace OpenSim.Region.Framework.Scenes
1373 // Ignore z component of vector 1422 // Ignore z component of vector
1374 Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f); 1423 Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f);
1375 LocalVectorToTarget2D.Normalize(); 1424 LocalVectorToTarget2D.Normalize();
1425
1426 //We're not nudging
1427 Nudging = false;
1376 agent_control_v3 += LocalVectorToTarget2D; 1428 agent_control_v3 += LocalVectorToTarget2D;
1377 1429
1378 // update avatar movement flags. the avatar coordinate system is as follows: 1430 // update avatar movement flags. the avatar coordinate system is as follows:
@@ -1455,7 +1507,7 @@ namespace OpenSim.Region.Framework.Scenes
1455 // m_log.DebugFormat( 1507 // m_log.DebugFormat(
1456 // "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3); 1508 // "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3);
1457 1509
1458 AddNewMovement(agent_control_v3, q); 1510 AddNewMovement(agent_control_v3, q, Nudging);
1459 1511
1460 if (update_movementflag) 1512 if (update_movementflag)
1461 Animator.UpdateMovementAnimations(); 1513 Animator.UpdateMovementAnimations();
@@ -1474,7 +1526,6 @@ namespace OpenSim.Region.Framework.Scenes
1474 m_sitAtAutoTarget = false; 1526 m_sitAtAutoTarget = false;
1475 PrimitiveBaseShape proxy = PrimitiveBaseShape.Default; 1527 PrimitiveBaseShape proxy = PrimitiveBaseShape.Default;
1476 //proxy.PCode = (byte)PCode.ParticleSystem; 1528 //proxy.PCode = (byte)PCode.ParticleSystem;
1477
1478 proxyObjectGroup = new SceneObjectGroup(UUID, Pos, Rotation, proxy); 1529 proxyObjectGroup = new SceneObjectGroup(UUID, Pos, Rotation, proxy);
1479 proxyObjectGroup.AttachToScene(m_scene); 1530 proxyObjectGroup.AttachToScene(m_scene);
1480 1531
@@ -1516,7 +1567,7 @@ namespace OpenSim.Region.Framework.Scenes
1516 } 1567 }
1517 m_moveToPositionInProgress = true; 1568 m_moveToPositionInProgress = true;
1518 m_moveToPositionTarget = new Vector3(locx, locy, locz); 1569 m_moveToPositionTarget = new Vector3(locx, locy, locz);
1519 } 1570 }
1520 catch (Exception ex) 1571 catch (Exception ex)
1521 { 1572 {
1522 //Why did I get this error? 1573 //Why did I get this error?
@@ -1538,7 +1589,7 @@ namespace OpenSim.Region.Framework.Scenes
1538 Velocity = Vector3.Zero; 1589 Velocity = Vector3.Zero;
1539 SendFullUpdateToAllClients(); 1590 SendFullUpdateToAllClients();
1540 1591
1541 //HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); 1592 HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); //KF ??
1542 } 1593 }
1543 //ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false); 1594 //ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false);
1544 m_requestedSitTargetUUID = UUID.Zero; 1595 m_requestedSitTargetUUID = UUID.Zero;
@@ -1576,38 +1627,40 @@ namespace OpenSim.Region.Framework.Scenes
1576 SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID); 1627 SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID);
1577 if (part != null) 1628 if (part != null)
1578 { 1629 {
1630 part.TaskInventory.LockItemsForRead(true);
1579 TaskInventoryDictionary taskIDict = part.TaskInventory; 1631 TaskInventoryDictionary taskIDict = part.TaskInventory;
1580 if (taskIDict != null) 1632 if (taskIDict != null)
1581 { 1633 {
1582 lock (taskIDict) 1634 foreach (UUID taskID in taskIDict.Keys)
1583 { 1635 {
1584 foreach (UUID taskID in taskIDict.Keys) 1636 UnRegisterControlEventsToScript(LocalId, taskID);
1585 { 1637 taskIDict[taskID].PermsMask &= ~(
1586 UnRegisterControlEventsToScript(LocalId, taskID); 1638 2048 | //PERMISSION_CONTROL_CAMERA
1587 taskIDict[taskID].PermsMask &= ~( 1639 4); // PERMISSION_TAKE_CONTROLS
1588 2048 | //PERMISSION_CONTROL_CAMERA
1589 4); // PERMISSION_TAKE_CONTROLS
1590 }
1591 } 1640 }
1592
1593 } 1641 }
1642 part.TaskInventory.LockItemsForRead(false);
1594 // Reset sit target. 1643 // Reset sit target.
1595 if (part.GetAvatarOnSitTarget() == UUID) 1644 if (part.GetAvatarOnSitTarget() == UUID)
1596 part.SetAvatarOnSitTarget(UUID.Zero); 1645 part.SetAvatarOnSitTarget(UUID.Zero);
1597
1598 m_parentPosition = part.GetWorldPosition(); 1646 m_parentPosition = part.GetWorldPosition();
1599 ControllingClient.SendClearFollowCamProperties(part.ParentUUID); 1647 ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
1600 } 1648 }
1649 // part.GetWorldRotation() is the rotation of the object being sat on
1650 // Rotation is the sittiing Av's rotation
1651
1652 Quaternion wr = Quaternion.Inverse(Quaternion.Inverse(Rotation) * Quaternion.Inverse(part.GetWorldRotation())); // world or. of the av
1653 Vector3 so = new Vector3(1.0f, 0f, 0f) * wr; // 1M infront of av
1654 Vector3 wso = so + part.GetWorldPosition() + ( m_pos * part.GetWorldRotation()); // + av sit offset!
1601 1655
1602 if (m_physicsActor == null) 1656 if (m_physicsActor == null)
1603 { 1657 {
1604 AddToPhysicalScene(false); 1658 AddToPhysicalScene(false);
1605 } 1659 }
1606 1660 AbsolutePosition = wso; //KF: Fix stand up.
1607 m_pos += m_parentPosition + new Vector3(0.0f, 0.0f, 2.0f*m_sitAvatarHeight);
1608 m_parentPosition = Vector3.Zero; 1661 m_parentPosition = Vector3.Zero;
1609 1662 m_parentID = 0;
1610 m_parentID = 0; 1663 part.IsOccupied = false;
1611 SendFullUpdateToAllClients(); 1664 SendFullUpdateToAllClients();
1612 m_requestedSitTargetID = 0; 1665 m_requestedSitTargetID = 0;
1613 if ((m_physicsActor != null) && (m_avHeight > 0)) 1666 if ((m_physicsActor != null) && (m_avHeight > 0))
@@ -1646,13 +1699,9 @@ namespace OpenSim.Region.Framework.Scenes
1646 Vector3 avSitOffSet = part.SitTargetPosition; 1699 Vector3 avSitOffSet = part.SitTargetPosition;
1647 Quaternion avSitOrientation = part.SitTargetOrientation; 1700 Quaternion avSitOrientation = part.SitTargetOrientation;
1648 UUID avOnTargetAlready = part.GetAvatarOnSitTarget(); 1701 UUID avOnTargetAlready = part.GetAvatarOnSitTarget();
1649 1702 bool SitTargetOccupied = (avOnTargetAlready != UUID.Zero);
1650 bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero)); 1703 bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored.
1651 bool SitTargetisSet = 1704 if (SitTargetisSet && !SitTargetOccupied)
1652 (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f && avSitOrientation.W == 1f &&
1653 avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f));
1654
1655 if (SitTargetisSet && SitTargetUnOccupied)
1656 { 1705 {
1657 //switch the target to this prim 1706 //switch the target to this prim
1658 return part; 1707 return part;
@@ -1666,7 +1715,7 @@ namespace OpenSim.Region.Framework.Scenes
1666 private void SendSitResponse(IClientAPI remoteClient, UUID targetID, Vector3 offset) 1715 private void SendSitResponse(IClientAPI remoteClient, UUID targetID, Vector3 offset)
1667 { 1716 {
1668 bool autopilot = true; 1717 bool autopilot = true;
1669 Vector3 pos = new Vector3(); 1718 Vector3 autopilotTarget = new Vector3();
1670 Quaternion sitOrientation = Quaternion.Identity; 1719 Quaternion sitOrientation = Quaternion.Identity;
1671 Vector3 cameraEyeOffset = Vector3.Zero; 1720 Vector3 cameraEyeOffset = Vector3.Zero;
1672 Vector3 cameraAtOffset = Vector3.Zero; 1721 Vector3 cameraAtOffset = Vector3.Zero;
@@ -1674,76 +1723,104 @@ namespace OpenSim.Region.Framework.Scenes
1674 1723
1675 //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID); 1724 //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID);
1676 SceneObjectPart part = FindNextAvailableSitTarget(targetID); 1725 SceneObjectPart part = FindNextAvailableSitTarget(targetID);
1677 if (part != null) 1726 if (part == null) return;
1678 { 1727
1679 // TODO: determine position to sit at based on scene geometry; don't trust offset from client 1728 // TODO: determine position to sit at based on scene geometry; don't trust offset from client
1680 // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it 1729 // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it
1681 1730
1682 // Is a sit target available? 1731 // part is the prim to sit on
1683 Vector3 avSitOffSet = part.SitTargetPosition; 1732 // offset is the world-ref vector distance from that prim center to the click-spot
1684 Quaternion avSitOrientation = part.SitTargetOrientation; 1733 // UUID is the UUID of the Avatar doing the clicking
1685 UUID avOnTargetAlready = part.GetAvatarOnSitTarget(); 1734
1686 1735 m_avInitialPos = AbsolutePosition; // saved to calculate unscripted sit rotation
1687 bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero)); 1736
1688 bool SitTargetisSet = 1737 // Is a sit target available?
1689 (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f && 1738 Vector3 avSitOffSet = part.SitTargetPosition;
1690 ( 1739 Quaternion avSitOrientation = part.SitTargetOrientation;
1691 avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f && avSitOrientation.W == 1f // Valid Zero Rotation quaternion 1740
1692 || avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 1f && avSitOrientation.W == 0f // W-Z Mapping was invalid at one point 1741 bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored.
1693 || avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f && avSitOrientation.W == 0f // Invalid Quaternion 1742 Quaternion partIRot = Quaternion.Inverse(part.GetWorldRotation());
1694 ) 1743
1695 )); 1744//Console.WriteLine("SendSitResponse offset=" + offset + " Occup=" + part.IsOccupied + " TargSet=" + SitTargetisSet);
1696 1745 // Sit analysis rewritten by KF 091125
1697 if (SitTargetisSet && SitTargetUnOccupied) 1746 if (SitTargetisSet) // scipted sit
1698 { 1747 {
1699 part.SetAvatarOnSitTarget(UUID); 1748 if (!part.IsOccupied)
1700 offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); 1749 {
1701 sitOrientation = avSitOrientation; 1750//Console.WriteLine("Scripted, unoccupied");
1702 autopilot = false; 1751 part.SetAvatarOnSitTarget(UUID); // set that Av will be on it
1703 } 1752 offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); // change ofset to the scripted one
1704 1753 sitOrientation = avSitOrientation; // Change rotatione to the scripted one
1705 pos = part.AbsolutePosition + offset; 1754 autopilot = false; // Jump direct to scripted llSitPos()
1706 //if (Math.Abs(part.AbsolutePosition.Z - AbsolutePosition.Z) > 1) 1755 }
1707 //{ 1756 else
1708 // offset = pos; 1757 {
1709 //autopilot = false; 1758//Console.WriteLine("Scripted, occupied");
1710 //} 1759 return;
1711 if (m_physicsActor != null) 1760 }
1712 { 1761 }
1713 // If we're not using the client autopilot, we're immediately warping the avatar to the location 1762 else // Not Scripted
1714 // We can remove the physicsActor until they stand up. 1763 {
1715 m_sitAvatarHeight = m_physicsActor.Size.Z; 1764 if ( (Math.Abs(offset.X) > 0.5f) || (Math.Abs(offset.Y) > 0.5f) )
1716 1765 {
1717 if (autopilot) 1766 // large prim & offset, ignore if other Avs sitting
1718 { 1767// offset.Z -= 0.05f;
1719 if (Util.GetDistanceTo(AbsolutePosition, pos) < 4.5) 1768 m_avUnscriptedSitPos = offset * partIRot; // (non-zero) sit where clicked
1720 { 1769 autopilotTarget = part.AbsolutePosition + offset; // World location of clicked point
1721 autopilot = false; 1770
1771//Console.WriteLine(" offset ={0}", offset);
1772//Console.WriteLine(" UnscriptedSitPos={0}", m_avUnscriptedSitPos);
1773//Console.WriteLine(" autopilotTarget={0}", autopilotTarget);
1774
1775 }
1776 else // small offset
1777 {
1778//Console.WriteLine("Small offset");
1779 if (!part.IsOccupied)
1780 {
1781 m_avUnscriptedSitPos = Vector3.Zero; // Zero = Sit on prim center
1782 autopilotTarget = part.AbsolutePosition;
1783 }
1784 else return; // occupied small
1785 } // end large/small
1786 } // end Scripted/not
1787 cameraAtOffset = part.GetCameraAtOffset();
1788 cameraEyeOffset = part.GetCameraEyeOffset();
1789 forceMouselook = part.GetForceMouselook();
1722 1790
1723 RemoveFromPhysicalScene(); 1791 if (m_physicsActor != null)
1724 AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight); 1792 {
1725 } 1793 // If we're not using the client autopilot, we're immediately warping the avatar to the location
1726 } 1794 // We can remove the physicsActor until they stand up.
1727 else 1795 m_sitAvatarHeight = m_physicsActor.Size.Z;
1796 if (autopilot)
1797 { // its not a scripted sit
1798// if (Util.GetDistanceTo(AbsolutePosition, autopilotTarget) < 4.5)
1799 if( (Math.Abs(AbsolutePosition.X - autopilotTarget.X) < 2.0f) && (Math.Abs(AbsolutePosition.Y - autopilotTarget.Y) < 2.0f) )
1728 { 1800 {
1801 autopilot = false; // close enough
1729 RemoveFromPhysicalScene(); 1802 RemoveFromPhysicalScene();
1730 } 1803 AbsolutePosition = autopilotTarget + new Vector3(0.0f, 0.0f, (m_sitAvatarHeight / 2.0f)); // Warp av to over sit target
1804 } // else the autopilot will get us close
1805 }
1806 else
1807 { // its a scripted sit
1808 RemoveFromPhysicalScene();
1731 } 1809 }
1732
1733 cameraAtOffset = part.GetCameraAtOffset();
1734 cameraEyeOffset = part.GetCameraEyeOffset();
1735 forceMouselook = part.GetForceMouselook();
1736 } 1810 }
1811 else return; // physactor is null!
1737 1812
1738 ControllingClient.SendSitResponse(targetID, offset, sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook); 1813 Vector3 offsetr = offset * partIRot;
1739 m_requestedSitTargetUUID = targetID; 1814 ControllingClient.SendSitResponse(part.UUID, offsetr, sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook);
1815 m_requestedSitTargetUUID = part.UUID; //KF: Correct autopilot target
1740 // This calls HandleAgentSit twice, once from here, and the client calls 1816 // This calls HandleAgentSit twice, once from here, and the client calls
1741 // HandleAgentSit itself after it gets to the location 1817 // HandleAgentSit itself after it gets to the location
1742 // It doesn't get to the location until we've moved them there though 1818 // It doesn't get to the location until we've moved them there though
1743 // which happens in HandleAgentSit :P 1819 // which happens in HandleAgentSit :P
1744 m_autopilotMoving = autopilot; 1820 m_autopilotMoving = autopilot;
1745 m_autoPilotTarget = pos; 1821 m_autoPilotTarget = autopilotTarget;
1746 m_sitAtAutoTarget = autopilot; 1822 m_sitAtAutoTarget = autopilot;
1823 m_initialSitTarget = autopilotTarget;
1747 if (!autopilot) 1824 if (!autopilot)
1748 HandleAgentSit(remoteClient, UUID); 1825 HandleAgentSit(remoteClient, UUID);
1749 } 1826 }
@@ -1839,29 +1916,55 @@ namespace OpenSim.Region.Framework.Scenes
1839 { 1916 {
1840 if (part.GetAvatarOnSitTarget() == UUID) 1917 if (part.GetAvatarOnSitTarget() == UUID)
1841 { 1918 {
1919//Console.WriteLine("Scripted Sit");
1920 // Scripted sit
1842 Vector3 sitTargetPos = part.SitTargetPosition; 1921 Vector3 sitTargetPos = part.SitTargetPosition;
1843 Quaternion sitTargetOrient = part.SitTargetOrientation; 1922 Quaternion sitTargetOrient = part.SitTargetOrientation;
1844
1845 //Quaternion vq = new Quaternion(sitTargetPos.X, sitTargetPos.Y+0.2f, sitTargetPos.Z+0.2f, 0);
1846 //Quaternion nq = new Quaternion(-sitTargetOrient.X, -sitTargetOrient.Y, -sitTargetOrient.Z, sitTargetOrient.w);
1847
1848 //Quaternion result = (sitTargetOrient * vq) * nq;
1849
1850 m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z); 1923 m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z);
1851 m_pos += SIT_TARGET_ADJUSTMENT; 1924 m_pos += SIT_TARGET_ADJUSTMENT;
1852 m_bodyRot = sitTargetOrient; 1925 m_bodyRot = sitTargetOrient;
1853 //Rotation = sitTargetOrient;
1854 m_parentPosition = part.AbsolutePosition; 1926 m_parentPosition = part.AbsolutePosition;
1855 1927 part.IsOccupied = true;
1856 //SendTerseUpdateToAllClients();
1857 } 1928 }
1858 else 1929 else
1859 { 1930 {
1860 m_pos -= part.AbsolutePosition; 1931//Console.WriteLine("NON Scripted Sit");
1932 // if m_avUnscriptedSitPos is zero then Av sits above center
1933 // Else Av sits at m_avUnscriptedSitPos
1934
1935 // Non-scripted sit by Kitto Flora 21Nov09
1936 // Calculate angle of line from prim to Av
1937 Quaternion partIRot = Quaternion.Inverse(part.GetWorldRotation());
1938 Vector3 sitTargetPos= part.AbsolutePosition + m_avUnscriptedSitPos;
1939 float y_diff = (m_avInitialPos.Y - sitTargetPos.Y);
1940 float x_diff = ( m_avInitialPos.X - sitTargetPos.X);
1941 if(Math.Abs(x_diff) < 0.001f) x_diff = 0.001f; // avoid div by 0
1942 if(Math.Abs(y_diff) < 0.001f) y_diff = 0.001f; // avoid pol flip at 0
1943 float sit_angle = (float)Math.Atan2( (double)y_diff, (double)x_diff);
1944 // NOTE: when sitting m_ pos and m_bodyRot are *relative* to the prim location/rotation, not 'World'.
1945 // Av sits at world euler <0,0, z>, translated by part rotation
1946 m_bodyRot = partIRot * Quaternion.CreateFromEulers(0f, 0f, sit_angle); // sit at 0,0,inv-click
1947
1861 m_parentPosition = part.AbsolutePosition; 1948 m_parentPosition = part.AbsolutePosition;
1862 } 1949 part.IsOccupied = true;
1863 } 1950 m_pos = new Vector3(0f, 0f, 0.05f) + // corrections to get Sit Animation
1864 else 1951 (new Vector3(0.0f, 0f, 0.61f) * partIRot) + // located on center
1952 (new Vector3(0.34f, 0f, 0.0f) * m_bodyRot) +
1953 m_avUnscriptedSitPos; // adds click offset, if any
1954 //Set up raytrace to find top surface of prim
1955 Vector3 size = part.Scale;
1956 float mag = 0.1f + (float)Math.Sqrt((size.X * size.X) + (size.Y * size.Y) + (size.Z * size.Z));
1957 Vector3 start = part.AbsolutePosition + new Vector3(0f, 0f, mag);
1958 Vector3 down = new Vector3(0f, 0f, -1f);
1959//Console.WriteLine("st={0} do={1} ma={2}", start, down, mag);
1960 m_scene.PhysicsScene.RaycastWorld(
1961 start, // Vector3 position,
1962 down, // Vector3 direction,
1963 mag, // float length,
1964 SitAltitudeCallback); // retMethod
1965 } // end scripted/not
1966 }
1967 else // no Av
1865 { 1968 {
1866 return; 1969 return;
1867 } 1970 }
@@ -1873,11 +1976,26 @@ namespace OpenSim.Region.Framework.Scenes
1873 1976
1874 Animator.TrySetMovementAnimation(sitAnimation); 1977 Animator.TrySetMovementAnimation(sitAnimation);
1875 SendFullUpdateToAllClients(); 1978 SendFullUpdateToAllClients();
1876 // This may seem stupid, but Our Full updates don't send avatar rotation :P
1877 // So we're also sending a terse update (which has avatar rotation)
1878 // [Update] We do now.
1879 //SendTerseUpdateToAllClients();
1880 } 1979 }
1980
1981 public void SitAltitudeCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 normal)
1982 {
1983 // KF: 091202 There appears to be a bug in Prim Edit Size - the process sometimes make a prim that RayTrace no longer
1984 // sees. Take/re-rez, or sim restart corrects the condition. Result of bug is incorrect sit height.
1985 if(hitYN)
1986 {
1987 // m_pos = Av offset from prim center to make look like on center
1988 // m_parentPosition = Actual center pos of prim
1989 // collisionPoint = spot on prim where we want to sit
1990 // collisionPoint.Z = global sit surface height
1991 SceneObjectPart part = m_scene.GetSceneObjectPart(localid);
1992 Quaternion partIRot = Quaternion.Inverse(part.GetWorldRotation());
1993 float offZ = collisionPoint.Z - m_initialSitTarget.Z;
1994 Vector3 offset = new Vector3(0.0f, 0.0f, offZ) * partIRot; // Altitude correction
1995//Console.WriteLine("sitPoint={0}, offset={1}", sitPoint, offset);
1996 m_pos += offset;
1997 }
1998 } // End SitAltitudeCallback KF.
1881 1999
1882 /// <summary> 2000 /// <summary>
1883 /// Event handler for the 'Always run' setting on the client 2001 /// Event handler for the 'Always run' setting on the client
@@ -1907,7 +2025,7 @@ namespace OpenSim.Region.Framework.Scenes
1907 /// </summary> 2025 /// </summary>
1908 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param> 2026 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param>
1909 /// <param name="rotation">The direction in which this avatar should now face. 2027 /// <param name="rotation">The direction in which this avatar should now face.
1910 public void AddNewMovement(Vector3 vec, Quaternion rotation) 2028 public void AddNewMovement(Vector3 vec, Quaternion rotation, bool Nudging)
1911 { 2029 {
1912 if (m_isChildAgent) 2030 if (m_isChildAgent)
1913 { 2031 {
@@ -1981,7 +2099,7 @@ namespace OpenSim.Region.Framework.Scenes
1981 2099
1982 // TODO: Add the force instead of only setting it to support multiple forces per frame? 2100 // TODO: Add the force instead of only setting it to support multiple forces per frame?
1983 m_forceToApply = direc; 2101 m_forceToApply = direc;
1984 2102 m_isNudging = Nudging;
1985 m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); 2103 m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
1986 } 2104 }
1987 2105
@@ -1996,7 +2114,7 @@ namespace OpenSim.Region.Framework.Scenes
1996 const float POSITION_TOLERANCE = 0.05f; 2114 const float POSITION_TOLERANCE = 0.05f;
1997 //const int TIME_MS_TOLERANCE = 3000; 2115 //const int TIME_MS_TOLERANCE = 3000;
1998 2116
1999 SendPrimUpdates(); 2117
2000 2118
2001 if (m_newCoarseLocations) 2119 if (m_newCoarseLocations)
2002 { 2120 {
@@ -2032,6 +2150,9 @@ namespace OpenSim.Region.Framework.Scenes
2032 CheckForBorderCrossing(); 2150 CheckForBorderCrossing();
2033 CheckForSignificantMovement(); // sends update to the modules. 2151 CheckForSignificantMovement(); // sends update to the modules.
2034 } 2152 }
2153
2154 //Sending prim updates AFTER the avatar terse updates are sent
2155 SendPrimUpdates();
2035 } 2156 }
2036 2157
2037 #endregion 2158 #endregion
@@ -2885,14 +3006,25 @@ namespace OpenSim.Region.Framework.Scenes
2885 { 3006 {
2886 if (m_forceToApply.HasValue) 3007 if (m_forceToApply.HasValue)
2887 { 3008 {
2888 Vector3 force = m_forceToApply.Value;
2889 3009
3010 Vector3 force = m_forceToApply.Value;
2890 m_updateflag = true; 3011 m_updateflag = true;
2891// movementvector = force;
2892 Velocity = force; 3012 Velocity = force;
2893 3013
2894 m_forceToApply = null; 3014 m_forceToApply = null;
2895 } 3015 }
3016 else
3017 {
3018 if (m_isNudging)
3019 {
3020 Vector3 force = Vector3.Zero;
3021
3022 m_updateflag = true;
3023 Velocity = force;
3024 m_isNudging = false;
3025 m_updateCount = UPDATE_COUNT; //KF: Update anims to pickup "STAND"
3026 }
3027 }
2896 } 3028 }
2897 3029
2898 public override void SetText(string text, Vector3 color, double alpha) 3030 public override void SetText(string text, Vector3 color, double alpha)
@@ -2942,10 +3074,15 @@ namespace OpenSim.Region.Framework.Scenes
2942 // Event called by the physics plugin to tell the avatar about a collision. 3074 // Event called by the physics plugin to tell the avatar about a collision.
2943 private void PhysicsCollisionUpdate(EventArgs e) 3075 private void PhysicsCollisionUpdate(EventArgs e)
2944 { 3076 {
3077 if (m_updateCount > 0) //KF: Update Anims for a short period. Many Anim
3078 { // changes are very asynchronous.
3079 Animator.UpdateMovementAnimations();
3080 m_updateCount--;
3081 }
3082
2945 if (e == null) 3083 if (e == null)
2946 return; 3084 return;
2947 3085
2948 //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f))
2949 // The Physics Scene will send updates every 500 ms grep: m_physicsActor.SubscribeEvents( 3086 // The Physics Scene will send updates every 500 ms grep: m_physicsActor.SubscribeEvents(
2950 // as of this comment the interval is set in AddToPhysicalScene 3087 // as of this comment the interval is set in AddToPhysicalScene
2951 if (Animator!=null) 3088 if (Animator!=null)
@@ -2956,6 +3093,12 @@ namespace OpenSim.Region.Framework.Scenes
2956 3093
2957 CollisionPlane = Vector4.UnitW; 3094 CollisionPlane = Vector4.UnitW;
2958 3095
3096 if (m_lastColCount != coldata.Count)
3097 {
3098 m_updateCount = 10;
3099 m_lastColCount = coldata.Count;
3100 }
3101
2959 if (coldata.Count != 0 && Animator != null) 3102 if (coldata.Count != 0 && Animator != null)
2960 { 3103 {
2961 switch (Animator.CurrentMovementAnimation) 3104 switch (Animator.CurrentMovementAnimation)
@@ -3603,5 +3746,16 @@ namespace OpenSim.Region.Framework.Scenes
3603 m_reprioritization_called = false; 3746 m_reprioritization_called = false;
3604 } 3747 }
3605 } 3748 }
3749
3750 private Vector3 Quat2Euler(Quaternion rot){
3751 float x = Utils.RAD_TO_DEG * (float)Math.Atan2((double)((2.0f * rot.X * rot.W) - (2.0f * rot.Y * rot.Z)) ,
3752 (double)(1 - (2.0f * rot.X * rot.X) - (2.0f * rot.Z * rot.Z)));
3753 float y = Utils.RAD_TO_DEG * (float)Math.Asin ((double)((2.0f * rot.X * rot.Y) + (2.0f * rot.Z * rot.W)));
3754 float z = Utils.RAD_TO_DEG * (float)Math.Atan2(((double)(2.0f * rot.Y * rot.W) - (2.0f * rot.X * rot.Z)) ,
3755 (double)(1 - (2.0f * rot.Y * rot.Y) - (2.0f * rot.Z * rot.Z)));
3756 return(new Vector3(x,y,z));
3757 }
3758
3759
3606 } 3760 }
3607} \ No newline at end of file 3761}
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;