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