aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework')
-rw-r--r--OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs7
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEntityInventory.cs3
-rw-r--r--OpenSim/Region/Framework/Interfaces/ISnmpModule.cs27
-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.cs50
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs80
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs26
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs685
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs145
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs722
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs653
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneViewer.cs2
15 files changed, 1698 insertions, 836 deletions
diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
index f8af367..958847b 100644
--- a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Xml;
29using OpenMetaverse; 30using OpenMetaverse;
30using OpenMetaverse.Packets; 31using OpenMetaverse.Packets;
31using OpenSim.Framework; 32using OpenSim.Framework;
@@ -82,6 +83,10 @@ namespace OpenSim.Region.Framework.Interfaces
82 UUID RezSingleAttachmentFromInventory( 83 UUID RezSingleAttachmentFromInventory(
83 IClientAPI remoteClient, UUID itemID, uint AttachmentPt, bool updateInventoryStatus); 84 IClientAPI remoteClient, UUID itemID, uint AttachmentPt, bool updateInventoryStatus);
84 85
86 // Same as above, but also load script states from a separate doc
87 UUID RezSingleAttachmentFromInventory(
88 IClientAPI remoteClient, UUID itemID, uint AttachmentPt, bool updateInventoryStatus, XmlDocument doc);
89
85 /// <summary> 90 /// <summary>
86 /// Rez multiple attachments from a user's inventory 91 /// Rez multiple attachments from a user's inventory
87 /// </summary> 92 /// </summary>
@@ -132,4 +137,4 @@ namespace OpenSim.Region.Framework.Interfaces
132 /// </param> 137 /// </param>
133 void ShowDetachInUserInventory(UUID itemID, IClientAPI remoteClient); 138 void ShowDetachInUserInventory(UUID itemID, IClientAPI remoteClient);
134 } 139 }
135} \ No newline at end of file 140}
diff --git a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
index fd43923..1e2f60b 100644
--- a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
@@ -105,6 +105,8 @@ namespace OpenSim.Region.Framework.Interfaces
105 /// <param name="stateSource"></param> 105 /// <param name="stateSource"></param>
106 void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource); 106 void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource);
107 107
108 ArrayList CreateScriptInstanceEr(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource);
109
108 /// <summary> 110 /// <summary>
109 /// Stop a script which is in this prim's inventory. 111 /// Stop a script which is in this prim's inventory.
110 /// </summary> 112 /// </summary>
@@ -214,5 +216,6 @@ namespace OpenSim.Region.Framework.Interfaces
214 /// A <see cref="Dictionary`2"/> 216 /// A <see cref="Dictionary`2"/>
215 /// </returns> 217 /// </returns>
216 Dictionary<UUID, string> GetScriptStates(); 218 Dictionary<UUID, string> GetScriptStates();
219 Dictionary<UUID, string> GetScriptStates(bool oldIDs);
217 } 220 }
218} 221}
diff --git a/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs b/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs
new file mode 100644
index 0000000..e01f649
--- /dev/null
+++ b/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs
@@ -0,0 +1,27 @@
1///////////////////////////////////////////////////////////////////
2//
3// (c) Careminster LImited, Melanie Thielker and the Meta7 Team
4//
5// This file is not open source. All rights reserved
6// Mod 2
7
8using OpenSim.Region.Framework.Scenes;
9
10public interface ISnmpModule
11{
12 void Trap(int code, string Message, Scene scene);
13 void Critical(string Message, Scene scene);
14 void Warning(string Message, Scene scene);
15 void Major(string Message, Scene scene);
16 void ColdStart(int step , Scene scene);
17 void Shutdown(int step , Scene scene);
18 //
19 // Node Start/stop events
20 //
21 void LinkUp(Scene scene);
22 void LinkDown(Scene scene);
23 void BootInfo(string data, Scene scene);
24 void trapDebug(string Module,string data, Scene scene);
25 void trapXMRE(int data, string Message, Scene scene);
26
27}
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 60f730d..386aab4 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 {
@@ -834,8 +849,12 @@ namespace OpenSim.Region.Framework.Scenes
834 public void RemoveTaskInventory(IClientAPI remoteClient, UUID itemID, uint localID) 849 public void RemoveTaskInventory(IClientAPI remoteClient, UUID itemID, uint localID)
835 { 850 {
836 SceneObjectPart part = GetSceneObjectPart(localID); 851 SceneObjectPart part = GetSceneObjectPart(localID);
837 SceneObjectGroup group = part.ParentGroup; 852 SceneObjectGroup group = null;
838 if (group != null) 853 if (part != null)
854 {
855 group = part.ParentGroup;
856 }
857 if (part != null && group != null)
839 { 858 {
840 TaskInventoryItem item = group.GetInventoryItem(localID, itemID); 859 TaskInventoryItem item = group.GetInventoryItem(localID, itemID);
841 if (item == null) 860 if (item == null)
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index de8ecc2..3d59615 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -156,6 +156,20 @@ namespace OpenSim.Region.Framework.Scenes
156 156
157 public IXfer XferManager; 157 public IXfer XferManager;
158 158
159 protected ISnmpModule m_snmpService = null;
160 public ISnmpModule SnmpService
161 {
162 get
163 {
164 if (m_snmpService == null)
165 {
166 m_snmpService = RequestModuleInterface<ISnmpModule>();
167 }
168
169 return m_snmpService;
170 }
171 }
172
159 protected IAssetService m_AssetService; 173 protected IAssetService m_AssetService;
160 protected IAuthorizationService m_AuthorizationService; 174 protected IAuthorizationService m_AuthorizationService;
161 175
@@ -613,6 +627,8 @@ namespace OpenSim.Region.Framework.Scenes
613 627
614 // Load region settings 628 // Load region settings
615 m_regInfo.RegionSettings = m_storageManager.DataStore.LoadRegionSettings(m_regInfo.RegionID); 629 m_regInfo.RegionSettings = m_storageManager.DataStore.LoadRegionSettings(m_regInfo.RegionID);
630 m_regInfo.WindlightSettings = m_storageManager.DataStore.LoadRegionWindlightSettings(m_regInfo.RegionID);
631
616 if (m_storageManager.EstateDataStore != null) 632 if (m_storageManager.EstateDataStore != null)
617 { 633 {
618 m_regInfo.EstateSettings = m_storageManager.EstateDataStore.LoadEstateSettings(m_regInfo.RegionID, false); 634 m_regInfo.EstateSettings = m_storageManager.EstateDataStore.LoadEstateSettings(m_regInfo.RegionID, false);
@@ -711,7 +727,7 @@ namespace OpenSim.Region.Framework.Scenes
711 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false); 727 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false);
712 // TODO: Change default to true once the feature is supported 728 // TODO: Change default to true once the feature is supported
713 m_usePreJump = startupConfig.GetBoolean("enableprejump", false); 729 m_usePreJump = startupConfig.GetBoolean("enableprejump", false);
714 730 m_usePreJump = true; // Above line fails!?
715 m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys); 731 m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys);
716 if (RegionInfo.NonphysPrimMax > 0) 732 if (RegionInfo.NonphysPrimMax > 0)
717 { 733 {
@@ -1031,6 +1047,15 @@ namespace OpenSim.Region.Framework.Scenes
1031 /// <param name="seconds">float indicating duration before restart.</param> 1047 /// <param name="seconds">float indicating duration before restart.</param>
1032 public virtual void Restart(float seconds) 1048 public virtual void Restart(float seconds)
1033 { 1049 {
1050 Restart(seconds, true);
1051 }
1052
1053 /// <summary>
1054 /// Given float seconds, this will restart the region. showDialog will optionally alert the users.
1055 /// </summary>
1056 /// <param name="seconds">float indicating duration before restart.</param>
1057 public virtual void Restart(float seconds, bool showDialog)
1058 {
1034 // notifications are done in 15 second increments 1059 // notifications are done in 15 second increments
1035 // so .. if the number of seconds is less then 15 seconds, it's not really a restart request 1060 // so .. if the number of seconds is less then 15 seconds, it's not really a restart request
1036 // It's a 'Cancel restart' request. 1061 // It's a 'Cancel restart' request.
@@ -1051,8 +1076,11 @@ namespace OpenSim.Region.Framework.Scenes
1051 m_restartTimer.Elapsed += new ElapsedEventHandler(RestartTimer_Elapsed); 1076 m_restartTimer.Elapsed += new ElapsedEventHandler(RestartTimer_Elapsed);
1052 m_log.Info("[REGION]: Restarting Region in " + (seconds / 60) + " minutes"); 1077 m_log.Info("[REGION]: Restarting Region in " + (seconds / 60) + " minutes");
1053 m_restartTimer.Start(); 1078 m_restartTimer.Start();
1054 m_dialogModule.SendNotificationToUsersInRegion( 1079 if (showDialog)
1080 {
1081 m_dialogModule.SendNotificationToUsersInRegion(
1055 UUID.Random(), String.Empty, RegionInfo.RegionName + String.Format(": Restarting in {0} Minutes", (int)(seconds / 60.0))); 1082 UUID.Random(), String.Empty, RegionInfo.RegionName + String.Format(": Restarting in {0} Minutes", (int)(seconds / 60.0)));
1083 }
1056 } 1084 }
1057 } 1085 }
1058 1086
@@ -1408,16 +1436,16 @@ namespace OpenSim.Region.Framework.Scenes
1408 // Check if any objects have reached their targets 1436 // Check if any objects have reached their targets
1409 CheckAtTargets(); 1437 CheckAtTargets();
1410 1438
1411 // Update SceneObjectGroups that have scheduled themselves for updates
1412 // Objects queue their updates onto all scene presences
1413 if (m_frame % m_update_objects == 0)
1414 m_sceneGraph.UpdateObjectGroups();
1415
1416 // Run through all ScenePresences looking for updates 1439 // Run through all ScenePresences looking for updates
1417 // Presence updates and queued object updates for each presence are sent to clients 1440 // Presence updates and queued object updates for each presence are sent to clients
1418 if (m_frame % m_update_presences == 0) 1441 if (m_frame % m_update_presences == 0)
1419 m_sceneGraph.UpdatePresences(); 1442 m_sceneGraph.UpdatePresences();
1420 1443
1444 // Update SceneObjectGroups that have scheduled themselves for updates
1445 // Objects queue their updates onto all scene presences
1446 if (m_frame % m_update_objects == 0)
1447 m_sceneGraph.UpdateObjectGroups();
1448
1421 int tmpPhysicsMS2 = Util.EnvironmentTickCount(); 1449 int tmpPhysicsMS2 = Util.EnvironmentTickCount();
1422 if ((m_frame % m_update_physics == 0) && m_physics_enabled) 1450 if ((m_frame % m_update_physics == 0) && m_physics_enabled)
1423 m_sceneGraph.UpdatePreparePhysics(); 1451 m_sceneGraph.UpdatePreparePhysics();
@@ -2119,7 +2147,7 @@ namespace OpenSim.Region.Framework.Scenes
2119 public bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) 2147 public bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates)
2120 { 2148 {
2121 return m_sceneGraph.AddNewSceneObject(sceneObject, attachToBackup, sendClientUpdates); 2149 return m_sceneGraph.AddNewSceneObject(sceneObject, attachToBackup, sendClientUpdates);
2122 } 2150 }
2123 2151
2124 /// <summary> 2152 /// <summary>
2125 /// Delete every object from the scene 2153 /// Delete every object from the scene
@@ -3467,6 +3495,9 @@ namespace OpenSim.Region.Framework.Scenes
3467 3495
3468 CapsModule.AddCapsHandler(agent.AgentID); 3496 CapsModule.AddCapsHandler(agent.AgentID);
3469 3497
3498 if ((teleportFlags & ((uint)TeleportFlags.ViaLandmark | (uint)TeleportFlags.ViaLocation | (uint)TeleportFlags.ViaLandmark | (uint)TeleportFlags.Default)) != 0)
3499 System.Threading.Thread.Sleep(2000);
3500
3470 if (!agent.child) 3501 if (!agent.child)
3471 { 3502 {
3472 if (TestBorderCross(agent.startpos,Cardinals.E)) 3503 if (TestBorderCross(agent.startpos,Cardinals.E))
@@ -3525,6 +3556,8 @@ namespace OpenSim.Region.Framework.Scenes
3525 } 3556 }
3526 } 3557 }
3527 // Honor parcel landing type and position. 3558 // Honor parcel landing type and position.
3559 /*
3560 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3528 if (land != null) 3561 if (land != null)
3529 { 3562 {
3530 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) 3563 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero)
@@ -3532,6 +3565,7 @@ namespace OpenSim.Region.Framework.Scenes
3532 agent.startpos = land.LandData.UserLocation; 3565 agent.startpos = land.LandData.UserLocation;
3533 } 3566 }
3534 } 3567 }
3568 */// This is now handled properly in ScenePresence.MakeRootAgent
3535 } 3569 }
3536 3570
3537 agent.teleportFlags = teleportFlags; 3571 agent.teleportFlags = teleportFlags;
diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
index bd8ccce..9d0e6f4 100644
--- a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
@@ -300,7 +300,7 @@ namespace OpenSim.Region.Framework.Scenes
300 d); 300 d);
301 } 301 }
302 } 302 }
303 303
304 public List<GridRegion> RequestNamedRegions(string name, int maxNumber) 304 public List<GridRegion> RequestNamedRegions(string name, int maxNumber)
305 { 305 {
306 return m_scene.GridService.GetRegionsByName(UUID.Zero, name, maxNumber); 306 return m_scene.GridService.GetRegionsByName(UUID.Zero, name, maxNumber);
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index ce11267..c16ba12 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -70,6 +70,9 @@ namespace OpenSim.Region.Framework.Scenes
70 70
71 protected Dictionary<UUID, ScenePresence> m_scenePresences = new Dictionary<UUID, ScenePresence>(); 71 protected Dictionary<UUID, ScenePresence> m_scenePresences = new Dictionary<UUID, ScenePresence>();
72 protected ScenePresence[] m_scenePresenceArray = new ScenePresence[0]; 72 protected ScenePresence[] m_scenePresenceArray = new ScenePresence[0];
73 protected List<ScenePresence> m_scenePresenceList = new List<ScenePresence>();
74
75 protected OpenMetaverse.ReaderWriterLockSlim m_scenePresencesLock = new OpenMetaverse.ReaderWriterLockSlim();
73 76
74 // SceneObjects is not currently populated or used. 77 // SceneObjects is not currently populated or used.
75 //public Dictionary<UUID, SceneObjectGroup> SceneObjects; 78 //public Dictionary<UUID, SceneObjectGroup> SceneObjects;
@@ -132,10 +135,16 @@ namespace OpenSim.Region.Framework.Scenes
132 135
133 protected internal void Close() 136 protected internal void Close()
134 { 137 {
135 lock (m_scenePresences) 138 m_scenePresencesLock.EnterWriteLock();
139 try
136 { 140 {
137 m_scenePresences.Clear(); 141 m_scenePresences.Clear();
138 m_scenePresenceArray = new ScenePresence[0]; 142 m_scenePresenceArray = new ScenePresence[0];
143 m_scenePresenceList = new List<ScenePresence>();
144 }
145 finally
146 {
147 m_scenePresencesLock.ExitWriteLock();
139 } 148 }
140 149
141 lock (m_dictionary_lock) 150 lock (m_dictionary_lock)
@@ -225,6 +234,30 @@ namespace OpenSim.Region.Framework.Scenes
225 protected internal bool AddRestoredSceneObject( 234 protected internal bool AddRestoredSceneObject(
226 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted) 235 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted)
227 { 236 {
237 // KF: Check for out-of-region, move inside and make static.
238 Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X,
239 sceneObject.RootPart.GroupPosition.Y,
240 sceneObject.RootPart.GroupPosition.Z);
241 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 ||
242 npos.X > Constants.RegionSize ||
243 npos.Y > Constants.RegionSize))
244 {
245 if (npos.X < 0.0) npos.X = 1.0f;
246 if (npos.Y < 0.0) npos.Y = 1.0f;
247 if (npos.Z < 0.0) npos.Z = 0.0f;
248 if (npos.X > Constants.RegionSize) npos.X = Constants.RegionSize - 1.0f;
249 if (npos.Y > Constants.RegionSize) npos.Y = Constants.RegionSize - 1.0f;
250
251 foreach (SceneObjectPart part in sceneObject.Children.Values)
252 {
253 part.GroupPosition = npos;
254 }
255 sceneObject.RootPart.Velocity = Vector3.Zero;
256 sceneObject.RootPart.AngularVelocity = Vector3.Zero;
257 sceneObject.RootPart.Acceleration = Vector3.Zero;
258 sceneObject.RootPart.Velocity = Vector3.Zero;
259 }
260
228 if (!alreadyPersisted) 261 if (!alreadyPersisted)
229 { 262 {
230 sceneObject.ForceInventoryPersistence(); 263 sceneObject.ForceInventoryPersistence();
@@ -518,7 +551,8 @@ namespace OpenSim.Region.Framework.Scenes
518 551
519 Entities[presence.UUID] = presence; 552 Entities[presence.UUID] = presence;
520 553
521 lock (m_scenePresences) 554 m_scenePresencesLock.EnterWriteLock();
555 try
522 { 556 {
523 if (!m_scenePresences.ContainsKey(presence.UUID)) 557 if (!m_scenePresences.ContainsKey(presence.UUID))
524 { 558 {
@@ -530,11 +564,12 @@ namespace OpenSim.Region.Framework.Scenes
530 Array.Copy(m_scenePresenceArray, newArray, oldLength); 564 Array.Copy(m_scenePresenceArray, newArray, oldLength);
531 newArray[oldLength] = presence; 565 newArray[oldLength] = presence;
532 m_scenePresenceArray = newArray; 566 m_scenePresenceArray = newArray;
567 m_scenePresenceList = new List<ScenePresence>(m_scenePresenceArray);
533 } 568 }
534 else 569 else
535 { 570 {
536 m_scenePresences[presence.UUID] = presence; 571 m_scenePresences[presence.UUID] = presence;
537 572
538 // Do a linear search through the array of ScenePresence references 573 // Do a linear search through the array of ScenePresence references
539 // and update the modified entry 574 // and update the modified entry
540 for (int i = 0; i < m_scenePresenceArray.Length; i++) 575 for (int i = 0; i < m_scenePresenceArray.Length; i++)
@@ -545,8 +580,13 @@ namespace OpenSim.Region.Framework.Scenes
545 break; 580 break;
546 } 581 }
547 } 582 }
583 m_scenePresenceList = new List<ScenePresence>(m_scenePresenceArray);
548 } 584 }
549 } 585 }
586 finally
587 {
588 m_scenePresencesLock.ExitWriteLock();
589 }
550 } 590 }
551 591
552 /// <summary> 592 /// <summary>
@@ -561,7 +601,8 @@ namespace OpenSim.Region.Framework.Scenes
561 agentID); 601 agentID);
562 } 602 }
563 603
564 lock (m_scenePresences) 604 m_scenePresencesLock.EnterWriteLock();
605 try
565 { 606 {
566 if (m_scenePresences.Remove(agentID)) 607 if (m_scenePresences.Remove(agentID))
567 { 608 {
@@ -580,12 +621,17 @@ namespace OpenSim.Region.Framework.Scenes
580 } 621 }
581 } 622 }
582 m_scenePresenceArray = newArray; 623 m_scenePresenceArray = newArray;
624 m_scenePresenceList = new List<ScenePresence>(m_scenePresenceArray);
583 } 625 }
584 else 626 else
585 { 627 {
586 m_log.WarnFormat("[SCENE] Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); 628 m_log.WarnFormat("[SCENE] Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID);
587 } 629 }
588 } 630 }
631 finally
632 {
633 m_scenePresencesLock.ExitWriteLock();
634 }
589 } 635 }
590 636
591 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) 637 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F)
@@ -706,8 +752,15 @@ namespace OpenSim.Region.Framework.Scenes
706 /// <returns></returns> 752 /// <returns></returns>
707 private List<ScenePresence> GetScenePresences() 753 private List<ScenePresence> GetScenePresences()
708 { 754 {
709 lock (m_scenePresences) 755 m_scenePresencesLock.EnterReadLock();
710 return new List<ScenePresence>(m_scenePresenceArray); 756 try
757 {
758 return m_scenePresenceList;
759 }
760 finally
761 {
762 m_scenePresencesLock.ExitReadLock();
763 }
711 } 764 }
712 765
713 /// <summary> 766 /// <summary>
@@ -718,10 +771,15 @@ namespace OpenSim.Region.Framework.Scenes
718 protected internal ScenePresence GetScenePresence(UUID agentID) 771 protected internal ScenePresence GetScenePresence(UUID agentID)
719 { 772 {
720 ScenePresence sp; 773 ScenePresence sp;
721 lock (m_scenePresences) 774 m_scenePresencesLock.EnterReadLock();
775 try
722 { 776 {
723 m_scenePresences.TryGetValue(agentID, out sp); 777 m_scenePresences.TryGetValue(agentID, out sp);
724 } 778 }
779 finally
780 {
781 m_scenePresencesLock.ExitReadLock();
782 }
725 return sp; 783 return sp;
726 } 784 }
727 785
@@ -756,10 +814,15 @@ namespace OpenSim.Region.Framework.Scenes
756 814
757 protected internal bool TryGetScenePresence(UUID agentID, out ScenePresence avatar) 815 protected internal bool TryGetScenePresence(UUID agentID, out ScenePresence avatar)
758 { 816 {
759 lock (m_scenePresences) 817 m_scenePresencesLock.EnterReadLock();
818 try
760 { 819 {
761 m_scenePresences.TryGetValue(agentID, out avatar); 820 m_scenePresences.TryGetValue(agentID, out avatar);
762 } 821 }
822 finally
823 {
824 m_scenePresencesLock.ExitReadLock();
825 }
763 return (avatar != null); 826 return (avatar != null);
764 } 827 }
765 828
@@ -1037,6 +1100,7 @@ namespace OpenSim.Region.Framework.Scenes
1037 Parallel.ForEach<ScenePresence>(GetScenePresences(), protectedAction); 1100 Parallel.ForEach<ScenePresence>(GetScenePresences(), protectedAction);
1038 */ 1101 */
1039 // For now, perform actiona serially 1102 // For now, perform actiona serially
1103
1040 foreach (ScenePresence sp in GetScenePresences()) 1104 foreach (ScenePresence sp in GetScenePresences())
1041 { 1105 {
1042 try 1106 try
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
index f7e46af..1149a20 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
@@ -46,12 +46,12 @@ namespace OpenSim.Region.Framework.Scenes
46 /// </summary> 46 /// </summary>
47 public void ForceInventoryPersistence() 47 public void ForceInventoryPersistence()
48 { 48 {
49 lock (m_parts) 49 lockPartsForRead(true);
50 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
51 lockPartsForRead(false);
52 foreach (SceneObjectPart part in values)
50 { 53 {
51 foreach (SceneObjectPart part in m_parts.Values) 54 part.Inventory.ForceInventoryPersistence();
52 {
53 part.Inventory.ForceInventoryPersistence();
54 }
55 } 55 }
56 } 56 }
57 57
@@ -74,19 +74,17 @@ namespace OpenSim.Region.Framework.Scenes
74 /// <summary> 74 /// <summary>
75 /// Stop the scripts contained in all the prims in this group 75 /// Stop the scripts contained in all the prims in this group
76 /// </summary> 76 /// </summary>
77 /// <param name="sceneObjectBeingDeleted">
78 /// Should be true if these scripts are being removed because the scene
79 /// object is being deleted. This will prevent spurious updates to the client.
80 /// </param>
81 public void RemoveScriptInstances(bool sceneObjectBeingDeleted) 77 public void RemoveScriptInstances(bool sceneObjectBeingDeleted)
82 { 78 {
83 lock (m_parts) 79 lockPartsForRead(true);
80 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
81 lockPartsForRead(false);
82
83 foreach (SceneObjectPart part in values)
84 { 84 {
85 foreach (SceneObjectPart part in m_parts.Values) 85 part.Inventory.RemoveScriptInstances(sceneObjectBeingDeleted);
86 {
87 part.Inventory.RemoveScriptInstances(sceneObjectBeingDeleted);
88 }
89 } 86 }
87
90 } 88 }
91 89
92 /// <summary> 90 /// <summary>
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 8aefd50..a4b8944 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -104,8 +104,78 @@ namespace OpenSim.Region.Framework.Scenes
104 /// since the group's last persistent backup 104 /// since the group's last persistent backup
105 /// </summary> 105 /// </summary>
106 private bool m_hasGroupChanged = false; 106 private bool m_hasGroupChanged = false;
107 private long timeFirstChanged; 107 private long timeFirstChanged = 0;
108 private long timeLastChanged; 108 private long timeLastChanged = 0;
109 private long m_maxPersistTime = 0;
110 private long m_minPersistTime = 0;
111 private Random m_rand;
112
113 private System.Threading.ReaderWriterLockSlim m_partsLock = new System.Threading.ReaderWriterLockSlim();
114
115 public void lockPartsForRead(bool locked)
116 {
117 if (locked)
118 {
119 if (m_partsLock.RecursiveReadCount > 0)
120 {
121 m_log.Error("[SceneObjectGroup.m_parts] Recursive read lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue.");
122 m_partsLock.ExitReadLock();
123 }
124 if (m_partsLock.RecursiveWriteCount > 0)
125 {
126 m_log.Error("[SceneObjectGroup.m_parts] Recursive read lock requested (write lock exists on this thread). This should not happen and means something needs to be fixed.");
127 m_partsLock.ExitWriteLock();
128 }
129
130 while (!m_partsLock.TryEnterReadLock(60000))
131 {
132 m_log.Error("[SceneObjectGroup.m_parts] Thread lock detected while trying to aquire READ lock of m_parts in SceneObjectGroup. I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed.");
133 if (m_partsLock.IsWriteLockHeld)
134 {
135 m_partsLock = new System.Threading.ReaderWriterLockSlim();
136 }
137 }
138 }
139 else
140 {
141 if (m_partsLock.RecursiveReadCount > 0)
142 {
143 m_partsLock.ExitReadLock();
144 }
145 }
146 }
147 public void lockPartsForWrite(bool locked)
148 {
149 if (locked)
150 {
151 if (m_partsLock.RecursiveReadCount > 0)
152 {
153 m_log.Error("[SceneObjectGroup.m_parts] Recursive write lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue.");
154 m_partsLock.ExitReadLock();
155 }
156 if (m_partsLock.RecursiveWriteCount > 0)
157 {
158 m_log.Error("[SceneObjectGroup.m_parts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
159 m_partsLock.ExitWriteLock();
160 }
161
162 while (!m_partsLock.TryEnterWriteLock(60000))
163 {
164 m_log.Error("[SceneObjectGroup.m_parts] Thread lock detected while trying to aquire WRITE lock of m_scripts in XEngine. I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed.");
165 if (m_partsLock.IsWriteLockHeld)
166 {
167 m_partsLock = new System.Threading.ReaderWriterLockSlim();
168 }
169 }
170 }
171 else
172 {
173 if (m_partsLock.RecursiveWriteCount > 0)
174 {
175 m_partsLock.ExitWriteLock();
176 }
177 }
178 }
109 179
110 public bool HasGroupChanged 180 public bool HasGroupChanged
111 { 181 {
@@ -116,6 +186,32 @@ namespace OpenSim.Region.Framework.Scenes
116 timeLastChanged = DateTime.Now.Ticks; 186 timeLastChanged = DateTime.Now.Ticks;
117 if (!m_hasGroupChanged) 187 if (!m_hasGroupChanged)
118 timeFirstChanged = DateTime.Now.Ticks; 188 timeFirstChanged = DateTime.Now.Ticks;
189 if (m_rootPart != null && m_rootPart.UUID != null && m_scene != null)
190 {
191 if (m_rand == null)
192 {
193 byte[] val = new byte[16];
194 m_rootPart.UUID.ToBytes(val, 0);
195 m_rand = new Random(BitConverter.ToInt32(val, 0));
196 }
197
198 if (m_scene.GetRootAgentCount() == 0)
199 {
200 //If the region is empty, this change has been made by an automated process
201 //and thus we delay the persist time by a random amount between 1.5 and 2.5.
202
203 float factor = 1.5f + (float)(m_rand.NextDouble());
204 m_maxPersistTime = (long)((float)m_scene.m_persistAfter * factor);
205 m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * factor);
206 }
207 else
208 {
209 //If the region is not empty, we want to obey the minimum and maximum persist times
210 //but add a random factor so we stagger the object persistance a little
211 m_maxPersistTime = (long)((float)m_scene.m_persistAfter * (1.0d - (m_rand.NextDouble() / 5.0d))); //Multiply by 1.0-1.5
212 m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * (1.0d + (m_rand.NextDouble() / 2.0d))); //Multiply by 0.8-1.0
213 }
214 }
119 } 215 }
120 m_hasGroupChanged = value; 216 m_hasGroupChanged = value;
121 } 217 }
@@ -131,8 +227,19 @@ namespace OpenSim.Region.Framework.Scenes
131 return false; 227 return false;
132 if (m_scene.ShuttingDown) 228 if (m_scene.ShuttingDown)
133 return true; 229 return true;
230
231 if (m_minPersistTime == 0 || m_maxPersistTime == 0)
232 {
233 m_maxPersistTime = m_scene.m_persistAfter;
234 m_minPersistTime = m_scene.m_dontPersistBefore;
235 }
236
134 long currentTime = DateTime.Now.Ticks; 237 long currentTime = DateTime.Now.Ticks;
135 if (currentTime - timeLastChanged > m_scene.m_dontPersistBefore || currentTime - timeFirstChanged > m_scene.m_persistAfter) 238
239 if (timeLastChanged == 0) timeLastChanged = currentTime;
240 if (timeFirstChanged == 0) timeFirstChanged = currentTime;
241
242 if (currentTime - timeLastChanged > m_minPersistTime || currentTime - timeFirstChanged > m_maxPersistTime)
136 return true; 243 return true;
137 return false; 244 return false;
138 } 245 }
@@ -258,13 +365,16 @@ namespace OpenSim.Region.Framework.Scenes
258 set 365 set
259 { 366 {
260 m_regionHandle = value; 367 m_regionHandle = value;
261 lock (m_parts) 368 lockPartsForRead(true);
262 { 369 {
263 foreach (SceneObjectPart part in m_parts.Values) 370 foreach (SceneObjectPart part in m_parts.Values)
264 { 371 {
372
265 part.RegionHandle = m_regionHandle; 373 part.RegionHandle = m_regionHandle;
374
266 } 375 }
267 } 376 }
377 lockPartsForRead(false);
268 } 378 }
269 } 379 }
270 380
@@ -298,6 +408,9 @@ namespace OpenSim.Region.Framework.Scenes
298 { 408 {
299 m_scene.CrossPrimGroupIntoNewRegion(val, this, true); 409 m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
300 } 410 }
411
412 lockPartsForRead(true);
413
301 if (RootPart.GetStatusSandbox()) 414 if (RootPart.GetStatusSandbox())
302 { 415 {
303 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) 416 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10)
@@ -305,17 +418,18 @@ namespace OpenSim.Region.Framework.Scenes
305 RootPart.ScriptSetPhysicsStatus(false); 418 RootPart.ScriptSetPhysicsStatus(false);
306 Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"), 419 Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"),
307 ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false); 420 ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false);
421 lockPartsForRead(false);
308 return; 422 return;
309 } 423 }
310 } 424 }
311 lock (m_parts) 425
426 foreach (SceneObjectPart part in m_parts.Values)
312 { 427 {
313 foreach (SceneObjectPart part in m_parts.Values) 428 part.GroupPosition = val;
314 {
315 part.GroupPosition = val;
316 }
317 } 429 }
318 430
431 lockPartsForRead(false);
432
319 //if (m_rootPart.PhysActor != null) 433 //if (m_rootPart.PhysActor != null)
320 //{ 434 //{
321 //m_rootPart.PhysActor.Position = 435 //m_rootPart.PhysActor.Position =
@@ -457,6 +571,7 @@ namespace OpenSim.Region.Framework.Scenes
457 /// </summary> 571 /// </summary>
458 public SceneObjectGroup() 572 public SceneObjectGroup()
459 { 573 {
574
460 } 575 }
461 576
462 /// <summary> 577 /// <summary>
@@ -473,7 +588,7 @@ namespace OpenSim.Region.Framework.Scenes
473 /// Constructor. This object is added to the scene later via AttachToScene() 588 /// Constructor. This object is added to the scene later via AttachToScene()
474 /// </summary> 589 /// </summary>
475 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) 590 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape)
476 { 591 {
477 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero)); 592 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero));
478 } 593 }
479 594
@@ -504,13 +619,16 @@ namespace OpenSim.Region.Framework.Scenes
504 619
505 public void SetFromItemID(UUID AssetId) 620 public void SetFromItemID(UUID AssetId)
506 { 621 {
507 lock (m_parts) 622 lockPartsForRead(true);
508 { 623 {
509 foreach (SceneObjectPart part in m_parts.Values) 624 foreach (SceneObjectPart part in m_parts.Values)
510 { 625 {
626
511 part.FromItemID = AssetId; 627 part.FromItemID = AssetId;
628
512 } 629 }
513 } 630 }
631 lockPartsForRead(false);
514 } 632 }
515 633
516 public UUID GetFromItemID() 634 public UUID GetFromItemID()
@@ -579,10 +697,11 @@ namespace OpenSim.Region.Framework.Scenes
579 Vector3 maxScale = Vector3.Zero; 697 Vector3 maxScale = Vector3.Zero;
580 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f); 698 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f);
581 699
582 lock (m_parts) 700 lockPartsForRead(true);
583 { 701 {
584 foreach (SceneObjectPart part in m_parts.Values) 702 foreach (SceneObjectPart part in m_parts.Values)
585 { 703 {
704
586 Vector3 partscale = part.Scale; 705 Vector3 partscale = part.Scale;
587 Vector3 partoffset = part.OffsetPosition; 706 Vector3 partoffset = part.OffsetPosition;
588 707
@@ -593,8 +712,11 @@ namespace OpenSim.Region.Framework.Scenes
593 maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X; 712 maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X;
594 maxScale.Y = (partscale.Y + partoffset.Y > maxScale.Y) ? partscale.Y + partoffset.Y : maxScale.Y; 713 maxScale.Y = (partscale.Y + partoffset.Y > maxScale.Y) ? partscale.Y + partoffset.Y : maxScale.Y;
595 maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z; 714 maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z;
715
596 } 716 }
597 } 717 }
718 lockPartsForRead(false);
719
598 finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X; 720 finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X;
599 finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y; 721 finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y;
600 finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z; 722 finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z;
@@ -610,10 +732,11 @@ namespace OpenSim.Region.Framework.Scenes
610 732
611 EntityIntersection result = new EntityIntersection(); 733 EntityIntersection result = new EntityIntersection();
612 734
613 lock (m_parts) 735 lockPartsForRead(true);
614 { 736 {
615 foreach (SceneObjectPart part in m_parts.Values) 737 foreach (SceneObjectPart part in m_parts.Values)
616 { 738 {
739
617 // Temporary commented to stop compiler warning 740 // Temporary commented to stop compiler warning
618 //Vector3 partPosition = 741 //Vector3 partPosition =
619 // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z); 742 // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z);
@@ -641,8 +764,10 @@ namespace OpenSim.Region.Framework.Scenes
641 result.distance = inter.distance; 764 result.distance = inter.distance;
642 } 765 }
643 } 766 }
767
644 } 768 }
645 } 769 }
770 lockPartsForRead(false);
646 return result; 771 return result;
647 } 772 }
648 773
@@ -655,10 +780,11 @@ namespace OpenSim.Region.Framework.Scenes
655 public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight) 780 public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight)
656 { 781 {
657 float maxX = -256f, maxY = -256f, maxZ = -256f, minX = 256f, minY = 256f, minZ = 256f; 782 float maxX = -256f, maxY = -256f, maxZ = -256f, minX = 256f, minY = 256f, minZ = 256f;
658 lock (m_parts) 783 lockPartsForRead(true);
659 { 784 {
660 foreach (SceneObjectPart part in m_parts.Values) 785 foreach (SceneObjectPart part in m_parts.Values)
661 { 786 {
787
662 Vector3 worldPos = part.GetWorldPosition(); 788 Vector3 worldPos = part.GetWorldPosition();
663 Vector3 offset = worldPos - AbsolutePosition; 789 Vector3 offset = worldPos - AbsolutePosition;
664 Quaternion worldRot; 790 Quaternion worldRot;
@@ -717,6 +843,8 @@ namespace OpenSim.Region.Framework.Scenes
717 backBottomRight.Y = orig.Y + (part.Scale.Y / 2); 843 backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
718 backBottomRight.Z = orig.Z - (part.Scale.Z / 2); 844 backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
719 845
846
847
720 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z); 848 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
721 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z); 849 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
722 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z); 850 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
@@ -888,6 +1016,7 @@ namespace OpenSim.Region.Framework.Scenes
888 minZ = backBottomLeft.Z; 1016 minZ = backBottomLeft.Z;
889 } 1017 }
890 } 1018 }
1019 lockPartsForRead(false);
891 1020
892 Vector3 boundingBox = new Vector3(maxX - minX, maxY - minY, maxZ - minZ); 1021 Vector3 boundingBox = new Vector3(maxX - minX, maxY - minY, maxZ - minZ);
893 1022
@@ -912,21 +1041,29 @@ namespace OpenSim.Region.Framework.Scenes
912 1041
913 public void SaveScriptedState(XmlTextWriter writer) 1042 public void SaveScriptedState(XmlTextWriter writer)
914 { 1043 {
1044 SaveScriptedState(writer, false);
1045 }
1046
1047 public void SaveScriptedState(XmlTextWriter writer, bool oldIDs)
1048 {
915 XmlDocument doc = new XmlDocument(); 1049 XmlDocument doc = new XmlDocument();
916 Dictionary<UUID,string> states = new Dictionary<UUID,string>(); 1050 Dictionary<UUID,string> states = new Dictionary<UUID,string>();
917 1051
918 // Capture script state while holding the lock 1052 // Capture script state while holding the lock
919 lock (m_parts) 1053 lockPartsForRead(true);
920 { 1054 {
921 foreach (SceneObjectPart part in m_parts.Values) 1055 foreach (SceneObjectPart part in m_parts.Values)
922 { 1056 {
923 Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates(); 1057
1058 Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates(oldIDs);
924 foreach (UUID itemid in pstates.Keys) 1059 foreach (UUID itemid in pstates.Keys)
925 { 1060 {
926 states.Add(itemid, pstates[itemid]); 1061 states.Add(itemid, pstates[itemid]);
927 } 1062 }
1063
928 } 1064 }
929 } 1065 }
1066 lockPartsForRead(false);
930 1067
931 if (states.Count > 0) 1068 if (states.Count > 0)
932 { 1069 {
@@ -1094,13 +1231,16 @@ namespace OpenSim.Region.Framework.Scenes
1094 1231
1095 public override void UpdateMovement() 1232 public override void UpdateMovement()
1096 { 1233 {
1097 lock (m_parts) 1234 lockPartsForRead(true);
1098 { 1235 {
1099 foreach (SceneObjectPart part in m_parts.Values) 1236 foreach (SceneObjectPart part in m_parts.Values)
1100 { 1237 {
1238
1101 part.UpdateMovement(); 1239 part.UpdateMovement();
1240
1102 } 1241 }
1103 } 1242 }
1243 lockPartsForRead(false);
1104 } 1244 }
1105 1245
1106 public ushort GetTimeDilation() 1246 public ushort GetTimeDilation()
@@ -1144,7 +1284,7 @@ namespace OpenSim.Region.Framework.Scenes
1144 /// <param name="part"></param> 1284 /// <param name="part"></param>
1145 public void AddPart(SceneObjectPart part) 1285 public void AddPart(SceneObjectPart part)
1146 { 1286 {
1147 lock (m_parts) 1287 lockPartsForWrite(true);
1148 { 1288 {
1149 part.SetParent(this); 1289 part.SetParent(this);
1150 m_parts.Add(part.UUID, part); 1290 m_parts.Add(part.UUID, part);
@@ -1154,6 +1294,7 @@ namespace OpenSim.Region.Framework.Scenes
1154 if (part.LinkNum == 2 && RootPart != null) 1294 if (part.LinkNum == 2 && RootPart != null)
1155 RootPart.LinkNum = 1; 1295 RootPart.LinkNum = 1;
1156 } 1296 }
1297 lockPartsForWrite(false);
1157 } 1298 }
1158 1299
1159 /// <summary> 1300 /// <summary>
@@ -1161,28 +1302,33 @@ namespace OpenSim.Region.Framework.Scenes
1161 /// </summary> 1302 /// </summary>
1162 private void UpdateParentIDs() 1303 private void UpdateParentIDs()
1163 { 1304 {
1164 lock (m_parts) 1305 lockPartsForRead(true);
1165 { 1306 {
1166 foreach (SceneObjectPart part in m_parts.Values) 1307 foreach (SceneObjectPart part in m_parts.Values)
1167 { 1308 {
1309
1168 if (part.UUID != m_rootPart.UUID) 1310 if (part.UUID != m_rootPart.UUID)
1169 { 1311 {
1170 part.ParentID = m_rootPart.LocalId; 1312 part.ParentID = m_rootPart.LocalId;
1171 } 1313 }
1314
1172 } 1315 }
1173 } 1316 }
1317 lockPartsForRead(false);
1174 } 1318 }
1175 1319
1176 public void RegenerateFullIDs() 1320 public void RegenerateFullIDs()
1177 { 1321 {
1178 lock (m_parts) 1322 lockPartsForRead(true);
1179 { 1323 {
1180 foreach (SceneObjectPart part in m_parts.Values) 1324 foreach (SceneObjectPart part in m_parts.Values)
1181 { 1325 {
1326
1182 part.UUID = UUID.Random(); 1327 part.UUID = UUID.Random();
1183 1328
1184 } 1329 }
1185 } 1330 }
1331 lockPartsForRead(false);
1186 } 1332 }
1187 1333
1188 // helper provided for parts. 1334 // helper provided for parts.
@@ -1263,27 +1409,32 @@ namespace OpenSim.Region.Framework.Scenes
1263 1409
1264 DetachFromBackup(); 1410 DetachFromBackup();
1265 1411
1266 lock (m_parts) 1412 lockPartsForRead(true);
1413 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1414 lockPartsForRead(false);
1415
1416 foreach (SceneObjectPart part in values)
1267 { 1417 {
1268 foreach (SceneObjectPart part in m_parts.Values)
1269 {
1270// part.Inventory.RemoveScriptInstances(); 1418// part.Inventory.RemoveScriptInstances();
1271 Scene.ForEachScenePresence(delegate(ScenePresence avatar) 1419
1420 Scene.ForEachScenePresence(delegate (ScenePresence sp)
1421 {
1422 if (sp.ParentID == LocalId)
1272 { 1423 {
1273 if (avatar.ParentID == LocalId) 1424 sp.StandUp();
1274 { 1425 }
1275 avatar.StandUp();
1276 }
1277 1426
1278 if (!silent) 1427 if (!silent)
1279 { 1428 {
1280 part.UpdateFlag = 0; 1429 part.UpdateFlag = 0;
1281 if (part == m_rootPart) 1430 if (part == m_rootPart)
1282 avatar.ControllingClient.SendKillObject(m_regionHandle, part.LocalId); 1431 sp.ControllingClient.SendKillObject(m_regionHandle, part.LocalId);
1283 } 1432 }
1284 }); 1433 });
1285 } 1434
1286 } 1435 }
1436
1437
1287 } 1438 }
1288 1439
1289 public void AddScriptLPS(int count) 1440 public void AddScriptLPS(int count)
@@ -1308,17 +1459,20 @@ namespace OpenSim.Region.Framework.Scenes
1308 1459
1309 scriptEvents aggregateScriptEvents=0; 1460 scriptEvents aggregateScriptEvents=0;
1310 1461
1311 lock (m_parts) 1462 lockPartsForRead(true);
1312 { 1463 {
1313 foreach (SceneObjectPart part in m_parts.Values) 1464 foreach (SceneObjectPart part in m_parts.Values)
1314 { 1465 {
1466
1315 if (part == null) 1467 if (part == null)
1316 continue; 1468 continue;
1317 if (part != RootPart) 1469 if (part != RootPart)
1318 part.ObjectFlags = objectflagupdate; 1470 part.ObjectFlags = objectflagupdate;
1319 aggregateScriptEvents |= part.AggregateScriptEvents; 1471 aggregateScriptEvents |= part.AggregateScriptEvents;
1472
1320 } 1473 }
1321 } 1474 }
1475 lockPartsForRead(false);
1322 1476
1323 m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0); 1477 m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0);
1324 m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0); 1478 m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0);
@@ -1360,42 +1514,52 @@ namespace OpenSim.Region.Framework.Scenes
1360 /// <param name="m_physicalPrim"></param> 1514 /// <param name="m_physicalPrim"></param>
1361 public void ApplyPhysics(bool m_physicalPrim) 1515 public void ApplyPhysics(bool m_physicalPrim)
1362 { 1516 {
1363 lock (m_parts) 1517 lockPartsForRead(true);
1518
1519 if (m_parts.Count > 1)
1364 { 1520 {
1365 if (m_parts.Count > 1) 1521 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1522 lockPartsForRead(false);
1523 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1524 foreach (SceneObjectPart part in values)
1366 { 1525 {
1367 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim); 1526
1368 foreach (SceneObjectPart part in m_parts.Values) 1527 if (part.LocalId != m_rootPart.LocalId)
1369 { 1528 {
1370 if (part.LocalId != m_rootPart.LocalId) 1529 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
1371 {
1372 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
1373 }
1374 } 1530 }
1375 1531
1376 // Hack to get the physics scene geometries in the right spot
1377 ResetChildPrimPhysicsPositions();
1378 }
1379 else
1380 {
1381 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1382 } 1532 }
1533 // Hack to get the physics scene geometries in the right spot
1534 ResetChildPrimPhysicsPositions();
1535 }
1536 else
1537 {
1538 lockPartsForRead(false);
1539 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1383 } 1540 }
1384 } 1541 }
1385 1542
1386 public void SetOwnerId(UUID userId) 1543 public void SetOwnerId(UUID userId)
1387 { 1544 {
1388 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); 1545 ForEachPart(delegate(SceneObjectPart part)
1546 {
1547
1548 part.OwnerID = userId;
1549
1550 });
1389 } 1551 }
1390 1552
1391 public void ForEachPart(Action<SceneObjectPart> whatToDo) 1553 public void ForEachPart(Action<SceneObjectPart> whatToDo)
1392 { 1554 {
1393 lock (m_parts) 1555 lockPartsForRead(true);
1556 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1557 lockPartsForRead(false);
1558 foreach (SceneObjectPart part in values)
1394 { 1559 {
1395 foreach (SceneObjectPart part in m_parts.Values) 1560
1396 { 1561 whatToDo(part);
1397 whatToDo(part); 1562
1398 }
1399 } 1563 }
1400 } 1564 }
1401 1565
@@ -1493,15 +1657,17 @@ namespace OpenSim.Region.Framework.Scenes
1493 RootPart.SendFullUpdate( 1657 RootPart.SendFullUpdate(
1494 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID)); 1658 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID));
1495 1659
1496 lock (m_parts) 1660 lockPartsForRead(true);
1497 { 1661 {
1498 foreach (SceneObjectPart part in m_parts.Values) 1662 foreach (SceneObjectPart part in m_parts.Values)
1499 { 1663 {
1664
1500 if (part != RootPart) 1665 if (part != RootPart)
1501 part.SendFullUpdate( 1666 part.SendFullUpdate(
1502 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID)); 1667 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID));
1503 } 1668 }
1504 } 1669 }
1670 lockPartsForRead(false);
1505 } 1671 }
1506 1672
1507 #region Copying 1673 #region Copying
@@ -1570,10 +1736,11 @@ namespace OpenSim.Region.Framework.Scenes
1570 1736
1571 List<SceneObjectPart> partList; 1737 List<SceneObjectPart> partList;
1572 1738
1573 lock (m_parts) 1739 lockPartsForRead(true);
1574 { 1740
1575 partList = new List<SceneObjectPart>(m_parts.Values); 1741 partList = new List<SceneObjectPart>(m_parts.Values);
1576 } 1742
1743 lockPartsForRead(false);
1577 1744
1578 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) 1745 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1579 { 1746 {
@@ -1796,13 +1963,40 @@ namespace OpenSim.Region.Framework.Scenes
1796 } 1963 }
1797 } 1964 }
1798 1965
1966 public void rotLookAt(Quaternion target, float strength, float damping)
1967 {
1968 SceneObjectPart rootpart = m_rootPart;
1969 if (rootpart != null)
1970 {
1971 if (IsAttachment)
1972 {
1973 /*
1974 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
1975 if (avatar != null)
1976 {
1977 Rotate the Av?
1978 } */
1979 }
1980 else
1981 {
1982 if (rootpart.PhysActor != null)
1983 { // APID must be implemented in your physics system for this to function.
1984 rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W);
1985 rootpart.PhysActor.APIDStrength = strength;
1986 rootpart.PhysActor.APIDDamping = damping;
1987 rootpart.PhysActor.APIDActive = true;
1988 }
1989 }
1990 }
1991 }
1992
1799 public void stopLookAt() 1993 public void stopLookAt()
1800 { 1994 {
1801 SceneObjectPart rootpart = m_rootPart; 1995 SceneObjectPart rootpart = m_rootPart;
1802 if (rootpart != null) 1996 if (rootpart != null)
1803 { 1997 {
1804 if (rootpart.PhysActor != null) 1998 if (rootpart.PhysActor != null)
1805 { 1999 { // APID must be implemented in your physics system for this to function.
1806 rootpart.PhysActor.APIDActive = false; 2000 rootpart.PhysActor.APIDActive = false;
1807 } 2001 }
1808 } 2002 }
@@ -1870,10 +2064,11 @@ namespace OpenSim.Region.Framework.Scenes
1870 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 2064 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
1871 newPart.SetParent(this); 2065 newPart.SetParent(this);
1872 2066
1873 lock (m_parts) 2067 lockPartsForWrite(true);
1874 { 2068 {
1875 m_parts.Add(newPart.UUID, newPart); 2069 m_parts.Add(newPart.UUID, newPart);
1876 } 2070 }
2071 lockPartsForWrite(false);
1877 2072
1878 SetPartAsNonRoot(newPart); 2073 SetPartAsNonRoot(newPart);
1879 2074
@@ -1936,7 +2131,7 @@ namespace OpenSim.Region.Framework.Scenes
1936 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0) 2131 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
1937 // return; 2132 // return;
1938 2133
1939 lock (m_parts) 2134 lockPartsForRead(true);
1940 { 2135 {
1941 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0); 2136 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0);
1942 2137
@@ -1956,9 +2151,12 @@ namespace OpenSim.Region.Framework.Scenes
1956 { 2151 {
1957 if (!IsSelected) 2152 if (!IsSelected)
1958 part.UpdateLookAt(); 2153 part.UpdateLookAt();
2154
1959 part.SendScheduledUpdates(); 2155 part.SendScheduledUpdates();
2156
1960 } 2157 }
1961 } 2158 }
2159 lockPartsForRead(false);
1962 } 2160 }
1963 2161
1964 public void ScheduleFullUpdateToAvatar(ScenePresence presence) 2162 public void ScheduleFullUpdateToAvatar(ScenePresence presence)
@@ -1967,27 +2165,29 @@ namespace OpenSim.Region.Framework.Scenes
1967 2165
1968 RootPart.AddFullUpdateToAvatar(presence); 2166 RootPart.AddFullUpdateToAvatar(presence);
1969 2167
1970 lock (m_parts) 2168 lockPartsForRead(true);
1971 { 2169 {
1972 foreach (SceneObjectPart part in m_parts.Values) 2170 foreach (SceneObjectPart part in m_parts.Values)
1973 { 2171 {
2172
1974 if (part != RootPart) 2173 if (part != RootPart)
1975 part.AddFullUpdateToAvatar(presence); 2174 part.AddFullUpdateToAvatar(presence);
2175
1976 } 2176 }
1977 } 2177 }
2178 lockPartsForRead(false);
1978 } 2179 }
1979 2180
1980 public void ScheduleTerseUpdateToAvatar(ScenePresence presence) 2181 public void ScheduleTerseUpdateToAvatar(ScenePresence presence)
1981 { 2182 {
1982// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1} just to avatar {2}", Name, UUID, presence.Name); 2183 lockPartsForRead(true);
1983 2184
1984 lock (m_parts) 2185 foreach (SceneObjectPart part in m_parts.Values)
1985 { 2186 {
1986 foreach (SceneObjectPart part in m_parts.Values) 2187 part.AddTerseUpdateToAvatar(presence);
1987 {
1988 part.AddTerseUpdateToAvatar(presence);
1989 }
1990 } 2188 }
2189
2190 lockPartsForRead(false);
1991 } 2191 }
1992 2192
1993 /// <summary> 2193 /// <summary>
@@ -2000,14 +2200,17 @@ namespace OpenSim.Region.Framework.Scenes
2000 checkAtTargets(); 2200 checkAtTargets();
2001 RootPart.ScheduleFullUpdate(); 2201 RootPart.ScheduleFullUpdate();
2002 2202
2003 lock (m_parts) 2203 lockPartsForRead(true);
2004 { 2204 {
2005 foreach (SceneObjectPart part in m_parts.Values) 2205 foreach (SceneObjectPart part in m_parts.Values)
2006 { 2206 {
2207
2007 if (part != RootPart) 2208 if (part != RootPart)
2008 part.ScheduleFullUpdate(); 2209 part.ScheduleFullUpdate();
2210
2009 } 2211 }
2010 } 2212 }
2213 lockPartsForRead(false);
2011 } 2214 }
2012 2215
2013 /// <summary> 2216 /// <summary>
@@ -2015,37 +2218,38 @@ namespace OpenSim.Region.Framework.Scenes
2015 /// </summary> 2218 /// </summary>
2016 public void ScheduleGroupForTerseUpdate() 2219 public void ScheduleGroupForTerseUpdate()
2017 { 2220 {
2018// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1}", Name, UUID); 2221 lockPartsForRead(true);
2019 2222 foreach (SceneObjectPart part in m_parts.Values)
2020 lock (m_parts)
2021 { 2223 {
2022 foreach (SceneObjectPart part in m_parts.Values) 2224 part.ScheduleTerseUpdate();
2023 {
2024 part.ScheduleTerseUpdate();
2025 }
2026 } 2225 }
2226
2227 lockPartsForRead(false);
2027 } 2228 }
2028 2229
2029 /// <summary> 2230 /// <summary>
2030 /// Immediately send a full update for this scene object. 2231 /// Immediately send a full update for this scene object.
2031 /// </summary> 2232 /// </summary>
2032 public void SendGroupFullUpdate() 2233 public void SendGroupFullUpdate()
2033 { 2234 {
2034 if (IsDeleted) 2235 if (IsDeleted)
2035 return; 2236 return;
2036 2237
2037// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); 2238// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID);
2038 2239
2039 RootPart.SendFullUpdateToAllClients(); 2240 RootPart.SendFullUpdateToAllClients();
2040 2241
2041 lock (m_parts) 2242 lockPartsForRead(true);
2042 { 2243 {
2043 foreach (SceneObjectPart part in m_parts.Values) 2244 foreach (SceneObjectPart part in m_parts.Values)
2044 { 2245 {
2246
2045 if (part != RootPart) 2247 if (part != RootPart)
2046 part.SendFullUpdateToAllClients(); 2248 part.SendFullUpdateToAllClients();
2249
2047 } 2250 }
2048 } 2251 }
2252 lockPartsForRead(false);
2049 } 2253 }
2050 2254
2051 /// <summary> 2255 /// <summary>
@@ -2077,14 +2281,15 @@ namespace OpenSim.Region.Framework.Scenes
2077 { 2281 {
2078 if (IsDeleted) 2282 if (IsDeleted)
2079 return; 2283 return;
2080 2284
2081 lock (m_parts) 2285 lockPartsForRead(true);
2082 { 2286 {
2083 foreach (SceneObjectPart part in m_parts.Values) 2287 foreach (SceneObjectPart part in m_parts.Values)
2084 { 2288 {
2085 part.SendTerseUpdateToAllClients(); 2289 part.SendTerseUpdateToAllClients();
2086 } 2290 }
2087 } 2291 }
2292 lockPartsForRead(false);
2088 } 2293 }
2089 2294
2090 #endregion 2295 #endregion
@@ -2098,16 +2303,18 @@ namespace OpenSim.Region.Framework.Scenes
2098 /// <returns>null if no child part with that linknum or child part</returns> 2303 /// <returns>null if no child part with that linknum or child part</returns>
2099 public SceneObjectPart GetLinkNumPart(int linknum) 2304 public SceneObjectPart GetLinkNumPart(int linknum)
2100 { 2305 {
2101 lock (m_parts) 2306 lockPartsForRead(true);
2102 { 2307 {
2103 foreach (SceneObjectPart part in m_parts.Values) 2308 foreach (SceneObjectPart part in m_parts.Values)
2104 { 2309 {
2105 if (part.LinkNum == linknum) 2310 if (part.LinkNum == linknum)
2106 { 2311 {
2312 lockPartsForRead(false);
2107 return part; 2313 return part;
2108 } 2314 }
2109 } 2315 }
2110 } 2316 }
2317 lockPartsForRead(false);
2111 2318
2112 return null; 2319 return null;
2113 } 2320 }
@@ -2135,17 +2342,19 @@ namespace OpenSim.Region.Framework.Scenes
2135 public SceneObjectPart GetChildPart(uint localID) 2342 public SceneObjectPart GetChildPart(uint localID)
2136 { 2343 {
2137 //m_log.DebugFormat("Entered looking for {0}", localID); 2344 //m_log.DebugFormat("Entered looking for {0}", localID);
2138 lock (m_parts) 2345 lockPartsForRead(true);
2139 { 2346 {
2140 foreach (SceneObjectPart part in m_parts.Values) 2347 foreach (SceneObjectPart part in m_parts.Values)
2141 { 2348 {
2142 //m_log.DebugFormat("Found {0}", part.LocalId); 2349 //m_log.DebugFormat("Found {0}", part.LocalId);
2143 if (part.LocalId == localID) 2350 if (part.LocalId == localID)
2144 { 2351 {
2352 lockPartsForRead(false);
2145 return part; 2353 return part;
2146 } 2354 }
2147 } 2355 }
2148 } 2356 }
2357 lockPartsForRead(false);
2149 2358
2150 return null; 2359 return null;
2151 } 2360 }
@@ -2175,17 +2384,19 @@ namespace OpenSim.Region.Framework.Scenes
2175 public bool HasChildPrim(uint localID) 2384 public bool HasChildPrim(uint localID)
2176 { 2385 {
2177 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID); 2386 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID);
2178 lock (m_parts) 2387 lockPartsForRead(true);
2179 { 2388 {
2180 foreach (SceneObjectPart part in m_parts.Values) 2389 foreach (SceneObjectPart part in m_parts.Values)
2181 { 2390 {
2182 //m_log.DebugFormat("Found {0}", part.LocalId); 2391 //m_log.DebugFormat("Found {0}", part.LocalId);
2183 if (part.LocalId == localID) 2392 if (part.LocalId == localID)
2184 { 2393 {
2394 lockPartsForRead(false);
2185 return true; 2395 return true;
2186 } 2396 }
2187 } 2397 }
2188 } 2398 }
2399 lockPartsForRead(false);
2189 2400
2190 return false; 2401 return false;
2191 } 2402 }
@@ -2235,53 +2446,57 @@ namespace OpenSim.Region.Framework.Scenes
2235 if (m_rootPart.LinkNum == 0) 2446 if (m_rootPart.LinkNum == 0)
2236 m_rootPart.LinkNum = 1; 2447 m_rootPart.LinkNum = 1;
2237 2448
2238 lock (m_parts) 2449 lockPartsForWrite(true);
2239 { 2450
2240 m_parts.Add(linkPart.UUID, linkPart); 2451 m_parts.Add(linkPart.UUID, linkPart);
2452
2453 lockPartsForWrite(false);
2241 2454
2242 // Insert in terms of link numbers, the new links 2455 // Insert in terms of link numbers, the new links
2243 // before the current ones (with the exception of 2456 // before the current ones (with the exception of
2244 // the root prim. Shuffle the old ones up 2457 // the root prim. Shuffle the old ones up
2245 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts) 2458 lockPartsForRead(true);
2459 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts)
2460 {
2461 if (kvp.Value.LinkNum != 1)
2246 { 2462 {
2247 if (kvp.Value.LinkNum != 1) 2463 // Don't update root prim link number
2248 { 2464 kvp.Value.LinkNum += objectGroup.PrimCount;
2249 // Don't update root prim link number
2250 kvp.Value.LinkNum += objectGroup.PrimCount;
2251 }
2252 } 2465 }
2466 }
2467 lockPartsForRead(false);
2253 2468
2254 linkPart.LinkNum = 2; 2469 linkPart.LinkNum = 2;
2255 2470
2256 linkPart.SetParent(this); 2471 linkPart.SetParent(this);
2257 linkPart.AddFlag(PrimFlags.CreateSelected); 2472 linkPart.AddFlag(PrimFlags.CreateSelected);
2258 2473
2259 //if (linkPart.PhysActor != null) 2474 //if (linkPart.PhysActor != null)
2260 //{ 2475 //{
2261 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); 2476 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
2262 2477
2263 //linkPart.PhysActor = null; 2478 //linkPart.PhysActor = null;
2264 //} 2479 //}
2265 2480
2266 //TODO: rest of parts 2481 //TODO: rest of parts
2267 int linkNum = 3; 2482 int linkNum = 3;
2268 foreach (SceneObjectPart part in objectGroup.Children.Values) 2483 foreach (SceneObjectPart part in objectGroup.Children.Values)
2484 {
2485 if (part.UUID != objectGroup.m_rootPart.UUID)
2269 { 2486 {
2270 if (part.UUID != objectGroup.m_rootPart.UUID) 2487 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2271 {
2272 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2273 }
2274 part.ClearUndoState();
2275 } 2488 }
2489 part.ClearUndoState();
2276 } 2490 }
2277 2491
2278 m_scene.UnlinkSceneObject(objectGroup.UUID, true); 2492 m_scene.UnlinkSceneObject(objectGroup.UUID, true);
2279 objectGroup.m_isDeleted = true; 2493 objectGroup.m_isDeleted = true;
2494
2495 objectGroup.lockPartsForWrite(true);
2280 2496
2281 lock (objectGroup.m_parts) 2497 objectGroup.m_parts.Clear();
2282 { 2498
2283 objectGroup.m_parts.Clear(); 2499 objectGroup.lockPartsForWrite(false);
2284 }
2285 2500
2286 // Can't do this yet since backup still makes use of the root part without any synchronization 2501 // Can't do this yet since backup still makes use of the root part without any synchronization
2287// objectGroup.m_rootPart = null; 2502// objectGroup.m_rootPart = null;
@@ -2351,11 +2566,12 @@ namespace OpenSim.Region.Framework.Scenes
2351 Quaternion worldRot = linkPart.GetWorldRotation(); 2566 Quaternion worldRot = linkPart.GetWorldRotation();
2352 2567
2353 // Remove the part from this object 2568 // Remove the part from this object
2354 lock (m_parts) 2569 lockPartsForWrite(true);
2355 { 2570 {
2356 m_parts.Remove(linkPart.UUID); 2571 m_parts.Remove(linkPart.UUID);
2357 } 2572 }
2358 2573 lockPartsForWrite(false);
2574 lockPartsForRead(true);
2359 if (m_parts.Count == 1 && RootPart != null) //Single prim is left 2575 if (m_parts.Count == 1 && RootPart != null) //Single prim is left
2360 RootPart.LinkNum = 0; 2576 RootPart.LinkNum = 0;
2361 else 2577 else
@@ -2366,6 +2582,7 @@ namespace OpenSim.Region.Framework.Scenes
2366 p.LinkNum--; 2582 p.LinkNum--;
2367 } 2583 }
2368 } 2584 }
2585 lockPartsForRead(false);
2369 2586
2370 linkPart.ParentID = 0; 2587 linkPart.ParentID = 0;
2371 linkPart.LinkNum = 0; 2588 linkPart.LinkNum = 0;
@@ -2687,9 +2904,12 @@ namespace OpenSim.Region.Framework.Scenes
2687 2904
2688 if (selectionPart != null) 2905 if (selectionPart != null)
2689 { 2906 {
2690 lock (m_parts) 2907 lockPartsForRead(true);
2908 List<SceneObjectPart> parts = new List<SceneObjectPart>(m_parts.Values);
2909 lockPartsForRead(false);
2910 foreach (SceneObjectPart part in parts)
2691 { 2911 {
2692 foreach (SceneObjectPart part in m_parts.Values) 2912 if (part.Scale.X > 10.0 || part.Scale.Y > 10.0 || part.Scale.Z > 10.0)
2693 { 2913 {
2694 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax || 2914 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax ||
2695 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax || 2915 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax ||
@@ -2699,12 +2919,13 @@ namespace OpenSim.Region.Framework.Scenes
2699 break; 2919 break;
2700 } 2920 }
2701 } 2921 }
2922 }
2702 2923
2703 foreach (SceneObjectPart part in m_parts.Values) 2924 foreach (SceneObjectPart part in parts)
2704 { 2925 {
2705 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect); 2926 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
2706 }
2707 } 2927 }
2928
2708 } 2929 }
2709 } 2930 }
2710 2931
@@ -2790,11 +3011,9 @@ namespace OpenSim.Region.Framework.Scenes
2790 scale.Y = m_scene.m_maxNonphys; 3011 scale.Y = m_scene.m_maxNonphys;
2791 if (scale.Z > m_scene.m_maxNonphys) 3012 if (scale.Z > m_scene.m_maxNonphys)
2792 scale.Z = m_scene.m_maxNonphys; 3013 scale.Z = m_scene.m_maxNonphys;
2793
2794 SceneObjectPart part = GetChildPart(localID); 3014 SceneObjectPart part = GetChildPart(localID);
2795 if (part != null) 3015 if (part != null)
2796 { 3016 {
2797 part.Resize(scale);
2798 if (part.PhysActor != null) 3017 if (part.PhysActor != null)
2799 { 3018 {
2800 if (part.PhysActor.IsPhysical) 3019 if (part.PhysActor.IsPhysical)
@@ -2809,7 +3028,7 @@ namespace OpenSim.Region.Framework.Scenes
2809 part.PhysActor.Size = scale; 3028 part.PhysActor.Size = scale;
2810 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); 3029 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
2811 } 3030 }
2812 //if (part.UUID != m_rootPart.UUID) 3031 part.Resize(scale);
2813 3032
2814 HasGroupChanged = true; 3033 HasGroupChanged = true;
2815 ScheduleGroupForFullUpdate(); 3034 ScheduleGroupForFullUpdate();
@@ -2851,73 +3070,71 @@ namespace OpenSim.Region.Framework.Scenes
2851 float y = (scale.Y / part.Scale.Y); 3070 float y = (scale.Y / part.Scale.Y);
2852 float z = (scale.Z / part.Scale.Z); 3071 float z = (scale.Z / part.Scale.Z);
2853 3072
2854 lock (m_parts) 3073 lockPartsForRead(true);
3074 if (x > 1.0f || y > 1.0f || z > 1.0f)
2855 { 3075 {
2856 if (x > 1.0f || y > 1.0f || z > 1.0f) 3076 foreach (SceneObjectPart obPart in m_parts.Values)
2857 { 3077 {
2858 foreach (SceneObjectPart obPart in m_parts.Values) 3078 if (obPart.UUID != m_rootPart.UUID)
2859 { 3079 {
2860 if (obPart.UUID != m_rootPart.UUID) 3080 Vector3 oldSize = new Vector3(obPart.Scale);
2861 { 3081 obPart.IgnoreUndoUpdate = true;
2862 obPart.IgnoreUndoUpdate = true;
2863 Vector3 oldSize = new Vector3(obPart.Scale);
2864 3082
2865 float f = 1.0f; 3083 float f = 1.0f;
2866 float a = 1.0f; 3084 float a = 1.0f;
2867 3085
2868 if (part.PhysActor != null && part.PhysActor.IsPhysical) 3086 if (part.PhysActor != null && part.PhysActor.IsPhysical)
3087 {
3088 if (oldSize.X*x > m_scene.m_maxPhys)
2869 { 3089 {
2870 if (oldSize.X*x > m_scene.m_maxPhys) 3090 f = m_scene.m_maxPhys / oldSize.X;
2871 { 3091 a = f / x;
2872 f = m_scene.m_maxPhys / oldSize.X; 3092 x *= a;
2873 a = f / x; 3093 y *= a;
2874 x *= a; 3094 z *= a;
2875 y *= a;
2876 z *= a;
2877 }
2878 if (oldSize.Y*y > m_scene.m_maxPhys)
2879 {
2880 f = m_scene.m_maxPhys / oldSize.Y;
2881 a = f / y;
2882 x *= a;
2883 y *= a;
2884 z *= a;
2885 }
2886 if (oldSize.Z*z > m_scene.m_maxPhys)
2887 {
2888 f = m_scene.m_maxPhys / oldSize.Z;
2889 a = f / z;
2890 x *= a;
2891 y *= a;
2892 z *= a;
2893 }
2894 } 3095 }
2895 else 3096 if (oldSize.Y*y > m_scene.m_maxPhys)
3097 {
3098 f = m_scene.m_maxPhys / oldSize.Y;
3099 a = f / y;
3100 x *= a;
3101 y *= a;
3102 z *= a;
3103 }
3104 if (oldSize.Z*z > m_scene.m_maxPhys)
2896 { 3105 {
2897 if (oldSize.X*x > m_scene.m_maxNonphys) 3106 f = m_scene.m_maxPhys / oldSize.Z;
2898 { 3107 a = f / z;
2899 f = m_scene.m_maxNonphys / oldSize.X; 3108 x *= a;
2900 a = f / x; 3109 y *= a;
2901 x *= a; 3110 z *= a;
2902 y *= a; 3111 }
2903 z *= a; 3112 }
2904 } 3113 else
2905 if (oldSize.Y*y > m_scene.m_maxNonphys) 3114 {
2906 { 3115 if (oldSize.X*x > m_scene.m_maxNonphys)
2907 f = m_scene.m_maxNonphys / oldSize.Y; 3116 {
2908 a = f / y; 3117 f = m_scene.m_maxNonphys / oldSize.X;
2909 x *= a; 3118 a = f / x;
2910 y *= a; 3119 x *= a;
2911 z *= a; 3120 y *= a;
2912 } 3121 z *= a;
2913 if (oldSize.Z*z > m_scene.m_maxNonphys) 3122 }
2914 { 3123 if (oldSize.Y*y > m_scene.m_maxNonphys)
2915 f = m_scene.m_maxNonphys / oldSize.Z; 3124 {
2916 a = f / z; 3125 f = m_scene.m_maxNonphys / oldSize.Y;
2917 x *= a; 3126 a = f / y;
2918 y *= a; 3127 x *= a;
2919 z *= a; 3128 y *= a;
2920 } 3129 z *= a;
3130 }
3131 if (oldSize.Z*z > m_scene.m_maxNonphys)
3132 {
3133 f = m_scene.m_maxNonphys / oldSize.Z;
3134 a = f / z;
3135 x *= a;
3136 y *= a;
3137 z *= a;
2921 } 3138 }
2922 obPart.IgnoreUndoUpdate = false; 3139 obPart.IgnoreUndoUpdate = false;
2923 obPart.StoreUndoState(); 3140 obPart.StoreUndoState();
@@ -2925,6 +3142,7 @@ namespace OpenSim.Region.Framework.Scenes
2925 } 3142 }
2926 } 3143 }
2927 } 3144 }
3145 lockPartsForRead(false);
2928 3146
2929 Vector3 prevScale = part.Scale; 3147 Vector3 prevScale = part.Scale;
2930 prevScale.X *= x; 3148 prevScale.X *= x;
@@ -2932,7 +3150,7 @@ namespace OpenSim.Region.Framework.Scenes
2932 prevScale.Z *= z; 3150 prevScale.Z *= z;
2933 part.Resize(prevScale); 3151 part.Resize(prevScale);
2934 3152
2935 lock (m_parts) 3153 lockPartsForRead(true);
2936 { 3154 {
2937 foreach (SceneObjectPart obPart in m_parts.Values) 3155 foreach (SceneObjectPart obPart in m_parts.Values)
2938 { 3156 {
@@ -2954,6 +3172,7 @@ namespace OpenSim.Region.Framework.Scenes
2954 obPart.StoreUndoState(); 3172 obPart.StoreUndoState();
2955 } 3173 }
2956 } 3174 }
3175 lockPartsForRead(false);
2957 3176
2958 if (part.PhysActor != null) 3177 if (part.PhysActor != null)
2959 { 3178 {
@@ -3056,7 +3275,7 @@ namespace OpenSim.Region.Framework.Scenes
3056 axDiff *= Quaternion.Inverse(partRotation); 3275 axDiff *= Quaternion.Inverse(partRotation);
3057 diff = axDiff; 3276 diff = axDiff;
3058 3277
3059 lock (m_parts) 3278 lockPartsForRead(true);
3060 { 3279 {
3061 foreach (SceneObjectPart obPart in m_parts.Values) 3280 foreach (SceneObjectPart obPart in m_parts.Values)
3062 { 3281 {
@@ -3066,6 +3285,7 @@ namespace OpenSim.Region.Framework.Scenes
3066 } 3285 }
3067 } 3286 }
3068 } 3287 }
3288 lockPartsForRead(false);
3069 3289
3070 AbsolutePosition = newPos; 3290 AbsolutePosition = newPos;
3071 3291
@@ -3199,25 +3419,25 @@ namespace OpenSim.Region.Framework.Scenes
3199 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); 3419 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
3200 } 3420 }
3201 3421
3202 lock (m_parts) 3422 lockPartsForRead(true);
3423
3424 foreach (SceneObjectPart prim in m_parts.Values)
3203 { 3425 {
3204 foreach (SceneObjectPart prim in m_parts.Values) 3426 if (prim.UUID != m_rootPart.UUID)
3205 { 3427 {
3206 if (prim.UUID != m_rootPart.UUID) 3428 prim.IgnoreUndoUpdate = true;
3207 { 3429 Vector3 axPos = prim.OffsetPosition;
3208 prim.IgnoreUndoUpdate = true; 3430 axPos *= oldParentRot;
3209 Vector3 axPos = prim.OffsetPosition; 3431 axPos *= Quaternion.Inverse(axRot);
3210 axPos *= oldParentRot; 3432 prim.OffsetPosition = axPos;
3211 axPos *= Quaternion.Inverse(axRot); 3433 Quaternion primsRot = prim.RotationOffset;
3212 prim.OffsetPosition = axPos; 3434 Quaternion newRot = primsRot * oldParentRot;
3213 Quaternion primsRot = prim.RotationOffset; 3435 newRot *= Quaternion.Inverse(axRot);
3214 Quaternion newRot = primsRot * oldParentRot; 3436 prim.RotationOffset = newRot;
3215 newRot *= Quaternion.Inverse(axRot); 3437 prim.ScheduleTerseUpdate();
3216 prim.RotationOffset = newRot;
3217 prim.ScheduleTerseUpdate();
3218 }
3219 } 3438 }
3220 } 3439 }
3440
3221 foreach (SceneObjectPart childpart in Children.Values) 3441 foreach (SceneObjectPart childpart in Children.Values)
3222 { 3442 {
3223 if (childpart != m_rootPart) 3443 if (childpart != m_rootPart)
@@ -3226,6 +3446,9 @@ namespace OpenSim.Region.Framework.Scenes
3226 childpart.StoreUndoState(); 3446 childpart.StoreUndoState();
3227 } 3447 }
3228 } 3448 }
3449
3450 lockPartsForRead(false);
3451
3229 m_rootPart.ScheduleTerseUpdate(); 3452 m_rootPart.ScheduleTerseUpdate();
3230 } 3453 }
3231 3454
@@ -3347,7 +3570,7 @@ namespace OpenSim.Region.Framework.Scenes
3347 if (atTargets.Count > 0) 3570 if (atTargets.Count > 0)
3348 { 3571 {
3349 uint[] localids = new uint[0]; 3572 uint[] localids = new uint[0];
3350 lock (m_parts) 3573 lockPartsForRead(true);
3351 { 3574 {
3352 localids = new uint[m_parts.Count]; 3575 localids = new uint[m_parts.Count];
3353 int cntr = 0; 3576 int cntr = 0;
@@ -3357,6 +3580,7 @@ namespace OpenSim.Region.Framework.Scenes
3357 cntr++; 3580 cntr++;
3358 } 3581 }
3359 } 3582 }
3583 lockPartsForRead(false);
3360 3584
3361 for (int ctr = 0; ctr < localids.Length; ctr++) 3585 for (int ctr = 0; ctr < localids.Length; ctr++)
3362 { 3586 {
@@ -3375,7 +3599,7 @@ namespace OpenSim.Region.Framework.Scenes
3375 { 3599 {
3376 //trigger not_at_target 3600 //trigger not_at_target
3377 uint[] localids = new uint[0]; 3601 uint[] localids = new uint[0];
3378 lock (m_parts) 3602 lockPartsForRead(true);
3379 { 3603 {
3380 localids = new uint[m_parts.Count]; 3604 localids = new uint[m_parts.Count];
3381 int cntr = 0; 3605 int cntr = 0;
@@ -3385,7 +3609,8 @@ namespace OpenSim.Region.Framework.Scenes
3385 cntr++; 3609 cntr++;
3386 } 3610 }
3387 } 3611 }
3388 3612 lockPartsForRead(false);
3613
3389 for (int ctr = 0; ctr < localids.Length; ctr++) 3614 for (int ctr = 0; ctr < localids.Length; ctr++)
3390 { 3615 {
3391 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]); 3616 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]);
@@ -3426,7 +3651,8 @@ namespace OpenSim.Region.Framework.Scenes
3426 if (atRotTargets.Count > 0) 3651 if (atRotTargets.Count > 0)
3427 { 3652 {
3428 uint[] localids = new uint[0]; 3653 uint[] localids = new uint[0];
3429 lock (m_parts) 3654 lockPartsForRead(true);
3655 try
3430 { 3656 {
3431 localids = new uint[m_parts.Count]; 3657 localids = new uint[m_parts.Count];
3432 int cntr = 0; 3658 int cntr = 0;
@@ -3436,6 +3662,10 @@ namespace OpenSim.Region.Framework.Scenes
3436 cntr++; 3662 cntr++;
3437 } 3663 }
3438 } 3664 }
3665 finally
3666 {
3667 lockPartsForRead(false);
3668 }
3439 3669
3440 for (int ctr = 0; ctr < localids.Length; ctr++) 3670 for (int ctr = 0; ctr < localids.Length; ctr++)
3441 { 3671 {
@@ -3454,7 +3684,8 @@ namespace OpenSim.Region.Framework.Scenes
3454 { 3684 {
3455 //trigger not_at_target 3685 //trigger not_at_target
3456 uint[] localids = new uint[0]; 3686 uint[] localids = new uint[0];
3457 lock (m_parts) 3687 lockPartsForRead(true);
3688 try
3458 { 3689 {
3459 localids = new uint[m_parts.Count]; 3690 localids = new uint[m_parts.Count];
3460 int cntr = 0; 3691 int cntr = 0;
@@ -3464,6 +3695,10 @@ namespace OpenSim.Region.Framework.Scenes
3464 cntr++; 3695 cntr++;
3465 } 3696 }
3466 } 3697 }
3698 finally
3699 {
3700 lockPartsForRead(false);
3701 }
3467 3702
3468 for (int ctr = 0; ctr < localids.Length; ctr++) 3703 for (int ctr = 0; ctr < localids.Length; ctr++)
3469 { 3704 {
@@ -3477,19 +3712,20 @@ namespace OpenSim.Region.Framework.Scenes
3477 public float GetMass() 3712 public float GetMass()
3478 { 3713 {
3479 float retmass = 0f; 3714 float retmass = 0f;
3480 lock (m_parts) 3715 lockPartsForRead(true);
3481 { 3716 {
3482 foreach (SceneObjectPart part in m_parts.Values) 3717 foreach (SceneObjectPart part in m_parts.Values)
3483 { 3718 {
3484 retmass += part.GetMass(); 3719 retmass += part.GetMass();
3485 } 3720 }
3486 } 3721 }
3722 lockPartsForRead(false);
3487 return retmass; 3723 return retmass;
3488 } 3724 }
3489 3725
3490 public void CheckSculptAndLoad() 3726 public void CheckSculptAndLoad()
3491 { 3727 {
3492 lock (m_parts) 3728 lockPartsForRead(true);
3493 { 3729 {
3494 if (!IsDeleted) 3730 if (!IsDeleted)
3495 { 3731 {
@@ -3514,6 +3750,7 @@ namespace OpenSim.Region.Framework.Scenes
3514 } 3750 }
3515 } 3751 }
3516 } 3752 }
3753 lockPartsForRead(false);
3517 } 3754 }
3518 3755
3519 protected void AssetReceived(string id, Object sender, AssetBase asset) 3756 protected void AssetReceived(string id, Object sender, AssetBase asset)
@@ -3534,7 +3771,7 @@ namespace OpenSim.Region.Framework.Scenes
3534 /// <param name="client"></param> 3771 /// <param name="client"></param>
3535 public void SetGroup(UUID GroupID, IClientAPI client) 3772 public void SetGroup(UUID GroupID, IClientAPI client)
3536 { 3773 {
3537 lock (m_parts) 3774 lockPartsForRead(true);
3538 { 3775 {
3539 foreach (SceneObjectPart part in m_parts.Values) 3776 foreach (SceneObjectPart part in m_parts.Values)
3540 { 3777 {
@@ -3544,6 +3781,7 @@ namespace OpenSim.Region.Framework.Scenes
3544 3781
3545 HasGroupChanged = true; 3782 HasGroupChanged = true;
3546 } 3783 }
3784 lockPartsForRead(false);
3547 3785
3548 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled 3786 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled
3549 // for the same object with very different properties. The caller must schedule the update. 3787 // for the same object with very different properties. The caller must schedule the update.
@@ -3565,11 +3803,12 @@ namespace OpenSim.Region.Framework.Scenes
3565 3803
3566 public void SetAttachmentPoint(byte point) 3804 public void SetAttachmentPoint(byte point)
3567 { 3805 {
3568 lock (m_parts) 3806 lockPartsForRead(true);
3569 { 3807 {
3570 foreach (SceneObjectPart part in m_parts.Values) 3808 foreach (SceneObjectPart part in m_parts.Values)
3571 part.SetAttachmentPoint(point); 3809 part.SetAttachmentPoint(point);
3572 } 3810 }
3811 lockPartsForRead(false);
3573 } 3812 }
3574 3813
3575 #region ISceneObject 3814 #region ISceneObject
@@ -3703,5 +3942,13 @@ namespace OpenSim.Region.Framework.Scenes
3703 3942
3704 return priority; 3943 return priority;
3705 } 3944 }
3945
3946 public void ResetOwnerChangeFlag()
3947 {
3948 ForEachPart(delegate(SceneObjectPart part)
3949 {
3950 part.ResetOwnerChangeFlag();
3951 });
3952 }
3706 } 3953 }
3707} 3954}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 46eadee..48e65a5 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -147,7 +147,7 @@ namespace OpenSim.Region.Framework.Scenes
147 147
148 // TODO: This needs to be persisted in next XML version update! 148 // TODO: This needs to be persisted in next XML version update!
149 [XmlIgnore] 149 [XmlIgnore]
150 public readonly int[] PayPrice = {-2,-2,-2,-2,-2}; 150 public int[] PayPrice = {-2,-2,-2,-2,-2};
151 [XmlIgnore] 151 [XmlIgnore]
152 public PhysicsActor PhysActor; 152 public PhysicsActor PhysActor;
153 153
@@ -274,6 +274,7 @@ namespace OpenSim.Region.Framework.Scenes
274 private Quaternion m_sitTargetOrientation = Quaternion.Identity; 274 private Quaternion m_sitTargetOrientation = Quaternion.Identity;
275 private Vector3 m_sitTargetPosition; 275 private Vector3 m_sitTargetPosition;
276 private string m_sitAnimation = "SIT"; 276 private string m_sitAnimation = "SIT";
277 private bool m_occupied; // KF if any av is sitting on this prim
277 private string m_text = String.Empty; 278 private string m_text = String.Empty;
278 private string m_touchName = String.Empty; 279 private string m_touchName = String.Empty;
279 private readonly UndoStack<UndoState> m_undo = new UndoStack<UndoState>(5); 280 private readonly UndoStack<UndoState> m_undo = new UndoStack<UndoState>(5);
@@ -452,12 +453,16 @@ namespace OpenSim.Region.Framework.Scenes
452 } 453 }
453 454
454 /// <value> 455 /// <value>
455 /// Access should be via Inventory directly - this property temporarily remains for xml serialization purposes 456 /// Get the inventory list
456 /// </value> 457 /// </value>
457 public TaskInventoryDictionary TaskInventory 458 public TaskInventoryDictionary TaskInventory
458 { 459 {
459 get { return m_inventory.Items; } 460 get {
460 set { m_inventory.Items = value; } 461 return m_inventory.Items;
462 }
463 set {
464 m_inventory.Items = value;
465 }
461 } 466 }
462 467
463 public uint ObjectFlags 468 public uint ObjectFlags
@@ -586,14 +591,12 @@ namespace OpenSim.Region.Framework.Scenes
586 set { m_LoopSoundSlavePrims = value; } 591 set { m_LoopSoundSlavePrims = value; }
587 } 592 }
588 593
589 [XmlIgnore]
590 public Byte[] TextureAnimation 594 public Byte[] TextureAnimation
591 { 595 {
592 get { return m_TextureAnimation; } 596 get { return m_TextureAnimation; }
593 set { m_TextureAnimation = value; } 597 set { m_TextureAnimation = value; }
594 } 598 }
595 599
596 [XmlIgnore]
597 public Byte[] ParticleSystem 600 public Byte[] ParticleSystem
598 { 601 {
599 get { return m_particleSystem; } 602 get { return m_particleSystem; }
@@ -647,7 +650,6 @@ namespace OpenSim.Region.Framework.Scenes
647 set 650 set
648 { 651 {
649 m_groupPosition = value; 652 m_groupPosition = value;
650
651 PhysicsActor actor = PhysActor; 653 PhysicsActor actor = PhysActor;
652 if (actor != null) 654 if (actor != null)
653 { 655 {
@@ -816,7 +818,16 @@ namespace OpenSim.Region.Framework.Scenes
816 /// <summary></summary> 818 /// <summary></summary>
817 public Vector3 Acceleration 819 public Vector3 Acceleration
818 { 820 {
819 get { return m_acceleration; } 821 get
822 {
823 PhysicsActor actor = PhysActor;
824 if (actor != null)
825 {
826 m_acceleration = actor.Acceleration;
827 }
828 return m_acceleration;
829 }
830
820 set { m_acceleration = value; } 831 set { m_acceleration = value; }
821 } 832 }
822 833
@@ -960,7 +971,8 @@ namespace OpenSim.Region.Framework.Scenes
960 if (IsAttachment) 971 if (IsAttachment)
961 return GroupPosition; 972 return GroupPosition;
962 973
963 return m_offsetPosition + m_groupPosition; } 974// return m_offsetPosition + m_groupPosition; }
975 return m_groupPosition + (m_offsetPosition * ParentGroup.RootPart.RotationOffset) ; } //KF: Rotation was ignored!
964 } 976 }
965 977
966 public SceneObjectGroup ParentGroup 978 public SceneObjectGroup ParentGroup
@@ -1112,6 +1124,13 @@ namespace OpenSim.Region.Framework.Scenes
1112 get { return _flags; } 1124 get { return _flags; }
1113 set { _flags = value; } 1125 set { _flags = value; }
1114 } 1126 }
1127
1128 [XmlIgnore]
1129 public bool IsOccupied // KF If an av is sittingon this prim
1130 {
1131 get { return m_occupied; }
1132 set { m_occupied = value; }
1133 }
1115 1134
1116 [XmlIgnore] 1135 [XmlIgnore]
1117 public UUID SitTargetAvatar 1136 public UUID SitTargetAvatar
@@ -1187,14 +1206,6 @@ namespace OpenSim.Region.Framework.Scenes
1187 } 1206 }
1188 } 1207 }
1189 1208
1190 /// <summary>
1191 /// Clear all pending updates of parts to clients
1192 /// </summary>
1193 private void ClearUpdateSchedule()
1194 {
1195 m_updateFlag = 0;
1196 }
1197
1198 private void SendObjectPropertiesToClient(UUID AgentID) 1209 private void SendObjectPropertiesToClient(UUID AgentID)
1199 { 1210 {
1200 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar) 1211 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
@@ -1934,12 +1945,17 @@ namespace OpenSim.Region.Framework.Scenes
1934 public Vector3 GetWorldPosition() 1945 public Vector3 GetWorldPosition()
1935 { 1946 {
1936 Quaternion parentRot = ParentGroup.RootPart.RotationOffset; 1947 Quaternion parentRot = ParentGroup.RootPart.RotationOffset;
1937
1938 Vector3 axPos = OffsetPosition; 1948 Vector3 axPos = OffsetPosition;
1939
1940 axPos *= parentRot; 1949 axPos *= parentRot;
1941 Vector3 translationOffsetPosition = axPos; 1950 Vector3 translationOffsetPosition = axPos;
1942 return GroupPosition + translationOffsetPosition; 1951 if(_parentID == 0)
1952 {
1953 return GroupPosition;
1954 }
1955 else
1956 {
1957 return ParentGroup.AbsolutePosition + translationOffsetPosition; //KF: Fix child prim position
1958 }
1943 } 1959 }
1944 1960
1945 /// <summary> 1961 /// <summary>
@@ -1950,7 +1966,7 @@ namespace OpenSim.Region.Framework.Scenes
1950 { 1966 {
1951 Quaternion newRot; 1967 Quaternion newRot;
1952 1968
1953 if (this.LinkNum == 0) 1969 if (this.LinkNum < 2) //KF Single or root prim
1954 { 1970 {
1955 newRot = RotationOffset; 1971 newRot = RotationOffset;
1956 } 1972 }
@@ -2596,17 +2612,18 @@ namespace OpenSim.Region.Framework.Scenes
2596 //Trys to fetch sound id from prim's inventory. 2612 //Trys to fetch sound id from prim's inventory.
2597 //Prim's inventory doesn't support non script items yet 2613 //Prim's inventory doesn't support non script items yet
2598 2614
2599 lock (TaskInventory) 2615 TaskInventory.LockItemsForRead(true);
2616
2617 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2600 { 2618 {
2601 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 2619 if (item.Value.Name == sound)
2602 { 2620 {
2603 if (item.Value.Name == sound) 2621 soundID = item.Value.ItemID;
2604 { 2622 break;
2605 soundID = item.Value.ItemID;
2606 break;
2607 }
2608 } 2623 }
2609 } 2624 }
2625
2626 TaskInventory.LockItemsForRead(false);
2610 } 2627 }
2611 2628
2612 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence sp) 2629 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence sp)
@@ -2675,38 +2692,7 @@ namespace OpenSim.Region.Framework.Scenes
2675 2692
2676 public void RotLookAt(Quaternion target, float strength, float damping) 2693 public void RotLookAt(Quaternion target, float strength, float damping)
2677 { 2694 {
2678 rotLookAt(target, strength, damping); 2695 m_parentGroup.rotLookAt(target, strength, damping); // This calls method in SceneObjectGroup.
2679 }
2680
2681 public void rotLookAt(Quaternion target, float strength, float damping)
2682 {
2683 if (IsAttachment)
2684 {
2685 /*
2686 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
2687 if (avatar != null)
2688 {
2689 Rotate the Av?
2690 } */
2691 }
2692 else
2693 {
2694 APIDDamp = damping;
2695 APIDStrength = strength;
2696 APIDTarget = target;
2697 }
2698 }
2699
2700 public void startLookAt(Quaternion rot, float damp, float strength)
2701 {
2702 APIDDamp = damp;
2703 APIDStrength = strength;
2704 APIDTarget = rot;
2705 }
2706
2707 public void stopLookAt()
2708 {
2709 APIDTarget = Quaternion.Identity;
2710 } 2696 }
2711 2697
2712 /// <summary> 2698 /// <summary>
@@ -2939,8 +2925,8 @@ namespace OpenSim.Region.Framework.Scenes
2939 { 2925 {
2940 const float ROTATION_TOLERANCE = 0.01f; 2926 const float ROTATION_TOLERANCE = 0.01f;
2941 const float VELOCITY_TOLERANCE = 0.001f; 2927 const float VELOCITY_TOLERANCE = 0.001f;
2942 const float POSITION_TOLERANCE = 0.05f; 2928 const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary
2943 const int TIME_MS_TOLERANCE = 3000; 2929 const int TIME_MS_TOLERANCE = 200; //llSetPos has a 200ms delay. This should NOT be 3 seconds.
2944 2930
2945 if (m_updateFlag == 1) 2931 if (m_updateFlag == 1)
2946 { 2932 {
@@ -2954,7 +2940,7 @@ namespace OpenSim.Region.Framework.Scenes
2954 Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE) 2940 Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE)
2955 { 2941 {
2956 AddTerseUpdateToAllAvatars(); 2942 AddTerseUpdateToAllAvatars();
2957 ClearUpdateSchedule(); 2943
2958 2944
2959 // This causes the Scene to 'poll' physical objects every couple of frames 2945 // This causes the Scene to 'poll' physical objects every couple of frames
2960 // bad, so it's been replaced by an event driven method. 2946 // bad, so it's been replaced by an event driven method.
@@ -2972,16 +2958,18 @@ namespace OpenSim.Region.Framework.Scenes
2972 m_lastAngularVelocity = AngularVelocity; 2958 m_lastAngularVelocity = AngularVelocity;
2973 m_lastTerseSent = Environment.TickCount; 2959 m_lastTerseSent = Environment.TickCount;
2974 } 2960 }
2961 //Moved this outside of the if clause so updates don't get blocked.. *sigh*
2962 m_updateFlag = 0; //Why were we calling a function to do this? Inefficient! *screams*
2975 } 2963 }
2976 else 2964 else
2977 { 2965 {
2978 if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes 2966 if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes
2979 { 2967 {
2980 AddFullUpdateToAllAvatars(); 2968 AddFullUpdateToAllAvatars();
2981 ClearUpdateSchedule(); 2969 m_updateFlag = 0; //Same here
2982 } 2970 }
2983 } 2971 }
2984 ClearUpdateSchedule(); 2972 m_updateFlag = 0;
2985 } 2973 }
2986 2974
2987 /// <summary> 2975 /// <summary>
@@ -3008,17 +2996,16 @@ namespace OpenSim.Region.Framework.Scenes
3008 if (!UUID.TryParse(sound, out soundID)) 2996 if (!UUID.TryParse(sound, out soundID))
3009 { 2997 {
3010 // search sound file from inventory 2998 // search sound file from inventory
3011 lock (TaskInventory) 2999 TaskInventory.LockItemsForRead(true);
3000 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
3012 { 3001 {
3013 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 3002 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound)
3014 { 3003 {
3015 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound) 3004 soundID = item.Value.ItemID;
3016 { 3005 break;
3017 soundID = item.Value.ItemID;
3018 break;
3019 }
3020 } 3006 }
3021 } 3007 }
3008 TaskInventory.LockItemsForRead(false);
3022 } 3009 }
3023 3010
3024 if (soundID == UUID.Zero) 3011 if (soundID == UUID.Zero)
@@ -3453,7 +3440,7 @@ namespace OpenSim.Region.Framework.Scenes
3453 3440
3454 public void StopLookAt() 3441 public void StopLookAt()
3455 { 3442 {
3456 m_parentGroup.stopLookAt(); 3443 m_parentGroup.stopLookAt(); // This calls method in SceneObjectGroup.
3457 3444
3458 m_parentGroup.ScheduleGroupForTerseUpdate(); 3445 m_parentGroup.ScheduleGroupForTerseUpdate();
3459 } 3446 }
@@ -4696,5 +4683,17 @@ namespace OpenSim.Region.Framework.Scenes
4696 { 4683 {
4697 return new Color4((byte)Color.R, (byte)Color.G, (byte)Color.B, (byte)(0xFF - Color.A)); 4684 return new Color4((byte)Color.R, (byte)Color.G, (byte)Color.B, (byte)(0xFF - Color.A));
4698 } 4685 }
4686
4687 public void ResetOwnerChangeFlag()
4688 {
4689 List<UUID> inv = Inventory.GetInventoryList();
4690
4691 foreach (UUID itemID in inv)
4692 {
4693 TaskInventoryItem item = Inventory.GetInventoryItem(itemID);
4694 item.OwnerChanged = false;
4695 Inventory.UpdateInventoryItem(item);
4696 }
4697 }
4699 } 4698 }
4700} 4699}
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 30eafd7..d76f029 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
127 private Vector3 m_lastPosition; 130 private Vector3 m_avInitialPos; // used to calculate unscripted sit rotation
131 private Vector3 m_avUnscriptedSitPos; // for non-scripted prims
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;
@@ -134,7 +140,6 @@ namespace OpenSim.Region.Framework.Scenes
134 private Vector3? m_forceToApply; 140 private Vector3? m_forceToApply;
135 private uint m_requestedSitTargetID; 141 private uint m_requestedSitTargetID;
136 private UUID m_requestedSitTargetUUID; 142 private UUID m_requestedSitTargetUUID;
137 public bool SitGround = false;
138 143
139 private SendCourseLocationsMethod m_sendCourseLocationsMethod; 144 private SendCourseLocationsMethod m_sendCourseLocationsMethod;
140 145
@@ -157,7 +162,6 @@ namespace OpenSim.Region.Framework.Scenes
157 private int m_perfMonMS; 162 private int m_perfMonMS;
158 163
159 private bool m_setAlwaysRun; 164 private bool m_setAlwaysRun;
160
161 private bool m_forceFly; 165 private bool m_forceFly;
162 private bool m_flyDisabled; 166 private bool m_flyDisabled;
163 167
@@ -183,7 +187,8 @@ namespace OpenSim.Region.Framework.Scenes
183 protected RegionInfo m_regionInfo; 187 protected RegionInfo m_regionInfo;
184 protected ulong crossingFromRegion; 188 protected ulong crossingFromRegion;
185 189
186 private readonly Vector3[] Dir_Vectors = new Vector3[9]; 190 private readonly Vector3[] Dir_Vectors = new Vector3[11];
191 private bool m_isNudging = false;
187 192
188 // Position of agent's camera in world (region cordinates) 193 // Position of agent's camera in world (region cordinates)
189 protected Vector3 m_CameraCenter; 194 protected Vector3 m_CameraCenter;
@@ -208,6 +213,7 @@ namespace OpenSim.Region.Framework.Scenes
208 private bool m_autopilotMoving; 213 private bool m_autopilotMoving;
209 private Vector3 m_autoPilotTarget; 214 private Vector3 m_autoPilotTarget;
210 private bool m_sitAtAutoTarget; 215 private bool m_sitAtAutoTarget;
216 private Vector3 m_initialSitTarget; //KF: First estimate of where to sit
211 217
212 private string m_nextSitAnimation = String.Empty; 218 private string m_nextSitAnimation = String.Empty;
213 219
@@ -218,6 +224,9 @@ namespace OpenSim.Region.Framework.Scenes
218 private bool m_followCamAuto; 224 private bool m_followCamAuto;
219 225
220 private int m_movementUpdateCount; 226 private int m_movementUpdateCount;
227 private int m_lastColCount = -1; //KF: Look for Collision chnages
228 private int m_updateCount = 0; //KF: Update Anims for a while
229 private static readonly int UPDATE_COUNT = 10; // how many frames to update for
221 private const int NumMovementsBetweenRayCast = 5; 230 private const int NumMovementsBetweenRayCast = 5;
222 231
223 private bool CameraConstraintActive; 232 private bool CameraConstraintActive;
@@ -245,7 +254,9 @@ namespace OpenSim.Region.Framework.Scenes
245 DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS, 254 DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS,
246 DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG, 255 DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG,
247 DIR_CONTROL_FLAG_FORWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS, 256 DIR_CONTROL_FLAG_FORWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS,
248 DIR_CONTROL_FLAG_BACKWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG, 257 DIR_CONTROL_FLAG_BACK_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG,
258 DIR_CONTROL_FLAG_LEFT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS,
259 DIR_CONTROL_FLAG_RIGHT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG,
249 DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG 260 DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG
250 } 261 }
251 262
@@ -452,7 +463,8 @@ namespace OpenSim.Region.Framework.Scenes
452 get 463 get
453 { 464 {
454 PhysicsActor actor = m_physicsActor; 465 PhysicsActor actor = m_physicsActor;
455 if (actor != null) 466// if (actor != null)
467 if ((actor != null) && (m_parentID == 0)) // KF Do NOT update m_pos here if Av is sitting!
456 m_pos = actor.Position; 468 m_pos = actor.Position;
457 469
458 return m_parentPosition + m_pos; 470 return m_parentPosition + m_pos;
@@ -473,7 +485,8 @@ namespace OpenSim.Region.Framework.Scenes
473 } 485 }
474 } 486 }
475 487
476 m_pos = value; 488 if (m_parentID == 0) // KF Do NOT update m_pos here if Av is sitting!
489 m_pos = value;
477 m_parentPosition = Vector3.Zero; 490 m_parentPosition = Vector3.Zero;
478 } 491 }
479 } 492 }
@@ -665,7 +678,7 @@ namespace OpenSim.Region.Framework.Scenes
665 CreateSceneViewer(); 678 CreateSceneViewer();
666 m_animator = new ScenePresenceAnimator(this); 679 m_animator = new ScenePresenceAnimator(this);
667 } 680 }
668 681
669 private ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo) : this() 682 private ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo) : this()
670 { 683 {
671 m_rootRegionHandle = reginfo.RegionHandle; 684 m_rootRegionHandle = reginfo.RegionHandle;
@@ -697,10 +710,7 @@ namespace OpenSim.Region.Framework.Scenes
697 m_reprioritization_timer.AutoReset = false; 710 m_reprioritization_timer.AutoReset = false;
698 711
699 AdjustKnownSeeds(); 712 AdjustKnownSeeds();
700
701 // TODO: I think, this won't send anything, as we are still a child here...
702 Animator.TrySetMovementAnimation("STAND"); 713 Animator.TrySetMovementAnimation("STAND");
703
704 // we created a new ScenePresence (a new child agent) in a fresh region. 714 // we created a new ScenePresence (a new child agent) in a fresh region.
705 // Request info about all the (root) agents in this region 715 // Request info about all the (root) agents in this region
706 // Note: This won't send data *to* other clients in that region (children don't send) 716 // Note: This won't send data *to* other clients in that region (children don't send)
@@ -756,25 +766,47 @@ namespace OpenSim.Region.Framework.Scenes
756 Dir_Vectors[3] = -Vector3.UnitY; //RIGHT 766 Dir_Vectors[3] = -Vector3.UnitY; //RIGHT
757 Dir_Vectors[4] = Vector3.UnitZ; //UP 767 Dir_Vectors[4] = Vector3.UnitZ; //UP
758 Dir_Vectors[5] = -Vector3.UnitZ; //DOWN 768 Dir_Vectors[5] = -Vector3.UnitZ; //DOWN
759 Dir_Vectors[8] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge 769 Dir_Vectors[6] = new Vector3(0.5f, 0f, 0f); //FORWARD_NUDGE
760 Dir_Vectors[6] = Vector3.UnitX*2; //FORWARD 770 Dir_Vectors[7] = new Vector3(-0.5f, 0f, 0f); //BACK_NUDGE
761 Dir_Vectors[7] = -Vector3.UnitX; //BACK 771 Dir_Vectors[8] = new Vector3(0f, 0.5f, 0f); //LEFT_NUDGE
772 Dir_Vectors[9] = new Vector3(0f, -0.5f, 0f); //RIGHT_NUDGE
773 Dir_Vectors[10] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge
762 } 774 }
763 775
764 private Vector3[] GetWalkDirectionVectors() 776 private Vector3[] GetWalkDirectionVectors()
765 { 777 {
766 Vector3[] vector = new Vector3[9]; 778 Vector3[] vector = new Vector3[11];
767 vector[0] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD 779 vector[0] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD
768 vector[1] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK 780 vector[1] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK
769 vector[2] = Vector3.UnitY; //LEFT 781 vector[2] = Vector3.UnitY; //LEFT
770 vector[3] = -Vector3.UnitY; //RIGHT 782 vector[3] = -Vector3.UnitY; //RIGHT
771 vector[4] = new Vector3(m_CameraAtAxis.Z, 0f, m_CameraUpAxis.Z); //UP 783 vector[4] = new Vector3(m_CameraAtAxis.Z, 0f, m_CameraUpAxis.Z); //UP
772 vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN 784 vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN
773 vector[8] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_Nudge 785 vector[6] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD_NUDGE
774 vector[6] = (new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z) * 2); //FORWARD Nudge 786 vector[7] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK_NUDGE
775 vector[7] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK Nudge 787 vector[8] = Vector3.UnitY; //LEFT_NUDGE
788 vector[9] = -Vector3.UnitY; //RIGHT_NUDGE
789 vector[10] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_NUDGE
776 return vector; 790 return vector;
777 } 791 }
792
793 private bool[] GetDirectionIsNudge()
794 {
795 bool[] isNudge = new bool[11];
796 isNudge[0] = false; //FORWARD
797 isNudge[1] = false; //BACK
798 isNudge[2] = false; //LEFT
799 isNudge[3] = false; //RIGHT
800 isNudge[4] = false; //UP
801 isNudge[5] = false; //DOWN
802 isNudge[6] = true; //FORWARD_NUDGE
803 isNudge[7] = true; //BACK_NUDGE
804 isNudge[8] = true; //LEFT_NUDGE
805 isNudge[9] = true; //RIGHT_NUDGE
806 isNudge[10] = true; //DOWN_Nudge
807 return isNudge;
808 }
809
778 810
779 #endregion 811 #endregion
780 812
@@ -843,6 +875,22 @@ namespace OpenSim.Region.Framework.Scenes
843 { 875 {
844 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N); 876 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N);
845 pos.Y = crossedBorder.BorderLine.Z - 1; 877 pos.Y = crossedBorder.BorderLine.Z - 1;
878 }
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 && m_userLevel < 200 && !m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid) && land.LandData.OwnerID != m_uuid)
890 {
891 pos = land.LandData.UserLocation;
892 }
893 }
846 } 894 }
847 895
848 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f) 896 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f)
@@ -977,9 +1025,10 @@ namespace OpenSim.Region.Framework.Scenes
977 public void Teleport(Vector3 pos) 1025 public void Teleport(Vector3 pos)
978 { 1026 {
979 bool isFlying = false; 1027 bool isFlying = false;
980 if (m_physicsActor != null)
981 isFlying = m_physicsActor.Flying;
982 1028
1029 if (m_physicsActor != null)
1030 isFlying = m_physicsActor.Flying;
1031
983 RemoveFromPhysicalScene(); 1032 RemoveFromPhysicalScene();
984 Velocity = Vector3.Zero; 1033 Velocity = Vector3.Zero;
985 AbsolutePosition = pos; 1034 AbsolutePosition = pos;
@@ -990,7 +1039,8 @@ namespace OpenSim.Region.Framework.Scenes
990 SetHeight(m_appearance.AvatarHeight); 1039 SetHeight(m_appearance.AvatarHeight);
991 } 1040 }
992 1041
993 SendTerseUpdateToAllClients(); 1042 SendTerseUpdateToAllClients();
1043
994 } 1044 }
995 1045
996 public void TeleportWithMomentum(Vector3 pos) 1046 public void TeleportWithMomentum(Vector3 pos)
@@ -1035,7 +1085,9 @@ namespace OpenSim.Region.Framework.Scenes
1035 { 1085 {
1036 AbsolutePosition = AbsolutePosition + new Vector3(0f, 0f, (1.56f / 6f)); 1086 AbsolutePosition = AbsolutePosition + new Vector3(0f, 0f, (1.56f / 6f));
1037 } 1087 }
1038 1088
1089 m_updateCount = UPDATE_COUNT; //KF: Trigger Anim updates to catch falling anim.
1090
1039 ControllingClient.SendAvatarTerseUpdate(new SendAvatarTerseData(m_rootRegionHandle, (ushort)(m_scene.TimeDilation * ushort.MaxValue), LocalId, 1091 ControllingClient.SendAvatarTerseUpdate(new SendAvatarTerseData(m_rootRegionHandle, (ushort)(m_scene.TimeDilation * ushort.MaxValue), LocalId,
1040 AbsolutePosition, Velocity, Vector3.Zero, m_bodyRot, new Vector4(0,0,1,AbsolutePosition.Z - 0.5f), m_uuid, null, GetUpdatePriority(ControllingClient))); 1092 AbsolutePosition, Velocity, Vector3.Zero, m_bodyRot, new Vector4(0,0,1,AbsolutePosition.Z - 0.5f), m_uuid, null, GetUpdatePriority(ControllingClient)));
1041 } 1093 }
@@ -1220,6 +1272,7 @@ namespace OpenSim.Region.Framework.Scenes
1220 m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999902"); 1272 m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999902");
1221 1273
1222 m_pos = m_LastFinitePos; 1274 m_pos = m_LastFinitePos;
1275
1223 if (!m_pos.IsFinite()) 1276 if (!m_pos.IsFinite())
1224 { 1277 {
1225 m_pos.X = 127f; 1278 m_pos.X = 127f;
@@ -1286,7 +1339,6 @@ namespace OpenSim.Region.Framework.Scenes
1286 m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(m_CameraCenter - posAdjusted), Vector3.Distance(m_CameraCenter, posAdjusted) + 0.3f, RayCastCameraCallback); 1339 m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(m_CameraCenter - posAdjusted), Vector3.Distance(m_CameraCenter, posAdjusted) + 0.3f, RayCastCameraCallback);
1287 } 1340 }
1288 } 1341 }
1289
1290 lock (scriptedcontrols) 1342 lock (scriptedcontrols)
1291 { 1343 {
1292 if (scriptedcontrols.Count > 0) 1344 if (scriptedcontrols.Count > 0)
@@ -1301,12 +1353,8 @@ namespace OpenSim.Region.Framework.Scenes
1301 1353
1302 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0) 1354 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0)
1303 { 1355 {
1304 // TODO: This doesn't prevent the user from walking yet. 1356 m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick.
1305 // Setting parent ID would fix this, if we knew what value 1357 Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED");
1306 // to use. Or we could add a m_isSitting variable.
1307 //Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED");
1308 SitGround = true;
1309
1310 } 1358 }
1311 1359
1312 // In the future, these values might need to go global. 1360 // In the future, these values might need to go global.
@@ -1356,6 +1404,11 @@ namespace OpenSim.Region.Framework.Scenes
1356 update_rotation = true; 1404 update_rotation = true;
1357 } 1405 }
1358 1406
1407 //guilty until proven innocent..
1408 bool Nudging = true;
1409 //Basically, if there is at least one non-nudge control then we don't need
1410 //to worry about stopping the avatar
1411
1359 if (m_parentID == 0) 1412 if (m_parentID == 0)
1360 { 1413 {
1361 bool bAllowUpdateMoveToPosition = false; 1414 bool bAllowUpdateMoveToPosition = false;
@@ -1370,9 +1423,12 @@ namespace OpenSim.Region.Framework.Scenes
1370 else 1423 else
1371 dirVectors = Dir_Vectors; 1424 dirVectors = Dir_Vectors;
1372 1425
1373 // The fact that m_movementflag is a byte needs to be fixed 1426 bool[] isNudge = GetDirectionIsNudge();
1374 // it really should be a uint 1427
1375 uint nudgehack = 250; 1428
1429
1430
1431
1376 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS) 1432 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS)
1377 { 1433 {
1378 if (((uint)flags & (uint)DCF) != 0) 1434 if (((uint)flags & (uint)DCF) != 0)
@@ -1382,40 +1438,28 @@ namespace OpenSim.Region.Framework.Scenes
1382 try 1438 try
1383 { 1439 {
1384 agent_control_v3 += dirVectors[i]; 1440 agent_control_v3 += dirVectors[i];
1385 //m_log.DebugFormat("[Motion]: {0}, {1}",i, dirVectors[i]); 1441 if (isNudge[i] == false)
1442 {
1443 Nudging = false;
1444 }
1386 } 1445 }
1387 catch (IndexOutOfRangeException) 1446 catch (IndexOutOfRangeException)
1388 { 1447 {
1389 // Why did I get this? 1448 // Why did I get this?
1390 } 1449 }
1391 1450
1392 if ((m_movementflag & (byte)(uint)DCF) == 0) 1451 if ((m_movementflag & (uint)DCF) == 0)
1393 { 1452 {
1394 if (DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
1395 {
1396 m_movementflag |= (byte)nudgehack;
1397 }
1398 m_movementflag += (byte)(uint)DCF; 1453 m_movementflag += (byte)(uint)DCF;
1399 update_movementflag = true; 1454 update_movementflag = true;
1400 } 1455 }
1401 } 1456 }
1402 else 1457 else
1403 { 1458 {
1404 if ((m_movementflag & (byte)(uint)DCF) != 0 || 1459 if ((m_movementflag & (uint)DCF) != 0)
1405 ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
1406 && ((m_movementflag & (byte)nudgehack) == nudgehack))
1407 ) // This or is for Nudge forward
1408 { 1460 {
1409 m_movementflag -= ((byte)(uint)DCF); 1461 m_movementflag -= (byte)(uint)DCF;
1410
1411 update_movementflag = true; 1462 update_movementflag = true;
1412 /*
1413 if ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
1414 && ((m_movementflag & (byte)nudgehack) == nudgehack))
1415 {
1416 m_log.Debug("Removed Hack flag");
1417 }
1418 */
1419 } 1463 }
1420 else 1464 else
1421 { 1465 {
@@ -1424,7 +1468,6 @@ namespace OpenSim.Region.Framework.Scenes
1424 } 1468 }
1425 i++; 1469 i++;
1426 } 1470 }
1427
1428 //Paupaw:Do Proper PID for Autopilot here 1471 //Paupaw:Do Proper PID for Autopilot here
1429 if (bResetMoveToPosition) 1472 if (bResetMoveToPosition)
1430 { 1473 {
@@ -1459,6 +1502,9 @@ namespace OpenSim.Region.Framework.Scenes
1459 // Ignore z component of vector 1502 // Ignore z component of vector
1460 Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f); 1503 Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f);
1461 LocalVectorToTarget2D.Normalize(); 1504 LocalVectorToTarget2D.Normalize();
1505
1506 //We're not nudging
1507 Nudging = false;
1462 agent_control_v3 += LocalVectorToTarget2D; 1508 agent_control_v3 += LocalVectorToTarget2D;
1463 1509
1464 // update avatar movement flags. the avatar coordinate system is as follows: 1510 // update avatar movement flags. the avatar coordinate system is as follows:
@@ -1547,13 +1593,13 @@ namespace OpenSim.Region.Framework.Scenes
1547 // m_log.DebugFormat( 1593 // m_log.DebugFormat(
1548 // "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3); 1594 // "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3);
1549 1595
1550 AddNewMovement(agent_control_v3, q); 1596 AddNewMovement(agent_control_v3, q, Nudging);
1551 1597
1552 1598
1553 } 1599 }
1554 } 1600 }
1555 1601
1556 if (update_movementflag && ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) == 0) && (m_parentID == 0) && !SitGround) 1602 if (update_movementflag)
1557 Animator.UpdateMovementAnimations(); 1603 Animator.UpdateMovementAnimations();
1558 1604
1559 m_scene.EventManager.TriggerOnClientMovement(this); 1605 m_scene.EventManager.TriggerOnClientMovement(this);
@@ -1568,7 +1614,6 @@ namespace OpenSim.Region.Framework.Scenes
1568 m_sitAtAutoTarget = false; 1614 m_sitAtAutoTarget = false;
1569 PrimitiveBaseShape proxy = PrimitiveBaseShape.Default; 1615 PrimitiveBaseShape proxy = PrimitiveBaseShape.Default;
1570 //proxy.PCode = (byte)PCode.ParticleSystem; 1616 //proxy.PCode = (byte)PCode.ParticleSystem;
1571
1572 proxyObjectGroup = new SceneObjectGroup(UUID, Pos, Rotation, proxy); 1617 proxyObjectGroup = new SceneObjectGroup(UUID, Pos, Rotation, proxy);
1573 proxyObjectGroup.AttachToScene(m_scene); 1618 proxyObjectGroup.AttachToScene(m_scene);
1574 1619
@@ -1610,7 +1655,7 @@ namespace OpenSim.Region.Framework.Scenes
1610 } 1655 }
1611 m_moveToPositionInProgress = true; 1656 m_moveToPositionInProgress = true;
1612 m_moveToPositionTarget = new Vector3(locx, locy, locz); 1657 m_moveToPositionTarget = new Vector3(locx, locy, locz);
1613 } 1658 }
1614 catch (Exception ex) 1659 catch (Exception ex)
1615 { 1660 {
1616 //Why did I get this error? 1661 //Why did I get this error?
@@ -1632,7 +1677,7 @@ namespace OpenSim.Region.Framework.Scenes
1632 Velocity = Vector3.Zero; 1677 Velocity = Vector3.Zero;
1633 SendFullUpdateToAllClients(); 1678 SendFullUpdateToAllClients();
1634 1679
1635 //HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); 1680 HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); //KF ??
1636 } 1681 }
1637 //ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false); 1682 //ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false);
1638 m_requestedSitTargetUUID = UUID.Zero; 1683 m_requestedSitTargetUUID = UUID.Zero;
@@ -1665,55 +1710,84 @@ namespace OpenSim.Region.Framework.Scenes
1665 /// </summary> 1710 /// </summary>
1666 public void StandUp() 1711 public void StandUp()
1667 { 1712 {
1668 if (SitGround)
1669 SitGround = false;
1670
1671 if (m_parentID != 0) 1713 if (m_parentID != 0)
1672 { 1714 {
1673 m_log.Debug("StandupCode Executed");
1674 SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID); 1715 SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID);
1675 if (part != null) 1716 if (part != null)
1676 { 1717 {
1718 part.TaskInventory.LockItemsForRead(true);
1677 TaskInventoryDictionary taskIDict = part.TaskInventory; 1719 TaskInventoryDictionary taskIDict = part.TaskInventory;
1678 if (taskIDict != null) 1720 if (taskIDict != null)
1679 { 1721 {
1680 lock (taskIDict) 1722 foreach (UUID taskID in taskIDict.Keys)
1681 { 1723 {
1682 foreach (UUID taskID in taskIDict.Keys) 1724 UnRegisterControlEventsToScript(LocalId, taskID);
1683 { 1725 taskIDict[taskID].PermsMask &= ~(
1684 UnRegisterControlEventsToScript(LocalId, taskID); 1726 2048 | //PERMISSION_CONTROL_CAMERA
1685 taskIDict[taskID].PermsMask &= ~( 1727 4); // PERMISSION_TAKE_CONTROLS
1686 2048 | //PERMISSION_CONTROL_CAMERA
1687 4); // PERMISSION_TAKE_CONTROLS
1688 }
1689 } 1728 }
1690
1691 } 1729 }
1730 part.TaskInventory.LockItemsForRead(false);
1692 // Reset sit target. 1731 // Reset sit target.
1693 if (part.GetAvatarOnSitTarget() == UUID) 1732 if (part.GetAvatarOnSitTarget() == UUID)
1694 part.SetAvatarOnSitTarget(UUID.Zero); 1733 part.SetAvatarOnSitTarget(UUID.Zero);
1695
1696 m_parentPosition = part.GetWorldPosition(); 1734 m_parentPosition = part.GetWorldPosition();
1697 ControllingClient.SendClearFollowCamProperties(part.ParentUUID); 1735 ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
1698 } 1736 }
1699 1737 // part.GetWorldRotation() is the rotation of the object being sat on
1700 if (m_physicsActor == null) 1738 // Rotation is the sittiing Av's rotation
1701 { 1739
1702 AddToPhysicalScene(false); 1740 Quaternion partRot;
1741// if (part.LinkNum == 1)
1742// { // Root prim of linkset
1743// partRot = part.ParentGroup.RootPart.RotationOffset;
1744// }
1745// else
1746// { // single or child prim
1747
1748// }
1749 if (part == null) //CW: Part may be gone. llDie() for example.
1750 {
1751 partRot = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
1752 }
1753 else
1754 {
1755 partRot = part.GetWorldRotation();
1703 } 1756 }
1704 1757
1705 m_pos += m_parentPosition + new Vector3(0.0f, 0.0f, 2.0f*m_sitAvatarHeight); 1758 Quaternion partIRot = Quaternion.Inverse(partRot);
1706 m_parentPosition = Vector3.Zero; 1759
1760 Quaternion avatarRot = Quaternion.Inverse(Quaternion.Inverse(Rotation) * partIRot); // world or. of the av
1761 Vector3 avStandUp = new Vector3(1.0f, 0f, 0f) * avatarRot; // 1M infront of av
1707 1762
1708 m_parentID = 0; 1763
1764 if (m_physicsActor == null)
1765 {
1766 AddToPhysicalScene(false);
1767 }
1768 //CW: If the part isn't null then we can set the current position
1769 if (part != null)
1770 {
1771 Vector3 avWorldStandUp = avStandUp + part.GetWorldPosition() + (m_pos * partRot); // + av sit offset!
1772 AbsolutePosition = avWorldStandUp; //KF: Fix stand up.
1773 part.IsOccupied = false;
1774 }
1775 else
1776 {
1777 //CW: Since the part doesn't exist, a coarse standup position isn't an issue
1778 AbsolutePosition = m_lastWorldPosition;
1779 }
1780
1781 m_parentPosition = Vector3.Zero;
1782 m_parentID = 0;
1709 SendFullUpdateToAllClients(); 1783 SendFullUpdateToAllClients();
1710 m_requestedSitTargetID = 0; 1784 m_requestedSitTargetID = 0;
1785
1711 if ((m_physicsActor != null) && (m_avHeight > 0)) 1786 if ((m_physicsActor != null) && (m_avHeight > 0))
1712 { 1787 {
1713 SetHeight(m_avHeight); 1788 SetHeight(m_avHeight);
1714 } 1789 }
1715 } 1790 }
1716
1717 Animator.TrySetMovementAnimation("STAND"); 1791 Animator.TrySetMovementAnimation("STAND");
1718 } 1792 }
1719 1793
@@ -1744,13 +1818,9 @@ namespace OpenSim.Region.Framework.Scenes
1744 Vector3 avSitOffSet = part.SitTargetPosition; 1818 Vector3 avSitOffSet = part.SitTargetPosition;
1745 Quaternion avSitOrientation = part.SitTargetOrientation; 1819 Quaternion avSitOrientation = part.SitTargetOrientation;
1746 UUID avOnTargetAlready = part.GetAvatarOnSitTarget(); 1820 UUID avOnTargetAlready = part.GetAvatarOnSitTarget();
1747 1821 bool SitTargetOccupied = (avOnTargetAlready != UUID.Zero);
1748 bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero)); 1822 bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored.
1749 bool SitTargetisSet = 1823 if (SitTargetisSet && !SitTargetOccupied)
1750 (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f && avSitOrientation.W == 1f &&
1751 avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f));
1752
1753 if (SitTargetisSet && SitTargetUnOccupied)
1754 { 1824 {
1755 //switch the target to this prim 1825 //switch the target to this prim
1756 return part; 1826 return part;
@@ -1764,84 +1834,153 @@ namespace OpenSim.Region.Framework.Scenes
1764 private void SendSitResponse(IClientAPI remoteClient, UUID targetID, Vector3 offset, Quaternion pSitOrientation) 1834 private void SendSitResponse(IClientAPI remoteClient, UUID targetID, Vector3 offset, Quaternion pSitOrientation)
1765 { 1835 {
1766 bool autopilot = true; 1836 bool autopilot = true;
1837 Vector3 autopilotTarget = new Vector3();
1838 Quaternion sitOrientation = Quaternion.Identity;
1767 Vector3 pos = new Vector3(); 1839 Vector3 pos = new Vector3();
1768 Quaternion sitOrientation = pSitOrientation;
1769 Vector3 cameraEyeOffset = Vector3.Zero; 1840 Vector3 cameraEyeOffset = Vector3.Zero;
1770 Vector3 cameraAtOffset = Vector3.Zero; 1841 Vector3 cameraAtOffset = Vector3.Zero;
1771 bool forceMouselook = false; 1842 bool forceMouselook = false;
1772 1843
1773 //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID); 1844 //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID);
1774 SceneObjectPart part = FindNextAvailableSitTarget(targetID); 1845 SceneObjectPart part = FindNextAvailableSitTarget(targetID);
1775 if (part != null) 1846 if (part == null) return;
1776 { 1847
1777 // TODO: determine position to sit at based on scene geometry; don't trust offset from client 1848 // TODO: determine position to sit at based on scene geometry; don't trust offset from client
1778 // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it 1849 // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it
1779 1850
1780 // Is a sit target available? 1851 // part is the prim to sit on
1781 Vector3 avSitOffSet = part.SitTargetPosition; 1852 // offset is the world-ref vector distance from that prim center to the click-spot
1782 Quaternion avSitOrientation = part.SitTargetOrientation; 1853 // UUID is the UUID of the Avatar doing the clicking
1783 UUID avOnTargetAlready = part.GetAvatarOnSitTarget(); 1854
1784 1855 m_avInitialPos = AbsolutePosition; // saved to calculate unscripted sit rotation
1785 bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero)); 1856
1786 bool SitTargetisSet = 1857 // Is a sit target available?
1787 (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f && 1858 Vector3 avSitOffSet = part.SitTargetPosition;
1788 ( 1859 Quaternion avSitOrientation = part.SitTargetOrientation;
1789 avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f && avSitOrientation.W == 1f // Valid Zero Rotation quaternion 1860
1790 || avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 1f && avSitOrientation.W == 0f // W-Z Mapping was invalid at one point 1861 bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored.
1791 || avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f && avSitOrientation.W == 0f // Invalid Quaternion 1862 // Quaternion partIRot = Quaternion.Inverse(part.GetWorldRotation());
1792 ) 1863 Quaternion partRot;
1793 )); 1864// if (part.LinkNum == 1)
1794 1865// { // Root prim of linkset
1795 if (SitTargetisSet && SitTargetUnOccupied) 1866// partRot = part.ParentGroup.RootPart.RotationOffset;
1796 { 1867// }
1797 part.SetAvatarOnSitTarget(UUID); 1868// else
1798 offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); 1869// { // single or child prim
1799 sitOrientation = avSitOrientation; 1870 partRot = part.GetWorldRotation();
1800 autopilot = false; 1871// }
1801 } 1872 Quaternion partIRot = Quaternion.Inverse(partRot);
1802 1873//Console.WriteLine("SendSitResponse offset=" + offset + " Occup=" + part.IsOccupied + " TargSet=" + SitTargetisSet);
1803 pos = part.AbsolutePosition + offset; 1874 // Sit analysis rewritten by KF 091125
1804 //if (Math.Abs(part.AbsolutePosition.Z - AbsolutePosition.Z) > 1) 1875 if (SitTargetisSet) // scipted sit
1805 //{ 1876 {
1806 // offset = pos; 1877 if (!part.IsOccupied)
1807 //autopilot = false; 1878 {
1808 //} 1879//Console.WriteLine("Scripted, unoccupied");
1809 if (m_physicsActor != null) 1880 part.SetAvatarOnSitTarget(UUID); // set that Av will be on it
1810 { 1881 offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); // change ofset to the scripted one
1811 // If we're not using the client autopilot, we're immediately warping the avatar to the location 1882 sitOrientation = avSitOrientation; // Change rotatione to the scripted one
1812 // We can remove the physicsActor until they stand up. 1883 autopilot = false; // Jump direct to scripted llSitPos()
1813 m_sitAvatarHeight = m_physicsActor.Size.Z; 1884 }
1814 1885 else
1815 if (autopilot) 1886 {
1816 { 1887//Console.WriteLine("Scripted, occupied");
1817 if (Util.GetDistanceTo(AbsolutePosition, pos) < 4.5) 1888 return;
1818 { 1889 }
1819 autopilot = false; 1890 }
1891 else // Not Scripted
1892 {
1893 if ( (Math.Abs(offset.X) > 0.5f) || (Math.Abs(offset.Y) > 0.5f) )
1894 {
1895 // large prim & offset, ignore if other Avs sitting
1896// offset.Z -= 0.05f;
1897 m_avUnscriptedSitPos = offset * partIRot; // (non-zero) sit where clicked
1898 autopilotTarget = part.AbsolutePosition + offset; // World location of clicked point
1899
1900//Console.WriteLine(" offset ={0}", offset);
1901//Console.WriteLine(" UnscriptedSitPos={0}", m_avUnscriptedSitPos);
1902//Console.WriteLine(" autopilotTarget={0}", autopilotTarget);
1903
1904 }
1905 else // small offset
1906 {
1907//Console.WriteLine("Small offset");
1908 if (!part.IsOccupied)
1909 {
1910 m_avUnscriptedSitPos = Vector3.Zero; // Zero = Sit on prim center
1911 autopilotTarget = part.AbsolutePosition;
1912//Console.WriteLine("UsSmall autopilotTarget={0}", autopilotTarget);
1913 }
1914 else return; // occupied small
1915 } // end large/small
1916 } // end Scripted/not
1917 cameraAtOffset = part.GetCameraAtOffset();
1918 cameraEyeOffset = part.GetCameraEyeOffset();
1919 forceMouselook = part.GetForceMouselook();
1920 if(cameraAtOffset == Vector3.Zero) cameraAtOffset = new Vector3(0f, 0f, 0.1f); //
1921 if(cameraEyeOffset == Vector3.Zero) cameraEyeOffset = new Vector3(0f, 0f, 0.1f); //
1820 1922
1821 RemoveFromPhysicalScene(); 1923 if (m_physicsActor != null)
1822 AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight); 1924 {
1823 } 1925 // If we're not using the client autopilot, we're immediately warping the avatar to the location
1824 } 1926 // We can remove the physicsActor until they stand up.
1825 else 1927 m_sitAvatarHeight = m_physicsActor.Size.Z;
1928 if (autopilot)
1929 { // its not a scripted sit
1930// if (Util.GetDistanceTo(AbsolutePosition, autopilotTarget) < 4.5)
1931 if( (Math.Abs(AbsolutePosition.X - autopilotTarget.X) < 2.0f) && (Math.Abs(AbsolutePosition.Y - autopilotTarget.Y) < 2.0f) )
1826 { 1932 {
1933 autopilot = false; // close enough
1934 m_lastWorldPosition = m_pos; /* CW - This give us a position to return the avatar to if the part is killed before standup.
1935 Not using the part's position because returning the AV to the last known standing
1936 position is likely to be more friendly, isn't it? */
1827 RemoveFromPhysicalScene(); 1937 RemoveFromPhysicalScene();
1828 } 1938 AbsolutePosition = autopilotTarget + new Vector3(0.0f, 0.0f, (m_sitAvatarHeight / 2.0f)); // Warp av to over sit target
1939 } // else the autopilot will get us close
1940 }
1941 else
1942 { // its a scripted sit
1943 m_lastWorldPosition = part.AbsolutePosition; /* CW - This give us a position to return the avatar to if the part is killed before standup.
1944 I *am* using the part's position this time because we have no real idea how far away
1945 the avatar is from the sit target. */
1946 RemoveFromPhysicalScene();
1829 } 1947 }
1830
1831 cameraAtOffset = part.GetCameraAtOffset();
1832 cameraEyeOffset = part.GetCameraEyeOffset();
1833 forceMouselook = part.GetForceMouselook();
1834 } 1948 }
1835 1949 else return; // physactor is null!
1836 ControllingClient.SendSitResponse(targetID, offset, sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook); 1950
1837 m_requestedSitTargetUUID = targetID; 1951 Vector3 offsetr; // = offset * partIRot;
1952 // KF: In a linkset, offsetr needs to be relative to the group root! 091208
1953 // offsetr = (part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) + (offset * partIRot);
1954 // if (part.LinkNum < 2) 091216 All this was necessary because of the GetWorldRotation error.
1955 // { // Single, or Root prim of linkset, target is ClickOffset * RootRot
1956 offsetr = offset * partIRot;
1957//
1958 // else
1959 // { // Child prim, offset is (ChildOffset * RootRot) + (ClickOffset * ChildRot)
1960 // offsetr = //(part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) +
1961 // (offset * partRot);
1962 // }
1963
1964//Console.WriteLine(" ");
1965//Console.WriteLine("link number ={0}", part.LinkNum);
1966//Console.WriteLine("Prim offset ={0}", part.OffsetPosition );
1967//Console.WriteLine("Root Rotate ={0}", part.ParentGroup.RootPart.RotationOffset);
1968//Console.WriteLine("Click offst ={0}", offset);
1969//Console.WriteLine("Prim Rotate ={0}", part.GetWorldRotation());
1970//Console.WriteLine("offsetr ={0}", offsetr);
1971//Console.WriteLine("Camera At ={0}", cameraAtOffset);
1972//Console.WriteLine("Camera Eye ={0}", cameraEyeOffset);
1973
1974 ControllingClient.SendSitResponse(part.UUID, offsetr, sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook);
1975 m_requestedSitTargetUUID = part.UUID; //KF: Correct autopilot target
1838 // This calls HandleAgentSit twice, once from here, and the client calls 1976 // This calls HandleAgentSit twice, once from here, and the client calls
1839 // HandleAgentSit itself after it gets to the location 1977 // HandleAgentSit itself after it gets to the location
1840 // It doesn't get to the location until we've moved them there though 1978 // It doesn't get to the location until we've moved them there though
1841 // which happens in HandleAgentSit :P 1979 // which happens in HandleAgentSit :P
1842 m_autopilotMoving = autopilot; 1980 m_autopilotMoving = autopilot;
1843 m_autoPilotTarget = pos; 1981 m_autoPilotTarget = autopilotTarget;
1844 m_sitAtAutoTarget = autopilot; 1982 m_sitAtAutoTarget = autopilot;
1983 m_initialSitTarget = autopilotTarget;
1845 if (!autopilot) 1984 if (!autopilot)
1846 HandleAgentSit(remoteClient, UUID); 1985 HandleAgentSit(remoteClient, UUID);
1847 } 1986 }
@@ -2136,31 +2275,66 @@ namespace OpenSim.Region.Framework.Scenes
2136 { 2275 {
2137 if (part != null) 2276 if (part != null)
2138 { 2277 {
2278//Console.WriteLine("Link #{0}, Rot {1}", part.LinkNum, part.GetWorldRotation());
2139 if (part.GetAvatarOnSitTarget() == UUID) 2279 if (part.GetAvatarOnSitTarget() == UUID)
2140 { 2280 {
2281//Console.WriteLine("Scripted Sit");
2282 // Scripted sit
2141 Vector3 sitTargetPos = part.SitTargetPosition; 2283 Vector3 sitTargetPos = part.SitTargetPosition;
2142 Quaternion sitTargetOrient = part.SitTargetOrientation; 2284 Quaternion sitTargetOrient = part.SitTargetOrientation;
2143
2144 //Quaternion vq = new Quaternion(sitTargetPos.X, sitTargetPos.Y+0.2f, sitTargetPos.Z+0.2f, 0);
2145 //Quaternion nq = new Quaternion(-sitTargetOrient.X, -sitTargetOrient.Y, -sitTargetOrient.Z, sitTargetOrient.w);
2146
2147 //Quaternion result = (sitTargetOrient * vq) * nq;
2148
2149 m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z); 2285 m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z);
2150 m_pos += SIT_TARGET_ADJUSTMENT; 2286 m_pos += SIT_TARGET_ADJUSTMENT;
2151 m_bodyRot = sitTargetOrient; 2287 m_bodyRot = sitTargetOrient;
2152 //Rotation = sitTargetOrient;
2153 m_parentPosition = part.AbsolutePosition; 2288 m_parentPosition = part.AbsolutePosition;
2154 2289 part.IsOccupied = true;
2155 //SendTerseUpdateToAllClients(); 2290Console.WriteLine("Scripted Sit ofset {0}", m_pos);
2156 } 2291 }
2157 else 2292 else
2158 { 2293 {
2159 m_pos -= part.AbsolutePosition; 2294 // if m_avUnscriptedSitPos is zero then Av sits above center
2295 // Else Av sits at m_avUnscriptedSitPos
2296
2297 // Non-scripted sit by Kitto Flora 21Nov09
2298 // Calculate angle of line from prim to Av
2299 Quaternion partIRot;
2300// if (part.LinkNum == 1)
2301// { // Root prim of linkset
2302// partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset);
2303// }
2304// else
2305// { // single or child prim
2306 partIRot = Quaternion.Inverse(part.GetWorldRotation());
2307// }
2308 Vector3 sitTargetPos= part.AbsolutePosition + m_avUnscriptedSitPos;
2309 float y_diff = (m_avInitialPos.Y - sitTargetPos.Y);
2310 float x_diff = ( m_avInitialPos.X - sitTargetPos.X);
2311 if(Math.Abs(x_diff) < 0.001f) x_diff = 0.001f; // avoid div by 0
2312 if(Math.Abs(y_diff) < 0.001f) y_diff = 0.001f; // avoid pol flip at 0
2313 float sit_angle = (float)Math.Atan2( (double)y_diff, (double)x_diff);
2314 // NOTE: when sitting m_ pos and m_bodyRot are *relative* to the prim location/rotation, not 'World'.
2315 // Av sits at world euler <0,0, z>, translated by part rotation
2316 m_bodyRot = partIRot * Quaternion.CreateFromEulers(0f, 0f, sit_angle); // sit at 0,0,inv-click
2317
2160 m_parentPosition = part.AbsolutePosition; 2318 m_parentPosition = part.AbsolutePosition;
2161 } 2319 part.IsOccupied = true;
2320 m_pos = new Vector3(0f, 0f, 0.05f) + // corrections to get Sit Animation
2321 (new Vector3(0.0f, 0f, 0.61f) * partIRot) + // located on center
2322 (new Vector3(0.34f, 0f, 0.0f) * m_bodyRot) +
2323 m_avUnscriptedSitPos; // adds click offset, if any
2324 //Set up raytrace to find top surface of prim
2325 Vector3 size = part.Scale;
2326 float mag = 2.0f; // 0.1f + (float)Math.Sqrt((size.X * size.X) + (size.Y * size.Y) + (size.Z * size.Z));
2327 Vector3 start = part.AbsolutePosition + new Vector3(0f, 0f, mag);
2328 Vector3 down = new Vector3(0f, 0f, -1f);
2329//Console.WriteLine("st={0} do={1} ma={2}", start, down, mag);
2330 m_scene.PhysicsScene.RaycastWorld(
2331 start, // Vector3 position,
2332 down, // Vector3 direction,
2333 mag, // float length,
2334 SitAltitudeCallback); // retMethod
2335 } // end scripted/not
2162 } 2336 }
2163 else 2337 else // no Av
2164 { 2338 {
2165 return; 2339 return;
2166 } 2340 }
@@ -2172,11 +2346,36 @@ namespace OpenSim.Region.Framework.Scenes
2172 2346
2173 Animator.TrySetMovementAnimation(sitAnimation); 2347 Animator.TrySetMovementAnimation(sitAnimation);
2174 SendFullUpdateToAllClients(); 2348 SendFullUpdateToAllClients();
2175 // This may seem stupid, but Our Full updates don't send avatar rotation :P
2176 // So we're also sending a terse update (which has avatar rotation)
2177 // [Update] We do now.
2178 //SendTerseUpdateToAllClients();
2179 } 2349 }
2350
2351 public void SitAltitudeCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 normal)
2352 {
2353 // KF: 091202 There appears to be a bug in Prim Edit Size - the process sometimes make a prim that RayTrace no longer
2354 // sees. Take/re-rez, or sim restart corrects the condition. Result of bug is incorrect sit height.
2355 if(hitYN)
2356 {
2357 // m_pos = Av offset from prim center to make look like on center
2358 // m_parentPosition = Actual center pos of prim
2359 // collisionPoint = spot on prim where we want to sit
2360 // collisionPoint.Z = global sit surface height
2361 SceneObjectPart part = m_scene.GetSceneObjectPart(localid);
2362 Quaternion partIRot;
2363// if (part.LinkNum == 1)
2364/// { // Root prim of linkset
2365// partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset);
2366// }
2367// else
2368// { // single or child prim
2369 partIRot = Quaternion.Inverse(part.GetWorldRotation());
2370// }
2371 float offZ = collisionPoint.Z - m_initialSitTarget.Z;
2372 Vector3 offset = new Vector3(0.0f, 0.0f, offZ) * partIRot; // Altitude correction
2373//Console.WriteLine("sitPoint={0}, offset={1}", sitPoint, offset);
2374 m_pos += offset;
2375// ControllingClient.SendClearFollowCamProperties(part.UUID);
2376
2377 }
2378 } // End SitAltitudeCallback KF.
2180 2379
2181 /// <summary> 2380 /// <summary>
2182 /// Event handler for the 'Always run' setting on the client 2381 /// Event handler for the 'Always run' setting on the client
@@ -2206,7 +2405,7 @@ namespace OpenSim.Region.Framework.Scenes
2206 /// </summary> 2405 /// </summary>
2207 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param> 2406 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param>
2208 /// <param name="rotation">The direction in which this avatar should now face. 2407 /// <param name="rotation">The direction in which this avatar should now face.
2209 public void AddNewMovement(Vector3 vec, Quaternion rotation) 2408 public void AddNewMovement(Vector3 vec, Quaternion rotation, bool Nudging)
2210 { 2409 {
2211 if (m_isChildAgent) 2410 if (m_isChildAgent)
2212 { 2411 {
@@ -2247,10 +2446,11 @@ namespace OpenSim.Region.Framework.Scenes
2247 Rotation = rotation; 2446 Rotation = rotation;
2248 Vector3 direc = vec * rotation; 2447 Vector3 direc = vec * rotation;
2249 direc.Normalize(); 2448 direc.Normalize();
2449 PhysicsActor actor = m_physicsActor;
2450 if ((vec.Z == 0f) && !actor.Flying) direc.Z = 0f; // Prevent camera WASD up.
2250 2451
2251 direc *= 0.03f * 128f * m_speedModifier; 2452 direc *= 0.03f * 128f * m_speedModifier;
2252 2453
2253 PhysicsActor actor = m_physicsActor;
2254 if (actor != null) 2454 if (actor != null)
2255 { 2455 {
2256 if (actor.Flying) 2456 if (actor.Flying)
@@ -2272,18 +2472,25 @@ namespace OpenSim.Region.Framework.Scenes
2272 { 2472 {
2273 if (direc.Z > 2.0f) 2473 if (direc.Z > 2.0f)
2274 { 2474 {
2275 direc.Z *= 3.0f; 2475 if(m_animator.m_animTickJump == -1)
2276 2476 {
2277 // TODO: PreJump and jump happen too quickly. Many times prejump gets ignored. 2477 direc.Z *= 3.0f; // jump
2278 Animator.TrySetMovementAnimation("PREJUMP"); 2478 }
2279 Animator.TrySetMovementAnimation("JUMP"); 2479 else
2480 {
2481 direc.Z *= 0.1f; // prejump
2482 }
2483 /* Animations are controlled via GetMovementAnimation() in ScenePresenceAnimator.cs
2484 Animator.TrySetMovementAnimation("PREJUMP");
2485 Animator.TrySetMovementAnimation("JUMP");
2486 */
2280 } 2487 }
2281 } 2488 }
2282 } 2489 }
2283 2490
2284 // TODO: Add the force instead of only setting it to support multiple forces per frame? 2491 // TODO: Add the force instead of only setting it to support multiple forces per frame?
2285 m_forceToApply = direc; 2492 m_forceToApply = direc;
2286 2493 m_isNudging = Nudging;
2287 m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); 2494 m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
2288 } 2495 }
2289 2496
@@ -2298,7 +2505,7 @@ namespace OpenSim.Region.Framework.Scenes
2298 const float POSITION_TOLERANCE = 0.05f; 2505 const float POSITION_TOLERANCE = 0.05f;
2299 //const int TIME_MS_TOLERANCE = 3000; 2506 //const int TIME_MS_TOLERANCE = 3000;
2300 2507
2301 SendPrimUpdates(); 2508
2302 2509
2303 if (m_newCoarseLocations) 2510 if (m_newCoarseLocations)
2304 { 2511 {
@@ -2334,6 +2541,9 @@ namespace OpenSim.Region.Framework.Scenes
2334 CheckForBorderCrossing(); 2541 CheckForBorderCrossing();
2335 CheckForSignificantMovement(); // sends update to the modules. 2542 CheckForSignificantMovement(); // sends update to the modules.
2336 } 2543 }
2544
2545 //Sending prim updates AFTER the avatar terse updates are sent
2546 SendPrimUpdates();
2337 } 2547 }
2338 2548
2339 #endregion 2549 #endregion
@@ -3150,6 +3360,7 @@ namespace OpenSim.Region.Framework.Scenes
3150 m_callbackURI = cAgent.CallbackURI; 3360 m_callbackURI = cAgent.CallbackURI;
3151 3361
3152 m_pos = cAgent.Position; 3362 m_pos = cAgent.Position;
3363
3153 m_velocity = cAgent.Velocity; 3364 m_velocity = cAgent.Velocity;
3154 m_CameraCenter = cAgent.Center; 3365 m_CameraCenter = cAgent.Center;
3155 //m_avHeight = cAgent.Size.Z; 3366 //m_avHeight = cAgent.Size.Z;
@@ -3238,14 +3449,25 @@ namespace OpenSim.Region.Framework.Scenes
3238 { 3449 {
3239 if (m_forceToApply.HasValue) 3450 if (m_forceToApply.HasValue)
3240 { 3451 {
3241 Vector3 force = m_forceToApply.Value;
3242 3452
3453 Vector3 force = m_forceToApply.Value;
3243 m_updateflag = true; 3454 m_updateflag = true;
3244// movementvector = force;
3245 Velocity = force; 3455 Velocity = force;
3246 3456
3247 m_forceToApply = null; 3457 m_forceToApply = null;
3248 } 3458 }
3459 else
3460 {
3461 if (m_isNudging)
3462 {
3463 Vector3 force = Vector3.Zero;
3464
3465 m_updateflag = true;
3466 Velocity = force;
3467 m_isNudging = false;
3468 m_updateCount = UPDATE_COUNT; //KF: Update anims to pickup "STAND"
3469 }
3470 }
3249 } 3471 }
3250 3472
3251 public override void SetText(string text, Vector3 color, double alpha) 3473 public override void SetText(string text, Vector3 color, double alpha)
@@ -3296,18 +3518,29 @@ namespace OpenSim.Region.Framework.Scenes
3296 { 3518 {
3297 if (e == null) 3519 if (e == null)
3298 return; 3520 return;
3299 3521
3300 //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f)) 3522 // The Physics Scene will send (spam!) updates every 500 ms grep: m_physicsActor.SubscribeEvents(
3301 // The Physics Scene will send updates every 500 ms grep: m_physicsActor.SubscribeEvents(
3302 // as of this comment the interval is set in AddToPhysicalScene 3523 // as of this comment the interval is set in AddToPhysicalScene
3303 if (Animator!=null) 3524 if (Animator!=null)
3304 Animator.UpdateMovementAnimations(); 3525 {
3526 if (m_updateCount > 0) //KF: DO NOT call UpdateMovementAnimations outside of the m_updateCount wrapper,
3527 { // else its will lock out other animation changes, like ground sit.
3528 Animator.UpdateMovementAnimations();
3529 m_updateCount--;
3530 }
3531 }
3305 3532
3306 CollisionEventUpdate collisionData = (CollisionEventUpdate)e; 3533 CollisionEventUpdate collisionData = (CollisionEventUpdate)e;
3307 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList; 3534 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList;
3308 3535
3309 CollisionPlane = Vector4.UnitW; 3536 CollisionPlane = Vector4.UnitW;
3310 3537
3538 if (m_lastColCount != coldata.Count)
3539 {
3540 m_updateCount = UPDATE_COUNT;
3541 m_lastColCount = coldata.Count;
3542 }
3543
3311 if (coldata.Count != 0 && Animator != null) 3544 if (coldata.Count != 0 && Animator != null)
3312 { 3545 {
3313 switch (Animator.CurrentMovementAnimation) 3546 switch (Animator.CurrentMovementAnimation)
@@ -3742,6 +3975,32 @@ namespace OpenSim.Region.Framework.Scenes
3742 return; 3975 return;
3743 } 3976 }
3744 3977
3978 XmlDocument doc = new XmlDocument();
3979 string stateData = String.Empty;
3980
3981 IAttachmentsService attServ = m_scene.RequestModuleInterface<IAttachmentsService>();
3982 if (attServ != null)
3983 {
3984 m_log.DebugFormat("[ATTACHMENT]: Loading attachment data from attachment service");
3985 stateData = attServ.Get(ControllingClient.AgentId.ToString());
3986 doc.LoadXml(stateData);
3987 }
3988
3989 Dictionary<UUID, string> itemData = new Dictionary<UUID, string>();
3990
3991 XmlNodeList nodes = doc.GetElementsByTagName("Attachment");
3992 if (nodes.Count > 0)
3993 {
3994 foreach (XmlNode n in nodes)
3995 {
3996 XmlElement elem = (XmlElement)n;
3997 string itemID = elem.GetAttribute("ItemID");
3998 string xml = elem.InnerXml;
3999
4000 itemData[new UUID(itemID)] = xml;
4001 }
4002 }
4003
3745 List<int> attPoints = m_appearance.GetAttachedPoints(); 4004 List<int> attPoints = m_appearance.GetAttachedPoints();
3746 foreach (int p in attPoints) 4005 foreach (int p in attPoints)
3747 { 4006 {
@@ -3761,9 +4020,26 @@ namespace OpenSim.Region.Framework.Scenes
3761 4020
3762 try 4021 try
3763 { 4022 {
3764 // Rez from inventory 4023 string xmlData;
3765 UUID asset 4024 XmlDocument d = new XmlDocument();
3766 = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p); 4025 UUID asset;
4026 if (itemData.TryGetValue(itemID, out xmlData))
4027 {
4028 d.LoadXml(xmlData);
4029 m_log.InfoFormat("[ATTACHMENT]: Found saved state for item {0}, loading it", itemID);
4030
4031 // Rez from inventory
4032 asset
4033 = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p, true, d);
4034
4035 }
4036 else
4037 {
4038 // Rez from inventory (with a null doc to let
4039 // CHANGED_OWNER happen)
4040 asset
4041 = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p, true, null);
4042 }
3767 4043
3768 m_log.InfoFormat( 4044 m_log.InfoFormat(
3769 "[ATTACHMENT]: Rezzed attachment in point {0} from item {1} and asset {2} ({3})", 4045 "[ATTACHMENT]: Rezzed attachment in point {0} from item {1} and asset {2} ({3})",
@@ -3914,5 +4190,16 @@ namespace OpenSim.Region.Framework.Scenes
3914 m_reprioritization_called = false; 4190 m_reprioritization_called = false;
3915 } 4191 }
3916 } 4192 }
4193
4194 private Vector3 Quat2Euler(Quaternion rot){
4195 float x = Utils.RAD_TO_DEG * (float)Math.Atan2((double)((2.0f * rot.X * rot.W) - (2.0f * rot.Y * rot.Z)) ,
4196 (double)(1 - (2.0f * rot.X * rot.X) - (2.0f * rot.Z * rot.Z)));
4197 float y = Utils.RAD_TO_DEG * (float)Math.Asin ((double)((2.0f * rot.X * rot.Y) + (2.0f * rot.Z * rot.W)));
4198 float z = Utils.RAD_TO_DEG * (float)Math.Atan2(((double)(2.0f * rot.Y * rot.W) - (2.0f * rot.X * rot.Z)) ,
4199 (double)(1 - (2.0f * rot.Y * rot.Y) - (2.0f * rot.Z * rot.Z)));
4200 return(new Vector3(x,y,z));
4201 }
4202
4203
3917 } 4204 }
3918} 4205}
diff --git a/OpenSim/Region/Framework/Scenes/SceneViewer.cs b/OpenSim/Region/Framework/Scenes/SceneViewer.cs
index c6cf4cc..4ba4fab 100644
--- a/OpenSim/Region/Framework/Scenes/SceneViewer.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneViewer.cs
@@ -75,7 +75,7 @@ namespace OpenSim.Region.Framework.Scenes
75 75
76 foreach (EntityBase e in m_presence.Scene.Entities) 76 foreach (EntityBase e in m_presence.Scene.Entities)
77 { 77 {
78 if (e is SceneObjectGroup) 78 if (e != null && e is SceneObjectGroup)
79 m_pendingObjects.Enqueue((SceneObjectGroup)e); 79 m_pendingObjects.Enqueue((SceneObjectGroup)e);
80 } 80 }
81 } 81 }